فهرست منبع

fix: 修改需求

bill 2 سال پیش
والد
کامیت
8fc5268f05

+ 1 - 1
config.js

@@ -1,3 +1,3 @@
 export default {
-  dev: false
+  dev: true
 }

+ 2 - 0
src/api/constant.ts

@@ -13,6 +13,8 @@ export const UPLOAD_HEADS = {
 }
 
 export const CASE_INFO = `/fusion/case/getInfo`
+// 校验密码
+export const AUTH_PWD = `/fusion/web/fireProject/getDetailWithoutAuth`
 
 // 融合模型列表
 export const FUSE_MODEL_LIST = `/fusion/caseFusion/list`

+ 2 - 2
src/api/instance.ts

@@ -25,8 +25,8 @@ export const {
 } = instance
 
 const gotoLogin = () => {
-  const loginHref = import.meta.env.DEV ? 'http://localhost:3000' : '/'
-  location.href = loginHref + '?redirect=' + escape(location.href) + '#/login'
+  // const loginHref = import.meta.env.DEV ? 'http://localhost:5174' : '/'
+  // location.href = loginHref + '?redirect=' + escape(location.href) + '#/login'
 }
 
 addReqErrorHandler(err => {

+ 57 - 18
src/api/sys.ts

@@ -1,30 +1,69 @@
-import { UPLOAD_FILE, UPLOAD_HEADS, CASE_INFO } from './constant'
-import { axios } from './instance'
-import { jsonToForm } from '@/utils'
-import { params } from '@/env'
+import { UPLOAD_FILE, UPLOAD_HEADS, CASE_INFO, AUTH_PWD } from "./constant";
+import { axios } from "./instance";
+import { jsonToForm } from "@/utils";
+import { params } from "@/env";
 
-type UploadFile = LocalFile | string
+type UploadFile = LocalFile | string;
 
-export const blobToFile = (blob: Blob, suffix = '.png') => new File([blob], `aaa${suffix}`)
+export const blobToFile = (blob: Blob, suffix = ".png") =>
+  new File([blob], `aaa${suffix}`);
 
-export const uploadFile = async (file: UploadFile, suffix = '.png') => {
-  if (typeof file === 'string') {
-    return file
+export const uploadFile = async (file: UploadFile, suffix = ".png") => {
+  if (typeof file === "string") {
+    return file;
   } else {
-    const uploadFile = file.blob instanceof File ? file.blob : blobToFile(file.blob, suffix)
+    const uploadFile =
+      file.blob instanceof File ? file.blob : blobToFile(file.blob, suffix);
     const url = await axios<string>({
-      method: 'POST',
-      url: UPLOAD_FILE, 
+      method: "POST",
+      url: UPLOAD_FILE,
       data: jsonToForm({ file: uploadFile }),
-      headers: {...UPLOAD_HEADS}
-    })
-    return url
+      headers: { ...UPLOAD_HEADS },
+    });
+    return url;
   }
+};
+
+export enum FireStatus {
+  incomplete = 0,
+  complete = 1,
 }
 
+export type FireProject = {
+  accidentDate: string;
+  createTime: string;
+  creatorDeptId: string;
+  caseId: number;
+  creatorId: string;
+  creatorName: string;
+  deptId: string;
+  editTime: string;
+  editorId: string;
+  editorName: string;
+  fireReason: string;
+  id: string;
+  isTeached: number;
+  organizerDeptName: string;
+  organizerUsers: string;
+  projectAddress: string;
+  projectName: string;
+  projectSite: string;
+  projectSiteCode: string;
+  projectSn: string;
+  status: FireStatus;
+  statusDesc: string;
+  updateTime: string;
+  isDelete?: number;
+};
+
 export interface Case {
-  caseTitle: string	
+  caseTitle: string;
+  tmProject?: FireProject;
 }
 
-export const getCaseInfo = () => 
-  axios.get<Case>(CASE_INFO, { params: { caseId: params.caseId } })
+export const getCaseInfo = () =>
+  axios.get<Case>(CASE_INFO, { params: { caseId: params.caseId } });
+
+// 校验密码
+export const authSharePassword = (randCode: string) =>
+  axios<boolean>(AUTH_PWD, { params: { randCode, caseId: params.caseId } });

+ 33 - 19
src/app.vue

@@ -14,29 +14,50 @@
       </router-view>
     </div>
   </ui-editor-layout>
+
+
+  <PwdModel v-if="inputPwd" @close="inputPwd = false" />
 </template>
 
 <script lang="ts" setup>
-import { custom } from '@/env'
-import { computed, ref, watchEffect } from 'vue'
-import { isEdit, prefix, appEl, initialSetting } from '@/store'
-import { getCaseInfo } from '@/api'
+import { custom, params } from '@/env'
+import { computed, ref, watch, watchEffect } from 'vue'
+import { isEdit, prefix, appEl, initialSetting, caseProject, refreshCase } from '@/store'
 import { currentLayout, RoutesName } from './router';
 import { loadPack } from '@/utils'
+import PwdModel from '@/layout/pwd.vue'
 
 const loaded = ref(false)
+const inputPwd = ref(false)
+const stopWatch = watch(currentLayout, async (layout) => {
+  if (!layout) {
+    return;
+  } else if (layout === RoutesName.signModel) {
+    loaded.value = true;
+    return;
+  }
 
-watchEffect(() => {
-  if (currentLayout.value && currentLayout.value !== RoutesName.signModel) {
-    loadPack(async () => {
-      await initialSetting()
-      loaded.value = true
+  // 单页面 非自己查看需要密码校验
+  if (currentLayout.value === RoutesName.show && !params.share) {
+    inputPwd.value = true
+    await new Promise<void>(resolve => {
+      const stopInputWatch = watchEffect(() => {
+        if (!inputPwd.value) {
+          stopInputWatch()
+          resolve()
+        }
+      })
     })
-  } else {
-    loaded.value = true
   }
-})
 
+  params.share = true
+  await loadPack(initialSetting)
+  await refreshCase()
+  console.log(caseProject.value)
+  prefix.value = caseProject.value!.caseTitle
+  loaded.value = true
+  stopWatch()
+}, { immediate: true })
 
 const layoutClassNames = computed(() => {
   return {
@@ -58,13 +79,6 @@ const layoutStyles = computed(() => {
 
   return styles
 })
-
-watchEffect(() => {
-  if (currentLayout.value && currentLayout.value !== RoutesName.signModel) {
-    getCaseInfo().then(ecase => prefix.value = ecase.caseTitle)  
-  }
-})
-
 </script>
 
 <style scoped lang="scss">

+ 12 - 0
src/assets/style/criminal.less

@@ -0,0 +1,12 @@
+.ant-modal-root {
+  @import 'ant-design-vue/dist/antd.less';
+  @primary-color: #26559B;
+  @menu-item-active-bg: #E6F7FF;
+  @table-selected-row-bg: #E6F7FF;
+  // .ant-table-tbody > tr.ant-table-row-selected > td {
+  //   background: none;
+  // }
+  .model-header .header-desc span {
+    color: @primary-color;
+  }
+}

+ 12 - 0
src/assets/style/fire.less

@@ -0,0 +1,12 @@
+.ant-modal-root {
+  @import 'ant-design-vue/dist/antd.less';
+  @primary-color: #D8000A;
+  @menu-item-active-bg: #E6F7FF;
+  @table-selected-row-bg: #E6F7FF;
+  // .ant-table-tbody > tr.ant-table-row-selected > td {
+  //   background: none;
+  // }
+  .model-header .header-desc span {
+    color: @primary-color;
+  }
+}

+ 8 - 3
src/env/index.ts

@@ -1,5 +1,5 @@
 import { stackFactory, flatStacksValue, strToParams } from '@/utils'
-import { ref } from 'vue'
+import { reactive, ref } from 'vue'
 
 import type { FuseModel, TaggingPosition, View } from '@/store'
 
@@ -40,15 +40,20 @@ export const custom = flatStacksValue({
 })
 
 
-export const params = strToParams(location.search) as unknown as Params
+export const params = reactive(strToParams(location.search)) as unknown as Params
 params.caseId = Number(params.caseId)
 params.share = Boolean(Number(params.share))
+export enum appType {
+  fire = "1",
+  criminal = "2"
+}
 export type Params = { 
   caseId: number,
   baseURL?: string,
   modelId?: string,
   m?: string
-  share: boolean,
+  share?: boolean,
+  app: appType
   token?: string
 }
 

+ 2 - 14
src/layout/edit/scene-select.vue

@@ -146,20 +146,8 @@ watch(visible, (visible, oldvisible) => {
 </style>
 
 <style lang="less">
-.ant-modal-root {
-  @import 'ant-design-vue/dist/antd.less'; // 引入官方提供的 less 样式入口文件
-  @primary-color: #26559B;
-  @menu-item-active-bg: #E6F7FF;
-  @table-selected-row-bg: #E6F7FF;
-  // .ant-table-tbody > tr.ant-table-row-selected > td {
-  //   background: none;
-  // }
-  .model-header .header-desc {
-    margin-bottom: 0;
-  }
-  .model-header .header-desc span {
-    color: @primary-color;
-  }
+.model-header .header-desc {
+  margin-bottom: 0;
 }
 .ant-modal-root .ant-table-tbody > tr > td {
   word-break: break-all;

+ 37 - 0
src/layout/pwd.vue

@@ -0,0 +1,37 @@
+<template>
+  <Modal width="400px" title="三维融合平台" :visible="visible" centered class="model-table">
+    <template #footer>
+      <Button key="submit" type="primary" @click="okHandler">确定</Button>
+    </template>
+    <FormItem label="访问密码" name="password">
+      <InputPassword v-model:value="password" />
+    </FormItem>
+  </Modal>
+</template>
+
+<script lang="ts" setup>
+import { Modal, FormItem, InputPassword, Button } from 'ant-design-vue'
+import { createLoadPack } from '@/utils'
+import { ref } from 'vue';
+import { authSharePassword } from '@/api';
+import { Message } from 'bill/index'
+
+const visible = ref(true)
+const password = ref('')
+
+const emit = defineEmits<{ (e: 'close'): void }>()
+
+const okHandler = createLoadPack(async () => {
+  if (!password.value) {
+    Message.error("请输入密码!")
+    return;
+  }
+
+  const pass = await authSharePassword(password.value)
+  if (pass) {
+    emit('close')
+  } else {
+    Message.error("密码错误,请重新输入。")
+  }
+})
+</script>

+ 1 - 0
src/layout/show/index.vue

@@ -36,6 +36,7 @@ import {
   initialGuides
 } from '@/store'
 
+
 const loaded = ref(false)
 const initialSys = async () => {
   await Promise.all([

+ 8 - 0
src/layout/show/slide-menu.vue

@@ -17,6 +17,7 @@ import { views, records, floders } from '@/store';
 import { computed } from 'vue';
 
 import type { RouteRaw } from '@/router'
+import { appType, params } from '@/env';
 
 export type MenuItem = {
   name: RoutesName,
@@ -35,6 +36,13 @@ const items = computed(() => {
       ...metas[RoutesName.summaryShow]
     }
   ]
+  if (params.app === appType.fire) {
+    items.unshift({
+      name: RoutesName.fireInfo,
+      config: getRouteConfig(RoutesName.fireInfo),
+      ...metas[RoutesName.fireInfo]
+    }) 
+  }
 
   if (views.value.length) {
     items.push({

+ 14 - 6
src/main.ts

@@ -3,23 +3,31 @@ import './style.scss'
 import App from './app.vue'
 import Components from 'bill/index'
 import router from './router'
-import { params } from '@/env'
+import { appType, params } from '@/env'
 import { addHook, addUnsetTokenURLS, delHook, delUnsetTokenURLS } from '@/api'
 import { currentLayout, RoutesName } from './router';
 import * as URL from '@/api/constant'
 
+
 const app = createApp(App)
 app.use(Components)
 app.use(router)
 app.mount('#app')
 
+if (params.app === appType.fire) {
+  import('./assets/style/fire.less')
+} else {
+  import('./assets/style/criminal.less')
+}
 
 watchEffect((onCleanup) => {
   if ([RoutesName.show, RoutesName.signModel].includes(currentLayout.value!)) {
+
     const untokenURLS = params.share 
       ? [
           URL.FUSE_MODEL_LIST,
           URL.MODEL_LIST,
+          URL.GET_SETTING,
           URL.TAGGING_LIST,
           URL.TAGGING_POINT_LIST,
           URL.TAGGING_STYLE_LIST,
@@ -32,17 +40,17 @@ watchEffect((onCleanup) => {
           URL.FOLDER_TYPE_LIST,
           URL.FLODER_LIST,
           URL.MODEL_SIGN,
-          URL.CASE_INFO
+          URL.CASE_INFO,
+          URL.AUTH_PWD
         ]
-      : []
+      : [URL.AUTH_PWD]
       
     const apiHook = {
       before(config: any) {
-        const isShare = Number(params.share)
         if (config.headers) {
-          config.headers.share = isShare
+          config.headers.share = '1'
         } else {
-          config.headers = { share: isShare }
+          config.headers = { share: '1' }
         }
       }
     }

+ 5 - 0
src/router/config.ts

@@ -89,6 +89,11 @@ export const routes = [
         component: () => import('@/views/summary/index.vue')
       },
       {
+        path: paths[RoutesName.fireInfo],
+        name: RoutesName.fireInfo,
+        component: () => import('@/views/fire/index.vue')
+      },
+      {
         path: paths[RoutesName.viewShow],
         name: RoutesName.viewShow,
         component: () => import('@/views/view/show.vue')

+ 8 - 0
src/router/constant.ts

@@ -29,6 +29,8 @@ export enum RoutesName {
   recordShow = 'recordShow',
   viewShow = 'viewShow',
   folderShow = 'folderShow',
+  // 火调信息详情页
+  fireInfo = 'fireInfo',
 
 
   // 单模型展示
@@ -55,6 +57,7 @@ export const paths = {
   [RoutesName.view]: 'view',
 
   [RoutesName.show]: '/show',
+  [RoutesName.fireInfo]: 'fireInfo',
   [RoutesName.summaryShow]: 'summary',
   [RoutesName.recordShow]: 'record',
   [RoutesName.viewShow]: 'view',
@@ -101,6 +104,11 @@ export const metas = {
     title: '视图',
     
   },
+  [RoutesName.fireInfo]: {
+    icon: 'list-scene',
+    title: '案件信息',
+    
+  },
   [RoutesName.recordShow]: {
     icon: 'list-record',
     title: '录屏'

+ 7 - 0
src/store/case.ts

@@ -0,0 +1,7 @@
+import { Case, getCaseInfo } from "@/api"
+import { ref } from 'vue'
+
+export const caseProject = ref<Case>()
+export const refreshCase = () => {
+  return getCaseInfo().then(data => caseProject.value = data)
+}

+ 2 - 1
src/store/index.ts

@@ -12,4 +12,5 @@ export * from './view'
 export * from './record-fragment'
 export * from './floder'
 export * from './floder-type'
-export * from './setting'
+export * from './setting'
+export * from './case'

+ 1 - 1
src/store/sys.ts

@@ -134,4 +134,4 @@ export const autoSetModeCallback = <T extends object>(current: T, setting: AutoS
 export const useAutoSetMode = <T extends object>(current: T, setting: AutoSetModeSetting<T>) => {
   const startWatch = autoSetModeCallback(current, setting)
   useViewStack(startWatch)
-}
+}

+ 98 - 0
src/views/fire/index.vue

@@ -0,0 +1,98 @@
+<template>
+  <LeftPano>
+    <div class="info">
+      <h2>案件信息</h2>
+      <p>
+        <span>项目编号:</span>
+        {{ caseProject.tmProject.projectSn }}
+      </p>
+      <p>
+        <span>起火地址:</span>
+        {{ caseProject.tmProject.projectAddress }}
+      </p>
+      <p>
+        <span>起火场所:</span>
+        {{ caseProject.tmProject.projectSite }}
+      </p>
+      <p>
+        <span>承办单位:</span>
+        {{ caseProject.tmProject.organizerDeptName }}
+      </p>
+      <p>
+        <span>起火对象:</span>
+        {{ caseProject.tmProject.projectName }}
+      </p>
+      <p>
+        <span>事故日期:</span>
+        {{ caseProject.tmProject.accidentDate }}
+      </p>
+      <p>
+        <span>火灾原因:</span>
+        {{ caseProject.tmProject.fireReason }}
+      </p>
+      <p>
+        <span>项目状态:</span>
+        {{ caseProject.tmProject.statusDesc }}
+      </p>
+      <p>
+        <span>教学项目:</span>
+        {{ caseProject.tmProject.isTeached ? '是' : '否' }}
+      </p>
+      <p>
+        <span>创建人:</span>
+        {{ caseProject.tmProject.creatorName }}
+      </p>
+      <p>
+        <span>编辑人:</span>
+        {{ caseProject.tmProject.editorName }}
+      </p>
+      <p>
+        <span>创建时间:</span>
+        {{ caseProject.tmProject.createTime }}
+      </p>
+      <p>
+        <span>最新编辑:</span>
+        {{ caseProject.tmProject.editTime }}
+      </p>
+    </div>
+  </LeftPano>
+</template>
+
+
+<script setup lang="ts">
+import { LeftPano } from '@/layout'
+import { caseProject } from '@/store/case'
+
+
+</script>
+
+<style lang="scss" scoped>
+.info {
+  h2 {
+    padding: 20px;
+    font-weight: bold;
+    display: flex;
+    justify-content: space-between;
+    border-bottom: 1px solid rgba(255, 255, 255, 0.16);
+    align-items: center;
+    margin-bottom: 0;
+  }
+
+  p {
+    padding: 0 30px;
+    margin: 20px 0;
+    color: rgba(255, 255, 255, 1);
+    font-size: 14px;
+    display: flex;
+
+    span {
+      flex: none;
+      display: inline-block;
+      width: 70px;
+      height: 100%;
+      margin-right: 20px;
+      color: rgba(255, 255, 255, 0.70);
+    }
+  }
+}
+</style>

+ 1 - 1
vite.config.ts

@@ -64,7 +64,7 @@ export default defineConfig({
   },
   server: {
     host: '0.0.0.0',
-    port: 5173,
+    port: 7173,
     open: true,
     proxy: proxy,
     https: true