gemercheung 10 mēneši atpakaļ
vecāks
revīzija
1b9ad2a77c

+ 6 - 1
src/components/head/index.vue

@@ -48,7 +48,10 @@ const props = withDefaults(
 );
 
 const activeValue = ref(props.modelValue || props.options[0].value);
-const emit = defineEmits<{ (e: "update:modelValue", modelValue: string): void }>();
+const emit = defineEmits<{
+  (e: "update:modelValue", modelValue: string): void;
+}>();
+
 const updateModelValue = (modelValue: string) => {
   if ("modelValue" in props) {
     console.log(modelValue, props);
@@ -58,6 +61,8 @@ const updateModelValue = (modelValue: string) => {
   }
 };
 const show = ref(true);
+
+
 </script>
 
 <style lang="scss" scoped>

+ 1 - 1
src/components/pagination/index.vue

@@ -26,7 +26,7 @@
           :class="{ selected: num === currSize }"
           @click="clickHandle(num)"
         >
-          {{ num }}条/页
+          {{ num }} 条/页
         </li>
       </ul>
     </div>

+ 7 - 0
src/router/config.ts

@@ -91,6 +91,12 @@ export const routes: Routes = [
         component: () => import("@/view/statistics/index.vue"),
         meta: { title: "数据统计", icon: "iconfire_user" },
       },
+      {
+        name: RouteName.media,
+        path: "/media/:caseId",
+        component: () => import("@/view/media/index.vue"),
+        meta: { title: "媒体库" },
+      },
     ],
   },
   {
@@ -99,4 +105,5 @@ export const routes: Routes = [
     component: () => import("@/view/case/draw/index.vue"),
     meta: { title: "绘制卷宗图" },
   },
+ 
 ];

+ 1 - 0
src/router/routeName.ts

@@ -15,6 +15,7 @@ export const RouteName = {
   role: "role",
   sceneInitiator: "sceneInitiator",
   sceneVisitor: "sceneVisitor",
+  media: "media",
 } as const;
 
 type RouteNamesType = typeof RouteName;

+ 226 - 0
src/view/case/caseFile copy.vue

