| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696 |
- <template>
- <Container
- :upload-resourse="uploadResourse"
- v-model:full="full"
- v-if="dataLoaded"
- :ref="(d: any) => initDraw(d?.draw)"
- >
- <template #header>
- <Header
- v-if="draw"
- :title="$t('tabulation.name1')"
- @screenshot="(val) => (needScreenshot = val)"
- />
- </template>
- <template #slide>
- <Slide v-if="draw" @update-map-image="setMapHandler" />
- </template>
- </Container>
- <Preview
- @change-origin="(origin) => setOrigin && setOrigin(origin)"
- :showLabelLine="coverSetting?.showViewportLabelLine"
- :cover-scale="coverSetting?.scale"
- :paperKey="tabulationData?.paperKey"
- :pixelRatio="needScreenshot ? needScreenshot : pixelRatio"
- :not-debounce="!!needScreenshot"
- :data="overviewData?.store"
- :tab-draw="draw"
- :scale="draw?.viewerConfig.scaleX"
- @change-config="(config) => (originConfig = config)"
- v-if="overviewData?.store.config?.proportion.scale"
- />
- <Dialog />
- </template>
- <script lang="ts" setup>
- import Header from "./header.vue";
- import Slide from "./slide.vue";
- import Container from "../../../components/container/container.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 {
- tabulationData,
- refreshTabulationData,
- tableCoverKey,
- tableCoverScaleKey,
- tableCompassKey,
- overviewData,
- refreshOverviewData,
- } from "../../store";
- import { ImageData } from "@/core/components/image";
- import { TextData } from "@/core/components/text";
- import { genTabulationData, getRealPixel, repTabulationStore } from "./gen-tab";
- import { IconData } from "@/core/components/icon";
- import { Transform } from "konva/lib/Util";
- import { MathUtils } from "three";
- import { components } from "@/core/components";
- import { ShapeType } from "@/index";
- import { copy, mergeFuns, round } from "@/utils/shared";
- 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";
- import { listener } from "@/utils/event";
- import { router } from "../../router";
- import { params } from "@/example/env";
- import { tableSerialTableKey } from "@/example/constant";
- import { addTable, getCurrentNdxRaw, syncTable } from "@/core/components/serial";
- import { ui18n } from "@/lang";
- 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;
- const paperKey = tabulationData.value.paperKey;
- const compass = 0;
- if (config.url && config.size.height && config.size.width) {
- const size = await getImageSize(window.platform.getResource(config.url));
- const cover = {
- url: config.url,
- ...size,
- proportion: {
- scale: (config.size.width / size.width) * 1000,
- unit: "mm",
- },
- };
- if (!tabulationData.value.store.config) {
- const layer = await genTabulationData(paperKey, compass, cover);
- tabulationData.value.store.layers[defaultLayer] = layer;
- } else {
- await repTabulationStore(paperKey, compass, cover, store);
- }
- }
- };
- const setMapHandler = async (config: { url: string; size: Size }) => {
- const size = await getImageSize(window.platform.getResource(config.url));
- const cover = {
- url: config.url,
- ...size,
- proportion: {
- scale: (config.size.width / size.width) * 1000,
- unit: "mm",
- },
- };
- const data = await genTabulationData(tabulationData.value.paperKey, undefined, cover);
- const store = draw.value!.store;
- const img = data.image?.find((item) => item.key === tableCoverKey);
- const text = data.text?.find((item) => item.key === tableCoverScaleKey);
- if (img && text) {
- const sImage = store.getTypeItems("image").find((item) => item.key === tableCoverKey);
- const sText = store
- .getTypeItems("text")
- .find((item) => item.key === tableCoverScaleKey);
- draw.value!.history.onceTrack(() => {
- if (sImage) {
- store.setItem("image", {
- id: sImage.id,
- value: { ...sImage, ...img, id: sImage.id },
- });
- } else {
- store.addItem("image", img);
- }
- if (sText) {
- store.setItem("text", {
- id: text.id,
- value: { ...sText, ...text, id: sText.id },
- });
- } else {
- store.addItem("text", text);
- }
- });
- }
- };
- // 序号处理
- {
- const serialTable = computed(() => {
- const tables = draw.value?.store.getTypeItems("table");
- console.log("update");
- return tables && tables.find((table) => table.key === tableSerialTableKey);
- });
- watchEffect((onCleanup) => {
- if (!draw.value || !serialTable.value) return;
- const un = draw.value.menusFilter.setShapeMenusFilter(
- serialTable.value.id,
- (menu) => [
- { label: ui18n.t("sys.update"), handler: () => updateSerialTable(false) },
- ...menu,
- ]
- );
- onCleanup(un);
- });
- const updateSerialTable = (autoGen = true) => {
- const d = draw.value;
- const overview = overviewData.value?.store.layers.default;
- const serials = overview.serial;
- if (!d) {
- return;
- }
- const pack = autoGen
- ? d.history.preventTrack.bind(d.history)
- : (run: () => void) => run();
- if (!serials?.length) {
- if (serialTable.value) {
- pack(() => {
- d.store.delItem("table", serialTable.value!.id);
- });
- }
- return;
- }
- const table = serialTable.value || addTable(d as any);
- const syncSerials = serials.map((item) => {
- let desc = "";
- if (item.joinIds) {
- const names = item.joinIds
- .map((id) => {
- const img = overview.image?.find((image) => image.id === id)?.name;
- return img || overview.icon?.find((image) => image.id === id)?.name;
- })
- .filter(Boolean);
- desc = names.join("、");
- }
- return {
- ...item,
- hideSerial: false,
- desc,
- };
- });
- // 找出没有关联的痕迹物证
- const images = [...(overview.image || []), ...(overview.icon || [])];
- images?.forEach((image) => {
- if (
- image.key !== "trace" ||
- syncSerials.some((item) => item.joinIds?.includes(image.id))
- )
- return;
- syncSerials.push({
- id: image.id,
- content: getCurrentNdxRaw(syncSerials),
- hideSerial: true,
- desc: image.name || "",
- } as any);
- });
- // 合并相同序号数据
- for (let i = 0; i < syncSerials.length; i++) {
- const self = syncSerials[i];
- for (let j = i + 1; j < syncSerials.length; j++) {
- if (syncSerials[j].content === self.content) {
- if (syncSerials[j].desc && self.desc !== syncSerials[j].desc) {
- self.desc = self.desc + "、" + syncSerials[j].desc;
- }
- syncSerials.splice(j--, 1);
- }
- }
- }
- draw.value?.runHook(() => syncTable(table, syncSerials));
- if (serialTable.value) {
- pack(() => {
- d.store.setItem("table", {
- id: serialTable.value!.id,
- value: serialTable.value!,
- });
- });
- } else {
- table.key = tableSerialTableKey;
- pack(() => {
- d.store.addItem("table", table);
- });
- }
- };
- watch(
- draw,
- (draw) => {
- if (!draw) return;
- if (!serialTable.value) {
- setTimeout(() => updateSerialTable(true), 500);
- }
- },
- { immediate: true }
- );
- }
- const needScreenshot = ref<false | number>(false);
- const coverSetting = computed(() => {
- const cover = draw.value?.store.items.find((item) => item.key === tableCoverKey);
- return cover?.userData as
- | { showScale: boolean; showViewportLabelLine?: 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 (import.meta.env.DEV && cover) {
- // draw.history.preventTrack(() => {
- // draw.store.delItem("image", cover!.id);
- // cover = null as any;
- // });
- // }
- const { margin, size } = getPaperConfig(
- paperConfigs[paperKey].size,
- paperConfigs[paperKey].scale
- );
- if (!cover) {
- cover = reactive({
- ...getBaseItem(),
- disableCopy: true,
- cornerRadius: 0,
- strokeWidth: 0,
- disableDelete: true,
- key: tableCoverKey,
- disableTransformer: true,
- userData: {
- showViewportLabelLine: true,
- showScale: true,
- scale: 0,
- },
- zIndex: -1,
- width: 0,
- height: 0,
- mat: [1, 0, 0, 1, 0, 0],
- itemName: ui18n.t("cover.itemName"),
- });
- const stopWatch = watch(
- originConfig,
- (config) => {
- if (!config) return;
- 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());
- },
- { flush: "sync", immediate: true }
- );
- cleanups.push(stopWatch);
- draw.store.addItem("image", cover);
- } else {
- delete cover.url;
- }
- let text = draw.store.items.find((item) => item.key === tableCoverScaleKey) as TextData;
- // if (import.meta.env.DEV && text) {
- // draw.history.preventTrack(() => {
- // draw.store.delItem("text", text!.id);
- // text = null as any;
- // });
- // }
- if (!text) {
- const width = getRealPixel(30, paperKey);
- const heihgt = getRealPixel(4.8, paperKey);
- const pos = getFixPosition(
- {
- right: margin[1] + getRealPixel(40, paperKey),
- top: margin[0] + getRealPixel(45, paperKey),
- },
- { width, height: heihgt },
- size
- );
- text = reactive({
- ...getBaseItem(),
- content: ``,
- width,
- heihgt,
- fontSize: getRealPixel(4, paperKey),
- disableEditText: true,
- key: tableCoverScaleKey,
- disableDelete: true,
- align: "center",
- mat: [1, 0, 0, 1, pos.x, pos.y],
- });
- 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);
- }
- // 兼容旧数据
- if (!cover.userData) {
- const scale =
- (cover.widthRaw! / cover.width) *
- paperConfigs[paperKey].scale *
- cover.proportion!.scale;
- cover.userData = {
- showScale: true,
- scale: round(scale, 1),
- };
- }
- 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);
- const scale = ref<number>();
- cleanups.push(
- watch(
- () => coverSetting.value?.scale,
- (v) => (scale.value = v),
- { immediate: true }
- ),
- watch(
- coverSetting,
- (setting) => {
- if (coverTexQue.value) {
- coverTexQue.value.content = setting ? `1:${setting.scale}` : "";
- coverTexQue.value.hide = !setting?.showScale;
- }
- },
- { deep: true }
- ),
- watch(
- coverTexQue,
- (tex, _, cleanup) => {
- if (!tex) return;
- cleanup(
- mountMenus.setShapeMenusFilter(tex.id, (menus) => {
- const newMenus = { ...menus };
- delete newMenus.align;
- delete newMenus.fontStyle;
- return newMenus;
- })
- );
- },
- { immediate: true }
- ),
- menusFilter.setShapeMenusFilter(cover.id, () => []),
- mountMenus.setShapeMenusFilter(cover.id, (menus) => ({
- ...menus,
- scale: {
- type: "fixProportion",
- label: ui18n.t("cover.fixProportion"),
- "layout-type": "row",
- get value() {
- return scale.value;
- },
- set value(val) {
- scale.value = Math.max(val || 0, 1);
- },
- onChange() {
- if (coverSetting.value) {
- coverSetting.value.scale = scale.value!;
- }
- },
- props: { min: 1 },
- },
- showScale: {
- type: "check",
- label: ui18n.t("cover.showProportion"),
- "layout-type": "row",
- get value() {
- return coverSetting.value?.showScale;
- },
- set value(val) {
- if (coverSetting.value) {
- coverSetting.value.showScale = val || false;
- }
- },
- props: {},
- },
- showViewportLabelLine: {
- type: "check",
- label: ui18n.t("tabulation.showLabelLine"),
- "layout-type": "row",
- get value() {
- return coverSetting.value?.showViewportLabelLine;
- },
- set value(val) {
- if (coverSetting.value) {
- coverSetting.value.showViewportLabelLine = val || false;
- }
- },
- props: {},
- },
- })),
- 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 }
- )
- );
- 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,
- });
- }
- });
- });
- };
- 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 !== ui18n.t("sys.hide"));
- })
- )
- );
- 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
- );
- watch(compass, (compass, _, onCleanup) => {
- if (!compass || !draw.value) return;
- const mountMenus = draw.value.mountFilter;
- const menusFilter = draw.value.menusFilter;
- const quits = [
- menusFilter.setShapeMenusFilter(compass.id, () => []),
- mountMenus.setShapeMenusFilter(compass.id, () => ({
- // ...des,
- rotate: {
- type: "num",
- label: ui18n.t("describes.rotate"),
- default: 0,
- props: {
- min: 0,
- max: 360,
- },
- "layout-type": "column",
- sort: 3,
- get value() {
- return round((new Transform(compass.mat).decompose().rotation + 360) % 360, 1);
- },
- set value(val) {
- const config = new Transform(compass.mat).decompose();
- compass.mat = new Transform()
- .translate(config.x, config.y)
- .scale(config.scaleX, config.scaleY)
- .rotate(MathUtils.degToRad(val)).m;
- nextTick(() => {
- draw.value?.stage!.findOne(`#${compass.id}`)?.fire("bound-change");
- });
- },
- },
- })),
- ];
- onCleanup(mergeFuns(quits));
- });
- watchEffect((onCleanup) => {
- const d = draw.value;
- if (!d?.stage?.container()) return;
- const dom = d.stage.container();
- onCleanup(
- listener(dom, "dblclick", () => {
- d.shapesStatus.actives.some((item) => {
- const id = item.id();
- if (d.store.getItemById(id)?.key === tableCoverKey) {
- router.push({
- ...router.currentRoute.value,
- name: "overview",
- query: params.value,
- } as any);
- }
- });
- })
- );
- });
- const title = computed(() => tabulationData.value?.title || ui18n.t("tabulation.name1"));
- watchEffect(() => {
- document.title = title.value;
- });
- window.platform.bus.on("requestError", (res: any) => {
- console.log(res);
- });
- </script>
|