FitProps.vue 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. <template>
  2. <div class="props">
  3. <t-tabs v-model="data.tab">
  4. <t-tab-panel :value="1" :label="$t('布局容器')">
  5. <t-space direction="vertical" class="py-16 w-full">
  6. <div class="form-item px-12">
  7. <label style="width: 67px">ID</label>
  8. <div style="padding-left: 8px; line-height: 30px">
  9. {{ data.fit.id }}
  10. </div>
  11. </div>
  12. <div class="form-item px-12" style="margin-top: -12px">
  13. <label style="width: 50px">{{$t('名称')}}</label>
  14. <div style="padding-left: 8px; line-height: 30px">
  15. <t-input class="ml-8" v-model="data.fit.name" :placeholder="$t('默认0')"></t-input>
  16. </div>
  17. </div>
  18. <div class="form-item px-12">
  19. <label>{{$t('靠左')}}</label>
  20. <div class="flex center" style="align-items: center">
  21. <t-switch size="small" v-model="data.fit.left"></t-switch>
  22. <t-input-number theme="normal" class="ml-8" @change="onFitChange" v-model="data.fit.leftValue" :placeholder="$t('默认0')"></t-input-number>
  23. </div>
  24. </div>
  25. <div class="form-item px-12">
  26. <label>{{$t('靠右')}}</label>
  27. <div class="flex center" style="align-items: center">
  28. <t-switch size="small" v-model="data.fit.right"></t-switch>
  29. <t-input-number theme="normal" class="ml-8" @change="onFitChange" v-model="data.fit.rightValue" :placeholder="$t('默认0')"></t-input-number>
  30. </div>
  31. </div>
  32. <div class="form-item px-12">
  33. <label>{{$t('靠上')}}</label>
  34. <div class="flex center" style="align-items: center">
  35. <t-switch size="small" v-model="data.fit.top"></t-switch>
  36. <t-input-number theme="normal" class="ml-8" @change="onFitChange" v-model="data.fit.topValue" :placeholder="$t('默认0')"></t-input-number>
  37. </div>
  38. </div>
  39. <div class="form-item px-12">
  40. <label>{{$t('靠下')}}</label>
  41. <div class="flex center" style="align-items: center">
  42. <t-switch size="small" v-model="data.fit.bottom"></t-switch>
  43. <t-input-number theme="normal" class="ml-8" v-model="data.fit.bottomValue" @change="onFitChange" :placeholder="$t('默认0')"></t-input-number>
  44. </div>
  45. </div>
  46. <div class="form-item px-12">
  47. <label>{{$t('展示图元')}}</label>
  48. <div>
  49. <t-switch size="small" @change="fitPenVisible"></t-switch>
  50. </div>
  51. </div>
  52. <div class="px-12">
  53. <div class="mb-8">{{$t('图元列表')}}</div>
  54. <div class="grid head">
  55. <div class="title">{{$t('名称')}}</div>
  56. <div class="title">{{$t('图元')}}id</div>
  57. <div class="title">{{$t('操作')}}</div>
  58. </div>
  59. <div class="body">
  60. <div :data-penid="item.value" v-for="(item, i) in data.list" class="grid" :class="data.active.includes(item.value) ? 'active' : ''">
  61. <span class="hover" @click="doActive(item.value)">
  62. {{ item.label }}
  63. </span>
  64. <span class="hover" @click="doActive(item.value)">
  65. {{ item.value }}
  66. </span>
  67. <t-popconfirm @confirm="doRemove(i)" :content="$t('确认移除吗')">
  68. <t-tooltip :content="$t('从布局容器中移除此图元')">
  69. <div class="hover"><delete-icon></delete-icon></div>
  70. </t-tooltip>
  71. </t-popconfirm>
  72. </div>
  73. </div>
  74. </div>
  75. </t-space>
  76. </t-tab-panel>
  77. </t-tabs>
  78. </div>
  79. </template>
  80. <script lang="ts" setup>
  81. import {
  82. reactive,
  83. onBeforeMount,
  84. ref,
  85. watch,
  86. onUnmounted,
  87. onMounted,
  88. } from 'vue';
  89. import { useSelection } from '@/services/selections';
  90. import { DeleteIcon } from 'tdesign-icons-vue-next';
  91. const data = reactive({
  92. fit: undefined,
  93. tab: 1,
  94. list: [],
  95. active: [],
  96. });
  97. const { selections } = useSelection();
  98. onBeforeMount(() => {
  99. data.fit = selections.fit;
  100. getChildrenList();
  101. });
  102. onMounted(() => {
  103. meta2d.on('active', active);
  104. meta2d.on('fit', childChange);
  105. });
  106. onUnmounted(() => {
  107. watcher();
  108. meta2d.off('active', active);
  109. meta2d.off('fit', childChange);
  110. });
  111. const childChange = () => {
  112. getChildrenList();
  113. };
  114. const watcher = watch(
  115. () => selections.fit.id,
  116. (id) => {
  117. data.fit = selections.fit;
  118. getChildrenList();
  119. }
  120. );
  121. const getChildrenList = () => {
  122. data.list = [];
  123. selections.fit&&selections.fit.children?.forEach((id) => {
  124. const pen = meta2d.store.pens[id];
  125. if (pen) {
  126. data.list.push({
  127. label: (pen as any).description || pen.name,
  128. value: pen.id,
  129. locked: pen.locked,
  130. visible: pen.visible,
  131. tag: (pen as any).tag,
  132. });
  133. }
  134. });
  135. };
  136. const fitPenVisible = (e) => {
  137. if (e) {
  138. meta2d.store.data.pens.forEach((pen) => {
  139. if (!selections.fit.children?.includes(pen.id)) {
  140. meta2d.setValue(
  141. { id: pen.id, visible: false },
  142. { render: false, doEvent: false, history: false }
  143. );
  144. }
  145. });
  146. meta2d.canvas.hideFit();
  147. meta2d.canvas.canvasImage.init();
  148. meta2d.canvas.canvasImageBottom.init();
  149. meta2d.render();
  150. } else {
  151. meta2d.store.data.pens.forEach((pen) => {
  152. if (!selections.fit.children?.includes(pen.id)) {
  153. meta2d.setValue(
  154. { id: pen.id, visible: true },
  155. { render: false, doEvent: false, history: false }
  156. );
  157. }
  158. });
  159. meta2d.canvas.showFit();
  160. meta2d.canvas.canvasImage.init();
  161. meta2d.canvas.canvasImageBottom.init();
  162. meta2d.render();
  163. }
  164. };
  165. const doActive = (id) => {
  166. let pen = meta2d.store.pens[id];
  167. meta2d.active([pen], false);
  168. };
  169. const doRemove = (idx) => {
  170. let childId = data.list[idx].value;
  171. data.fit.children.splice(idx, 1);
  172. meta2d.inactive();
  173. meta2d.setVisible(meta2d.store.pens[childId], false);
  174. getChildrenList();
  175. };
  176. const active = () => {
  177. data.active = meta2d.store.active.map((pen) => pen.id);
  178. const element = document.body.querySelector(
  179. `[data-penid="${data.active[0]}"]`
  180. );
  181. if (element) {
  182. element.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
  183. }
  184. };
  185. const onFitChange = () => {
  186. meta2d.canvas.updateFitRect(data.fit);
  187. };
  188. </script>
  189. <style lang="postcss" scoped>
  190. .props {
  191. .grid {
  192. grid-template-columns: 100px 100px auto;
  193. padding: 0 12px;
  194. &.head {
  195. background: var(--color-background-input);
  196. line-height: 36px;
  197. margin-bottom: 6px;
  198. .title {
  199. line-height: 36px;
  200. }
  201. }
  202. }
  203. .active {
  204. color: var(--color-primary);
  205. }
  206. .body {
  207. max-height: 300px;
  208. overflow-y: auto;
  209. }
  210. }
  211. </style>