@@ -0,0 +1,226 @@
+<template>
+  <com-head
+    :options="options"
+    v-model="currentTypeId"
+    notContent
+    v-if="options.length"
+  />
+
+  <div class="body-layer">
+    <template v-if="currentTypeId === 2">
+      <Photos :caseId="caseId" :title="caseInfoData.caseTitle" />
+    </template>
+    <template v-else-if="currentTypeId === 3">
+      <Records :caseId="caseId" :title="caseInfoData.caseTitle" />
+    </template>
+    <template v-else-if="currentTypeId === 4">
+      <Manifest :caseId="caseId" :title="caseInfoData.caseTitle" />
+    </template>
+    <template v-else>
+      <div class="body-head">
+        <h3 style="visibility: hidden">场景管理</h3>
+        <div>
+          <template v-if="isDraw">
+            <el-button type="primary" @click="gotoDraw(BoardType.map, -1)">
+              创建{{ BoardTypeDesc[BoardType.map] }}
+            </el-button>
+            <el-button type="primary" @click="gotoDraw(BoardType.scene, -1)">
+              创建{{ BoardTypeDesc[BoardType.scene] }}
+            </el-button>
+          </template>
+          <el-button type="primary" @click="addCaseFileHandler">
+            上传
+          </el-button>
+        </div>
+      </div>
+
+      <el-table
+        :data="files"
+        tooltip-effect="dark"
+        style="width: 100%"
+        size="large"
+      >
+        <el-table-column label="序号" width="70" v-slot:default="{ $index }">
+          <div style="text-align: center">
+            {{ $index + 1 }}
+          </div>
+        </el-table-column>
+        <el-table-column
+          label="名称"
+          v-slot:default="{ row }: { row: CaseFile }"
+        >
+          <span v-if="!inputCaseTitles.includes(row)">
+            {{ row.filesTitle }}
+            <el-icon class="edit-title" @click="inputCaseTitles.push(row)">
+              <EditPen />
+            </el-icon>
+          </span>
+          <template v-else>
+            <ElInput
+              v-model="row.filesTitle"
+              placeholder="请输入文件名"
+              focus
+              :maxlength="50"
+              style="width: 280px"
+            >
+              <template #append>
+                <el-button type="primary" plain @click="updateFileTitle(row)">
+                  确定
+                </el-button>
+              </template>
+            </ElInput>
+          </template>
+        </el-table-column>
+        <el-table-column label="创建时间" prop="createTime"></el-table-column>
+        <el-table-column
+          label="操作"
+          v-slot:default="{ row }: { row: CaseFile }"
+        >
+          <span class="oper-span" @click="query(row)"> 查看 </span>
+          <span
+            class="oper-span"
+            @click="gotoDraw(row.imgType!, row.filesId)"
+            v-if="row.imgType !== null"
+          >
+            编辑
+          </span>
+          <span class="oper-span delBtn" @click="del(row)"> 删除 </span>
+        </el-table-column>
+      </el-table>
+    </template>
+  </div>
+</template>
+
+<script setup lang="ts">
+import comHead from "@/components/head/index.vue";
+import { confirm } from "@/helper/message";
+import { RouteName, router } from "@/router";
+import { FileDrawType, BoardTypeDesc } from "@/constant/caseFile";
+import { computed, onMounted, onUnmounted, ref, watchEffect } from "vue";
+import { addCaseFile } from "./quisk";
+import { title, desc } from "@/store/system";
+import {
+  CaseFile,
+  CaseFileType,
+  getCaseFileTypes,
+  getCaseFiles,
+  delCaseFile,
+  BoardType,
+} from "@/store/caseFile";
+import { getCaseInfo, updateCaseInfo } from "@/store/case";
+import { appConstant } from "@/app";
+import { ElIcon, ElInput, ElMessage } from "element-plus";
+import Photos from "./photos/index.vue";
+import Records from "./records/index.vue";
+import Manifest from "./records/manifest.vue";
+
+const caseId = computed(() => {
+  const caseId = router.currentRoute.value.params.caseId;
+  if (caseId) {
+    return Number(caseId);
+  }
+});
+const caseInfoData = ref<any>();
+
+const inputCaseTitles = ref<CaseFile[]>([]);
+
+const updateFileTitle = async (caseFile: CaseFile) => {
+  if (!caseFile.filesTitle.trim()) {
+    return ElMessage.error("卷宗标题不能为空!");
+  }
+  await updateCaseInfo(caseFile);
+  inputCaseTitles.value = inputCaseTitles.value.filter(
+    (item) => item !== caseFile
+  );
+};
+
+const currentTypeId = ref<number>();
+const types = ref<CaseFileType[]>([]);
+const options = computed(() =>
+  types.value.map((item) => ({
+    name: item.filesTypeName,
+    value: item.filesTypeId,
+  }))
+);
+const isDraw = computed(() => currentTypeId.value === FileDrawType);
+
+const files = ref<CaseFile[]>([]);
+const refresh = async () => {
+  files.value = await getCaseFiles({
+    caseId: caseId.value!,
+    filesTypeId: currentTypeId.value,
+  });
+};
+watchEffect(() => caseId.value && currentTypeId.value && refresh());
+
+const query = (file: CaseFile) => {
+  const ext = file.filesUrl
+    .substring(file.filesUrl.lastIndexOf("."))
+    .toLocaleLowerCase();
+  if ([".raw", ".dcm"].includes(ext)) {
+    window.open(
+      `/xfile-viewer/index.html?file=${file.filesUrl}&name=${file.filesTitle}&time=` +
+        Date.now()
+    );
+  } else {
+    window.open(file.filesUrl + "?time=" + Date.now());
+  }
+};
+const del = async (file: CaseFile) => {
+  if (await confirm("确定要删除此数据?")) {
+    await delCaseFile({ caseId: caseId.value!, filesId: file.filesId });
+    refresh();
+  }
+};
+
+const addCaseFileHandler = async () => {
+  await addCaseFile({ caseId: caseId.value!, fileType: currentTypeId.value! });
+  refresh();
+};
+
+const gotoDraw = (type: BoardType, id: number) => {
+  router.push({
+    name: RouteName.drawCaseFile,
+    params: { caseId: caseId.value!, type, id },
+  });
+};
+
+onMounted(async () => {
+  try {
+    types.value = await getCaseFileTypes();
+    currentTypeId.value = types.value[0].filesTypeId;
+    const caseInfo = await getCaseInfo(caseId.value!);
+    if (caseInfo) {
+      caseInfoData.value = caseInfo;
+      title.value =
+        (await getCaseInfo(caseId.value!)).caseTitle + " | 卷宗管理";
+      desc.value = "";
+    } else {
+      console.error("该案件不存在!");
+      throw "该案件不存在!";
+    }
+  } catch (error) {
+    console.error("该案件不存在!");
+    // debugger;
+    //TODO 由于没有登录状态可以判断或hook插入,只能延时进入no-case router当前的router
+    setTimeout(() => {
+      console.log("current-router", router.currentRoute.value.name);
+      if (router.currentRoute.value.name !== "login") {
+        router.replace({ name: RouteName.noCase });
+      }
+    }, 1000);
+  }
+});
+
+onUnmounted(() => {
+  title.value = appConstant.title;
+  desc.value = appConstant.desc;
+});
+</script>
+
+<style scoped lang="scss">
+.edit-title {
+  cursor: pointer;
+  margin-left: 10px;
+}
+</style>

