index.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. <template>
  2. <Container
  3. :upload-resourse="uploadResourse"
  4. v-model:full="full"
  5. :ref="(d: any) => (draw = d?.draw)"
  6. >
  7. <template #header>
  8. <Header v-if="inited" :title="title" />
  9. </template>
  10. <template #slide>
  11. <Slide v-if="inited" />
  12. </template>
  13. </Container>
  14. <Dialog />
  15. </template>
  16. <script lang="ts" setup>
  17. import Header from "./header.vue";
  18. import Slide from "./slide.vue";
  19. import Container from "../../../components/container/container.vue";
  20. import { computed, nextTick, ref, watch, watchEffect } from "vue";
  21. import { Draw } from "../../../components/container/use-draw";
  22. import Dialog from "../../../dialog/dialog.vue";
  23. import {
  24. tabulationData,
  25. refreshTabulationData,
  26. tableCoverKey,
  27. tableCoverScaleKey,
  28. tableCompassKey,
  29. } from "../../store";
  30. import { ImageData } from "@/core/components/image";
  31. import { TextData } from "@/core/components/text";
  32. import {
  33. genTabulationData,
  34. getCoverPaperScale,
  35. getRealPixel,
  36. repTabulationStore,
  37. setCoverPaperScale,
  38. } from "./gen-tab";
  39. import { IconData } from "@/core/components/icon";
  40. import { Transform } from "konva/lib/Util";
  41. import { MathUtils } from "three";
  42. import { components } from "@/core/components";
  43. import { ShapeType } from "@/index";
  44. import { round } from "@/utils/shared";
  45. import { PaperKey } from "@/example/components/slide/actions";
  46. import { StoreData } from "@/core/store/store";
  47. import { getImageSize } from "@/utils/shape";
  48. import { tabCustomStyle } from "./defStyle";
  49. import { defaultLayer } from "@/constant";
  50. const uploadResourse = window.platform.uploadResourse;
  51. const full = ref(false);
  52. const draw = ref<Draw>();
  53. const setMap = async (paperKey: PaperKey, compass: number, store: StoreData) => {
  54. const data = tabulationData.value;
  55. if (data.mapUrl && data.high && data.width) {
  56. const size = await getImageSize(data.mapUrl);
  57. const cover = {
  58. url: data.mapUrl,
  59. ...size,
  60. proportion: {
  61. scale: (data.width / size.width) * 1000,
  62. unit: "mm",
  63. },
  64. };
  65. if (!data.store.config) {
  66. const layer = await genTabulationData(paperKey, compass, cover);
  67. data.store.layers[defaultLayer] = layer;
  68. } else {
  69. await repTabulationStore(paperKey, compass, cover, store);
  70. }
  71. }
  72. };
  73. const inited = ref(false);
  74. const init = async (draw: Draw) => {
  75. await refreshTabulationData();
  76. draw.config.showCompass = false;
  77. draw.config.showGrid = false;
  78. draw.config.showLabelLine = false;
  79. draw.config.showComponentSize = false;
  80. const config: any = tabulationData.value.store.config || {};
  81. const p = tabulationData.value.paperKey;
  82. await setMap(p, 0, tabulationData.value.store);
  83. draw.store.setStore({
  84. ...tabulationData.value.store,
  85. config: {
  86. ...config,
  87. compass: {
  88. rotation: 0,
  89. ...(config.compass || {}),
  90. url: "./icons/compass.svg",
  91. },
  92. proportion: {
  93. scale: 1 / getRealPixel(1, p),
  94. unit: "mm",
  95. },
  96. },
  97. });
  98. inited.value = true;
  99. return tabCustomStyle(p);
  100. };
  101. watch(draw, (draw, _, onCleanup) => {
  102. if (draw) {
  103. for (const type in components) {
  104. draw.menusFilter.setMenusFilter(type as ShapeType, (items) => {
  105. return items.filter((item) => item.label !== "隐藏");
  106. });
  107. }
  108. let des = false;
  109. let unInit: () => void;
  110. init(draw).then((_unInit) => {
  111. if (!des) {
  112. unInit = _unInit;
  113. } else {
  114. _unInit();
  115. }
  116. });
  117. onCleanup(() => {
  118. unInit && unInit();
  119. des = true;
  120. });
  121. }
  122. });
  123. const cover = computed(
  124. () => draw.value?.store.items.find((item) => item.key === tableCoverKey) as ImageData
  125. );
  126. const coverScale = computed({
  127. get: () =>
  128. cover.value &&
  129. Math.round(getCoverPaperScale(cover.value, tabulationData.value.paperKey)),
  130. set: (val) => {
  131. setCoverPaperScale(cover.value, tabulationData.value.paperKey, val);
  132. },
  133. });
  134. watch(cover, (cover, _, onCleanup) => {
  135. if (!cover || !draw.value || !cover.widthRaw || !cover.heightRaw || !cover.proportion)
  136. return;
  137. const mountMenus = draw.value.mountFilter;
  138. const menusFilter = draw.value.menusFilter;
  139. menusFilter.setShapeMenusFilter(cover.id, () => []);
  140. mountMenus.setShapeMenusFilter(cover.id, (des) => ({
  141. ...des,
  142. scale: {
  143. type: "fixProportion",
  144. label: "缩放比例",
  145. "layout-type": "row",
  146. get value() {
  147. return coverScale.value;
  148. },
  149. set value(val) {
  150. coverScale.value = val;
  151. },
  152. props: { min: 1 },
  153. },
  154. showScale: {
  155. type: "check",
  156. label: "显示比例",
  157. "layout-type": "row",
  158. get value() {
  159. return (cover as any).showScale || false;
  160. },
  161. set value(val) {
  162. (cover as any).showScale = val;
  163. },
  164. props: {},
  165. },
  166. }));
  167. onCleanup(() => {
  168. mountMenus.setShapeMenusFilter(cover.id);
  169. menusFilter.setShapeMenusFilter(cover.id);
  170. });
  171. });
  172. const coverScaleText = computed(() => {
  173. return draw.value?.store.items.find(
  174. (item) => item.key === tableCoverScaleKey
  175. ) as TextData;
  176. });
  177. watch(
  178. () => {
  179. return {
  180. text: coverScaleText.value,
  181. exists: cover.value,
  182. show: (cover.value as any)?.showScale,
  183. content: coverScale.value ? `1:${coverScale.value}` : "",
  184. };
  185. },
  186. ({ text, show, exists, content }) => {
  187. if (!text) return;
  188. draw.value!.history.preventTrack(() => {
  189. if (!exists) {
  190. draw.value!.store.delItem("text", text.id);
  191. } else {
  192. draw.value!.store.setItem("text", {
  193. value: { hide: !show, content },
  194. id: text.id,
  195. });
  196. }
  197. });
  198. },
  199. { flush: "post" }
  200. );
  201. const compass = computed(
  202. () => draw.value?.store.items.find((item) => item.key === tableCompassKey) as IconData
  203. );
  204. watch(compass, (compass, _, onCleanup) => {
  205. if (!compass || !draw.value) return;
  206. const mountMenus = draw.value.mountFilter;
  207. const menusFilter = draw.value.menusFilter;
  208. menusFilter.setShapeMenusFilter(compass.id, () => []);
  209. mountMenus.setShapeMenusFilter(compass.id, (des) => ({
  210. // ...des,
  211. rotate: {
  212. type: "num",
  213. label: "旋转角度",
  214. default: 0,
  215. props: {
  216. min: 0,
  217. max: 360,
  218. },
  219. "layout-type": "column",
  220. sort: 3,
  221. get value() {
  222. return round((new Transform(compass.mat).decompose().rotation + 360) % 360, 1);
  223. },
  224. set value(val) {
  225. const config = new Transform(compass.mat).decompose();
  226. compass.mat = new Transform()
  227. .translate(config.x, config.y)
  228. .scale(config.scaleX, config.scaleY)
  229. .rotate(MathUtils.degToRad(val)).m;
  230. nextTick(() => {
  231. draw.value?.stage!.findOne(`#${compass.id}`)?.fire("bound-change");
  232. });
  233. },
  234. },
  235. }));
  236. onCleanup(() => {
  237. mountMenus.setShapeMenusFilter(compass.id);
  238. menusFilter.setShapeMenusFilter(compass.id);
  239. });
  240. });
  241. const title = computed(() => tabulationData.value?.title || "图纸");
  242. watchEffect(() => {
  243. document.title = title.value;
  244. });
  245. </script>