tangning 7 mesi fa
parent
commit
b87c10b6ea

+ 3 - 6
src/view/case/draw/board/editCAD/History/Change.js

@@ -7,8 +7,7 @@ import { coordinate } from "../Coordinate";
 
 export default class Change {
   constructor() {
-    this.lastData = {
-    }; // 每次都是当前数据和lastData进行比较,一般在mouseDown的时候存储进来
+    this.lastData = {}; // 每次都是当前数据和lastData进行比较,一般在mouseDown的时候存储进来
     this.elements = {}; // 当前的变化
   }
 
@@ -250,10 +249,8 @@ export default class Change {
     const cells = floorplanService.getCells();
 
     for (const key in cells) {
-      console.log('compareCells', key, cells);
       const cell = cells[key];
-      console.log('compareCells', cell, this.lastData);
-      const lastCell = this.lastData.cells && this.lastData.cells[key] || undefined;
+      const lastCell = this.lastData.cells[key];
       // 不存在意味着增加
       if (!lastCell) {
         const item = {
@@ -533,7 +530,7 @@ export default class Change {
     this.elements.title = null;
     const title = floorplanService.getTitle();
     const lastTitle = this.lastData.title;
-    console.log('compareTitle', title, lastTitle);
+
     const flag = historyUtil.isDifferentForTitle(title, lastTitle);
     if (flag) {
       const item = {

+ 1 - 3
src/view/case/draw/board/editCAD/Layer.js

@@ -511,9 +511,7 @@ export default class Layer {
             stateService.setDraggingItem(stateService.selectItem);
           }
         } else {
-          const sign = floorplanService.getSign(draggingItem.vectorId) || {
-            center: { x: 0, y: 0 },
-          };
+          const sign = floorplanService.getSign(draggingItem.vectorId);
           mathUtil.clonePoint(sign.center, position);
         }
         break;

+ 0 - 1
src/view/case/draw/board/useBoard.ts

@@ -68,7 +68,6 @@ const getStore = async (caseId: number, fileId: number, type: BoardType) => {
     }
   } else {
     const fileInfo = await getCaseFileImageInfo(fileId);
-    console.log('getCaseFileImageInfo', fileInfo);
     if (fileInfo) {
       console.log(fileInfo);
       data = {

+ 3 - 0
src/view/case/draw/c.ts

@@ -0,0 +1,3 @@
+import { ref } from "vue";
+
+export const inputIng = ref(false);

+ 1 - 1
src/view/case/draw/eshape.vue

@@ -21,6 +21,7 @@
 import { computed, onMounted, onUnmounted, ref } from "vue";
 import { BoardShape, compass, title } from "./board";
 import { components } from "./edit-shape";
+import { inputIng } from "./c";
 
 const props = defineProps<{ shape: BoardShape }>();
 const emit = defineEmits<{
@@ -33,7 +34,6 @@ const editComponent = computed(() => {
     return components[type];
   }
 });
-const inputIng = ref(false);
 
 const delHandler = () => {
   props.shape.delete();

+ 7 - 4
src/view/case/draw/header.vue

@@ -45,6 +45,7 @@
 import { BoardType } from "@/store/caseFile";
 import { BoardTypeDesc } from "@/constant/caseFile";
 import { onMounted, onUnmounted } from "vue";
+import { inputIng } from "./c";
 
 const props = defineProps<{
   type: BoardType;
@@ -67,10 +68,12 @@ const keydownHandler = (ev: KeyboardEvent) => {
   } else if (["Control", "Ctrl"].includes(ev.key)) {
     const downKey = ev.key;
     const secondaryHandler = (ev: KeyboardEvent) => {
-      if (ev.key.toUpperCase() === "Y" && !props.forwardDisabled) {
-        emit("forward");
-      } else if (ev.key.toUpperCase() === "Z" && !props.backDisabled) {
-        emit("back");
+      if (!inputIng.value) {
+        if (ev.key.toUpperCase() === "Y" && !props.forwardDisabled) {
+          emit("forward");
+        } else if (ev.key.toUpperCase() === "Z" && !props.backDisabled) {
+          emit("back");
+        }
       }
     };
     window.addEventListener("keydown", secondaryHandler);

+ 229 - 0
src/view/case/draw/index copy.vue

@@ -0,0 +1,229 @@
+<template>
+  <div class="df-layout">
+    <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" /> -->
+      <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 { computed, nextTick, ref } 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 } from "@/store/case";
+import {
+  BoardType,
+  SaveCaseFileImageInfo,
+  TitleShapeData,
+  saveCaseFileImageInfo,
+} from "@/store/caseFile";
+import { uploadFile } from "@/store/system";
+
+const dom = ref<HTMLCanvasElement>();
+
+const fmtId = ref(0);
+const pmtId = ref(0);
+const props = computed(() => {
+  const route = router.currentRoute.value;
+  if (route.name !== RouteName.drawCaseFile || !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!,
+    };
+  }
+});
+
+const backPageHandler = () => {
+  board.value && board.value.clear();
+  router.back();
+};
+
+const setBackImage = (blob: Blob) => {
+  board.value!.setImage(URL.createObjectURL(blob));
+};
+
+const updateAddShape = async (s, d) => {
+  if (d) {
+    state.value.addData = await uploadFile(d);
+  }
+  state.value.addShape = s;
+};
+
+const trackImage = async () => {
+  const data =
+    props.value!.type === BoardType.scene
+      ? await selectFuseImage(props.value!)
+      : await selectMapImage({});
+
+  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);
+    }
+  }
+};
+
+const { board, state } = useBoard(props);
+
+// 获取通用数据
+const getStore = async () => {
+  const store = await board.value!.getStore();
+  const titleShape = store.shapes.find(
+    (shape: any) => shape.type === title
+  ) as TitleShapeData;
+  return { store, titleShape };
+};
+function getList() {
+  let caseId = props.value?.caseId;
+  updateByTreeFileLists(caseId).then(res => {
+    let newlist =  res.find(ele => ele.filesTypeName == '三录材料')?.childrenList || [];
+    let slclList = newlist.find(ele => ele.filesTypeName == '现场图')?.childrenList || [];
+    fmtId.value = slclList.find(ele => ele.filesTypeName == '平面图').filesTypeId
+    pmtId.value = slclList.find(ele => ele.filesTypeName == '方面图').filesTypeId
+  })
+}
+getList();
+// 保存数据
+const saveHandler = async () => {
+  const { store, titleShape } = await getStore();
+  const args = props.value!;
+
+  const blob = await board.value!.export();
+  const body: SaveCaseFileImageInfo = {
+    caseId: args.caseId,
+    imgType: args.type,
+    file: new File([blob], `${args.type}_${args.fileId}.jpg`),
+    filesTitle: titleShape?.text || `${args.caseId}_${BoardTypeDesc[args.type]}`,
+    content: store && JSON.stringify(store),
+  };
+  args.inAdd || (body.filesId = props.value!.fileId);
+  console.log('args1', args, body);
+  const { data } = await uploadNewFile(body);
+  const rse = await addByMediaLiBrary({ ...body, caseId: args.caseId,filesTypeId: args.type == 1 ? pmtId.value:fmtId.value, uploadId: data.id });
+  console.log('args2',rse, { ...body,caseId: args.caseId, type: args.type, id: data.id });
+  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`);
+};
+</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>

+ 3 - 15
src/view/case/draw/index.vue

@@ -15,7 +15,7 @@
     />
 
     <div class="df-layout-child">
-      <!-- <Eshape v-model:shape="state.selectShape" v-if="state.selectShape" /> -->
+      <Eshape v-model:shape="state.selectShape" v-if="state.selectShape" />
       <div class="df-sider">
         <Slider
           :type="props.type"
@@ -59,9 +59,6 @@ import {
 import { uploadFile } from "@/store/system";
 
 const dom = ref<HTMLCanvasElement>();
-
-const fmtId = ref(0);
-const pmtId = ref(0);
 const props = computed(() => {
   const route = router.currentRoute.value;
   if (route.name !== RouteName.drawCaseFile || !dom.value) {
@@ -124,16 +121,7 @@ const getStore = async () => {
   ) as TitleShapeData;
   return { store, titleShape };
 };
-function getList() {
-  let caseId = props.value?.caseId;
-  updateByTreeFileLists(caseId).then(res => {
-    let newlist =  res.find(ele => ele.filesTypeName == '三录材料')?.childrenList || [];
-    let slclList = newlist.find(ele => ele.filesTypeName == '现场图')?.childrenList || [];
-    fmtId.value = slclList.find(ele => ele.filesTypeName == '平面图').filesTypeId
-    pmtId.value = slclList.find(ele => ele.filesTypeName == '方面图').filesTypeId
-  })
-}
-getList();
+
 // 保存数据
 const saveHandler = async () => {
   const { store, titleShape } = await getStore();
@@ -160,7 +148,7 @@ const saveHandler = async () => {
   }
   await nextTick();
   setTimeout(() => {
-    // location.reload();
+    location.reload();
   }, 100);
 };
 

+ 2 - 2
src/view/case/draw/selectFuseImage.vue

@@ -167,9 +167,9 @@ watchEffect(async (onClanup) => {
 <style lang="scss" scoped>
 .house-layout {
   --w: calc(540 / 390 * var(--h));
-  --h: 600px;
+  --h: 610px;
   display: flex;
-  height: 560px;
+  height: var(--h);
 }
 
 .iframe-layout {

+ 115 - 39
src/view/case/draw/selectMapImage.vue

@@ -5,12 +5,22 @@
         <el-button :icon="Search" />
       </template>
     </el-input>
-    <div class="search-result" v-show="keyword" ref="resultEl"></div>
+    <div class="rrr">
+      <div class="search-result" v-show="keyword && showSearch" ref="resultEl"></div>
+      <div class="search-sh" v-show="keyword">
+        <el-button style="width: 100%" @click="showSearch = !showSearch">
+          {{ showSearch ? "收起" : "展开" }}搜索结果
+        </el-button>
+      </div>
+    </div>
   </div>
-  <div class="def-select-map" ref="mapEl"></div>
+  <div class="def-select-map-layout">
+    <div class="def-select-map" ref="mapEl"></div>
+  </div>
+
   <div class="def-map-info" v-if="info">
-    <p><span>经度</span>{{ info.lat }}</p>
-    <p><span>维度</span>{{ info.lng }}</p>
+    <p><span>度</span>{{ info.lat }}</p>
+    <p><span>度</span>{{ info.lng }}</p>
     <p><span>缩放级别</span>{{ info.zoom }}</p>
   </div>
 </template>
@@ -22,52 +32,114 @@ import { ref, watchEffect } from "vue";
 import { QuiskExpose } from "@/helper/mount";
 import { debounce } from "@/util";
 
-export type MapImage = { blob: Blob | null };
-type MapInfo = { lat: number; lng: number; zoom: number };
-const props = defineProps<{ text: boolean }>();
+export type MapImage = { blob: Blob | null; search: MapInfo | null };
+type MapInfo = { lat: number; lng: number; zoom: number; text: string };
+
 const keyword = ref("");
+const showSearch = ref(true);
 const info = ref<MapInfo>();
-const maps = ref();
+const searchInfo = ref<MapInfo>();
+
+watchEffect(() => {
+  if (keyword.value) {
+    showSearch.value = true;
+  }
+});
+
 const mapEl = ref<HTMLDivElement>();
 const resultEl = ref<HTMLDivElement>();
 const searchAMap = ref<any>();
-let map = {};
-const getMapInfo = (): MapInfo => {
-    var zoom = map.getZoom(); //获取当前地图级别
-    var center = map.getCenter();
-    return {
-      zoom,
-      lat: center.lat,
-      lng: center.lng,
-    };
-  };
+
 watchEffect(async (onCleanup) => {
   if (!mapEl.value || !resultEl.value) {
     return;
   }
   const AMap = await AMapLoader.load({
-    plugins: ["AMap.PlaceSearch"],
+    plugins: ["AMap.PlaceSearch", "AMap.Event"],
     key: "e661b00bdf2c44cccf71ef6070ef41b8",
     version: "2.0",
   });
 
-  map = new AMap.Map(mapEl.value, {
+  const map = new AMap.Map(mapEl.value, {
     WebGLParams: {
       preserveDrawingBuffer: true,
     },
     resizeEnable: true,
   });
-  maps.value = map;
   const placeSearch = new AMap.PlaceSearch({
     pageSize: 5,
+    showCover: false,
     pageIndex: 1,
     map: map,
     panel: resultEl.value,
     autoFitView: true,
   });
+  const setSearch = (data) => {
+    searchInfo.value = {
+      text: data.pname + data.cityname + data.adname + data.address,
+      lat: data.location.lat,
+      lng: data.location.lng,
+      zoom: 0,
+    };
+  };
+
+  placeSearch.on("listElementClick", (e) => {
+    setSearch(e.data);
+    showSearch.value = false;
+  });
+  let clickMarker;
+
+  map.on("click", function (e) {
+    // 获取点击位置的经纬度坐标
+    var latitude = e.lnglat.lat;
+    var longitude = e.lnglat.lng;
+
+    searchInfo.value = {
+      text: "",
+      lat: latitude,
+      lng: longitude,
+      zoom: 0,
+    };
+    clickMarker && map.remove(clickMarker);
+    clickMarker = null;
+    // 在地图上添加标记
+    clickMarker = new AMap.Marker({
+      position: [longitude, latitude],
+      title: "点击位置",
+    });
+
+    map.add(clickMarker);
+  });
+  placeSearch.on("complete", function (result) {
+    setTimeout(() => {
+      const markers = map.getAllOverlays("marker");
+      for (const marker of markers) {
+        marker.on("click", () => {
+          clickMarker && map.remove(clickMarker);
+          clickMarker = null;
+          setSearch(marker._data);
+        });
+      }
+    }, 500);
+  });
+
+  const getMapInfo = (): MapInfo => {
+    var zoom = map.getZoom(); //获取当前地图级别
+    var center = map.getCenter();
+    return {
+      text: "",
+      zoom,
+      lat: center.lat,
+      lng: center.lng,
+    };
+  };
   //绑定地图移动与缩放事件
-  map.on("moveend", () => (info.value = getMapInfo()));
-  map.on("zoomend", () => (info.value = getMapInfo()));
+  map.on("moveend", () => {
+    info.value = getMapInfo();
+  });
+  map.on("zoomend", () => {
+    info.value = getMapInfo();
+  });
   searchAMap.value = placeSearch;
 
   onCleanup(() => {
@@ -85,22 +157,12 @@ watchEffect(() => {
 
 defineExpose<QuiskExpose>({
   submit() {
-    if(props.text){
-      let center = map.getCenter();
-      return {
-        search: {
-          text: keyword.value,
-          lat: center.lat,
-          lng: center.lng,
-        }
-      }
-    }
     return new Promise<MapImage>((resolve) => {
       if (mapEl.value) {
         const canvas = mapEl.value.querySelector("canvas") as HTMLCanvasElement;
-        canvas.toBlob((blob) => resolve({ blob }));
+        canvas.toBlob((blob) => resolve({ blob, search: searchInfo.value! }));
       } else {
-        resolve({ blob: null });
+        resolve({ blob: null, search: null });
       }
     });
   },
@@ -115,11 +177,15 @@ defineExpose<QuiskExpose>({
   z-index: 2;
 }
 
-.search-result {
+.rrr {
   position: absolute;
   left: 0;
   right: 0;
   z-index: 1;
+}
+
+.search-sh,
+.search-result {
   overflow: hidden;
 
   &.show {
@@ -145,9 +211,19 @@ defineExpose<QuiskExpose>({
   }
 }
 
-.def-select-map {
-  width: 540px;
-  height: 390px;
+.def-select-map-layout {
+  --scale: 1.5;
+  width: 100%;
+  padding-top: calc((390 / 540) * 100%);
+  position: relative;
   z-index: 1;
 }
+
+.def-select-map {
+  position: absolute;
+  left: 0;
+  top: 0;
+  width: 100%;
+  height: 100%;
+}
 </style>

+ 3 - 4
src/view/case/draw/slider.vue

@@ -87,7 +87,7 @@ import { coverImageSize } from "@/util/image-rotate";
 import { uploadFile } from "@/store/system";
 import { ElMessage } from "element-plus";
 import { confirm } from "@/helper/message";
-console.log('metas, labels, images', metas, labels, images);
+
 const props = defineProps<{
   type: BoardType;
   existsBgImage: boolean;
@@ -95,9 +95,8 @@ const props = defineProps<{
 }>();
 
 const fileDesc = {
-  [BoardType.scene]: "平面图",
+  [BoardType.scene]: "户型图",
   [BoardType.map]: "方位图",
-  [BoardType.aimap]: " AI 平面图 ",
 };
 const emit = defineEmits<{
   (e: "update:addShape", val: MetaShapeType | null, data?: any): void;
@@ -108,7 +107,7 @@ const emit = defineEmits<{
 const cover = reactive(
   useUpload({
     maxSize: maxFileSize,
-    formats: [".jpg", ".png"],
+    formats: [".jpg", ".png", ".raw"],
   })
 );
 

+ 229 - 0
src/view/case/index copy.vue

@@ -0,0 +1,229 @@
+<template>
+  <div class="df-layout">
+    <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" /> -->
+      <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 { computed, nextTick, ref } 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 } from "@/store/case";
+import {
+  BoardType,
+  SaveCaseFileImageInfo,
+  TitleShapeData,
+  saveCaseFileImageInfo,
+} from "@/store/caseFile";
+import { uploadFile } from "@/store/system";
+
+const dom = ref<HTMLCanvasElement>();
+
+const fmtId = ref(0);
+const pmtId = ref(0);
+const props = computed(() => {
+  const route = router.currentRoute.value;
+  if (route.name !== RouteName.drawCaseFile || !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!,
+    };
+  }
+});
+
+const backPageHandler = () => {
+  board.value && board.value.clear();
+  router.back();
+};
+
+const setBackImage = (blob: Blob) => {
+  board.value!.setImage(URL.createObjectURL(blob));
+};
+
+const updateAddShape = async (s, d) => {
+  if (d) {
+    state.value.addData = await uploadFile(d);
+  }
+  state.value.addShape = s;
+};
+
+const trackImage = async () => {
+  const data =
+    props.value!.type === BoardType.scene
+      ? await selectFuseImage(props.value!)
+      : await selectMapImage({});
+
+  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);
+    }
+  }
+};
+
+const { board, state } = useBoard(props);
+
+// 获取通用数据
+const getStore = async () => {
+  const store = await board.value!.getStore();
+  const titleShape = store.shapes.find(
+    (shape: any) => shape.type === title
+  ) as TitleShapeData;
+  return { store, titleShape };
+};
+function getList() {
+  let caseId = props.value?.caseId;
+  updateByTreeFileLists(caseId).then(res => {
+    let newlist =  res.find(ele => ele.filesTypeName == '三录材料')?.childrenList || [];
+    let slclList = newlist.find(ele => ele.filesTypeName == '现场图')?.childrenList || [];
+    fmtId.value = slclList.find(ele => ele.filesTypeName == '平面图').filesTypeId
+    pmtId.value = slclList.find(ele => ele.filesTypeName == '方面图').filesTypeId
+  })
+}
+getList();
+// 保存数据
+const saveHandler = async () => {
+  const { store, titleShape } = await getStore();
+  const args = props.value!;
+
+  const blob = await board.value!.export();
+  const body: SaveCaseFileImageInfo = {
+    caseId: args.caseId,
+    imgType: args.type,
+    file: new File([blob], `${args.type}_${args.fileId}.jpg`),
+    filesTitle: titleShape?.text || `${args.caseId}_${BoardTypeDesc[args.type]}`,
+    content: store && JSON.stringify(store),
+  };
+  args.inAdd || (body.filesId = props.value!.fileId);
+  console.log('args1', args, body);
+  const { data } = await uploadNewFile(body);
+  const rse = await addByMediaLiBrary({ ...body, caseId: args.caseId,filesTypeId: args.type == 1 ? pmtId.value:fmtId.value, uploadId: data.id });
+  console.log('args2',rse, { ...body,caseId: args.caseId, type: args.type, id: data.id });
+  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`);
+};
+</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>