+ 9 - 0
src/view/case/editMenu.vue

@@ -105,6 +105,15 @@ const menus = computed(() => {
         }
       },
     },
+    {
+      key: "file",
+      label: "媒体库",
+      onClick: () => {
+        window.open(
+          router.resolve({ name: RouteName.media, params: { caseId: caseId } }).href
+        );
+      },
+    },
     ...(props.lastMenu || []).map((item) => ({
       ...item,
       onClick: () => item.onClick(caseId),

+ 48 - 0
src/view/media/index.scss

@@ -0,0 +1,48 @@
+.media {
+  .sub-tab {
+    width: 100%;
+    :deep(.el-tabs__nav-wrap:after) {
+      height: 0;
+    }
+    :deep(.el-tabs__active-bar) {
+      height: 0;
+    }
+  }
+  .media-head {
+    position: relative;
+    .btn {
+      position: absolute;
+      right: 10px;
+      top: 8px;
+      z-index: 100;
+    }
+  }
+
+  .media-list {
+    display: flex;
+    width: 100%;
+    padding: 30px 0;
+    flex-direction: row;
+    flex-wrap: wrap;
+    justify-content: space-evenly;
+    align-items: center;
+    gap: 30px;
+    .cover {
+      display: flex;
+      width: 300px;
+      height: 235px;
+      justify-content: center;
+      flex-direction: column;
+      &:hover {
+        cursor: pointer;
+      }
+      .title {
+        text-align: center;
+        line-height: 48px;
+      }
+      img {
+        object-fit: scale-down;
+      }
+    }
+  }
+}

+ 77 - 0
src/view/media/index.vue

@@ -0,0 +1,77 @@
+<template>
+  <com-head
+    :options="options"
+    v-model="currentTypeId"
+    notContent
+    v-if="options.length"
+  />
+
+  <div class="body-layer media">
+    <div class="body-head media-head">
+      <el-button type="primary" class="btn" @click="handleUploadClick">
+        上传
+      </el-button>
+
+      <el-tabs
+        v-model="subTabName"
+        class="sub-tab"
+        @tab-click="handleSubtabClick"
+      >
+        <el-tab-pane
+          v-for="sub in subOptions"
+          :label="sub.name"
+          :name="sub.value"
+        >
+          <div class="media-list">
+            <div v-for="i in 40" class="cover" @click="handerPhotoEdit">
+              <img src="https://placehold.co/600x400" />
+              <span class="title">{{ i }}.jpg</span>
+            </div>
+          </div>
+        </el-tab-pane>
+      </el-tabs>
+    </div>
+  </div>
+</template>
+<script setup lang="ts">
+import { onMounted, ref } from "vue";
+import comHead from "@/components/head/index.vue";
+import { title, desc } from "@/store/system";
+
+const currentTypeId = ref<number>(1);
+const options = ref([
+  { name: "现场照片", value: 1 },
+  { name: "痕迹物证", value: 2 },
+]);
+const subOptions = ref([
+  { name: "方位照片", value: 1 },
+  { name: "中心现场", value: 2 },
+  { name: "概貌照片", value: 3 },
+  { name: "细目照片", value: 4 },
+  { name: "重点部位", value: 5 },
+  { name: "尸体照片", value: 6 },
+  { name: "关联现场", value: 7 },
+  { name: "其他", value: 8 },
+]);
+
+const subTabName = ref(1);
+
+const handleSubtabClick = () => {};
+const handleUploadClick = () => {
+  console.log("handleUploadClick");
+};
+
+const handerPhotoEdit = () => {
+  console.log("handerPhotoEdit");
+  
+};
+
+onMounted(async () => {
+  title.value = " xxxx | 媒体库";
+  desc.value = "";
+});
+</script>
+
+<style lang="scss" scoped>
+@import url("./index.scss");
+</style>