|
@@ -0,0 +1,286 @@
|
|
|
+<template>
|
|
|
+ <div class="df-layout">
|
|
|
+ <login />
|
|
|
+ <Header
|
|
|
+ class="df-header"
|
|
|
+ :type="props.type"
|
|
|
+ @back-page="backPageHandler"
|
|
|
+ @back="board.back()"
|
|
|
+ @forward="board.forward()"
|
|
|
+ @view-init="board.viewInit()"
|
|
|
+ @save="saveHandler"
|
|
|
+ @export="exportHandler"
|
|
|
+ :back-disabled="state.backDisabled"
|
|
|
+ :forward-disabled="state.forwardDisabled"
|
|
|
+ v-if="props && board"
|
|
|
+ />
|
|
|
+
|
|
|
+ <div class="df-layout-child">
|
|
|
+ <Eshape v-model:shape="state.selectShape" v-if="state.selectShape" @cropping="handleCropping" />
|
|
|
+ <div class="df-sider">
|
|
|
+ <Slider
|
|
|
+ :type="props.type"
|
|
|
+ :add-shape="state.addShape"
|
|
|
+ :exists-bg-image="state.exixtsBgImage"
|
|
|
+ @update:add-shape="updateAddShape"
|
|
|
+ @track-image="trackImage"
|
|
|
+ @selectImage="setBackImage"
|
|
|
+ v-if="props"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="df-content">
|
|
|
+ <div class="df-content-layout">
|
|
|
+ <div class="df-board">
|
|
|
+ <canvas ref="dom" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+import Header from "./header.vue";
|
|
|
+import Slider from "./slider.vue";
|
|
|
+import Eshape from "./eshape.vue";
|
|
|
+import login from "./login.vue";
|
|
|
+import { computed, nextTick, ref, watch, onMounted } from "vue";
|
|
|
+import { RouteName, router } from "@/router";
|
|
|
+import { useBoard, title } from "./board/useBoard";
|
|
|
+import { selectFuseImage, selectMapImage } from "@/view/case/quisk";
|
|
|
+import { CaseTagging } from "@/store/caseTagging";
|
|
|
+import saveAs from "@/util/file-serve";
|
|
|
+import { BoardTypeDesc } from "@/constant/caseFile";
|
|
|
+import { addByMediaLiBrary, updateByTreeFileLists, uploadNewFile, getUrlSrc, addUserOrUpDate } from "@/store/case";
|
|
|
+import { imageCropper } from "@/view/system/quisk";
|
|
|
+import {
|
|
|
+ BoardType,
|
|
|
+ SaveCaseFileImageInfo,
|
|
|
+ TitleShapeData,
|
|
|
+ saveCaseFileImageInfo,
|
|
|
+} from "@/store/caseFile";
|
|
|
+import { uploadFile } from "@/store/system";
|
|
|
+const list = ref({
|
|
|
+ xct:[],
|
|
|
+ xczp:[],
|
|
|
+ klbj:[],
|
|
|
+});
|
|
|
+const fmtId = ref(0);
|
|
|
+const pmtId = ref(0);
|
|
|
+// const board = ref(null);
|
|
|
+// const state = ref({});
|
|
|
+const ognFilesUrl = ref('')
|
|
|
+const dom = ref<HTMLCanvasElement>();
|
|
|
+const props = computed(() => {
|
|
|
+ const route = router.currentRoute.value;
|
|
|
+ if (route.name !== 'drawShareFile' || !dom.value) {
|
|
|
+ return null;
|
|
|
+ } else {
|
|
|
+ const params = route.params;
|
|
|
+ const fileId = Number(params.id);
|
|
|
+ return {
|
|
|
+ caseId: Number(params.caseId),
|
|
|
+ inAdd: fileId === -1,
|
|
|
+ fileId,
|
|
|
+ type: params.type.toString() as BoardType,
|
|
|
+ dom: dom.value!,
|
|
|
+ };
|
|
|
+ }
|
|
|
+});
|
|
|
+console.log('listprops', props.value);
|
|
|
+const {board, state} = useBoard(props);
|
|
|
+async function getList() {
|
|
|
+ updateByTreeFileLists(props.caseId).then(res => {
|
|
|
+ let newlist = res.find(ele => ele.filesTypeName == '三录材料')?.childrenList || [];
|
|
|
+ list.value.xct = newlist.find(ele => ele.filesTypeName == '现场图')?.childrenList || [];
|
|
|
+ pmtId.value = list.value.xct.find(ele => ele.filesTypeName == '平面图').filesTypeId
|
|
|
+ fmtId.value = list.value.xct.find(ele => ele.filesTypeName == '方位图').filesTypeId
|
|
|
+ console.log('list.value', list.value)
|
|
|
+ // if(pmtId.value || fmtId.value) {
|
|
|
+ // }
|
|
|
+ })
|
|
|
+}
|
|
|
+const backPageHandler = () => {
|
|
|
+ board.value && board.value.clear();
|
|
|
+ router.replace({ name: RouteName.material, params: { caseId: props.caseId } });
|
|
|
+ // router.back();
|
|
|
+};
|
|
|
+
|
|
|
+const setBackImage = (blob: Blob) => {
|
|
|
+ console.log('setBackImage', blob, board.value);
|
|
|
+ board.value!.setImage(URL.createObjectURL(blob));
|
|
|
+};
|
|
|
+
|
|
|
+const updateAddShape = async (s, d) => {
|
|
|
+ if (d) {
|
|
|
+ state.value.addData = getUrlSrc({type: 102}) + '/' + await uploadFile(d);
|
|
|
+ console.log('state.value', state.value.addData);
|
|
|
+ }
|
|
|
+ state.value.addShape = s;
|
|
|
+};
|
|
|
+
|
|
|
+const trackImage = async () => {
|
|
|
+ const data =
|
|
|
+ props.value!.type === BoardType.scene
|
|
|
+ ? await selectFuseImage(props.value!)
|
|
|
+ : await selectMapImage({});
|
|
|
+ console.log('户型图', data);
|
|
|
+ if (data?.ognFilesUrl) {
|
|
|
+ ognFilesUrl.value = data.ognFilesUrl;
|
|
|
+ }
|
|
|
+ if (data?.blob) {
|
|
|
+ setBackImage(data.blob);
|
|
|
+ if ("taggings" in data) {
|
|
|
+ const tags = data.taggings as CaseTagging[];
|
|
|
+ const table = await board.value!.calcTableShape([
|
|
|
+ ["序号", "标注"],
|
|
|
+ ...tags.map((tag, index) => [`序号${index + 1}`, tag.tagTitle]),
|
|
|
+ ]);
|
|
|
+ board.value!.setDefaultTable(null, table.content);
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+// watch(props, (newValue) => {
|
|
|
+// if(!newValue) return;
|
|
|
+// const BoardData = useBoard(props)
|
|
|
+// board.value = BoardData.board;
|
|
|
+// state.value = BoardData.state;
|
|
|
+// console.log('watchEffect111', newValue, props, board.value)
|
|
|
+// // const board = ref(null);
|
|
|
+// // const state = ref(null);
|
|
|
+// })
|
|
|
+console.log('useBoard', board, state)
|
|
|
+
|
|
|
+// 获取通用数据
|
|
|
+const getStore = async () => {
|
|
|
+ const store = await board.value!.getStore();
|
|
|
+ console.log('getStore', store, board.value, state.value);
|
|
|
+ const titleShape = store.shapes.find(
|
|
|
+ (shape: any) => shape.type === title
|
|
|
+ ) as TitleShapeData;
|
|
|
+ return { store, titleShape, ognFilesUrl: store.ognFilesUrl };
|
|
|
+};
|
|
|
+const isUrl = (string) => {
|
|
|
+ try {
|
|
|
+ new URL(string);
|
|
|
+ return true;
|
|
|
+ } catch (err) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+//裁剪
|
|
|
+const handleCropping = async (data) => {
|
|
|
+ const appStore = await getStore();
|
|
|
+ const args = props.value!;
|
|
|
+ let imgUrl = args.inAdd ? ognFilesUrl.value : appStore.store.ognFilesUrl;
|
|
|
+ const {width, height } = appStore.store.floors?.[0].bgImage;
|
|
|
+ const blob = await fetch(imgUrl || state.value.selectShape.data.url).then(res => res.blob());
|
|
|
+ const cropBlob = await imageCropper({
|
|
|
+ img: blob,
|
|
|
+ fixed: [width, height]
|
|
|
+ })
|
|
|
+ console.log(cropBlob)
|
|
|
+ setBackImage(cropBlob)
|
|
|
+ // if (data) {
|
|
|
+ // state.value.croppingData = data;
|
|
|
+ // board.value!.setCropping(data);
|
|
|
+ // }
|
|
|
+};
|
|
|
+// 保存数据
|
|
|
+const saveHandler = async () => {
|
|
|
+ const { store, titleShape } = await getStore();
|
|
|
+ const args = props.value!;
|
|
|
+ console.log('titleShape', store, titleShape);
|
|
|
+ const blob = await board.value!.export();
|
|
|
+ let filesTitle = titleShape?.text || `${args.caseId}_${BoardTypeDesc[args.type]}`
|
|
|
+ const body: SaveCaseFileImageInfo = {
|
|
|
+ caseId: args.caseId,
|
|
|
+ imgType: args.type,
|
|
|
+ file: new File([blob], `${filesTitle}.jpg`),
|
|
|
+ filesTitle: filesTitle,
|
|
|
+ content: store && JSON.stringify(store),
|
|
|
+ ognFileUrl: ognFilesUrl.value || store.ognFilesUrl,
|
|
|
+ };
|
|
|
+ args.inAdd || (body.filesId = props.value!.fileId);
|
|
|
+ const { data } = await uploadNewFile(body);
|
|
|
+ const route = router.currentRoute.value;
|
|
|
+ const getFunction = route.name == 'drawShareFile' ? addUserOrUpDate : addByMediaLiBrary
|
|
|
+ const rse = await getFunction({ ...body, caseId: args.caseId,filesTypeId: args.type != BoardType.scene ? fmtId.value : pmtId.value, uploadId: data.id, fileUrl: data.fileUrl, imgType: 0 });
|
|
|
+ if (args.inAdd) {
|
|
|
+ router.replace({
|
|
|
+ name: RouteName.drawCaseFile,
|
|
|
+ params: { caseId: args.caseId, type: args.type, id: rse.filesId },
|
|
|
+ });
|
|
|
+ }
|
|
|
+ await nextTick();
|
|
|
+ setTimeout(() => {
|
|
|
+ // location.reload();
|
|
|
+ }, 100);
|
|
|
+};
|
|
|
+
|
|
|
+// 导出图片
|
|
|
+const exportHandler = async () => {
|
|
|
+ const { titleShape } = await getStore();
|
|
|
+ const blob = await board.value!.export();
|
|
|
+ saveAs(blob, `${titleShape.text}.jpg`);
|
|
|
+};
|
|
|
+onMounted(() => {
|
|
|
+ getList()
|
|
|
+})
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.df-layout {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ height: 100vh;
|
|
|
+ background: #f0f2f5;
|
|
|
+}
|
|
|
+
|
|
|
+.df-header {
|
|
|
+ flex: none;
|
|
|
+}
|
|
|
+
|
|
|
+.df-layout-child {
|
|
|
+ width: 100%;
|
|
|
+ height: calc(100% - 5.4rem);
|
|
|
+ display: flex;
|
|
|
+ position: relative;
|
|
|
+}
|
|
|
+
|
|
|
+.df-sider {
|
|
|
+ flex: 0 0 340px;
|
|
|
+ overflow-y: auto;
|
|
|
+ box-sizing: border-box;
|
|
|
+ background: #fff;
|
|
|
+}
|
|
|
+
|
|
|
+.df-content {
|
|
|
+ flex: 1;
|
|
|
+ display: grid;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ height: 100%;
|
|
|
+ overflow: auto;
|
|
|
+}
|
|
|
+
|
|
|
+.df-content-layout {
|
|
|
+ --w: 297px;
|
|
|
+ --h: 210px;
|
|
|
+ --padding: 0;
|
|
|
+ --calc: 3.5;
|
|
|
+ border: calc(var(--padding) * var(--calc)) solid #fff;
|
|
|
+}
|
|
|
+
|
|
|
+.df-board {
|
|
|
+ // border: 1px solid #000;
|
|
|
+ width: calc(var(--w) * var(--calc));
|
|
|
+ height: calc(var(--h) * var(--calc));
|
|
|
+ box-sizing: border-box;
|
|
|
+ canvas {
|
|
|
+ background: #fff;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|