|
|
@@ -2,16 +2,28 @@
|
|
|
<Container
|
|
|
:upload-resourse="uploadResourse"
|
|
|
v-model:full="full"
|
|
|
- :ref="(d: any) => (draw = d?.draw)"
|
|
|
+ v-if="dataLoaded"
|
|
|
+ :ref="(d: any) => initDraw(d?.draw)"
|
|
|
>
|
|
|
<template #header>
|
|
|
- <Header v-if="inited" title="图纸" />
|
|
|
+ <Header v-if="draw" title="图纸" @screenshot="(val) => (needScreenshot = val)" />
|
|
|
</template>
|
|
|
<template #slide>
|
|
|
- <Slide v-if="inited" @update-map-image="setMapHandler" />
|
|
|
+ <Slide v-if="draw" @update-map-image="setMapHandler" />
|
|
|
</template>
|
|
|
</Container>
|
|
|
|
|
|
+ <Preview
|
|
|
+ @change-origin="(origin) => setOrigin && setOrigin(origin)"
|
|
|
+ :cover-scale="coverSetting?.scale"
|
|
|
+ :paperKey="tabulationData?.paperKey"
|
|
|
+ :pixelRatio="needScreenshot ? 4 : pixelRatio"
|
|
|
+ :not-debounce="needScreenshot"
|
|
|
+ :data="overviewData?.store"
|
|
|
+ :scale="draw?.viewerConfig.scaleX"
|
|
|
+ @change-config="(config) => (originConfig = config)"
|
|
|
+ v-if="overviewData?.store.config?.proportion.scale"
|
|
|
+ />
|
|
|
<Dialog />
|
|
|
</template>
|
|
|
|
|
|
@@ -19,7 +31,16 @@
|
|
|
import Header from "./header.vue";
|
|
|
import Slide from "./slide.vue";
|
|
|
import Container from "../../../components/container/container.vue";
|
|
|
-import { computed, nextTick, ref, watch, watchEffect } from "vue";
|
|
|
+import {
|
|
|
+ computed,
|
|
|
+ nextTick,
|
|
|
+ onUnmounted,
|
|
|
+ reactive,
|
|
|
+ ref,
|
|
|
+ shallowRef,
|
|
|
+ watch,
|
|
|
+ watchEffect,
|
|
|
+} from "vue";
|
|
|
import { Draw } from "../../../components/container/use-draw";
|
|
|
import Dialog from "../../../dialog/dialog.vue";
|
|
|
import {
|
|
|
@@ -28,16 +49,12 @@ import {
|
|
|
tableCoverKey,
|
|
|
tableCoverScaleKey,
|
|
|
tableCompassKey,
|
|
|
+ overviewData,
|
|
|
+ refreshOverviewData,
|
|
|
} from "../../store";
|
|
|
import { ImageData } from "@/core/components/image";
|
|
|
import { TextData } from "@/core/components/text";
|
|
|
-import {
|
|
|
- genTabulationData,
|
|
|
- getCoverPaperScale,
|
|
|
- getRealPixel,
|
|
|
- repTabulationStore,
|
|
|
- setCoverPaperScale,
|
|
|
-} from "./gen-tab";
|
|
|
+import { genTabulationData, getRealPixel, repTabulationStore } from "./gen-tab";
|
|
|
import { IconData } from "@/core/components/icon";
|
|
|
import { Transform } from "konva/lib/Util";
|
|
|
import { MathUtils } from "three";
|
|
|
@@ -48,10 +65,21 @@ import { getImageSize } from "@/utils/shape";
|
|
|
import { tabCustomStyle } from "../defStyle";
|
|
|
import { defaultLayer } from "@/constant";
|
|
|
import { Size } from "@/utils/math";
|
|
|
+import Preview from "./overview-viewport.vue";
|
|
|
+import { Image } from "konva/lib/shapes/Image";
|
|
|
+import { Group } from "konva/lib/Group";
|
|
|
+import { getBaseItem } from "@/core/components/util";
|
|
|
+import {
|
|
|
+ getPaperConfig,
|
|
|
+ paperConfigs,
|
|
|
+ PaperKey,
|
|
|
+} from "@/example/components/slide/actions";
|
|
|
+import { getFixPosition } from "@/utils/bound";
|
|
|
|
|
|
const uploadResourse = window.platform.uploadResourse;
|
|
|
const full = ref(false);
|
|
|
const draw = ref<Draw>();
|
|
|
+const pixelRatio = ref(window.devicePixelRatio);
|
|
|
|
|
|
const setMap = async (config: { url: string; size: Size }) => {
|
|
|
const store = tabulationData.value.store;
|
|
|
@@ -120,111 +148,158 @@ const setMapHandler = async (config: { url: string; size: Size }) => {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-const inited = ref(false);
|
|
|
-const init = async (draw: Draw) => {
|
|
|
- const quitMerges: Array<() => void> = [];
|
|
|
- await refreshTabulationData();
|
|
|
- draw.config.showCompass = false;
|
|
|
- draw.config.showGrid = false;
|
|
|
- draw.config.showLabelLine = false;
|
|
|
- draw.config.showComponentSize = false;
|
|
|
-
|
|
|
- const config: any = tabulationData.value.store.config || {};
|
|
|
- const data = tabulationData.value;
|
|
|
- const p = tabulationData.value.paperKey;
|
|
|
- await setMap({ url: data.mapUrl!, size: { width: data.width!, height: data.high! } });
|
|
|
- draw.store.setStore({
|
|
|
- ...tabulationData.value.store,
|
|
|
- config: {
|
|
|
- ...config,
|
|
|
- compass: {
|
|
|
- rotation: 0,
|
|
|
- ...(config.compass || {}),
|
|
|
- url: "./icons/compass.svg",
|
|
|
- },
|
|
|
- proportion: {
|
|
|
- scale: 1 / getRealPixel(1, p),
|
|
|
- unit: "mm",
|
|
|
+const needScreenshot = ref(false);
|
|
|
+const coverSetting = computed(() => {
|
|
|
+ const cover = draw.value?.store.items.find((item) => item.key === tableCoverKey);
|
|
|
+ return cover?.userData as { showScale: boolean; scale: number } | undefined;
|
|
|
+});
|
|
|
+let setOrigin: (canvas: HTMLCanvasElement) => void;
|
|
|
+const originConfig = shallowRef<{ size: Size; scale: number }>();
|
|
|
+const setCover = (paperKey: PaperKey, draw: Draw) => {
|
|
|
+ const cleanups: (() => void)[] = [];
|
|
|
+ const cleanup = () => {
|
|
|
+ mergeFuns(cleanups)();
|
|
|
+ cleanups.length = 0;
|
|
|
+ };
|
|
|
+ let cover = draw.store.items.find((item) => item.key === tableCoverKey) as ImageData;
|
|
|
+ if (!cover) {
|
|
|
+ cover = reactive({
|
|
|
+ ...getBaseItem(),
|
|
|
+ cornerRadius: 0,
|
|
|
+ strokeWidth: 0,
|
|
|
+ disableDelete: true,
|
|
|
+ key: tableCoverKey,
|
|
|
+ disableTransformer: true,
|
|
|
+ userData: {
|
|
|
+ showScale: true,
|
|
|
+ scale: 0,
|
|
|
},
|
|
|
- strokeProportion: {
|
|
|
- scale: 1 / getRealPixel(1, p),
|
|
|
- unit: "mm",
|
|
|
+ zIndex: -1,
|
|
|
+ width: 0,
|
|
|
+ height: 0,
|
|
|
+ mat: [1, 0, 0, 1, 0, 0],
|
|
|
+ itemName: "比例",
|
|
|
+ });
|
|
|
+ const stopWatch = watch(
|
|
|
+ originConfig,
|
|
|
+ (config) => {
|
|
|
+ if (!config) return;
|
|
|
+ const { margin, size } = getPaperConfig(
|
|
|
+ paperConfigs[paperKey].size,
|
|
|
+ paperConfigs[paperKey].scale
|
|
|
+ );
|
|
|
+ const pos = getFixPosition(
|
|
|
+ {
|
|
|
+ left: config.size.width / 2 + margin[3] + getRealPixel(15, paperKey),
|
|
|
+ bottom: -config.size.height / 2 + margin[2] + getRealPixel(15, paperKey),
|
|
|
+ },
|
|
|
+ config.size,
|
|
|
+ size
|
|
|
+ );
|
|
|
+ const mat = new Transform().translate(pos.x, pos.y).m;
|
|
|
+
|
|
|
+ draw.history.preventTrack(() => {
|
|
|
+ draw.store.setItem("image", {
|
|
|
+ id: cover.id,
|
|
|
+ value: {
|
|
|
+ mat: mat,
|
|
|
+ userData: {
|
|
|
+ ...cover.userData,
|
|
|
+ scale: config.scale,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ });
|
|
|
+ });
|
|
|
+ nextTick(() => stopWatch());
|
|
|
},
|
|
|
- },
|
|
|
- });
|
|
|
- inited.value = true;
|
|
|
- quitMerges.push(tabCustomStyle(p, draw));
|
|
|
- return () => mergeFuns(quitMerges)();
|
|
|
-};
|
|
|
-watch(draw, (draw, _, onCleanup) => {
|
|
|
- if (draw) {
|
|
|
- const quits: (() => void)[] = [
|
|
|
- mergeFuns(
|
|
|
- Object.keys(components).map((type) =>
|
|
|
- draw.menusFilter.setMenusFilter(type as ShapeType, (items) => {
|
|
|
- return items.filter((item) => item.label !== "隐藏");
|
|
|
- })
|
|
|
- )
|
|
|
- ),
|
|
|
- ];
|
|
|
+ { flush: "sync", immediate: true }
|
|
|
+ );
|
|
|
+ cleanups.push(stopWatch);
|
|
|
+ draw.store.addItem("image", cover);
|
|
|
+ } else {
|
|
|
+ delete cover.url;
|
|
|
+ }
|
|
|
|
|
|
- let des = false;
|
|
|
- let unInit: () => void;
|
|
|
- init(draw).then((_unInit) => {
|
|
|
- if (!des) {
|
|
|
- unInit = _unInit;
|
|
|
- } else {
|
|
|
- _unInit();
|
|
|
- }
|
|
|
- });
|
|
|
- quits.push(() => {
|
|
|
- unInit && unInit();
|
|
|
- des = true;
|
|
|
+ let text = draw.store.items.find((item) => item.key === tableCoverScaleKey) as TextData;
|
|
|
+ if (!text) {
|
|
|
+ text = reactive({
|
|
|
+ ...getBaseItem(),
|
|
|
+ content: ``,
|
|
|
+ width: getRealPixel(30, paperKey),
|
|
|
+ heihgt: getRealPixel(4.8, paperKey),
|
|
|
+ fontSize: getRealPixel(4, paperKey),
|
|
|
+ disableEditText: true,
|
|
|
+ key: tableCoverScaleKey,
|
|
|
+ disableDelete: true,
|
|
|
+ align: "center",
|
|
|
+ mat: [1, 0, 0, 1, 0, 0],
|
|
|
});
|
|
|
- onCleanup(mergeFuns(quits));
|
|
|
+ draw.store.addItem("text", text);
|
|
|
+ let stopWatch = watch(
|
|
|
+ () => cover.width && cover.height,
|
|
|
+ (loaded) => {
|
|
|
+ if (loaded) {
|
|
|
+ const mat = [...cover.mat];
|
|
|
+ const x = mat[4] - (text.width || 0) / 2;
|
|
|
+ const y = mat[5] + cover.height / 2 + getRealPixel(5, paperKey);
|
|
|
+ mat[4] = x;
|
|
|
+ mat[5] = y;
|
|
|
+ draw.history.preventTrack(() => {
|
|
|
+ draw.store.setItem("text", { id: text.id, value: { mat } });
|
|
|
+ });
|
|
|
+ nextTick(() => {
|
|
|
+ stopWatch();
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+ cleanups.push(stopWatch);
|
|
|
}
|
|
|
-});
|
|
|
-
|
|
|
-const cover = computed(
|
|
|
- () => draw.value?.store.items.find((item) => item.key === tableCoverKey) as ImageData
|
|
|
-);
|
|
|
-watchEffect(() => {
|
|
|
- if (cover.value && draw.value) {
|
|
|
- draw.value.excludeSelection.push(cover.value.id);
|
|
|
+ // 兼容旧数据
|
|
|
+ if (!cover.userData) {
|
|
|
+ const scale =
|
|
|
+ (cover.widthRaw! / cover.width) *
|
|
|
+ paperConfigs[paperKey].scale *
|
|
|
+ cover.proportion!.scale;
|
|
|
+ console.log("兼容旧cover");
|
|
|
+ cover.userData = {
|
|
|
+ showScale: true,
|
|
|
+ scale: round(scale, 1),
|
|
|
+ };
|
|
|
}
|
|
|
-});
|
|
|
-const coverScale = computed({
|
|
|
- get: () =>
|
|
|
- cover.value &&
|
|
|
- Math.round(getCoverPaperScale(cover.value, tabulationData.value.paperKey)),
|
|
|
- set: (val) => {
|
|
|
- setCoverPaperScale(cover.value, tabulationData.value.paperKey, val);
|
|
|
- },
|
|
|
-});
|
|
|
-watch(cover, (cover, _, onCleanup) => {
|
|
|
- if (!cover || !draw.value || !cover.widthRaw || !cover.heightRaw || !cover.proportion)
|
|
|
- return;
|
|
|
- const mountMenus = draw.value.mountFilter;
|
|
|
- const menusFilter = draw.value.menusFilter;
|
|
|
- const quits = [
|
|
|
- watchEffect(() => {
|
|
|
- console.log(cover);
|
|
|
- console.log("当前图片宽高:", cover.width, cover.height);
|
|
|
- console.log("当前图片真实宽高:", cover.widthRaw, cover.heightRaw);
|
|
|
- console.log("当前图片比例:", { ...cover.proportion });
|
|
|
- }),
|
|
|
+
|
|
|
+ const coverQue = computed(() => draw.store.getItem("image", cover.id));
|
|
|
+ const coverTexQue = computed(() => draw.store.getItem("text", text.id));
|
|
|
+
|
|
|
+ const mountMenus = draw.mountFilter;
|
|
|
+ const menusFilter = draw.menusFilter;
|
|
|
+ draw.excludeSelection.push(cover.id);
|
|
|
+
|
|
|
+ cleanups.push(
|
|
|
+ watch(
|
|
|
+ coverSetting,
|
|
|
+ (setting) => {
|
|
|
+ if (coverTexQue.value) {
|
|
|
+ coverTexQue.value.content = setting ? `1:${setting.scale}` : "";
|
|
|
+ coverTexQue.value.hide = !setting?.showScale;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { deep: true }
|
|
|
+ ),
|
|
|
menusFilter.setShapeMenusFilter(cover.id, () => []),
|
|
|
- mountMenus.setShapeMenusFilter(cover.id, (des) => ({
|
|
|
- ...des,
|
|
|
+ mountMenus.setShapeMenusFilter(cover.id, (menus) => ({
|
|
|
+ ...menus,
|
|
|
scale: {
|
|
|
type: "fixProportion",
|
|
|
label: "缩放比例",
|
|
|
"layout-type": "row",
|
|
|
get value() {
|
|
|
- return coverScale.value;
|
|
|
+ return coverSetting.value?.scale;
|
|
|
},
|
|
|
set value(val) {
|
|
|
- coverScale.value = Math.max(val || 0, 1);
|
|
|
+ if (coverSetting.value) {
|
|
|
+ coverSetting.value.scale = Math.max(val || 0, 1);
|
|
|
+ }
|
|
|
},
|
|
|
props: { min: 1 },
|
|
|
},
|
|
|
@@ -233,47 +308,129 @@ watch(cover, (cover, _, onCleanup) => {
|
|
|
label: "显示比例",
|
|
|
"layout-type": "row",
|
|
|
get value() {
|
|
|
- return (cover as any).showScale || false;
|
|
|
+ return coverSetting.value?.showScale;
|
|
|
},
|
|
|
set value(val) {
|
|
|
- (cover as any).showScale = val;
|
|
|
+ if (coverSetting.value) {
|
|
|
+ coverSetting.value.showScale = val || false;
|
|
|
+ }
|
|
|
},
|
|
|
props: {},
|
|
|
},
|
|
|
})),
|
|
|
- ];
|
|
|
- onCleanup(mergeFuns(quits));
|
|
|
-});
|
|
|
+ watch(coverQue, (cover) => {
|
|
|
+ if (!cover) {
|
|
|
+ draw.history.preventTrack(() => {
|
|
|
+ draw.store.delItem("text", text.id);
|
|
|
+ });
|
|
|
+ cleanup();
|
|
|
+ }
|
|
|
+ }),
|
|
|
+ watch(
|
|
|
+ originConfig,
|
|
|
+ (config, _) => {
|
|
|
+ if (coverQue.value) {
|
|
|
+ coverQue.value.width = config?.size.width || 0;
|
|
|
+ coverQue.value.height = config?.size.height || 0;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { deep: true, immediate: true }
|
|
|
+ )
|
|
|
+ );
|
|
|
|
|
|
-const coverScaleText = computed(() => {
|
|
|
- return draw.value?.store.items.find(
|
|
|
- (item) => item.key === tableCoverScaleKey
|
|
|
- ) as TextData;
|
|
|
-});
|
|
|
-watch(
|
|
|
- () => {
|
|
|
- return {
|
|
|
- text: coverScaleText.value,
|
|
|
- exists: cover.value,
|
|
|
- show: (cover.value as any)?.showScale,
|
|
|
- content: coverScale.value ? `1:${coverScale.value}` : "",
|
|
|
- };
|
|
|
- },
|
|
|
- ({ text, show, exists, content }) => {
|
|
|
- if (!text) return;
|
|
|
- draw.value!.history.preventTrack(() => {
|
|
|
- if (!exists) {
|
|
|
- draw.value!.store.delItem("text", text.id);
|
|
|
- } else {
|
|
|
- draw.value!.store.setItem("text", {
|
|
|
- value: { hide: !show, content },
|
|
|
- id: text.id,
|
|
|
+ setOrigin = (origin) => {
|
|
|
+ const stage = draw.stage!;
|
|
|
+ const $group = stage.findOne<Group>(`#${cover.id}`);
|
|
|
+ const $image = $group?.findOne<Image>(".repShape");
|
|
|
+ if (!$group || !$image) return;
|
|
|
+ // cover.url = origin!.toDataURL();
|
|
|
+ $image.image(origin);
|
|
|
+ };
|
|
|
+ return cleanup;
|
|
|
+};
|
|
|
+
|
|
|
+let clearDraw: (() => void) | undefined;
|
|
|
+onUnmounted(() => (clearDraw = undefined));
|
|
|
+const dataLoaded = ref(false);
|
|
|
+Promise.all([refreshOverviewData(), refreshTabulationData()]).then(
|
|
|
+ () => (dataLoaded.value = true)
|
|
|
+);
|
|
|
+
|
|
|
+const lowVersionHandler = (_draw: Draw) => {
|
|
|
+ // 旧数据处理
|
|
|
+ _draw.history.preventTrack(() => {
|
|
|
+ _draw.store.getTypeItems("image").forEach((item) => {
|
|
|
+ if (item.key === tableCoverKey) {
|
|
|
+ _draw.store.setItem("image", {
|
|
|
+ value: {
|
|
|
+ itemName: undefined,
|
|
|
+ disableDelete: false,
|
|
|
+ },
|
|
|
+ id: item.id,
|
|
|
});
|
|
|
}
|
|
|
});
|
|
|
- },
|
|
|
- { flush: "post" }
|
|
|
-);
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+const initDraw = async (_draw: Draw) => {
|
|
|
+ if (_draw === draw.value) return;
|
|
|
+ clearDraw && clearDraw();
|
|
|
+ if (!_draw) return;
|
|
|
+ const quitMerges: Array<() => void> = [];
|
|
|
+
|
|
|
+ _draw.config.showCompass = false;
|
|
|
+ _draw.config.showGrid = false;
|
|
|
+ _draw.config.showLabelLine = false;
|
|
|
+ _draw.config.showComponentSize = false;
|
|
|
+ _draw.viewer.setScaleRange(0.2, 5);
|
|
|
+ const config: any = tabulationData.value.store.config || {};
|
|
|
+ const data = tabulationData.value;
|
|
|
+ const p = tabulationData.value.paperKey;
|
|
|
+ await setMap({ url: data.mapUrl!, size: { width: data.width!, height: data.high! } });
|
|
|
+ _draw.store.setStore({
|
|
|
+ ...tabulationData.value.store,
|
|
|
+ config: {
|
|
|
+ ...config,
|
|
|
+ compass: {
|
|
|
+ rotation: 0,
|
|
|
+ ...(config.compass || {}),
|
|
|
+ url: "./icons/compass.svg",
|
|
|
+ },
|
|
|
+ proportion: {
|
|
|
+ scale: 1 / getRealPixel(1, p),
|
|
|
+ unit: "mm",
|
|
|
+ },
|
|
|
+ strokeProportion: {
|
|
|
+ scale: 1 / getRealPixel(1, p),
|
|
|
+ unit: "mm",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ });
|
|
|
+ quitMerges.push(tabCustomStyle(p, _draw));
|
|
|
+ if (overviewData.value.store?.config?.proportion.scale) {
|
|
|
+ _draw.history.preventTrack(() => {
|
|
|
+ const quit = setCover(p, _draw);
|
|
|
+ quit && quitMerges.push(quit);
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ lowVersionHandler(_draw);
|
|
|
+ }
|
|
|
+ quitMerges.concat(
|
|
|
+ Object.keys(components).map((type) =>
|
|
|
+ _draw.menusFilter.setMenusFilter(type as ShapeType, (items) => {
|
|
|
+ return items.filter((item) => item.label !== "隐藏");
|
|
|
+ })
|
|
|
+ )
|
|
|
+ );
|
|
|
+ clearDraw = () => {
|
|
|
+ console.error("clear");
|
|
|
+ draw.value = undefined;
|
|
|
+ mergeFuns(quitMerges)();
|
|
|
+ clearDraw = undefined;
|
|
|
+ };
|
|
|
+ draw.value = _draw;
|
|
|
+};
|
|
|
|
|
|
const compass = computed(
|
|
|
() => draw.value?.store.items.find((item) => item.key === tableCompassKey) as IconData
|