tangning 8 tháng trước cách đây
mục cha
commit
6f0f0bcdae

+ 1 - 0
package.json

@@ -19,6 +19,7 @@
     "js-base64": "^3.7.5",
     "mime": "^3.0.0",
     "mitt": "^3.0.1",
+    "province-city-china": "^8.5.8",
     "qs": "^6.11.2",
     "sass": "^1.64.2",
     "unplugin-element-plus": "^0.7.2",

+ 7 - 6
src/app/criminal/routeConfig.ts

@@ -15,12 +15,13 @@ export const menuRouteNames = [
   CriminalRouteName.other,
   CriminalRouteName.aiList,
   CriminalRouteName.dossier,
-  CriminalRouteName.camera,
-  CriminalRouteName.example,
-  CriminalRouteName.organization,
-  CriminalRouteName.role,
-  CriminalRouteName.user,
-  CriminalRouteName.downloadLog,
+  // CriminalRouteName.caseFile,
+  // CriminalRouteName.camera,
+  // CriminalRouteName.example,
+  // CriminalRouteName.organization,
+  // CriminalRouteName.role,
+  // CriminalRouteName.user,
+  // CriminalRouteName.downloadLog,
 ];
 
 export const routes: Routes = [

+ 2 - 2
src/app/criminal/store/example.ts

@@ -20,5 +20,5 @@ export const delExample = (example: Example) =>
 export const addExample = (caseTitle: string) =>
   axios.post(setExampleUrl, { caseTitle });
 
-export const setExample = (caseTitle: string, id: number) =>
-  axios.post(setExampleUrl, { caseTitle, caseId: id });
+export const setExample = (params) =>
+  axios.post(setExampleUrl, params);

+ 4 - 4
src/app/criminal/view/login/index.vue

@@ -98,10 +98,10 @@ watch(
     console.log("form", form);
     if (!form.phone) {
       verification.phone = "请输入手机号";
-    } else if (form.phone == "88888888888") {
-      verification.phone = "";
-    } else {
-      verification.phone = PHONE.REG.test(form.phone) ? "" : PHONE.tip;
+    // } else if (form.phone == "88888888888") {
+    //   verification.phone = "";
+    // } else {
+    //   verification.phone = PHONE.REG.test(form.phone) ? "" : PHONE.tip;
     }
     if (!form.psw) {
       verification.psw = "请输入密码";

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 0
src/assets/svg/file.svg


+ 225 - 0
src/components/viewImg/index.vue

@@ -0,0 +1,225 @@
+<template>
+  <div>
+    <div class="demo-image__preview">
+      <el-image-viewer
+        hide-on-click-modal
+        @close="
+          () => {
+            showViewer = false;
+          }
+        "
+        v-if="showViewer"
+        :url-list="initFileList"
+      />
+    </div>
+    <div class="imgList flex justify-start flex-wrap">
+      <div
+        class="maskContainer previewBox my-4 mr-4"
+        :style="{ width: width, height: height }"
+        v-for="(item, index) in list"
+        :key="index"
+      >
+        <div class="demo-image__preview h-full w-full">
+          <el-image :src="urlFilter(item.filesUrl)" class="originalImg" fit="cover">
+            <template #error>
+              <div class="image-slot el-image__error">
+                <el-icon :size="30"><PictureFilled /></el-icon>
+              </div>
+            </template>
+          </el-image>
+        </div>
+        <div class="mask">
+          <div class="zoomInImg" @click="showImgView(item.filesUrl)">
+            <el-icon color="#fff"><zoom-in /></el-icon>
+          </div>
+          <div
+            v-if="!edit"
+            class="downloadImg"
+            @click="handleItem('edit', item)"
+          >
+            <el-icon color="#fff"><Edit /></el-icon>
+          </div>
+          <div
+            v-if="!deleteShow"
+            class="downloadImg"
+            @click="handleItem('delete', item)"
+          >
+            <el-icon color="red"><Delete /></el-icon>
+          </div>
+          <!-- <div v-if="!close" class="close" @click="handleItem('close', item)">
+            <el-icon color="red"><CircleCloseFilled /></el-icon>
+          </div> -->
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, defineEmits, watchEffect, computed } from "vue";
+import { router } from "@/router";
+import { ElMessage, ElMessageBox } from "element-plus";
+import fileImg from "@/assets/svg/file.svg";
+import { delCaseFile, } from "@/store/caseFile";
+const caseId = computed(() => {
+  const caseId = router.currentRoute.value.params.caseId;
+  if (caseId) {
+    return Number(caseId);
+  }
+});
+const emits = defineEmits(['handleItem']);
+const props = defineProps({
+  width: {
+    type: String,
+    default: "66px",
+    required: false,
+  },
+  height: {
+    type: String,
+    default: "66px",
+    required: false,
+  },
+  edit: {
+    type: Boolean,
+    default: false,
+    required: false,
+  },
+  deleteShow: {
+    type: Boolean,
+    default: false,
+    required: false,
+  },
+  close: {
+    type: Boolean,
+    default: false,
+    required: false,
+  },
+  list: {
+    type: Array,
+    default() {
+      return [];
+   }
+  }
+});
+const currSize = ref({ width: 0, height: 0 });
+const fileList = ref([".doc", ".docx", ".pdf", ".xls", ".xlsx"]);
+const initFileList = ref([
+  "https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg",
+  "https://fuss10.elemecdn.com/1/34/19aa98b1fcb2781c4fba33d850549jpeg.jpeg",
+  "https://fuss10.elemecdn.com/0/6f/e35ff375812e6b0020b6b4e8f9583jpeg.jpeg",
+  // "https://fuss10.elemecdn.com/9/bb/e27858e973f5d7d3904835f46abbdjpeg.jpeg",
+  // "https://fuss10.elemecdn.com/d/e6/c4d93a3805b3ce3f323f7974e6f78jpeg.jpeg",
+  // "https://fuss10.elemecdn.com/3/28/bbf893f792f03a54408b3b7a7ebf0jpeg.jpeg",
+  // "https://fuss10.elemecdn.com/2/11/6535bcfb26e4c79b48ddde44f4b6fjpeg.jpeg",
+]);
+const urlFilter = (url) => {
+  const fileType = url.substring(url.lastIndexOf(".")).toLowerCase();
+  console.log(url, fileType, "urlFilter");
+  return fileList.value.includes(fileType) ? fileImg : url ;
+ }
+watchEffect(() => {
+  if (props.list.length) {
+    let newlist = props.list.map(item => item.filesUrl);
+    initFileList.value = newlist;
+  }
+});
+
+const url = ref("");
+const showViewer = ref(false);
+const previewList = ref([]);
+const showImgView = (src) => {
+  console.log(src, "showImgView");
+  const fileType = src.substring(src.lastIndexOf(".")).toLowerCase();
+  console.log(fileType, fileList.value.includes(fileType), "urlFilter");
+  if(fileList.value.includes(fileType)){
+    window.open(window.location.origin + src);
+    return;
+  }
+  url.value = src;
+  showViewer.value = true;
+  // previewList.value = [src];
+};
+const handleItem = (type, item) => {
+  if(type == 'delete'){
+    del(item)
+    return
+  }
+  emits("handleItem", type, item);
+};
+const del = async (file) => {
+  console.log(file, "file");
+  ElMessageBox.confirm("确定删除?", "提示", {
+    confirmButtonText: "确定",
+    cancelButtonText: "取消",
+    type: "warning",
+  }).then(async () => {
+    await delCaseFile({ caseId: caseId.value, filesId: file.filesId });
+    emits("handleItem", 'delete', file);
+    ElMessage({
+      type: "success",
+      message: "删除成功",
+    });
+  });
+};
+</script>
+
+<style lang="scss" scoped>
+.maskContainer {
+  position: relative;
+  line-height: 0;
+  width: 66px;
+  height: 66px;
+  padding: 7px;
+  border: 1px solid #d9d9d9;
+  &:hover {
+    .mask {
+      opacity: 1;
+    }
+
+    img {
+      transform: scale(1.1);
+    }
+  }
+
+  .mask {
+    transition: all 0.5s;
+    opacity: 0;
+    position: absolute;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    left: 0;
+    background: rgba($color: #000000, $alpha: 0.3);
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    div {
+      margin: 3px;
+    }
+    .close {
+      position: absolute;
+      right: 0;
+      top: 0;
+    }
+    .svgBox {
+      height: 40px;
+      width: 40px;
+      background: rgb(#000, 0.3);
+      border-radius: 50%;
+      margin: 10px;
+      padding: 10px;
+      cursor: pointer;
+    }
+
+    svg {
+      // color: #fff;
+      width: 14px;
+      height: 14px;
+    }
+  }
+  .originalImg {
+    height: 100%;
+    width: 100%;
+  }
+}
+</style>

+ 2 - 2
src/constant/scene.ts

@@ -2,8 +2,8 @@ import { appConstant } from "@/app";
 import { ModelSceneStatus, QuoteSceneStatus, SceneType } from "@/store/scene";
 
 export const SceneTypeDesc: { [key in SceneType]: string } = {
-  [SceneType.SWKK]: "八目",
-  [SceneType.SWKJ]: "双目转台",
+  [SceneType.SWKK]: "点云场景",
+  [SceneType.SWKJ]: "Mesh 场景",
   [SceneType.SWSS]: "激光转台点云场景",
   [SceneType.SWMX]: "三维模型",
   [SceneType.SWSSMX]: "激光转台Mesh场景",

+ 1 - 0
src/helper/mount.ts

@@ -108,6 +108,7 @@ export const quiskMountFactory =
           destroy();
         },
         onSubmit: async () => {
+          console.log('====>', ref);
           const ret = ref.submit && ((await ref.submit()) as any);
           if (ret) {
             resolve(ret);

+ 1 - 1
src/hook/pagging.ts

@@ -102,7 +102,7 @@ export const usePagging = <PARAM, RAW, NRAW>(
       }, {} as any);
 
     const data = await props.get(params);
-
+    console.log('await', data);
     pag.total = data.total;
     tableOperate.tableState.value.rows = data.list as any;
     await nextTick();

+ 2 - 0
src/request/config.ts

@@ -21,6 +21,7 @@ import {
   uploadModel,
   userLogin,
   userReg,
+  newFileupload,
 } from "./urls";
 
 // 不需要登录就能请求的接口
@@ -45,6 +46,7 @@ export const fileUrls = [
   uploadFile,
   insertCaseFile,
   saveCaseFileInfo,
+  newFileupload,
 ];
 // 需要限定卫GET请求方式的url
 export const GetUrls = [getRoleList, getCompanyList];

+ 5 - 2
src/request/index.ts

@@ -45,12 +45,15 @@ axios.interceptors.request.use(async (config) => {
   }
 
   const { token, userId } = getAuth();
+  console.log("token",getAuth, token, "userId", userId, config.url);
   if (!token && !~notLoginUrls.indexOf(config.url)) {
-    router.replace({ name: RouteName.login });
+    // router.replace({ name: RouteName.login });
     throw "用户未登录";
   }
-
+  let caseId = router.currentRoute.value?.params?.caseId
   config.headers.token = token;
+  config.headers['caseid'] = caseId;
+  config.headers['page-type'] = 'edit';
   config.headers.userid = userId;
 
   if (~GetUrls.indexOf(config.url)) {

+ 20 - 2
src/request/urls.ts

@@ -11,7 +11,8 @@ export const getListByDeptId = "/fusion/web/role/getAllRoleList";
 export const userLogin = "/fusion/fdLogin";
 // 权限
 export const userperInfo = "/fusion/web/user/getPerInfo";
-export const userInfo = "/fusion/web/user/getUserInfo";
+// export const userInfo = "/fusion/web/user/getUserInfo";
+export const userInfo = "/service/manage/sysUser/getInfo";
 // 注册
 export const userReg = "/web/user/register";
 // 发送注册短信
@@ -63,7 +64,6 @@ export const getCompanyList = "/web/department/getAll";
 
 /** ----------------VR模型接口---------------- */
 // 获取场景列表
-export const getSceneList = "/fusion/scene/list";
 export const delScene = "/fusion/scene/deleteNum";
 export const checkGenMeshScene = "/fusion/scene/sceneDetail";
 export const genMeshSceneByCloud = "/fusion/scene/buildSceneObj";
@@ -169,6 +169,7 @@ export const fireDetailByPsw = "/fusion/web/fireProject/getDetailWithoutAuth"; /
 
 // case相关
 export const caseInfo = "/fusion/case/getInfo";
+export const caseInquestInfo = "/fusion/caseInquestInfo/info";
 export const caseFileTypes = "/fusion/caseFilesType/allList";
 export const caseFiles = "/fusion/caseFiles/allList";
 export const caseFileInfo = "/fusion/caseFiles/info";
@@ -176,6 +177,7 @@ export const saveCaseFileInfo = "/fusion/caseFiles/addOrUpdateImg";
 export const insertCaseFile = "/fusion/caseFiles/add";
 export const deleteCaseFile = "/fusion/caseFiles/delete";
 export const updateCaseFile = "/fusion/caseFiles/updateTitle";
+export const newFileupload = "/service/manage/common/upload/fileNew";
 
 // 火调链接地址设置密码
 export const setCasePsw = "/fusion/web/fireProject/updateRandomCode";
@@ -215,3 +217,19 @@ export const downloadSceneList = "/fusion/sceneDownLog/list";
 export const offLine = "/web/fireProject/offLine"; //{roomId}
 export const onLine = "/web/fireProject/onLine"; //{roomId}
 export const onLineCheck = "/web/fireProject/onLineCheck";
+// 案件相关接口
+export const sceneList = "/service/manage/case/sceneList"; //{roomId}
+export const getCaseByNum = "/service/manage/case/getCaseByNum"; //{roomId}
+export const newCaseInfo = "/fusion/caseInquestInfo/info";
+export const getByTree = "/fusion/caseFilesType/getByTree";
+export const updateFileType = "/fusion/caseFiles/updateFileType";
+export const addByMediaLibrary = "/fusion/caseFiles/addByMediaLibrary";
+export const addmodelByMediaLibrary = "/fusion/model/addByMediaLibrary";
+export const criminalInfo = "/fusion/caseInquestCriminal/info";
+export const saveOrUpdate = "/fusion/caseInquestCriminal/saveOrUpdate";
+export const downDocx = "/fusion/caseInquestCriminal/downDocx";
+export const getSceneList = "/service/manage/scene/list";
+export const getDictFileList = "/service/manage/dict/getByKey/media-library";
+export const getListFileList = "/service/manage/dictFile/pageList/media-library";
+
+

+ 6 - 6
src/router/config.ts

@@ -111,12 +111,6 @@ export const routes: Routes = [
         meta: { title: "用户管理", icon: "iconfire_user" },
       },
       {
-        name: RouteName.caseFile,
-        path: "case/file/:caseId",
-        component: () => import("@/view/case/caseFile.vue"),
-        meta: { title: "卷宗管理" },
-      },
-      {
         name: RouteName.statistics,
         path: "/statistics",
         component: () => import("@/view/statistics/index.vue"),
@@ -128,6 +122,12 @@ export const routes: Routes = [
         component: () => import("@/view/vrmodel/downloadLog.vue"),
         meta: { title: "下载记录", icon: "icon-query_home" },
       },
+      {
+        name: RouteName.caseFile,
+        path: "case/file/:caseId",
+        component: () => import("@/view/case/caseFile.vue"),
+        meta: { title: "卷宗管理" },
+      },
     ],
   },
   {

+ 81 - 2
src/store/case.ts

@@ -7,9 +7,20 @@ import {
   setCasePsw,
   syncInfo,
   updateCaseFile,
+  caseInquestInfo,
+  newFileupload,
+  getDictFileList,
+  getByTree,
+  getListFileList,
+  addByMediaLibrary,
+  updateFileType,
+  saveOrUpdate,
+  criminalInfo,
 } from "@/request";
+import { router } from "@/router";
 import { ModelScene, QuoteScene, Scene, SceneType } from "./scene";
 import { CaseFile } from "./caseFile";
+import { ref } from "vue";
 
 export type Case = {
   caseId: number;
@@ -20,14 +31,30 @@ export type Case = {
   userName: number;
 };
 
+export const treeList = ref([]);
+
 export const setCaseSharePWD = (params: { caseId: number; randCode: string }) =>
   axios.post(setCasePsw, params);
 
 export const getCaseSharePWD = async (params: { caseId: number }) =>
   (await axios.get<string>(getCasePsw, { params })).data;
 
-export const getCaseInfo = async (caseId: number) =>
-  (await axios.get<Case>(caseInfo, { params: { caseId } })).data;
+export const addByMediaLiBrary = async (params) =>
+  (await axios.post<string>(addByMediaLibrary, params)).data;
+
+export const AddsaveOrUpdate = async (params) =>
+  (await axios.post<string>(saveOrUpdate, params)).data;
+
+export const getcaseInDate = async (params) =>
+  (await axios.post<string>(criminalInfo, params)).data;
+  // (await axios.get<string>(info, { params:params })).data;
+
+export const getCaseInfo = async (params) =>
+  (await axios.post<Case>(caseInfo, params)).data;
+
+export const getCaseInquestInfo = async (caseId: number) =>
+  (await axios.get(caseInquestInfo, { params: { caseId } })).data;
+
 
 export const updateCaseInfo = async (caseFile: CaseFile) =>
   await axios.post(updateCaseFile, {
@@ -39,6 +66,45 @@ export const getCaseSceneList = async (caseId: number): Promise<Scene[]> => {
   return (await axios.get(caseSceneList, { params: { caseId } })).data;
 };
 
+export const getFilepageList = async (params): Promise<Scene[]> => {
+  return (await axios.post(getListFileList, params)).data;
+};
+export const getupdateFileType = async (params): Promise<Scene[]> => {
+  return (await axios.post(updateFileType, params)).data;
+};
+
+export const getDictFileLists = async (type: number): Promise<Scene[]> => {
+  return (await axios.get(getDictFileList, { params: { type: type } })).data;
+};
+
+export const updateByTreeFileLists = async (caseId = router.currentRoute.value?.params?.caseId): Promise<Scene[]> => {
+  let list = (await axios.get(getByTree, { params: { caseId:caseId } })).data
+  treeList.value = list;
+  return list;
+};
+export const updateSelectByTreeFileLists = async (): Promise<Scene[]> => {
+  function getTreeList(list: any[]) {
+    return list.map(item => {
+      if (item.childrenList) {
+        return {
+          value: item.filesTypeId,
+          label: item.filesTypeName,
+          children: getTreeList(item.childrenList)
+        };
+      }
+      return {
+        value: item.filesTypeId,
+        label: item.filesTypeName,
+      }
+    })
+  }
+  return getTreeList((await axios.get(getByTree, { params: { caseId: '' } })).data)
+};
+
+export const getByTreeFileLists = async () => {
+  return treeList.value
+};
+
 export const getSyncSceneInfo = async (caseId: number) => {
   return (await axios.post<string>(syncInfo, { caseId })).data;
 };
@@ -69,3 +135,16 @@ export const getCaseScenes = (scenes: Scene[]) => {
 
 export const replaceCaseScenes = (caseId: number, caseScenes: CaseScenes) =>
   axios.post(repCaseScenes, { sceneNumParam: caseScenes, caseId });
+
+export const uploadNewFile = (data) => {
+  console.log('uploadNewFile',data);
+  return axios<undefined>({
+    method: "POST",
+    url: newFileupload,
+    data: data,
+    // onUploadProgress(event: any) {
+    //   data.onProgress(Math.round((event.loaded / event.total) * 100) || 0);
+    // },
+  });
+}
+

+ 1 - 1
src/store/role.ts

@@ -128,7 +128,7 @@ export const refreshRole = async () => {
     ? RoleLevel.systemAdmin
     : RoleLevel.corps;
   // console.log(, user.value.info.permsList);
-  setPermission(userPermListCover(user.value.info.permsList));
+  // setPermission(userPermListCover(user.value.info.permsList));
 
   // const { perm, level } = await getRole(roleId.value);
   // setPermission(serviceCoverUserPermission(perm as any));

+ 5 - 4
src/store/system.ts

@@ -11,7 +11,8 @@ import { appConstant } from "@/app";
 import { ref, watchEffect } from "vue";
 
 export type LoginProps = {
-  phoneNum: string;
+  phoneNum?: string;
+  userName?: string;
   code: string;
   password: string;
 };
@@ -39,9 +40,9 @@ export const login = async (props: LoginProps) => {
 };
 
 if (user.value.token) {
-  axios.get(userInfo).then((res) => {
-    refreshUserInfo(res.data);
-  });
+  // axios.get(userInfo).then((res) => {
+  //   refreshUserInfo(res.data);
+  // });
 }
 
 export const uploadFile = async (file: File) => {

+ 3 - 3
src/store/user.ts

@@ -50,7 +50,7 @@ export const getUsers = async (deptId?: string) =>
 // 当前用户的信息
 
 export const user = ref({
-  token: getLocal(`${appConstant.deptId}Token`, ""),
+  token: getLocal(`token`, "") || 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOjEsImRldmljZSI6ImRlZmF1bHQtZGV2aWNlIiwiZWZmIjotMSwicm5TdHIiOiJ2U1FBRVF6UVpIZXhqS1ZMOFo3UmxSSVpUMDhTajdQZyIsImlkIjoxLCJ1c2VySWQiOjgxNywiaXNBZG1pbiI6MSwicGxhdGZvcm1JZCI6MSwidXNlck5hbWUiOiJzdXBlci1hZG1pbiIsIm5pY2tOYW1lIjoi6LaF57qn566h55CG5ZGYIn0.pdpmpIaUf5IKMEMI_3aKot-4ZS7YfOggUIC6jn3W290',
   info: getLocal("info", {} as UserInfo),
 });
 
@@ -135,8 +135,8 @@ export const transformSWToken = async (scene: QuoteScene) => {
   const res = await axios.get(getSWToken, { params: { num: scene.num } });
   return res.data.token;
 };
-
-changSaveLocal(`${appConstant.deptId}Token`, () => user.value.token);
+console.log('changSaveLocal', user.value);
+changSaveLocal(`token`, () => user.value.token);
 changSaveLocal("info", () => user.value.info);
 
 // 设置全局请求hook

+ 88 - 0
src/view/abstract/getGeo.ts

@@ -0,0 +1,88 @@
+
+
+import data from "province-city-china/dist/level.json";
+
+const tw = {
+    name: "台湾省",
+    province: "71",
+    code: "710000",
+    children: [
+        {
+            code: '710101', name: '台北市', province: '71', city: '01', children: [
+                { code: '710101', name: '内湖区', province: '71', city: '01', area: '01' },
+                { code: '710102', name: '南港区', province: '71', city: '01', area: '02' },
+                { code: '710103', name: '中正区', province: '71', city: '01', area: '03' },
+                { code: '710104', name: '万华区', province: '71', city: '01', area: '04' },
+                { code: '710105', name: '大同区', province: '71', city: '01', area: '05' },
+                { code: '710106', name: '中山区', province: '71', city: '01', area: '06' },
+                { code: '710107', name: '松山区', province: '71', city: '01', area: '07' },
+                { code: '710108', name: '大安区', province: '71', city: '01', area: '08' },
+                { code: '710109', name: '信义区', province: '71', city: '01', area: '09' },
+                { code: '710110', name: '文山区', province: '71', city: '01', area: '10' },
+                { code: '710111', name: '士林区', province: '71', city: '01', area: '11' },
+                { code: '710112', name: '北投区', province: '71', city: '01', area: '12' }
+            ],
+        },
+        {
+            code: '710102', name: '高雄市', province: '71', city: '02', children: [],
+        },
+        {
+            code: '710103', name: '台南市', province: '71', city: '03', children: [],
+        },
+        {
+            code: '710104', name: '台中市', province: '71', city: '04', children: [],
+        },
+        {
+            code: '710105', name: '桃园市', province: '71', city: '05', children: [],
+        },
+        {
+            code: '710106', name: '金门县', province: '71', city: '06', children: [],
+        },
+        {
+            code: '710107', name: '南投县', province: '71', city: '07', children: [],
+        },
+
+        {
+            code: '710108', name: '宜兰县', province: '71', city: '08', children: [],
+        },
+        {
+            code: '710109', name: '基隆市', province: '71', city: '09', children: [],
+        },
+        {
+            code: '710110', name: '新竹县', province: '71', city: '10', children: [],
+        },
+        {
+            code: '710111', name: '澎湖县', province: '71', city: '11', children: [],
+        },
+        {
+            code: '710112', name: '苗栗县', province: '71', city: '12', children: [],
+        },
+        {
+            code: '710113', name: '彰化县', province: '71', city: '13', children: [],
+        },
+        {
+            code: '710114', name: '嘉义市', province: '71', city: '14', children: [],
+        },
+        {
+            code: '710115', name: '云林县', province: '71', city: '15', children: [],
+        },
+        {
+            code: '710116', name: '屏东县', province: '71', city: '16', children: [],
+        },
+        {
+            code: '710117', name: '台东县', province: '71', city: '17', children: [],
+        },
+        {
+            code: '710118', name: '花莲县', province: '71', city: '18', children: [],
+        },
+    ],
+}
+const geoData = data.map(c => {
+    if (c.code === '710000') {
+        c = tw
+    }
+    return c
+})
+
+console.log('geoData-1', geoData)
+export { geoData }

+ 359 - 111
src/view/abstract/index.vue

@@ -1,10 +1,222 @@
 <template>
   <div class="abstract">
     <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
-      <el-tab-pane label="案件信息" name="1" />
-      <el-tab-pane label="勘验信息" name="2" />
+      <el-tab-pane label="案件信息" name="1">
+        <el-form
+          ref="exampleRef"
+          :model="bindExample"
+          label-position="top"
+          :rules="rules"
+          label-width="auto"
+          class="demo-ruleForm"
+          size="default"
+          status-icon
+        >
+          <div class="form-content">
+            <el-form-item label="案件名称" required prop="caseTitle">
+              <el-input
+                v-model="bindExample.caseTitle"
+                placeholder="请输入"
+                show-word-limit
+                maxlength="100"
+              />
+            </el-form-item>
+            <el-form-item label="立案编号" prop="caseNum">
+              <el-input
+                v-model="bindExample.caseNum"
+                placeholder="请输入"
+                show-word-limit
+                maxlength="100"
+              />
+            </el-form-item>
+            <el-form-item label="案件类别" required prop="caseCategory">
+              <el-select
+                v-model="bindExample.caseCategory"
+                placeholder="请选择案件类别"
+              >
+                <el-option
+                  v-for="item in criminalType"
+                  :label="item"
+                  :value="item"
+                />
+              </el-select>
+            </el-form-item>
+            <el-form-item label="案发时间" required prop="crimeTime">
+              <el-date-picker
+                v-model="bindExample.crimeTime"
+                type="date"
+                aria-label="请选择案发时间"
+                placeholder="请选择案发时间"
+                style="width: 100%"
+                value-format="YYYY-MM-DD"
+              />
+            </el-form-item>
+
+            <el-form-item label="案发区域" prop="name">
+              <!-- <el-input
+                v-model="bindExample.caseRegion"
+                placeholder="请输入案发区域"
+                show-word-limit
+                maxlength="100"
+              /> -->
+              <el-cascader
+        size="large"
+        style="width: 100%"
+        :props="selectSetting"
+        :options="(geoData as any as CascaderOption[])"
+        v-model="bindExample.caseRegion"
+      ></el-cascader>
+            </el-form-item>
+            <el-form-item label="案件地点">
+              <el-input
+                v-model="bindExample.caseAddress"
+                placeholder="输入名称搜索"
+                clearable
+                disabled
+              >
+                <template #append>
+                  <el-button :icon="Search" @click="searchAMapAddress" />
+                </template>
+              </el-input>
+            </el-form-item>
+            <!-- <el-form-item label="案发地点" prop="name">
+          <el-input
+            v-model="bindExample.caseAddress"
+            placeholder="请输入"
+            show-word-limit
+            maxlength="100"
+          />
+        </el-form-item> -->
+            <el-form-item label="是否命案" prop="region">
+              <el-select
+                v-model="bindExample.homicideCase"
+                placeholder="请选择"
+              >
+                <el-option label="是" :value="1" />
+                <el-option label="否" :value="0" />
+              </el-select>
+            </el-form-item>
+            <el-form-item label="是否刑案" prop="region">
+              <el-select
+                v-model="bindExample.criminalCase"
+                placeholder="请选择"
+              >
+                <el-option label="是" :value="1" />
+                <el-option label="否" :value="0" />
+              </el-select>
+            </el-form-item>
+            <el-form-item label="经纬度" prop="name">
+              <el-input
+                v-model="bindExample.latAndLong"
+                placeholder="请输入"
+                show-word-limit
+                maxlength="100"
+              />
+            </el-form-item>
+            <el-form-item>
+              <el-button
+                class="w-full"
+                type="primary"
+                @click="submitForm(exampleRef)"
+              >
+                保存
+              </el-button>
+            </el-form-item>
+          </div>
+        </el-form>
+      </el-tab-pane>
+      <el-tab-pane label="勘验信息" name="2">
+        <el-form
+          ref="ruleFormRef"
+          :model="ruleForm"
+          label-position="top"
+          :rules="rules"
+          label-width="auto"
+          class="demo-ruleForm"
+          size="default"
+          status-icon
+        >
+          <el-form-item label="指挥中心电话时间">
+            <el-date-picker
+              v-model="ruleForm.commandTime"
+              type="date"
+              placeholder="请选择"
+              aria-label="请选择"
+              style="width: 100%"
+            />
+          </el-form-item>
+          <el-form-item label="接警时间">
+            <el-date-picker
+              v-model="ruleForm.alarmTime"
+              type="date"
+              placeholder="请选择"
+              aria-label="请选择"
+              style="width: 100%"
+            />
+          </el-form-item>
+          <el-form-item label="报警人">
+            <el-input
+              v-model="ruleForm.alarmName"
+              placeholder="请输入"
+              show-word-limit
+              maxlength="100"
+            />
+          </el-form-item>
+          <el-form-item label="现场勘验单位">
+            <el-input
+              v-model="ruleForm.inquestDept"
+              placeholder="请输入"
+              show-word-limit
+              maxlength="100"
+            />
+          </el-form-item>
+          <el-form-item label="指派/报告单位">
+            <el-input
+              v-model="ruleForm.assignDept"
+              placeholder="请输入"
+              show-word-limit
+              maxlength="100"
+            />
+          </el-form-item>
+          <el-form-item label="指派方式">
+            <el-input
+              v-model="ruleForm.assignType"
+              placeholder="请输入"
+              show-word-limit
+              maxlength="100"
+            />
+          </el-form-item>
+          <el-form-item label="勘验时间">
+            <el-date-picker
+              v-model="ruleForm.times"
+              type="daterange"
+              start-placeholder="开始时间"
+              end-placeholder="结束时间"
+              format="YYYY-MM-DD"
+              date-format="YYYY/MM/DD ddd"
+            />
+          </el-form-item>
+          <el-form-item label="勘验地点">
+            <el-input
+              v-model="ruleForm.inquestAddress"
+              placeholder="请输入"
+              show-word-limit
+              maxlength="100"
+            />
+          </el-form-item>
+          <el-form-item>
+            <el-button
+              class="w-full"
+              type="primary"
+              @click="submitForm(ruleFormRef)"
+            >
+              保存
+            </el-button>
+          </el-form-item>
+        </el-form>
+      </el-tab-pane>
     </el-tabs>
-    <el-form
+    <!-- <el-form
       ref="ruleFormRef"
       :model="ruleForm"
       label-position="top"
@@ -17,64 +229,77 @@
       <div class="form-content" v-if="activeName == 1">
         <el-form-item label="案件名称" required>
           <el-input
-            v-model="ruleForm.name"
+            v-model="bindExample.caseTitle"
             placeholder="请输入"
             show-word-limit
             maxlength="100"
           />
         </el-form-item>
-        <el-form-item label="立案编号" prop="name">
+        <el-form-item label="立案编号" prop="caseNum">
           <el-input
-            v-model="ruleForm.name"
+            v-model="bindExample.caseNum"
             placeholder="请输入"
             show-word-limit
             maxlength="100"
           />
         </el-form-item>
-        <el-form-item label="案件类别" prop="name">
-          <el-input v-model="ruleForm.name" placeholder="请输入" />
+        <el-form-item label="案件类别" required>
+          <el-select
+            v-model="bindExample.caseCategory"
+            placeholder="请选择案件类别"
+          >
+            <el-option
+              v-for="item in criminalType"
+              :label="item"
+              :value="item"
+            />
+          </el-select>
         </el-form-item>
         <el-form-item label="案发时间" required>
           <el-date-picker
-            v-model="ruleForm.date1"
+            v-model="bindExample.crimeTime"
             type="date"
             aria-label="Pick a date"
-            placeholder="Pick a date"
+            placeholder="请选择案发时间"
             style="width: 100%"
           />
         </el-form-item>
 
         <el-form-item label="案发区域" prop="name">
           <el-input
-            v-model="ruleForm.name"
-            placeholder="请输入"
+            v-model="bindExample.caseRegion"
+            placeholder="请输入案发区域"
             show-word-limit
             maxlength="100"
           />
         </el-form-item>
-        <el-form-item label="案发地点" prop="name">
+        <el-form-item label="案件地点">
           <el-input
-            v-model="ruleForm.name"
-            placeholder="请输入"
-            show-word-limit
-            maxlength="100"
-          />
+            v-model="bindExample.caseAddress"
+            placeholder="输入名称搜索"
+            clearable
+            disabled
+          >
+            <template #append>
+              <el-button :icon="Search" @click="searchAMapAddress" />
+            </template>
+          </el-input>
         </el-form-item>
         <el-form-item label="是否命案" prop="region">
-          <el-select v-model="ruleForm.region" placeholder="请选择">
-            <el-option label="是" value="1" />
-            <el-option label="否" value="0" />
+          <el-select v-model="bindExample.homicideCase" placeholder="请选择">
+            <el-option label="是" :value="1" />
+            <el-option label="否" :value="0" />
           </el-select>
         </el-form-item>
         <el-form-item label="是否刑案" prop="region">
-          <el-select v-model="ruleForm.region" placeholder="请选择">
-            <el-option label="是" value="1" />
-            <el-option label="否" value="0" />
+          <el-select v-model="bindExample.criminalCase" placeholder="请选择">
+            <el-option label="是" :value="1" />
+            <el-option label="否" :value="0" />
           </el-select>
         </el-form-item>
         <el-form-item label="经纬度" prop="name">
           <el-input
-            v-model="ruleForm.name"
+            v-model="bindExample.latAndLong"
             placeholder="请输入"
             show-word-limit
             maxlength="100"
@@ -84,25 +309,25 @@
       <div class="form-content" v-else>
         <el-form-item label="指挥中心电话时间" required>
           <el-date-picker
-            v-model="ruleForm.date1"
+            v-model="ruleForm.commandTime"
             type="date"
-            aria-label="Pick a date"
-            placeholder="Pick a date"
+            placeholder="请选择"
+            aria-label="请选择"
             style="width: 100%"
           />
         </el-form-item>
         <el-form-item label="接警时间" required>
           <el-date-picker
-            v-model="ruleForm.date1"
+            v-model="ruleForm.alarmTime"
             type="date"
-            aria-label="Pick a date"
-            placeholder="Pick a date"
+            placeholder="请选择"
+            aria-label="请选择"
             style="width: 100%"
           />
         </el-form-item>
         <el-form-item label="报警人" required>
           <el-input
-            v-model="ruleForm.name"
+            v-model="ruleForm.alarmName"
             placeholder="请输入"
             show-word-limit
             maxlength="100"
@@ -110,7 +335,7 @@
         </el-form-item>
         <el-form-item label="现场勘验单位" required>
           <el-input
-            v-model="ruleForm.name"
+            v-model="ruleForm.inquestDept"
             placeholder="请输入"
             show-word-limit
             maxlength="100"
@@ -118,7 +343,7 @@
         </el-form-item>
         <el-form-item label="指派/报告单位" required>
           <el-input
-            v-model="ruleForm.name"
+            v-model="ruleForm.assignDept"
             placeholder="请输入"
             show-word-limit
             maxlength="100"
@@ -126,7 +351,7 @@
         </el-form-item>
         <el-form-item label="指派方式" required>
           <el-input
-            v-model="ruleForm.name"
+            v-model="ruleForm.assignType"
             placeholder="请输入"
             show-word-limit
             maxlength="100"
@@ -134,35 +359,17 @@
         </el-form-item>
         <el-form-item label="勘验时间">
           <el-date-picker
-            v-model="ruleForm.date1"
+            v-model="ruleForm.times"
             type="daterange"
             start-placeholder="开始时间"
             end-placeholder="结束时间"
             format="YYYY-MM-DD"
             date-format="YYYY/MM/DD ddd"
           />
-          <!-- <el-col :span="11">
-            <el-date-picker
-              v-model="ruleForm.date1"
-              type="date"
-              placeholder="Pick a date"
-              style="width: 100%"
-            />
-          </el-col>
-          <el-col :span="2" class="text-center">
-            <span class="text-gray-500">-</span>
-          </el-col>
-          <el-col :span="11">
-            <el-time-picker
-              v-model="ruleForm.date2"
-              placeholder="Pick a time"
-              style="width: 100%"
-            />
-          </el-col> -->
         </el-form-item>
         <el-form-item label="勘验地点" required>
           <el-input
-            v-model="ruleForm.name"
+            v-model="ruleForm.inquestAddress"
             placeholder="请输入"
             show-word-limit
             maxlength="100"
@@ -179,98 +386,132 @@
           保存
         </el-button>
       </el-form-item>
-    </el-form>
+    </el-form> -->
   </div>
 </template>
 
 <script setup lang="ts">
-import { computed, ref, reactive } from "vue";
+import { computed, ref, reactive, onMounted } from "vue";
+import { Search } from "@element-plus/icons-vue";
+import { ElMessage, CascaderOption, CascaderProps } from "element-plus";
+import { Example, setExample, addExample } from "@/app/criminal/store/example";
+import { selectMapImage } from "@/view/case/quisk";
+import { geoData } from "./getGeo";
+import { getCaseInfo, getCaseInquestInfo, AddsaveOrUpdate, getcaseInDate } from "@/store/case";
+const selectSetting = ref<CascaderProps>({
+  value: "name",
+  label: "name",
+});
+import { router } from "@/router";
 const active = ref(true);
+const caseId = computed(() => {
+  const caseId = router.currentRoute.value.params.caseId;
+  if (caseId) {
+    return Number(caseId);
+  }
+});
 const ruleFormRef = ref(null);
+const exampleRef = ref(null);
 const activeName = ref("1");
-const ruleForm = reactive({
-  name: "Hello",
-  region: "",
-  count: "",
-  date1: "",
-  date2: "",
-  delivery: false,
+const ruleForm = ref({
+  commandTime: "",
+  alarmTime: "",
+  alarmName: "",
+  inquestDept: "",
+  assignDept: "",
+  inquestAddress: "",
   location: "",
-  type: [],
+  times: [],
   resource: "",
   desc: "",
 });
+const bindExample = ref({
+  caseTitle: "",
+  caseNum: "",
+  caseCategory: "",
+  crimeTime: "",
+  caseRegion: [],
+  caseAddress: "",
+  homicideCase: 0,
+  criminalCase: 0,
+  latAndLong: "",
+  criminalType: "",
+});
+const criminalType = [
+  "杀人",
+  "爆炸",
+  "放火",
+  "强奸",
+  "绑架",
+  "投毒",
+  "破坏",
+  "伤害致死",
+  "入室抢劫",
+  "入室盗窃",
+  "抢劫",
+  "抢夺",
+  "盗窃类",
+  "接触性诈骗",
+];
+onMounted(async () => {
+  console.log("caseInfo", caseId.value);
+  const caseInfo = await getcaseInDate(caseId.value);
+  const caseData = await getCaseInquestInfo(caseId.value)
+  console.log("caseInfo", caseInfo, caseData);
+  if (caseInfo) {
+    ruleForm.value = caseInfo;
+    bindExample.value = caseInfo;
+
+ }
+});
 const options = Array.from({ length: 10000 }).map((_, idx) => ({
   value: `${idx + 1}`,
   label: `${idx + 1}`,
 }));
 const rules = reactive({
-  name: [
-    { required: true, message: "Please input Activity name", trigger: "blur" },
-    { min: 3, max: 5, message: "Length should be 3 to 5", trigger: "blur" },
-  ],
-  region: [
+  caseTitle: [
     {
       required: true,
-      message: "Please select Activity zone",
-      trigger: "change",
+      message: "请输入",
+      trigger: "blur",
     },
   ],
-  count: [
+  caseNum: [
     {
       required: true,
-      message: "Please select Activity count",
-      trigger: "change",
+      message: "请输入",
+      trigger: "blur",
     },
   ],
-  date1: [
+  crimeTime: [
     {
-      type: "date",
       required: true,
-      message: "Please pick a date",
+      message: "请选择",
       trigger: "change",
     },
   ],
-  date2: [
-    {
-      type: "date",
-      required: true,
-      message: "Please pick a time",
-      trigger: "change",
-    },
-  ],
-  location: [
-    {
-      required: true,
-      message: "Please select a location",
-      trigger: "change",
-    },
-  ],
-  type: [
-    {
-      type: "array",
-      required: true,
-      message: "Please select at least one activity type",
-      trigger: "change",
-    },
-  ],
-  resource: [
-    {
-      required: true,
-      message: "Please select activity resource",
-      trigger: "change",
-    },
-  ],
-  desc: [
-    { required: true, message: "Please input activity form", trigger: "blur" },
+  caseCategory: [
+    { required: true, message: "请选择", trigger: "change" },
   ],
 });
 const showModal = ref(false);
+const submit = async () => {
+  if(activeName.value == "1") {
+    if (!bindExample.value.caseTitle || !bindExample.value.caseTitle.trim()) {
+      ElMessage.error("案件名称不能为空");
+      throw "案件名称不能为空";
+    }
+    setExample({...bindExample.value, caseId :caseId.value })
+  }else{
+    AddsaveOrUpdate({...ruleForm.value, caseId :caseId.value })
+  }
+};
 const submitForm = async (formEl) => {
   if (!formEl) return;
   await formEl.validate((valid, fields) => {
     if (valid) {
       console.log("submit!");
+      submit();
     } else {
       console.log("error submit!", fields);
     }
@@ -286,6 +527,13 @@ function handleActive(params) {
 async function handleAdd() {
   console.log("handleAdd");
 }
+const searchAMapAddress = async () => {
+  const data = await selectMapImage({text: true});
+  console.log("searchAMapAddress", data);
+  if (!data?.search) return;
+  bindExample.value.caseAddress = data.search.text;
+  bindExample.value.latAndLong = `${data.search.lat},${data.search.lng}`;
+};
 </script>
 <style lang="scss" scoped>
 .abstract {
@@ -294,7 +542,7 @@ async function handleAdd() {
     margin-bottom: 14px;
   }
   .form-content {
-    height: calc(100vh - 225px);
+    height: calc(100vh - 175px);
     overflow-y: scroll;
   }
   .demo-tabs {

+ 9 - 6
src/view/aiList/index.vue

@@ -3,7 +3,7 @@
     <div>场景列表</div>
     <div>仅 Mesh 场景支持 AI 现勘,请在列表中选择一个场景</div>
     <div class="blList">
-      <div class="listItem py-2" v-for="item in 3" :key="itme">
+      <div class="listItem p-2 cursor-pointer" v-for="item in 3" :key="itme" :class="{active: active == item}" @click="handleItem(item)">
         <div class="title1">场景{{ item }}</div>
       </div>
     </div>
@@ -16,22 +16,22 @@ import { addCaseFile } from "../originalPhoto/quisk";
 import { ElMessage, ElMessageBox } from "element-plus";
 import { useUpload } from "@/hook/upload";
 import { Delete, Edit } from "@element-plus/icons-vue";
-const active = ref(true);
 const srcList = [
   "https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg",
   "https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg",
 ];
-const settype = ref(false);
+const active = ref(null);
 const ruleFormRef = ref(null);
 const activeName = ref("1");
 const showModal = ref(false);
 const { size, fileList, upload, removeFile, previewFile, file, accept } =
   useUpload({
     maxSize: 10 * 1024 * 1024,
-    formats: [".word", ".pdf"],
+    formats: [".doc", ".docx", , ".pdf"],
   });
-const handleClick = (tab) => {
-  console.log(tab);
+const handleItem = (item) => {
+  console.log('handleItem', item);
+  active.value = item;
 };
 const submitForm = async (formEl) => {
   if (!formEl) return;
@@ -83,5 +83,8 @@ function handleDel() {
       line-height: 32px;
     }
   }
+  .active{
+    background-color: #f0f2f5;
+  }
 }
 </style>

+ 1 - 0
src/view/case/addCaseFile.vue

@@ -75,6 +75,7 @@ const caseFile = ref<CaseFile>({
 const { size, fileList, upload, removeFile, previewFile, file, accept } = useUpload({
   maxSize: maxFileSize,
   formats: props.fileType === FileDrawType ? DrawFormats : OtherFormats,
+  upload: (file) => caseFile.value.filesTitle = file?.name,
 });
 
 const formatDesc = computed(() =>

+ 24 - 13
src/view/case/draw/selectMapImage.vue

@@ -24,14 +24,23 @@ import { debounce } from "@/util";
 
 export type MapImage = { blob: Blob | null };
 type MapInfo = { lat: number; lng: number; zoom: number };
-
+const props = defineProps<{ text: boolean }>();
 const keyword = ref("");
 const info = ref<MapInfo>();
-
+const maps = ref();
 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;
@@ -42,12 +51,13 @@ watchEffect(async (onCleanup) => {
     version: "2.0",
   });
 
-  const map = new AMap.Map(mapEl.value, {
+  map = new AMap.Map(mapEl.value, {
     WebGLParams: {
       preserveDrawingBuffer: true,
     },
     resizeEnable: true,
   });
+  maps.value = map;
   const placeSearch = new AMap.PlaceSearch({
     pageSize: 5,
     pageIndex: 1,
@@ -55,15 +65,6 @@ watchEffect(async (onCleanup) => {
     panel: resultEl.value,
     autoFitView: true,
   });
-  const getMapInfo = (): MapInfo => {
-    var zoom = map.getZoom(); //获取当前地图级别
-    var center = map.getCenter();
-    return {
-      zoom,
-      lat: center.lat,
-      lng: center.lng,
-    };
-  };
   //绑定地图移动与缩放事件
   map.on("moveend", () => (info.value = getMapInfo()));
   map.on("zoomend", () => (info.value = getMapInfo()));
@@ -84,6 +85,16 @@ 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;

+ 84 - 43
src/view/dossier/index.vue

@@ -6,18 +6,20 @@
         class="upload-demo"
         :multiple="false"
         drag
-        :limit="1"
-        :disabled="!!file"
+        :show-file-list="false"
         :before-upload="upload"
         :file-list="fileList"
-        :http-request="() => {}"
+        :http-request="uploadNewFile"
+        :on-success="handleSuccess"
         :on-preview="previewFile"
         :accept="accept"
         :before-remove="removeFile"
       >
         <div type="primary" :disabled="!!file">
           <div>点击或拖拽文件上传</div>
-          <div class="">支持 pdf、word 格式图片上传</div>
+          <div class="">
+            支持≤10MB jpg\png\jpeg格式图片,及≤500MB pdf\doc文件上传
+          </div>
         </div>
       </el-upload>
     </div>
@@ -27,52 +29,34 @@
         class="upload-demo"
         :multiple="false"
         drag
-        :limit="1"
-        :disabled="!!file"
         :before-upload="upload"
         :file-list="fileList"
-        :http-request="() => {}"
+        :on-success="handleSuccess1"
+        :http-request="uploadNewFile"
         :on-preview="previewFile"
         :accept="accept"
         :before-remove="removeFile"
       >
         <div type="primary" :disabled="!!file">
           <div>点击或拖拽文件上传</div>
-          <div class="">支持 pdf、word 格式图片上传</div>
+          <div class="">
+            支持≤10MB jpg\png\jpeg格式图片,及≤500MB pdf\doc文件上传
+          </div>
         </div>
       </el-upload>
     </div>
     <div class="blList">
-
-      <div class="listItem py-2" v-for="item in 3" :key="itme">
-                <div class="title1">一级标题</div>
-                <div class="list2">
-                  <div class="title2">2级标题</div>
-
-                  <div
-                    class="item2 inline-block relative"
-                    v-for="(item2, index) in srcList"
-                    :key="index"
-                  >
-                    <el-icon
-                      :size="20"
-                      class="absolute z-1 cursor-pointer"
-                      style="right: -0px; top: -8px"
-                    >
-                      <CircleCloseFilled @click="handleDel" />
-                    </el-icon>
-                    <el-image
-                      class="z-0 relative"
-                      :preview-src-list="srcList"
-                      preview-teleported
-                      :initial-index="index"
-                      style="width: 80px; height: 80px; margin-right: 10px"
-                      :src="item2"
-                      :fit="fit"
-                    />
-                  </div>
-                </div>
-              </div>
+      <div class="listItem py-2" v-for="(item, index) in list" :key="index">
+        <div class="title1">{{ item.filesTypeName }}</div>
+        <viewImg :list="item.caseFilesList || []" @handleItem="handleItem" /> 
+        <!-- <div
+          class="list2"
+          v-for="(item2, index2) in item.childrenList"
+          :key="index2"
+        >
+          <div class="title2">{{ item2.filesTypeName }}</div>
+        </div> -->
+      </div>
     </div>
   </div>
 </template>
@@ -81,8 +65,12 @@
 import { computed, ref, reactive } from "vue";
 import { addCaseFile } from "../originalPhoto/quisk";
 import { ElMessage, ElMessageBox } from "element-plus";
+import { uploadNewFile, addByMediaLiBrary } from "@/store/case";
 import { useUpload } from "@/hook/upload";
+import { updateByTreeFileLists } from "@/store/case";
 import { Delete, Edit } from "@element-plus/icons-vue";
+import viewImg from "@/components/viewImg/index.vue"
+import { router } from "@/router";
 const active = ref(true);
 const srcList = [
   "https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg",
@@ -91,12 +79,16 @@ const srcList = [
 const settype = ref(false);
 const ruleFormRef = ref(null);
 const activeName = ref("1");
+const list = ref([]);
+const ssjId = ref(0);
+const zjjId = ref(0);
 const showModal = ref(false);
-const { size, fileList, upload, removeFile, previewFile, file, accept } =
-  useUpload({
-    maxSize: 10 * 1024 * 1024,
-    formats: [".word", ".pdf"],
-  });
+const caseId = computed(() => router.currentRoute.value?.params?.caseId);
+getList();
+const { size, fileList, removeFile, previewFile, file, accept } = useUpload({
+  maxSize: 10 * 1024 * 1024,
+  formats: [".jpg", ".png", ".jpeg", ".doc", ".docx", ".pdf"],
+});
 const handleClick = (tab) => {
   console.log(tab);
 };
@@ -114,9 +106,58 @@ const resetForm = (formEl) => {
   if (!formEl) return;
   formEl.resetFields();
 };
+function getList() {
+  updateByTreeFileLists(caseId.value).then((res) => {
+    let newlist = res.find((ele) => ele.filesTypeName == "案件卷宗") || [];
+    list.value = newlist.childrenList || [];
+    ssjId.value = newlist.childrenList.find(
+      (ele) => ele.filesTypeName == "诉讼卷"
+    ).filesTypeId;
+    zjjId.value = newlist.childrenList.find(
+      (ele) => ele.filesTypeName == "证据卷"
+    ).filesTypeId;
+    console.log("list.value", list.value);
+  });
+}
+function handleSuccess(item) {
+  let uploadId = item?.data.id;
+  addByMediaLiBrary({ caseId: caseId.value, filesTypeId: ssjId.value, uploadId }).then((res) => {
+    getList();
+  });
+}
+function handleSuccess1(item) {
+  let uploadId = item?.data.id;
+  addByMediaLiBrary({ caseId: caseId.value, filesTypeId: zjjId.value, uploadId }).then((res) => {
+    getList();
+  });
+}
+const upload = async (file: File) => {
+  const fileType = file.name
+    .substring(file.name.lastIndexOf("."))
+    .toUpperCase();
+  let imgList = [".jpg", ".png", ".jpeg", ".doc", ".docx", ".pdf"];
+  let fileList = [".doc", ".docx", ".pdf"];
+  if (!imgList.some((type) => type.toUpperCase() === fileType)) {
+    ElMessage.error(`请上传pdf、word 格式文件和 jpg、png、jpeg格式图片图片`);
+    return false;
+  } else if (
+    (fileList.includes(fileType) && file.size > 500 * 1024 * 1024) ||
+    file.size > 100 * 1024 * 1024
+  ) {
+    ElMessage.error(
+      `请上传≤10MB jpg、png、jpeg格式图片,及≤500MB pdf、doc文件`
+    );
+    return false;
+  } else {
+    return file;
+  }
+};
 function handleActive(params) {
   console.log("handleActive", params);
 }
+function handleItem(type, item) {
+  console.log("handleItem", type, item);
+}
 async function handleAdd() {
   await addCaseFile({ caseId: 2, fileType: 1 });
   console.log("handleAdd");

+ 5 - 4
src/view/layout/index.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="layer">
-    <ly-top class="top" v-if="!isSystem" />
+    <ly-top class="top" />
     <div class="content">
       <router-view v-slot="{ Component }" v-if="isSystem">
         <component :is="Component" />
@@ -8,7 +8,7 @@
       <template v-else>
         <ly-slide class="slide" :names="menuRouteNames" v-if="!hiddenSlide" />
         <div class="view" :class="{ full: hiddenSlide }">
-          <div class="app-wrap m-4">
+          <div class="app-wrap m-4" v-if="!hiddenSlide">
             <div
               class="app-scene"
               ref="sceneRef"
@@ -44,11 +44,12 @@ import lySlide from "./slide/index.vue";
 import { routeIsSystem, router } from "@/router";
 import { computed, ref } from "vue";
 import { menuRouteNames } from "@/app";
-console.log(menuRouteNames, 'menuRouteNames');
+import { updateByTreeFileLists } from "@/store/case";
+console.log(menuRouteNames, 'menuRouteNames', router.currentRoute.value.name);
 const sceneURL = ref('https://test.4dkankan.com/spg.html?m=KK-t-iN6cFCdwibf')
 
 const isSystem = computed(() => routeIsSystem());
-
+updateByTreeFileLists()
 const hiddenSlide = computed(
   () => !menuRouteNames.includes(router.currentRoute.value.name as string)
 );

+ 81 - 108
src/view/material/index.vue

@@ -25,111 +25,30 @@
           >
             绘制方位图
           </el-button>
-          <div class="phote my-4">
-            <p class="pb-4">平面图</p>
-            <div class="pmt-phote w-full flex justify-between">
-              <div
-                class="phote-item"
-                style="width: calc(50% - 10px)"
-                v-for="(item, index) in srcList"
-                :key="index"
-              >
-                <el-image
-                  style="width: 100%; height: 100px"
-                  :src="item"
-                  :zoom-rate="1.2"
-                  :max-scale="7"
-                  :min-scale="0.2"
-                  :preview-src-list="srcList"
-                  preview-teleported
-                  :initial-index="index"
-                  fit="cover"
-                />
-                <div class="but flex justify-around">
-                  <el-icon :size="20"><Edit /></el-icon>
-                  <el-icon color="red" :size="20"><Delete /></el-icon>
-                </div>
-              </div>
-            </div>
-          </div>
-
-          <div class="phote my-4">
-            <p class="pb-4">方位图</p>
-            <div class="pmt-phote w-full flex justify-between">
-              <div
-                class="phote-item"
-                style="width: calc(50% - 10px)"
-                v-for="(item, index) in srcList"
-                :key="index"
-              >
-                <el-image
-                  style="width: 100%; height: 100px"
-                  :src="item"
-                  :zoom-rate="1.2"
-                  :max-scale="7"
-                  :min-scale="0.2"
-                  :preview-src-list="srcList"
-                  preview-teleported
-                  :initial-index="index"
-                  fit="cover"
-                />
-                <div class="but flex justify-around">
-                  <el-icon :size="20"><Edit /></el-icon>
-                  <el-icon color="red" :size="20"><Delete /></el-icon>
-                </div>
-              </div>
+          <div class="phote my-4 w-full" v-for="item,index in list.xct" :key="index">
+            <p class="pb-4">{{item.filesTypeName}}</p>
+            <div class="pmt-phote w-full flex justify-between ">
+              <viewImg :list="item.caseFilesList || []"  @handleItem="handleItem" height="66px" />
             </div>
           </div>
         </div>
       </el-tab-pane>
       <el-tab-pane class="h-full" label="现场照片" name="2">
-        <div class="scene relative h-full">
-          <el-button class="w-full" @click="handleAdd">上传</el-button>
+        <div class="scene h-full">
+          <el-button class="w-full" @click="handleAdd(['三录材料', '现场照片'])">上传</el-button>
           <!-- <el-button class="w-full my-4"  style="margin-left: 0; margin-right: 0">添加场景</el-button> -->
           <div class="scene-list">
-            <div
-              class="scene-title flex justify-between content-center py-4"
-              style="line-height: 14px"
-            >
-              <span>场景列表</span>
-              <span @click="settype = !settype">{{
-                settype ? "完成" : "修改分类"
-              }}</span>
-            </div>
             <div class="list">
-              <div class="listItem py-2" v-for="item in 3" :key="itme">
-                <div class="title1">一级标题</div>
-                <div class="list2">
-                  <div class="title2">2级标题</div>
-
-                  <div
-                    class="item2 inline-block relative"
-                    v-for="(item2, index) in srcList"
-                    :key="index"
-                  >
-                    <el-icon
-                      :size="20"
-                      class="absolute z-1 cursor-pointer"
-                      style="right: -0px; top: -8px"
-                    >
-                      <CircleCloseFilled @click="handleDel" v-if="!settype" />
-                      <EditPen v-else />
-                    </el-icon>
-                    <el-image
-                      class="z-0 relative"
-                      :preview-src-list="srcList"
-                      preview-teleported
-                      :initial-index="index"
-                      style="width: 80px; height: 80px; margin-right: 10px"
-                      :src="item2"
-                      :fit="fit"
-                    />
-                  </div>
+              <div class="listItem py-2" v-for="item,index in list.xczp" :key="index">
+                <div class="title1">{{item.filesTypeName}}</div>
+                <div class="list2" v-for="item2,index2 in item.childrenList" :key="index2">
+                  <div class="title2">{{item2.filesTypeName}}</div>
+                  <viewImg :list="item2.caseFilesList || []" @handleItem="handleItem" />
                 </div>
               </div>
             </div>
           </div>
-          <el-button class="w-full absolute bottom-0" @click="handleAdd">照片制卷</el-button>
+          <el-button class="w-full" @click="handleAdd()">照片制卷</el-button>
         </div>
       </el-tab-pane>
       <el-tab-pane label="勘验笔录" name="3">
@@ -137,12 +56,13 @@
           <el-upload
             class="upload-demo"
             :multiple="false"
+            :show-file-list="false"
             drag
             :limit="1"
-            :disabled="!!file"
             :before-upload="upload"
             :file-list="fileList"
-            :http-request="() => {}"
+            :http-request="uploadNewFile"
+            :on-success="handleSuccess"
             :on-preview="previewFile"
             :accept="accept"
             :before-remove="removeFile"
@@ -152,20 +72,20 @@
               <div class="">支持 pdf、word 格式图片上传</div>
             </div>
           </el-upload>
-          <el-button class="w-full" @click="handleAdd">在线填写</el-button>
+          <el-button class="w-full mt-2" @click="handleAdd">在线填写</el-button>
         </div>
         <div class="blList">
-          <div class="bllistItem flex justify-between items-center mt-2">
-            <div>点击或拖拽文件上传11</div>
-            <el-dropdown>
+          <div class="bllistItem flex justify-between items-center mt-2" v-for="item,index in list.klbj" :key="index">
+            <div>{{item.filesTitle}}</div>
+            <el-dropdown @command="(command)=>{handleCommand(command, item)}">
               <el-icon>
                 <MoreFilled />
               </el-icon>
               <template #dropdown>
                 <el-dropdown-menu>
-                  <el-dropdown-item>编辑</el-dropdown-item>
-                  <el-dropdown-item>删除</el-dropdown-item>
-                  <el-dropdown-item>下载</el-dropdown-item>
+                  <el-dropdown-item command="edit">编辑</el-dropdown-item>
+                  <el-dropdown-item command="delete">删除</el-dropdown-item>
+                  <el-dropdown-item command="down">下载</el-dropdown-item>
                 </el-dropdown-menu>
               </template>
             </el-dropdown>
@@ -177,28 +97,51 @@
 </template>
 
 <script setup lang="ts">
+import { uploadNewFile, addByMediaLiBrary } from "@/store/case";
 import { computed, ref, reactive } from "vue";
 import { addCaseFile } from "../originalPhoto/quisk";
 import { ElMessage, ElMessageBox } from "element-plus";
 import { useUpload } from "@/hook/upload";
+import { router } from "@/router";
+import { updateByTreeFileLists, getByTreeFileLists } from "@/store/case";
 import { Delete, Edit } from "@element-plus/icons-vue";
+import viewImg from "@/components/viewImg/index.vue"
+import { delCaseFile, } from "@/store/caseFile";
+const caseId = computed(() => (router.currentRoute.value?.params?.caseId));
 const active = ref(true);
+const list = ref({
+  xct:[],
+  xczp:[],
+  klbj:[],
+});
+getList()
 const srcList = [
   "https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg",
   "https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg",
 ];
 const settype = ref(false);
 const ruleFormRef = ref(null);
-const activeName = ref("1");
+const klblId = ref(0);
+const activeName = ref('1');
 const showModal = ref(false);
 const { size, fileList, upload, removeFile, previewFile, file, accept } =
   useUpload({
     maxSize: 10 * 1024 * 1024,
-    formats: [".word", ".pdf"],
+    formats: [".doc", ".docx", , ".pdf"],
   });
 const handleClick = (tab) => {
   console.log(tab);
 };
+function getList() {
+  updateByTreeFileLists(caseId.value).then(res => {
+    let newlist =  res.find(ele => ele.filesTypeName == '三录材料')?.childrenList || [];
+    list.value.xct = newlist.find(ele => ele.filesTypeName == '现场图')?.childrenList || [];
+    list.value.xczp = newlist.find(ele => ele.filesTypeName == '现场照片')?.childrenList || [];
+    list.value.klbj = newlist.find(ele => ele.filesTypeName == '勘验笔录')?.caseFilesList || [];
+    klblId.value = newlist.find(ele => ele.filesTypeName == '勘验笔录').filesTypeId
+    console.log('list.value', list.value)
+  })
+}
 const submitForm = async (formEl) => {
   if (!formEl) return;
   await formEl.validate((valid, fields) => {
@@ -216,26 +159,56 @@ const resetForm = (formEl) => {
 function handleActive(params) {
   console.log("handleActive", params);
 }
-async function handleAdd() {
-  await addCaseFile({ caseId: 2, fileType: 1 });
+function handleItem(type, item) {
+  console.log("handleItem", type, item);
+}
+function handleSuccess(item) {
+  let uploadId = item?.data.id;
+  addByMediaLiBrary({ caseId: caseId.value, filesTypeId: klblId.value, uploadId }).then((res) => {
+    getList();
+  });
+}
+async function handleAdd(filesTypeName) {
+  await addCaseFile({ caseId: caseId.value, fileType: 1, filesTypeName });
+  getList()
   console.log("handleAdd");
 }
-function handleDel() {
+const handleCommand = (command: string | number | object, item) => {
+  switch (command) {
+    case "edit":
+      ElMessage(`click on item ${command}`)
+      break;
+    case "delete":
+      handleDel(item)
+      break;
+    default:
+      console.log("other", command);
+  }
+  // ElMessage(`click on item ${command}`)
+}
+function handleDel(item) {
   ElMessageBox.confirm("确定删除?", "提示", {
     confirmButtonText: "确定",
     cancelButtonText: "取消",
     type: "warning",
-  }).then(() => {
+  }).then(async () => {
+    await delCaseFile({ caseId: caseId.value, filesId: item.filesId });
     ElMessage({
       type: "success",
       message: "删除成功",
     });
+    getList()
   });
 }
 </script>
 <style lang="scss" scoped>
 .abstract {
   height: 100%;
+  .el-tab-pane{
+    height: 100%;
+    overflow-y: scroll;
+    position: relative;
+  }
   .el-form-item--label-top {
     margin-bottom: 14px;
   }

+ 48 - 16
src/view/originalPhoto/addCaseFile.vue

@@ -7,15 +7,17 @@
   >
     <el-form-item label="分类:" class="mandatory">
       <el-cascader
-        v-model="caseFile.type"
+        v-model="caseFile.filesTypeId"
+        :how-all-levels="false"
+        style="width: 300px;"
         :options="fileOptions"
         :props="{
-          checkStrictly: true,
+          checkStrictly: false,
         }"
         clearable
       />
     </el-form-item>
-    <el-form-item label="文件:" class="mandatory uploadFile">
+    <el-form-item label="文件:" class="mandatory uploadFile" style="margin-left: 12px">
       <el-upload
         class="upload-demo"
         :multiple="false"
@@ -24,7 +26,8 @@
         :disabled="!!file"
         :before-upload="upload"
         :file-list="fileList"
-        :http-request="() => {}"
+        :http-request="uploadNewFile"
+        :on-success="handleSuccess"
         :on-preview="previewFile"
         :accept="accept"
         :before-remove="removeFile"
@@ -43,7 +46,7 @@
           </div>
         </template>
       </el-upload>
-      <el-button type="primary" class="mtk" @click="handleAdd"
+      <el-button style="margin-left: 20px" type="primary" class="mtk" @click="handleAdd"
         >从媒体库上传</el-button
       >
     </el-form-item>
@@ -51,32 +54,51 @@
 </template>
 
 <script setup lang="ts">
+import { uploadNewFile, addByMediaLiBrary } from "@/store/case";
 import {
   DrawFormatDesc,
   DrawFormats,
   FileDrawType,
   OtherFormatDesc,
   OtherFormats,
-  fileOptions
 } from "@/constant/caseFile";
 import { maxFileSize } from "@/constant/caseFile";
 import { useUpload } from "@/hook/upload";
 import { CaseFile, addCaseFile } from "@/store/caseFile";
 import { ElMessage, UploadFile } from "element-plus";
-import { computed, ref, watchEffect } from "vue";
+import { computed, ref, watchEffect, onMounted } from "vue";
 import { addCaseScenes } from "./quisk";
 import { QuiskExpose } from "@/helper/mount";
+import { updateSelectByTreeFileLists } from "@/store/case";
 
 const props = defineProps<{
   caseId: number;
   fileType: number;
+  filesTypeName: [string];
 }>();
+const fileOptions = ref([])
+
+onMounted(async () => {
+  let newfileOptions = await updateSelectByTreeFileLists();
+  if(props.filesTypeName){
+    let newChildren = newfileOptions
+    props.filesTypeName.map(ele => {
+      newChildren = newChildren.find((item) => item.label == ele).children || []
+    })
+    fileOptions.value = newChildren
+    // fileOptions.value = newfileOptions.find((item) => item.label == props.filesTypeName).children || [];
+  } else {
+    fileOptions.value = newfileOptions;
+  }
+  console.log('fileOptions', fileOptions.value, newfileOptions);
+});
 
 const caseFile = ref({
   caseId: props.caseId,
   filesTypeId: props.fileType,
   filesTitle: "",
-  type: '',
+  dictId: '',
+  uploadId: '',
 });
 
 const { size, fileList, upload, removeFile, previewFile, file, accept } = useUpload({
@@ -88,26 +110,36 @@ const formatDesc = computed(() =>
   'jpg、png、jpeg、mp4上传'
 );
 
+// 上传请求
+const handleSuccess = (option) => {
+  console.log('handleSuccess', option);
+}
+
 const handleAdd = async () => {
   await addCaseScenes();
 };
 watchEffect(() => {
+  console.log('file', file.value);
   if (file.value?.name) {
-    caseFile.value.filesTitle = file.value?.name.substring(0, 50);
+    caseFile.value.uploadId = file.value?.response?.data.id
   }
 });
 
 defineExpose<QuiskExpose>({
   async submit() {
+    console.log('filesTypeId', caseFile.value);
     if (!file.value) {
-      ElMessage.error("请上传件");
-      throw "请上传件";
-    } else if (!caseFile.value.filesTitle.trim()) {
-      ElMessage.error("附件标题不能为空!");
-      throw "附件标题不能为空!";
+      ElMessage.error("请上传件");
+      throw "请上传件";
+    } else if (!caseFile.value.filesTypeId) {
+      ElMessage.error("文件类别不能为空!");
+      throw "文件类别不能为空!";
     }
-
-    await addCaseFile({ ...caseFile.value, file: file.value });
+    let filesTypeId = caseFile.value.filesTypeId?.slice(-1),
+    uploadId = file.value?.response?.data.id
+    let params = { ...caseFile.value, file: file.value, filesTypeId: filesTypeId[0], uploadId  };
+    console.log('filesTypeId', params);
+    await addByMediaLiBrary(params);
     return caseFile.value;
   },
 });

+ 165 - 0
src/view/originalPhoto/addLibrary.vue

@@ -0,0 +1,165 @@
+<template>
+  <el-form
+    ref="form"
+    :model="caseFile"
+    label-width="90px"
+    class="camera-from dispatch-file-from jm-file-upload"
+  >
+    <el-form-item label="分类:" class="mandatory">
+      <el-select
+      v-model="caseFile.dictId"
+      placeholder="请选择分类"
+      size="large"
+      style="width: 240px"
+    >
+      <el-option
+        v-for="item in options"
+        :key="item.id"
+        :label="item.dictName"
+        :value="item.id"
+      />
+    </el-select>
+      <!-- <el-cascader
+        v-model="caseFile.type"
+        :options="fileOptions"
+        :props="{
+          checkStrictly: true,
+        }"
+        clearable
+      /> -->
+    </el-form-item>
+    <el-form-item label="文件:" class="mandatory uploadFile" style="margin-left: 12px">
+      <el-upload
+        class="upload-demo"
+        :multiple="false"
+        drag
+        :limit="1"
+        :disabled="!!file"
+        :before-upload="upload"
+        :file-list="fileList"
+        :http-request="()=>{}"
+        :on-success="handleSuccess"
+        :on-preview="previewFile"
+        :accept="accept"
+        :before-remove="removeFile"
+      >
+        <div type="primary" :disabled="!!file">
+          <div>点击或拖拽文件上传</div>
+          <div class="">{{ size }}以内的{{ formatDesc }}</div>
+        </div>
+        <template v-slot:file="{ file }: { file: UploadFile }">
+          <div class="file" @click.stop="previewFile()">
+            <div>
+              <el-icon><Document /></el-icon>
+              <span class="name">{{ file.name }}</span>
+            </div>
+            <el-icon @click.stop="removeFile()"><Close /></el-icon>
+          </div>
+        </template>
+      </el-upload>
+    </el-form-item>
+  </el-form>
+</template>
+
+<script setup lang="ts">
+import {
+  DrawFormatDesc,
+  DrawFormats,
+  FileDrawType,
+  OtherFormatDesc,
+  OtherFormats,
+  fileOptions
+} from "@/constant/caseFile";
+import { maxFileSize } from "@/constant/caseFile";
+import { useUpload } from "@/hook/upload";
+import { CaseFile, addCaseFile } from "@/store/caseFile";
+import { getDictFileLists, uploadNewFile } from "@/store/case";
+import { ElMessage, UploadFile } from "element-plus";
+import { computed, ref, watchEffect, onMounted } from "vue";
+import { addCaseScenes } from "./quisk";
+import { QuiskExpose } from "@/helper/mount";
+
+const props = defineProps<{
+  caseId: number;
+  fileType: number;
+}>();
+
+const caseFile = ref({
+  caseId: props.caseId,
+  filesTypeId: props.fileType,
+  filesTitle: "",
+  type: '',
+  dictId: ''
+});
+const options = ref([])
+onMounted(async () => {
+  const res = await getDictFileLists(1);
+  console.log('onMounted', res);
+  options.value = res;
+});
+
+const { size, fileList, upload, removeFile, previewFile, file, accept } = useUpload({
+  maxSize: 2000 * 1024 * 1024,
+  formats: [".jpg", ".png", ".jpeg", ".mp4", ".wav", ".mp3", ".shp"],
+});
+
+const formatDesc = computed(() =>
+  'jpg、png、jpeg、mp4、wav、mp3、shp上传'
+);
+
+// 上传请求
+const handleSuccess = (option) => {
+  console.log(option);
+}
+
+const handleAdd = async () => {
+  await addCaseScenes();
+};
+watchEffect(() => {
+  if (file.value?.name) {
+    caseFile.value.filesTitle = file.value?.name.substring(0, 50);
+  }
+});
+
+defineExpose<QuiskExpose>({
+  async submit() {
+    if (!file.value) {
+      ElMessage.error("请上传附件");
+      throw "请上传附件";
+    } else if (!caseFile.value.filesTitle.trim()) {
+      ElMessage.error("附件标题不能为空!");
+      throw "附件标题不能为空!";
+    }
+
+    await uploadNewFile({ dictId: caseFile.value.dictId, file: file.value });
+    return 
+  },
+});
+</script>
+
+<style scoped lang="scss">
+.upload-demo {
+  overflow: hidden;
+}
+
+.file {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  > div {
+    display: flex;
+    align-items: center;
+  }
+
+  .name {
+    margin-left: 10px;
+  }
+}
+.jm-file-upload {
+  .mtk {
+    position: absolute;
+    right: 0;
+    top: 0;
+  }
+}
+</style>

+ 11 - 8
src/view/originalPhoto/addScenes.vue

@@ -21,7 +21,7 @@
         <el-table-column label="名称" v-slot:default="{ row }">
           {{ params.isSwmx ? row.modelTitle : row.name }}
         </el-table-column>
-        <el-table-column label="格式" prop="deptName"></el-table-column>
+        <el-table-column label="格式" prop="fileTypeStr"></el-table-column>
         <el-table-column label="大小" prop="modelDateType" v-if="params.isSwmx" />
         <el-table-column label="分组" prop="createTime" v-slot:default="{ row }">
           {{ row.createTime.substr(0, 16) }}
@@ -49,7 +49,7 @@
 import VRModelList from "./list.vue";
 import { Scene } from "@/store/scene";
 import { CaseScenes } from "@/store/case";
-import { useScenePaggingParams } from "@/view/vrmodel/pagging";
+import { useScenePaggingParams } from "./pagging";
 import { onMounted, ref, watch, watchEffect } from "vue";
 import {
   getCaseSceneList,
@@ -76,10 +76,10 @@ watch(
 // 复选框同步
 watchEffect(() => {
   if (!tableRef.value) return;
-  const selectKeys = caseScenes.value.find(
-    (item) => item.type === params.pagging.state.query.type
-  )!.numList;
-
+  const selectKeys = []
+  // caseScenes.value.find(
+  //   (item) => item.type === params.pagging.state.query.type
+  // )!.numList;
   params.pagging.state.table.rows.forEach((scene) => {
     tableRef.value!.toggleRowSelection(scene, selectKeys.includes(getSceneKey(scene)));
   });
@@ -104,8 +104,11 @@ const changeSelection = (selectScenes: Scene[]) => {
 onMounted(async () => {
   caseScenes.value = getCaseScenes(await getCaseSceneList(props.caseId));
 });
-
+const submit = () => {
+  console.log(caseScenes.value);
+  // () => replaceCaseScenes(props.caseId, caseScenes.value)
+};
 defineExpose<QuiskExpose>({
-  submit: () => replaceCaseScenes(props.caseId, caseScenes.value),
+  submit,
 });
 </script>

+ 41 - 12
src/view/originalPhoto/index.vue

@@ -5,25 +5,25 @@
     <div class="scene-list">
       <div class="scene-title flex justify-between content-center py-4" style="line-height: 14px">
         <span >场景列表</span>
-        <span  @click="settype = !settype">{{settype?'完成':'修改分类'}}</span>
+        <!-- <span  @click="settype = !settype">{{settype?'完成':'修改分类'}}</span> -->
       </div>
       <div class="list">
         <div
           class="listItem py-2"
-          v-for="item in 3"
-          :key="itme"
+          v-for="item,index in list"
+          :key="index"
         >
-          <div class="title1">一级标题</div>
-          <div class="list2">
-          <div class="title2">2级标题</div>
-          
-          <div class="item2 inline-block relative" v-for="(item2, index) in srcList" :key="index">
+          <div class="title1">{{item.filesTypeName}}</div>
+          <div class="list2" v-for="item2,index2 in item.childrenList" :key="index2">
+          <div class="title2">{{item2.filesTypeName}}</div>
+          <viewImg :list="item2.caseFilesList || []" width="calc(50% - 18px)" height="100px" @handleItem="handleItem" />
+          <!-- <div class="item2 inline-block relative" v-for="(item2, index) in srcList" :key="index">
             <el-icon :size="20" class="absolute z-1 cursor-pointer" style="right: -0px; top: -8px">
               <CircleCloseFilled v-if="!settype" />
               <EditPen v-else />
             </el-icon>
             <el-image class="z-0 relative" preview-teleported :preview-src-list="srcList" :initial-index="index" style="width: 80px; height: 80px;margin-right: 10px" :src="item2" :fit="fit" />
-            </div>
+            </div> -->
           </div>
         </div>
       </div>
@@ -32,17 +32,46 @@
 </template>
 
 <script setup lang="ts">
+import viewImg from "@/components/viewImg/index.vue"
 import { computed, ref } from "vue";
-import { addCaseFile } from "./quisk";
+import { updateByTreeFileLists, getByTreeFileLists } from "@/store/case";
+import { router } from "@/router";
+import { addCaseFile, setTypeFile } from "./quisk";
+const caseId = computed(() => (router.currentRoute.value?.params?.caseId));
 const active = ref(true);
 const settype = ref(false);
 const showModal = ref(false);
 const srcList = ["https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg","https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg"]
+const list = ref([]);
+getList()
 function handleActive(params) {
   console.log("handleActive", params);
 }
+function getList() {
+  updateByTreeFileLists(caseId.value).then(res => {
+    list.value = res.find(ele => ele.filesTypeName == '原始照片')?.childrenList || [];
+  })
+}
 async function handleAdd() {
-  await addCaseFile({ caseId: 2, fileType: 1 });
-  console.log("handleAdd");
+  await addCaseFile({ caseId: caseId.value, fileType: 1, filesTypeName: ['原始照片'] });
+  getList();
+}
+async function handleItem(type, item) {
+  console.log("handleItem", type, item);
+  if(type == 'edit'){
+    await setTypeFile({
+      ...item,caseId:caseId.value
+    })
+  }
+  getList();
 }
 </script>
+<style scoped lang="scss">
+.scene{
+  height: 100%;
+  overflow-x: scroll;
+  .scene-list{
+    // height: 100%;
+  }
+}
+</style>

+ 25 - 2
src/view/originalPhoto/list.vue

@@ -6,7 +6,18 @@
         <el-button type="primary" plain @click="params.pagging.queryReset"
           >重置</el-button
         >
-        <el-button type="primary" @click="params.pagging.refresh">上传文件</el-button>
+        <!-- :disabled="!!file" -->
+        <!-- <el-upload
+        class="upload-demo"
+        :multiple="false"
+        :limit="1"
+        :before-upload="upload"
+        :show-file-list="false"
+        :http-request="() => {}"
+        :accept="accept"
+      > -->
+        <el-button style="margin-left: 12px" type="primary" @click="handleAdd">上传文件</el-button>
+      <!-- </el-upload> -->
       </el-form-item>
     </el-form>
 
@@ -26,11 +37,19 @@
 import comHead from "@/components/head/index.vue";
 import comPagination from "@/components/pagination/index.vue";
 import { SceneType } from "@/store/scene";
+import { useFirePagging } from "./pagging";
 import { SceneTypeDesc } from "@/constant/scene";
 import { useScenePaggingParams } from "./pagging";
+import { useUpload } from "@/hook/upload";
+import { addLibraryFile } from "./quisk";
 
+const { pagging } = useScenePaggingParams();
 defineProps<{ params: ReturnType<typeof useScenePaggingParams> }>();
-
+const { size, fileList, upload, removeFile, previewFile, file, accept } =
+  useUpload({
+    maxSize: 2000 * 1024 * 1024,
+    formats: [".jpg", ".png", ".jpeg", ".mp4", ".wav", ".mp3", ".shp"],
+  });
 const headOptions = [
   { value: SceneType.SWKK, name: SceneTypeDesc[SceneType.SWKK] },
   { value: SceneType.SWKJ, name: SceneTypeDesc[SceneType.SWKJ] },
@@ -40,4 +59,8 @@ const headOptions = [
   { value: SceneType.SWYDMX, name: SceneTypeDesc[SceneType.SWYDMX] },
   { value: SceneType.SWMX, name: SceneTypeDesc[SceneType.SWMX] },
 ];
+const handleAdd = async () => {
+  await addLibraryFile();
+  pagging.refresh();
+};
 </script>

+ 4 - 3
src/view/originalPhoto/pagging.ts

@@ -1,17 +1,18 @@
 import { usePagging } from "@/hook/pagging";
 import { SceneType, getScenePagging } from "@/store/scene";
+import { getFilepageList } from "@/store/case";
+
 import { computed, reactive, watch, watchEffect } from "vue";
 
 export const useScenePaggingParams = () => {
   const pagging = usePagging({
-    get: getScenePagging,
+    get: getFilepageList,
     paramsTemlate: {
-      type: SceneType.SWKK,
       sceneName: "",
       modelTitle: "",
       deptId: "",
       snCode: "",
-      sceneType: '1',
+      type: '1',
     },
   });
 

+ 7 - 1
src/view/originalPhoto/quisk.ts

@@ -1,4 +1,5 @@
 import AddCaseFile from "./addCaseFile.vue";
+import AddLibrary from "./addLibrary.vue";
 import AddScenes from "./addScenes.vue";
 import setType from "./setType.vue";
 import { quiskMountFactory } from "@/helper/mount";
@@ -6,7 +7,7 @@ import { nextTick } from "vue";
 
 export const addCaseFile = quiskMountFactory(AddCaseFile, {
   title: "上传附件",
-  width: 550,
+  width: 570,
 });
 
 export const addCaseScenes = quiskMountFactory(AddScenes, {
@@ -14,6 +15,11 @@ export const addCaseScenes = quiskMountFactory(AddScenes, {
   width: 1000,
 });
 
+export const addLibraryFile = quiskMountFactory(AddLibrary, {
+  title: "上传文件",
+  width: 550,
+});
+
 export const setTypeFile = quiskMountFactory(setType, {
   title: "修改分类",
   width: 550,

+ 27 - 16
src/view/originalPhoto/setType.vue

@@ -7,10 +7,11 @@
   >
     <el-form-item label="分类:" class="mandatory">
       <el-cascader
-        v-model="caseFile.type"
+      style="width: 300px;"
+        v-model="caseFile.filesTypeId"
         :options="fileOptions"
         :props="{
-          checkStrictly: true,
+          checkStrictly: false,
         }"
         clearable
       />
@@ -25,28 +26,34 @@ import {
   FileDrawType,
   OtherFormatDesc,
   OtherFormats,
-  fileOptions
 } from "@/constant/caseFile";
 import { maxFileSize } from "@/constant/caseFile";
 import { useUpload } from "@/hook/upload";
 import { CaseFile, addCaseFile } from "@/store/caseFile";
 import { ElMessage, UploadFile } from "element-plus";
-import { computed, ref, watchEffect } from "vue";
+import { computed, ref, watchEffect, onMounted } from "vue";
 import { addCaseScenes } from "./quisk";
 import { QuiskExpose } from "@/helper/mount";
+import { updateSelectByTreeFileLists, getupdateFileType } from "@/store/case";
 
 const props = defineProps<{
   caseId: number;
-  fileType: number;
+  filesTypeId: number;
+  filesId: number;
 }>();
+const fileOptions = ref([])
 
+onMounted(async () => {
+  fileOptions.value = await updateSelectByTreeFileLists();
+  console.log(fileOptions.value);
+});
 const caseFile = ref({
   caseId: props.caseId,
-  filesTypeId: props.fileType,
+  filesTypeId: props.filesTypeId,
   filesTitle: "",
-  type: '',
+  filesId: props.filesId,
 });
-
+console.log(caseFile.value, '===caseFile');
 const { size, fileList, upload, removeFile, previewFile, file, accept } = useUpload({
   maxSize: 10 * 1024 * 1024,
   formats: [".jpg", ".jpeg", ".png", '.mp4'],
@@ -67,15 +74,19 @@ watchEffect(() => {
 
 defineExpose<QuiskExpose>({
   async submit() {
-    if (!file.value) {
-      ElMessage.error("请上传附件");
-      throw "请上传附件";
-    } else if (!caseFile.value.filesTitle.trim()) {
-      ElMessage.error("附件标题不能为空!");
-      throw "附件标题不能为空!";
+    console.log(caseFile.value, "文件列表");
+    if (!caseFile.value.filesTypeId) {
+      ElMessage.error("分类不能为空");
+      throw "分类不能为空";
+    } 
+    let filesTypeId
+    if(caseFile.value.filesTypeId instanceof Array){
+      filesTypeId = caseFile.value.filesTypeId?.slice(-1)[0]
+    }else {
+      filesTypeId = caseFile.value.filesTypeId
     }
-
-    await addCaseFile({ ...caseFile.value, file: file.value });
+    // let filesTypeId = caseFile.value.filesTypeId?.slice(-1)
+    await getupdateFileType({...caseFile.value , filesTypeId});
     return caseFile.value;
   },
 });

+ 63 - 43
src/view/other/index.vue

@@ -6,18 +6,18 @@
         class="upload-demo"
         :multiple="false"
         drag
-        :limit="1"
-        :disabled="!!file"
+        :show-file-list="false"
         :before-upload="upload"
         :file-list="fileList"
-        :http-request="() => {}"
+        :http-request="uploadNewFile"
+        :on-success="handleSuccess"
         :on-preview="previewFile"
         :accept="accept"
         :before-remove="removeFile"
       >
         <div type="primary" :disabled="!!file">
           <div>点击或拖拽文件上传</div>
-          <div class="">支持 pdf、word 格式图片上传</div>
+          <div class="">支持{{ fileInfo.DrawFormatDesc }}格式上传</div>
         </div>
       </el-upload>
     </div>
@@ -27,52 +27,26 @@
         class="upload-demo"
         :multiple="false"
         drag
-        :limit="1"
-        :disabled="!!file"
         :before-upload="upload"
         :file-list="fileList"
-        :http-request="() => {}"
+            :show-file-list="false"
+        :http-request="uploadNewFile"
+        :on-success="handleSuccess1"
         :on-preview="previewFile"
         :accept="accept"
         :before-remove="removeFile"
       >
         <div type="primary" :disabled="!!file">
           <div>点击或拖拽文件上传</div>
-          <div class="">支持 pdf、word 格式图片上传</div>
+          <div class="">支持{{ fileInfo.DrawFormatDesc }}格式上传</div>
         </div>
       </el-upload>
     </div>
     <div class="blList">
-
-      <div class="listItem py-2" v-for="item in 3" :key="itme">
-                <div class="title1">一级标题</div>
-                <div class="list2">
-                  <div class="title2">2级标题</div>
-
-                  <div
-                    class="item2 inline-block relative"
-                    v-for="(item2, index) in srcList"
-                    :key="index"
-                  >
-                    <el-icon
-                      :size="20"
-                      class="absolute z-1 cursor-pointer"
-                      style="right: -0px; top: -8px"
-                    >
-                      <CircleCloseFilled @click="handleDel" />
-                    </el-icon>
-                    <el-image
-                      class="z-0 relative"
-                      :preview-src-list="srcList"
-                      preview-teleported
-                      :initial-index="index"
-                      style="width: 80px; height: 80px; margin-right: 10px"
-                      :src="item2"
-                      :fit="fit"
-                    />
-                  </div>
-                </div>
-              </div>
+      <div class="listItem py-2" v-for="(item, index) in list" :key="index">
+        <div class="title1">{{ item.filesTypeName }}</div>
+        <viewImg :list="item.caseFilesList || []" @handleItem="handleItem" />
+      </div>
     </div>
   </div>
 </template>
@@ -82,8 +56,14 @@ import { computed, ref, reactive } from "vue";
 import { addCaseFile } from "../originalPhoto/quisk";
 import { ElMessage, ElMessageBox } from "element-plus";
 import { useUpload } from "@/hook/upload";
+import { uploadNewFile, addByMediaLiBrary } from "@/store/case";
+import { updateByTreeFileLists } from "@/store/case";
+import { delCaseFile, } from "@/store/caseFile";
+import { router } from "@/router";
+import viewImg from "@/components/viewImg/index.vue";
 import { Delete, Edit } from "@element-plus/icons-vue";
 const active = ref(true);
+const caseId = computed(() => router.currentRoute.value?.params?.caseId);
 const srcList = [
   "https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg",
   "https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg",
@@ -91,11 +71,21 @@ const srcList = [
 const settype = ref(false);
 const ruleFormRef = ref(null);
 const activeName = ref("1");
+const xzclId = ref(0);
+const qtclId = ref(0);
+const list = ref([]);
+const fileInfo = ref({
+  accept: ".jpg, .jpeg, .png, .mp4",
+  formats: [".jpg", ".jpeg", ".png", ".mp4"],
+  DrawFormatDesc: "jpg、png、jpeg、mp4上传",
+  fileSize: 10 * 1024 * 1024,
+});
+getList();
 const showModal = ref(false);
 const { size, fileList, upload, removeFile, previewFile, file, accept } =
   useUpload({
-    maxSize: 10 * 1024 * 1024,
-    formats: [".word", ".pdf"],
+    formats: fileInfo.value.formats,
+    maxSize: fileInfo.value.fileSize,
   });
 const handleClick = (tab) => {
   console.log(tab);
@@ -110,6 +100,20 @@ const submitForm = async (formEl) => {
     }
   });
 };
+function getList() {
+  updateByTreeFileLists(caseId.value).then((res) => {
+    let newlist = res.find((ele) => ele.filesTypeName == "其他资料") || [];
+    console.log("updateByTreeFileLists", newlist);
+    list.value = newlist.childrenList || [];
+    xzclId.value = newlist.childrenList.find(
+      (ele) => ele.filesTypeName == "侦查实验"
+    ).filesTypeId;
+    qtclId.value = newlist.childrenList.find(
+      (ele) => ele.filesTypeName == "其他材料"
+    ).filesTypeId;
+    console.log("list.value", list.value);
+  });
+}
 const resetForm = (formEl) => {
   if (!formEl) return;
   formEl.resetFields();
@@ -118,21 +122,37 @@ function handleActive(params) {
   console.log("handleActive", params);
 }
 async function handleAdd() {
-  await addCaseFile({ caseId: 2, fileType: 1 });
+  await addCaseFile({ caseId: caseId.value, fileType: 1 });
   console.log("handleAdd");
 }
-function handleDel() {
+function handleSuccess(item) {
+  let uploadId = item?.data.id;
+  addByMediaLiBrary({ caseId: caseId.value, filesTypeId: xzclId.value, uploadId }).then((res) => {
+    getList();
+  });
+}
+function handleSuccess1(item) {
+  let uploadId = item?.data.id;
+  addByMediaLiBrary({ caseId: caseId.value, filesTypeId: qtclId.value, uploadId }).then((res) => {
+    getList();
+  });
+}
+function handleDel(item) {
   ElMessageBox.confirm("确定删除?", "提示", {
     confirmButtonText: "确定",
     cancelButtonText: "取消",
     type: "warning",
-  }).then(() => {
+  }).then(async () => {
+    await delCaseFile({ caseId: caseId.value, filesId: item.filesId });
     ElMessage({
       type: "success",
       message: "删除成功",
     });
   });
 }
+function handleItem(type, item) {
+  console.log("handleItem", type, item);
+}
 </script>
 <style lang="scss" scoped>
 .abstract {

+ 19 - 7
src/view/vrmodel/index.vue

@@ -10,11 +10,11 @@
         <div class="list" v-if="active">
           <div
             class="listItem flex justify-between py-2"
-            v-for="item in 3"
-            :key="itme"
+            v-for="item,index in list"
+            :key="index"
           >
-            <span>场景列表{{ item }}</span>
-            <div quaternary type="primary">编辑</div>
+            <span>{{ item.name || item.modelTitle }}</span>
+            <div class="cursor-pointer" quaternary type="primary">编辑</div>
           </div>
         </div>
       </div>
@@ -22,22 +22,34 @@
 </template>
 
 <script setup lang="ts">
+import { getCaseSceneList } from "@/store/case";
+import { router } from "@/router";
 import comSelect from "@/components/company-select/index.vue";
 import List from "./list.vue";
 import SceneContent from "./sceneContent.vue";
 import ModelContent from "./modelContent.vue";
 import { useScenePaggingParams } from "./pagging";
-import { computed, ref } from "vue";
+import { computed, ref, onMounted } from "vue";
 import { tableModelScene } from "./quisk";
 const active = ref(true);
+const list = ref([]);
 const showModal = ref(false);
 const params = useScenePaggingParams();
-const component = computed(() => (params.isSwmx ? ModelContent : SceneContent));
+const caseId = computed(() => (router.currentRoute.value?.params?.caseId));
+onMounted(() => {
+  geiList();
+  console.log("router.currentRoute.value", caseId);
+});
+async function geiList() {
+  list.value = await getCaseSceneList(caseId.value);
+  console.log("res", list.value);
+}
 function handleActive(params) {
   console.log("handleActive", params);
 }
 async function handleAdd() {
-  console.log("handleAdd");
+  let list = await tableModelScene();
+  console.log("handleAdd", list);
   if (await tableModelScene({})) {
     console.log("刷新列表");
   }

+ 5 - 5
src/view/vrmodel/list.vue

@@ -35,10 +35,10 @@ defineProps<{ params: ReturnType<typeof useScenePaggingParams> }>();
 const headOptions = [
   { value: SceneType.SWKK, name: SceneTypeDesc[SceneType.SWKK] },
   { value: SceneType.SWKJ, name: SceneTypeDesc[SceneType.SWKJ] },
-  { value: SceneType.SWSS, name: SceneTypeDesc[SceneType.SWSS] },
-  { value: SceneType.SWSSMX, name: SceneTypeDesc[SceneType.SWSSMX] },
-  { value: SceneType.SWYDSS, name: SceneTypeDesc[SceneType.SWYDSS] },
-  { value: SceneType.SWYDMX, name: SceneTypeDesc[SceneType.SWYDMX] },
-  { value: SceneType.SWMX, name: SceneTypeDesc[SceneType.SWMX] },
+  // { value: SceneType.SWSS, name: SceneTypeDesc[SceneType.SWSS] },
+  // { value: SceneType.SWSSMX, name: SceneTypeDesc[SceneType.SWSSMX] },
+  // { value: SceneType.SWYDSS, name: SceneTypeDesc[SceneType.SWYDSS] },
+  // { value: SceneType.SWYDMX, name: SceneTypeDesc[SceneType.SWYDMX] },
+  // { value: SceneType.SWMX, name: SceneTypeDesc[SceneType.SWMX] },
 ];
 </script>

+ 61 - 2
src/view/vrmodel/sceneContent.vue

@@ -6,10 +6,12 @@
   <el-table
     class="mybody-head"
     :data="pagging.state.table.rows"
+    ref="tableRef"
     tooltip-effect="dark"
     style="width: 100%;height: 250px;"
     :height="250"
     size="large"
+    @selection-change="changeSelection"
   >
     <!-- -1 计算失败  0 计算中 1 计算成功并可以外网访问,不能编辑 2计算成功只能内网,能编辑 -->
     <el-table-column type="selection" width="55" />
@@ -18,7 +20,7 @@
         {{ pagging.state.pag.size * (pagging.state.pag.currentPage - 1) + $index + 1 }}
       </div>
     </el-table-column> -->
-    <el-table-column label="场景标题11" prop="name"></el-table-column>
+    <el-table-column label="场景标题" prop="sceneName"></el-table-column>
     <el-table-column label="S/N码" prop="snCode"></el-table-column>
     <!-- <el-table-column label="浏览数量" prop="viewCount"></el-table-column> -->
     <el-table-column label="拍摄时间" prop="createTime" v-slot:default="{ row }">
@@ -96,7 +98,34 @@ import { QuoteSceneStatusDesc } from "@/constant/scene";
 import { OpenType, openSceneUrl } from "../case/help";
 import { confirm } from "@/helper/message";
 import { sceneDownload } from "./quisk";
-
+import { useScenePaggingParams } from "./pagging";
+import { QuiskExpose } from "@/helper/mount";
+import { onMounted, ref, watch, watchEffect } from "vue";
+import {
+  getCaseSceneList,
+  getCaseScenes,
+  getSceneKey,
+  replaceCaseScenes,
+} from "@/store/case";
+const params = useScenePaggingParams();
+const tableRef = ref(null);
+const caseScenes = ref([
+  {
+    type: 0,
+    numList: [],
+  },
+  {
+    type: 1,
+    numList: [],
+  }
+]);
+const submit = () => {
+    // replaceCaseScenes(props.caseId, caseScenes.value)
+    console.log("submit", caseScenes.value);
+  }
+defineExpose<QuiskExpose>({
+  submit
+});
 const props = defineProps<{ pagging: ScenePagging }>();
 const delSceneHandler = async (scene: QuoteScene) => {
   if (await confirm("确定要删除当前场景吗?")) {
@@ -104,6 +133,36 @@ const delSceneHandler = async (scene: QuoteScene) => {
     props.pagging.refresh();
   }
 };
+// 复选框同步
+watchEffect(() => {
+  if (!tableRef.value) return;
+  const selectKeys = caseScenes.value.find(
+    (item) => item.type === params.pagging.state.query.type
+  )!.numList;
+
+  params.pagging.state.table.rows.forEach((scene) => {
+    tableRef.value!.toggleRowSelection(scene, selectKeys.includes(getSceneKey(scene)));
+  });
+});
+const changeSelection = (selectScenes) => {
+  if (params.pagging.loading) return;
+  const pagScenes = params.pagging.state.table.rows;
+  const type = params.pagging.state.query.sceneType;
+  console.log('changeSelection', params, type);
+  const typeCaseScenes = caseScenes.value.find((item) => item.type == type)!;
+  const oldKeys = caseScenes.value.find((item) => item.type == type)!.numList;
+  const pagKeys = pagScenes.map(getSceneKey);
+  const selectKeys = selectScenes.map(getSceneKey);
+  console.log('changeSelection', oldKeys, pagKeys, selectKeys);
+  let newlist = oldKeys
+    // 保留其他页的key,剔除当前页的key
+    .filter((key) => !pagKeys.includes(key))
+    // 拼接上当前页选中的key
+    .concat(selectKeys);
+  typeCaseScenes.numList = [...new Set(newlist)];
+  console.log('changeSelection', selectScenes, caseScenes.value);
+
+};
 const sceneDownloadHandler = (scene: QuoteScene) => {
   sceneDownload({ scene });
 };

+ 15 - 5
src/view/vrmodel/tableModel.vue

@@ -4,7 +4,7 @@
       <el-form-item label="场景名称:" style="width: 250px">
         <el-input v-model="params.keyword" placeholder="请输入"></el-input>
       </el-form-item>
-      <el-form-item label="类型:" style="width: 250px">
+      <!-- <el-form-item label="类型:" style="width: 250px">
         <el-select
           v-model="params.pagging.state.query.sceneType"
           placeholder="Select"
@@ -18,11 +18,10 @@
         :value="item.value"
       />
     </el-select>
-        <!-- <com-select v-model="params.pagging.state.query.deptId" /> -->
-      </el-form-item>
+      </el-form-item> -->
     </template>
     <template v-slot:content>
-      <component :is="component" :pagging="params.pagging" />
+      <component :is="component" :pagging="params.pagging" ref="contentRef" />
     </template>
   </List>
 </template>
@@ -33,7 +32,8 @@ import List from "./list.vue";
 import SceneContent from "./sceneContent.vue";
 import ModelContent from "./modelContent.vue";
 import { useScenePaggingParams } from "./pagging";
-import { computed } from "vue";
+import { QuiskExpose } from "@/helper/mount";
+import { computed, ref } from "vue";
 const options = [
   {
     value: '1',
@@ -46,5 +46,15 @@ const options = [
 ]
 
 const params = useScenePaggingParams();
+console.log('params.isSwmx', params.isSwmx, 'ModelContent');
 const component = computed(() => (params.isSwmx ? ModelContent : SceneContent));
+const  contentRef = ref(null);
+const submit = async () => {
+    // replaceCaseScenes(props.caseId, caseScenes.value)
+    await contentRef.value?.submit()
+    // console.log("submit", caseScenes.value);
+  }
+defineExpose<QuiskExpose>({
+  submit
+});
 </script>

+ 3 - 3
vite.config.ts

@@ -46,12 +46,12 @@ export default defineConfig({
     host: "0.0.0.0",
     proxy: {
       "/api": {
-        target: dev ? "http://test-mix3d.4dkankan.com" : "mix3d.4dkankan.com",
+        target: dev ? "http://192.168.0.25" : "mix3d.4dkankan.com",
         changeOrigin: true,
         rewrite: (path) => path.replace(new RegExp(`^/api`), ""),
       },
       "/fusion": {
-        target: dev ? "https://test-mix3d.4dkankan.com" : "mix3d.4dkankan.com",
+        target: dev ? "http://192.168.0.25" : "mix3d.4dkankan.com",
         changeOrigin: true,
         rewrite: (path) => path.replace(new RegExp(`^/api`), "/fusion"),
       },
@@ -70,7 +70,7 @@ export default defineConfig({
         rewrite: (path) => path.replace(new RegExp(`^/swkk`), ""),
       },
       "/service": {
-        target: dev ? "https://test.4dkankan.com" : "https://www.4dkankan.com",
+        target: dev ? "http://192.168.0.25" : "https://www.4dkankan.com",
         changeOrigin: true,
       },
       "/swss": {

+ 12 - 0
yarn.lock

@@ -297,6 +297,11 @@
   resolved "https://mirrors.cloud.tencent.com/npm/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz#a7f69e3665d3da9b115f9e71671dae1b97e13671"
   integrity sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==
 
+"@province-city-china/types@8.5.8":
+  version "8.5.8"
+  resolved "https://mirrors.cloud.tencent.com/npm/@province-city-china/types/-/types-8.5.8.tgz#bc75b8a6f25652987adab3a518ece7a2cf96cf4d"
+  integrity sha512-KZ3NyM8HsaBVcn5BRhWaOeZRhqEvm18PfB6HfRDuZfwwWhJLoTxB81mTENrBlONr2g8fy/fSbjsh44gvOj+/Lw==
+
 "@rollup/pluginutils@^5.0.2", "@rollup/pluginutils@^5.1.2":
   version "5.1.3"
   resolved "https://mirrors.cloud.tencent.com/npm/@rollup/pluginutils/-/pluginutils-5.1.3.tgz#3001bf1a03f3ad24457591f2c259c8e514e0dbdf"
@@ -1071,6 +1076,13 @@ postcss@^8.4.27, postcss@^8.4.48:
     picocolors "^1.1.1"
     source-map-js "^1.2.1"
 
+province-city-china@^8.5.8:
+  version "8.5.8"
+  resolved "https://mirrors.cloud.tencent.com/npm/province-city-china/-/province-city-china-8.5.8.tgz#b1f28cfe917388e67684cfb64f7cf2a5c30ed44a"
+  integrity sha512-gUV5kSOWHVufemkq6lygb0ngNZ4snMcONmr3QzxHuj1MYOQPphiyjHplfmywcVGWdGQgim30RXia/mYB007eLg==
+  dependencies:
+    "@province-city-china/types" "8.5.8"
+
 proxy-from-env@^1.1.0:
   version "1.1.0"
   resolved "https://mirrors.cloud.tencent.com/npm/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"