From 59569559a1d90d7a4340e5474346353fb823a0c1 Mon Sep 17 00:00:00 2001
From: dongyukun <1208714201@qq.com>
Date: 星期五, 15 十一月 2024 17:01:00 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'

---
 src/views/data/video/nvr/index.vue             |  187 ++--
 src/api/data/plan/item/index.ts                |    2 
 src/views/data/video/nvr/NvrCamera.vue         |  174 ++--
 types/env.d.ts                                 |    1 
 src/views/bpm/model/index.vue                  |   17 
 src/api/data/video/image/index.ts              |   50 +
 src/views/Home/Index.vue                       |   29 
 src/api/model/mcs/index.ts                     |    5 
 src/utils/is.ts                                |    3 
 src/views/model/pre/analysis/index.vue         | 1099 ++++++++++++++++---------------
 src/views/model/pre/item/MmPredictItemForm.vue |   24 
 /dev/null                                      |   28 
 src/views/Login/components/LoginForm.vue       |   32 
 src/views/data/video/camera/index.vue          |  197 +++--
 src/utils/hostMap.ts                           |    2 
 src/api/model/sche/model/index.ts              |   21 
 src/views/data/video/camera/CameraImage.vue    |  114 +++
 17 files changed, 1,113 insertions(+), 872 deletions(-)

diff --git a/src/api/data/plan/item/index.ts b/src/api/data/plan/item/index.ts
index e42e999..eec13e9 100644
--- a/src/api/data/plan/item/index.ts
+++ b/src/api/data/plan/item/index.ts
@@ -50,7 +50,7 @@
 
 //获取下拉集合
 export const getItemList = (params: PageParam) => {
-  return request.get({ url: '/data/plan-item/getList', params})
+  return request.get({ url: '/data/plan-item/list', params})
 }
 
 // 查询Plan图表
diff --git a/src/api/data/video/image/index.ts b/src/api/data/video/image/index.ts
new file mode 100644
index 0000000..d2d5f7a
--- /dev/null
+++ b/src/api/data/video/image/index.ts
@@ -0,0 +1,50 @@
+import request from '@/config/axios'
+
+export interface ImageVO {
+  id: undefined,
+  cameraId: string,
+  imagePath: string,
+  imageUrl: string,
+  createDate: undefined,
+}
+
+// 查询列表
+export const getImagePage = (params: PageParam) => {
+  return request.get({url: '/data/video/image/page', params})
+}
+
+// 获得
+export const getImage = (id: number) => {
+  return request.get({url: '/data/video/image/get?id=' + id})
+}
+
+// 查询应用列表
+export const getImageList = () => {
+  return request.get({url: '/data/video/image/list'})
+}
+
+// 新增
+export const createImage = (data: ImageVO) => {
+  return request.post({url: '/data/video/image/create', data})
+}
+
+// 修改
+export const updateImage = (data: ImageVO) => {
+  return request.put({url: '/data/video/image/update', data})
+}
+
+// 删除
+export const deleteImage = (id: number) => {
+  return request.delete({url: '/data/video/image/delete?id=' + id})
+}
+
+// 导出
+export const exportImage = (params: ImageVO) => {
+  return request.download({url: '/data/video/image/export-excel', params})
+}
+
+//预览摄像头截图
+export const getPreviewUrl = (url: string) => {
+  const host = import.meta.env.VITE_VIDEO_CAMERA_DOMAIN ? import.meta.env.VITE_VIDEO_CAMERA_DOMAIN : window.location.host
+  return `http://${host}:8899` + url
+}
diff --git a/src/api/model/mcs/index.ts b/src/api/model/mcs/index.ts
index 2cdaef3..4f55207 100644
--- a/src/api/model/mcs/index.ts
+++ b/src/api/model/mcs/index.ts
@@ -1,7 +1,7 @@
 import request from '@/config/axios'
 
 export interface PreDataBarLineReqVO {
-  queryIds: string[],
+  outIds: string[],
   predictTime: string,
   startTime: string,
   endTime: string
@@ -13,6 +13,9 @@
   endTime: string
 }
 
+export const getPredictItemTree = () => {
+  return request.get({ url: '/model/api/mcs/predict-item/tree'})
+}
 
 export const getPreDataCharts = (data: PreDataBarLineReqVO) => {
   return request.post({ url: '/model/api/mcs/predict-data/charts', data })
diff --git a/src/api/model/sche/model/index.ts b/src/api/model/sche/model/index.ts
index 3c5b8bc..8863d31 100644
--- a/src/api/model/sche/model/index.ts
+++ b/src/api/model/sche/model/index.ts
@@ -1,7 +1,9 @@
 import request from '@/config/axios'
 import * as DataPointApi from '@/api/data/da/point'
 import * as PredictItemApi from '@/api/model/pre/item'
+import * as PlanItemApi from '@/api/data/plan/item'
 import {CommonEnabled} from "@/utils/constants";
+import {getItemList, ItemVO} from "@/api/data/plan/item";
 
 export interface ScheduleModelVO {
   id: string
@@ -100,8 +102,25 @@
       )
     })
   }
+
+  const planItemList = ref([] as PlanItemApi.ItemVO)
+  planItemList.value = await PlanItemApi.getItemList({
+  })
+  const planList = []
+  if (planItemList.value) {
+    planItemList.value.forEach(item => {
+      planList.push(
+        {
+          id: item.id,
+          name:  item.itemName
+        }
+      )
+    })
+  }
+
   return {
     'DATAPOINT':pointList,
-    'PREDICTITEM': itemList
+    'PREDICTITEM': itemList,
+    'PLAN': planList,
   }
 }
diff --git a/src/utils/hostMap.ts b/src/utils/hostMap.ts
index 81df37d..c2904af 100644
--- a/src/utils/hostMap.ts
+++ b/src/utils/hostMap.ts
@@ -1,6 +1,6 @@
 const map = {
   "//localhost:7200/": "//wujie-micro.github.io/demo-vue2/",
-  "//localhost:90/": "//localhost:90/",
+  "//localhost:9000/": "//localhost:9000/",
   "//localhost:8000/": "//wujie-micro.github.io/demo-main-vue/",
 };
 
diff --git a/src/utils/is.ts b/src/utils/is.ts
index eec86a9..39812b6 100644
--- a/src/utils/is.ts
+++ b/src/utils/is.ts
@@ -98,8 +98,9 @@
 export const isClient = !isServer
 
 export const isUrl = (path: string): boolean => {
+  // fix:修复hash路由无法跳转的问题
   const reg =
-    /(((^https?:(?:\/\/)?)(?:[-:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&%@.\w_]*)#?(?:[\w]*))?)$/
+    /(((^https?:(?:\/\/)?)(?:[-:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%#\/.\w-_]*)?\??(?:[-\+=&%@.\w_]*)#?(?:[\w]*))?)$/
   return reg.test(path)
 }
 
diff --git a/src/views/Home/Index.vue b/src/views/Home/Index.vue
index aa64a85..822f800 100644
--- a/src/views/Home/Index.vue
+++ b/src/views/Home/Index.vue
@@ -5,9 +5,9 @@
   <el-skeleton :loading="loading" animated>
     <div id="app" v-for="(item, index) in appList" :key="`dynamics-${index}`">
       <div class="card" @click="gotoApp(item)">
-        <img :src="item.icon" style="width: 100px; height: 100px" />
+        <img :src="item.icon" style="width: 100px; height: 100px"/>
         <div>
-          {{item.appName}}
+          {{ item.appName }}
         </div>
       </div>
     </div>
@@ -19,12 +19,11 @@
 import * as AppApi from '@/api/system/app'
 import {Apps} from "@/views/Home/types";
 import {CACHE_KEY, useCache} from "@/hooks/web/useCache";
-import * as authUtil from "@/utils/auth";
 
 
-defineOptions({ name: 'Home' })
+defineOptions({name: 'Home'})
 
-const { wsCache } = useCache()
+const {wsCache} = useCache()
 
 const loading = ref(true)
 
@@ -35,7 +34,7 @@
   appList = Object.assign(appList, data)
 }
 
-const getAppMenuList = async (id) => {
+const getAppMenuList = async (id, appCode) => {
   const data = await AppApi.getAppMenuList(id)
   let userInfo = wsCache.get(CACHE_KEY.USER)
   userInfo.menus = data
@@ -55,32 +54,38 @@
 
 // 进入应用
 const gotoApp = async (item) => {
+  let path = window.location.pathname
+  let appName = path.split("/")[0]
+  console.log(appName)
   let id = item.id
   let type = item.type
-  if(type === 0) {
-    getAppMenuList(id)
+  let appCode = item.appCode
+  if (type === 0) {
+    await getAppMenuList(id, appCode)
   } else {
     const data = await AppApi.getAppMenuList(id)
     let userInfo = wsCache.get(CACHE_KEY.USER)
     userInfo.menus = data
     wsCache.set(CACHE_KEY.USER, userInfo)
     wsCache.set(CACHE_KEY.ROLE_ROUTERS, data)
-    // await OAuth2Login(formData.value)
-    // window.open(item.appDomain + '/login?appid=' + item.id + "&username=" + authUtil.getLoginForm().username, '_blank')
     window.open(item.appDomain + '/index', '_blank')
+    // window.open('/plat/shasteel', '_blank')
+    // window.location.href = '/plat/shasteel'
+    // window.location.href = `/plat/shasteel?key=energy&url=http://localhost:9000&energy=/energy/demo`
   }
 }
 
 </script>
 
 <style lang="scss" scoped>
-#app{
+#app {
   width: 300px;
   height: 200px;
   display: inline-block;
   background: transparent;
 }
-.card{
+
+.card {
   border: thin dashed gainsboro;
   width: 150px;
   height: 120px;
diff --git a/src/views/Login/components/LoginForm.vue b/src/views/Login/components/LoginForm.vue
index 22a80b2..bc3a32a 100644
--- a/src/views/Login/components/LoginForm.vue
+++ b/src/views/Login/components/LoginForm.vue
@@ -12,7 +12,7 @@
     <el-row style="margin-right: -10px; margin-left: -10px">
       <el-col :span="24" style="padding-right: 10px; padding-left: 10px">
         <el-form-item>
-          <LoginFormTitle style="width: 100%" />
+          <LoginFormTitle style="width: 100%"/>
         </el-form-item>
       </el-col>
       <el-col :span="24" style="padding-right: 10px; padding-left: 10px">
@@ -86,27 +86,27 @@
   </el-form>
 </template>
 <script lang="ts" setup>
-import { ElLoading } from 'element-plus'
+import {ElLoading} from 'element-plus'
 import LoginFormTitle from './LoginFormTitle.vue'
-import type { RouteLocationNormalizedLoaded } from 'vue-router'
+import type {RouteLocationNormalizedLoaded} from 'vue-router'
 
-import { useIcon } from '@/hooks/web/useIcon'
+import {useIcon} from '@/hooks/web/useIcon'
 
 import * as authUtil from '@/utils/auth'
-import { usePermissionStore } from '@/store/modules/permission'
+import {usePermissionStore} from '@/store/modules/permission'
 import * as LoginApi from '@/api/login'
-import { LoginStateEnum, useFormValid, useLoginState } from './useLogin'
+import {LoginStateEnum, useFormValid, useLoginState} from './useLogin'
 
-defineOptions({ name: 'LoginForm' })
+defineOptions({name: 'LoginForm'})
 
-const { t } = useI18n()
-const iconHouse = useIcon({ icon: 'ep:house' })
-const iconAvatar = useIcon({ icon: 'ep:avatar' })
-const iconLock = useIcon({ icon: 'ep:lock' })
+const {t} = useI18n()
+const iconHouse = useIcon({icon: 'ep:house'})
+const iconAvatar = useIcon({icon: 'ep:avatar'})
+const iconLock = useIcon({icon: 'ep:lock'})
 const formLogin = ref()
-const { validForm } = useFormValid(formLogin)
-const { getLoginState } = useLoginState()
-const { currentRoute, push } = useRouter()
+const {validForm} = useFormValid(formLogin)
+const {getLoginState} = useLoginState()
+const {currentRoute, push} = useRouter()
 const permissionStore = usePermissionStore()
 const redirect = ref<string>('')
 const loginLoading = ref(false)
@@ -199,14 +199,14 @@
       authUtil.removeLoginForm()
     }
     authUtil.setToken(res)
-    if (!redirect.value) {
+    if (!redirect.value || redirect.value == "/") {
       redirect.value = '/index'
     }
     // 判断是否为SSO登录
     if (redirect.value.indexOf('sso') !== -1) {
       window.location.href = window.location.href.replace('/login?redirect=', '')
     } else {
-      push({ path: redirect.value || permissionStore.addRouters[0].path })
+      push({path: redirect.value || permissionStore.addRouters[0].path})
     }
   } finally {
     loginLoading.value = false
diff --git a/src/views/bpm/model/index.vue b/src/views/bpm/model/index.vue
index f8b0b75..a20ea4e 100644
--- a/src/views/bpm/model/index.vue
+++ b/src/views/bpm/model/index.vue
@@ -163,14 +163,6 @@
           <el-button
             link
             type="primary"
-            @click="handleSimpleDesign(scope.row.id)"
-            v-hasPermi="['bpm:model:update']"
-          >
-            仿钉钉设计流程
-          </el-button>
-          <el-button
-            link
-            type="primary"
             @click="handleDeploy(scope.row)"
             v-hasPermi="['bpm:model:deploy']"
           >
@@ -328,15 +320,6 @@
 const handleDesign = (row) => {
   push({
     name: 'BpmModelEditor',
-    query: {
-      modelId: row.id
-    }
-  })
-}
-
-const handleSimpleDesign = (row) => {
-  push({
-    name: 'SimpleWorkflowDesignEditor',
     query: {
       modelId: row.id
     }
diff --git a/src/views/bpm/simpleWorkflow/index.vue b/src/views/bpm/simpleWorkflow/index.vue
deleted file mode 100644
index 144615e..0000000
--- a/src/views/bpm/simpleWorkflow/index.vue
+++ /dev/null
@@ -1,28 +0,0 @@
-<template>
-  <div>
-    <section class="dingflow-design">
-      <div class="box-scale">
-        <nodeWrap v-model:nodeConfig="nodeConfig" />
-        <div class="end-node">
-          <div class="end-node-circle"></div>
-          <div class="end-node-text">流程结束</div>
-        </div>
-      </div>
-    </section>
-  </div>
-</template>
-<script lang="ts" setup>
-import nodeWrap from '@/components/SimpleProcessDesigner/src/nodeWrap.vue'
-defineOptions({ name: 'SimpleWorkflowDesignEditor' })
-let nodeConfig = ref({
-  nodeName: '发起人',
-  type: 0,
-  id: 'root',
-  formPerms: {},
-  nodeUserList: [],
-  childNode: {}
-})
-</script>
-<style>
-@import url('@/components/SimpleProcessDesigner/theme/workflow.css');
-</style>
\ No newline at end of file
diff --git a/src/views/data/video/camera/CameraImage.vue b/src/views/data/video/camera/CameraImage.vue
new file mode 100644
index 0000000..335983b
--- /dev/null
+++ b/src/views/data/video/camera/CameraImage.vue
@@ -0,0 +1,114 @@
+<template>
+  <el-dialog v-model="dialogVisible" :title="dialogTitle" :close="handleClose"
+             style="width: 50%; margin-top: 20px; overflow: auto; z-index: 1">
+    <!-- 列表 -->
+    <el-table v-loading="loading" :data="list">
+      <el-table-column
+        label="截图时间"
+        align="center"
+        prop="createDate"
+        :formatter="dateFormatter"
+        width="200"
+      />
+      <el-table-column label="图片路径" align="center" prop="imagePath" width="500"
+                       :show-overflow-tooltip="true"/>
+      <el-table-column label="图片预览" align="center" prop="imageUrl">
+        <template #default="scope">
+          <el-image style="height: 50px; z-index: 1"
+                    :src="getPreviewUrl(scope.row.imageUrl)"
+                    :preview-src-list="getPreviewSrcList(scope.row.imageUrl)" fit="cover"
+                    preview-teleported/>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" min-width="60" fixed="right">
+        <template #default="scope">
+          <el-button
+            link
+            type="danger"
+            style="z-index: 1"
+            @click="handleDelete(scope.row.id)"
+            v-hasPermi="['video:camera:delete']"
+          >
+            删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="open"
+    />
+  </el-dialog>
+</template>
+<script lang="ts" setup>
+import * as ImageApi from '@/api/data/video/image'
+import {getPreviewUrl} from "@/api/data/video/image";
+import {dateFormatter} from "@/utils/formatTime";
+
+defineOptions({name: 'CameraImage'})
+
+const message = useMessage() // 消息弹窗
+const {t} = useI18n() // 国际化
+const dialogTitle = ref('截图列表')
+const loading = ref(true) // 列表的加载中
+const total = ref(0) // 列表的总页数
+const list = ref([]) // 列表的数据
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  id: undefined,
+  brand: undefined,
+  code: undefined,
+  device: undefined,
+  cameraId: '',
+  imagePath: undefined,
+  imageUrl: undefined,
+  createDate: undefined,
+})
+const cameraId = ref('')
+const dialogVisible = ref(false)
+
+/** 查询列表 */
+const open = async (camera_id: string) => {
+  dialogVisible.value = true
+  cameraId.value = camera_id
+  queryParams.cameraId = camera_id
+  loading.value = true
+  try {
+    const data = await ImageApi.getImagePage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+defineExpose({open}) // 提供 open 方法,用于打开弹窗
+
+const handleClose = async () => {
+  dialogVisible.value = false
+}
+
+const getPreviewSrcList = (imageUrl: string) => {
+  let previewSrcList: string[] = []
+  previewSrcList.push(getPreviewUrl(imageUrl))
+  return previewSrcList
+}
+
+/** 删除按钮操作 */
+const handleDelete = async (id: number) => {
+  try {
+    // 删除的二次确认
+    await message.delConfirm()
+    // 发起删除
+    await ImageApi.deleteImage(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await open(cameraId.value)
+  } catch {
+  }
+}
+</script>
diff --git a/src/views/data/video/camera/index.vue b/src/views/data/video/camera/index.vue
index d0fbbe6..add49c5 100644
--- a/src/views/data/video/camera/index.vue
+++ b/src/views/data/video/camera/index.vue
@@ -61,11 +61,11 @@
       </el-form-item>
       <el-form-item>
         <el-button @click="handleQuery">
-          <Icon icon="ep:search" class="mr-5px" />
+          <Icon icon="ep:search" class="mr-5px"/>
           搜索
         </el-button>
         <el-button @click="resetQuery">
-          <Icon icon="ep:refresh" class="mr-5px" />
+          <Icon icon="ep:refresh" class="mr-5px"/>
           重置
         </el-button>
         <el-button
@@ -74,7 +74,7 @@
           @click="openForm('create')"
           v-hasPermi="['video:camera:save']"
         >
-          <Icon icon="ep:plus" class="mr-5px" />
+          <Icon icon="ep:plus" class="mr-5px"/>
           新增
         </el-button>
         <el-button
@@ -84,7 +84,7 @@
           :loading="exportLoading"
           v-hasPermi="['video:camera:export']"
         >
-          <Icon icon="ep:download" class="mr-5px" />
+          <Icon icon="ep:download" class="mr-5px"/>
           导出
         </el-button>
       </el-form-item>
@@ -96,20 +96,21 @@
     <el-table v-loading="loading" :data="list">
       <el-table-column label="品牌" align="center" prop="brand" width="80">
         <template #default="scope">
-          <dict-tag :type="DICT_TYPE.CAMERA_BRAND" :value="scope.row.brand" />
+          <dict-tag :type="DICT_TYPE.CAMERA_BRAND" :value="scope.row.brand"/>
         </template>
       </el-table-column>
       <el-table-column label="设备类型" align="center" prop="device" width="200"/>
       <el-table-column label="编码" align="center" prop="code" width="200"/>
-      <el-table-column label="IP" align="center" prop="ip" />
-      <el-table-column label="端口" align="center" prop="port" width="100"/>
+      <el-table-column label="IP" align="center" prop="ip"/>
+      <el-table-column label="端口" align="center" prop="port" width="80"/>
+      <el-table-column label="通道" align="center" prop="channel" width="80"/>
       <el-table-column label="用户名" align="center" prop="username" width="100"/>
       <el-table-column label="状态" prop="status" width="80">
         <template #default="scope">
-          <dict-tag :type="DICT_TYPE.NVR_ONLINE_STATUS" :value="scope.row.status" />
+          <dict-tag :type="DICT_TYPE.NVR_ONLINE_STATUS" :value="scope.row.status"/>
         </template>
       </el-table-column>
-      <el-table-column label="位置" align="center" prop="location" />
+      <el-table-column label="位置" align="center" prop="location"/>
       <el-table-column label="备注" align="center" prop="remark" width="150"/>
       <el-table-column label="操作" align="center" min-width="110" fixed="right">
         <template #default="scope">
@@ -129,6 +130,14 @@
           >
             删除
           </el-button>
+          <el-button
+            link
+            type="success"
+            @click="imageHandle(scope.row.id)"
+            v-hasPermi="['video:image:query']"
+          >
+            查看截图
+          </el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -142,99 +151,109 @@
   </ContentWrap>
 
   <!-- 表单弹窗:添加/修改 -->
-  <CameraForm ref="formRef" @success="getList" />
+  <CameraForm ref="formRef" @success="getList"/>
 
+  <CameraImage ref="imageFormRef"/>
 
 </template>
 <script lang="ts" setup>
 import {DICT_TYPE, getIntDictOptions} from '@/utils/dict'
-  import download from '@/utils/download'
-  import * as CameraApi from '@/api/data/video/camera'
-  import CameraForm from './CameraForm.vue'
+import download from '@/utils/download'
+import * as CameraApi from '@/api/data/video/camera'
+import CameraForm from './CameraForm.vue'
+import CameraImage from './CameraImage.vue'
 
-  defineOptions({name: 'Camera'})
 
-  const message = useMessage() // 消息弹窗
-  const {t} = useI18n() // 国际化
+defineOptions({name: 'Camera'})
 
-  const loading = ref(true) // 列表的加载中
-  const total = ref(0) // 列表的总页数
-  const list = ref([]) // 列表的数据
-  const queryParams = reactive({
-    pageNo: 1,
-    pageSize: 10,
-    type: 1,
-    brand: undefined,
-    ip: undefined,
-    code: undefined,
-    device: undefined,
-    location: undefined,
-    status: undefined
-  })
-  const queryFormRef = ref() // 搜索的表单
-  const exportLoading = ref(false) // 导出的加载中
+const message = useMessage() // 消息弹窗
+const {t} = useI18n() // 国际化
 
-  /** 查询列表 */
-  const getList = async () => {
-    loading.value = true
-    try {
-      const data = await CameraApi.getCameraPage(queryParams)
-      list.value = data.list
-      total.value = data.total
-    } finally {
-      loading.value = false
-    }
+const loading = ref(true) // 列表的加载中
+const total = ref(0) // 列表的总页数
+const list = ref([]) // 列表的数据
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  type: 1,
+  brand: undefined,
+  ip: undefined,
+  code: undefined,
+  device: undefined,
+  location: undefined,
+  status: undefined
+})
+const queryFormRef = ref() // 搜索的表单
+const exportLoading = ref(false) // 导出的加载中
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await CameraApi.getCameraPage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
   }
+}
 
-  /** 搜索按钮操作 */
-  const handleQuery = () => {
-    queryParams.pageNo = 1
-    getList()
-  }
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
+}
 
-  /** 重置按钮操作 */
-  const resetQuery = () => {
-    queryFormRef.value.resetFields()
-    handleQuery()
-  }
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value.resetFields()
+  queryParams.brand = undefined
+  handleQuery()
+}
 
-  /** 添加/修改操作 */
-  const formRef = ref()
-  const openForm = (type: string, id?: number) => {
-    formRef.value.open(type, id)
-  }
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (type: string, id?: number) => {
+  formRef.value.open(type, id)
+}
 
-  /** 删除按钮操作 */
-  const handleDelete = async (id: number) => {
-    try {
-      // 删除的二次确认
-      await message.delConfirm()
-      // 发起删除
-      await CameraApi.deleteCamera(id)
-      message.success(t('common.delSuccess'))
-      // 刷新列表
-      await getList()
-    } catch {
-    }
-  }
-
-  /** 导出按钮操作 */
-  const handleExport = async () => {
-    try {
-      // 导出的二次确认
-      await message.exportConfirm()
-      // 发起导出
-      exportLoading.value = true
-      const data = await CameraApi.exportCamera(queryParams)
-      download.excel(data, '录像机列表.xls')
-    } catch {
-    } finally {
-      exportLoading.value = false
-    }
-  }
-
-  /** 初始化 **/
-  onMounted(async () => {
+/** 删除按钮操作 */
+const handleDelete = async (id: number) => {
+  try {
+    // 删除的二次确认
+    await message.delConfirm()
+    // 发起删除
+    await CameraApi.deleteCamera(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
     await getList()
-  })
+  } catch {
+  }
+}
+
+/** 查看截图 */
+const imageFormRef = ref()
+const imageHandle = (id: string) => {
+  imageFormRef.value.open(id)
+}
+
+/** 导出按钮操作 */
+const handleExport = async () => {
+  try {
+    // 导出的二次确认
+    await message.exportConfirm()
+    // 发起导出
+    exportLoading.value = true
+    const data = await CameraApi.exportCamera(queryParams)
+    download.excel(data, '录像机列表.xls')
+  } catch {
+  } finally {
+    exportLoading.value = false
+  }
+}
+
+/** 初始化 **/
+onMounted(async () => {
+  await getList()
+})
 </script>
diff --git a/src/views/data/video/nvr/NvrCamera.vue b/src/views/data/video/nvr/NvrCamera.vue
index 0ff49b3..212ff57 100644
--- a/src/views/data/video/nvr/NvrCamera.vue
+++ b/src/views/data/video/nvr/NvrCamera.vue
@@ -6,95 +6,104 @@
     @close="handleClose"
     size="60%">
     <div class="mod-dev__camera" style="padding: 10px;">
-    <el-form
-      class="-mb-15px"
-      :model="queryParams"
-      ref="queryFormRef"
-      :inline="true"
-      label-width="68px"
-    >
-      <el-form-item label="监控区域" prop="code">
-        <el-input
-          v-model="queryParams.location"
-          placeholder="请输入监控区域"
-          clearable
-          @keyup.enter="handleQuery"
-          class="!w-240px"
-        />
-      </el-form-item>
-      <el-form-item>
-        <el-button @click="handleQuery">
-          <Icon icon="ep:search" class="mr-5px" />
-          搜索
-        </el-button>
-        <el-button @click="resetQuery">
-          <Icon icon="ep:refresh" class="mr-5px" />
-          重置
-        </el-button>
-        <el-button
-          type="primary"
-          plain
-          @click="openForm('create')"
-        >
-          <Icon icon="ep:plus" class="mr-5px" />
-          新增
-        </el-button>
-        <el-button
-          type="success"
-          plain
-          @click="handleExport"
-          :loading="exportLoading"
-          v-hasPermi="['dev:camera:export']"
-        >
-          <Icon icon="ep:download" class="mr-5px" />
-          导出
-        </el-button>
-      </el-form-item>
-    </el-form>
-
-  <!-- 列表 -->
-    <el-table v-loading="loading" :data="list">
-      <el-table-column label="编码" align="center" prop="code" width="80" />
-      <el-table-column label="抓图方式" align="center" prop="captureType" width="80">
-        <template #default="scope">
-          <dict-tag :type="DICT_TYPE.CAPTURE_TYPE" :value="scope.row.captureType" />
-        </template>
-      </el-table-column>
-      <el-table-column label="通道" align="center" prop="channel" width="80"  />
-      <el-table-column label="监控区域" align="center" prop="location" />
-      <el-table-column label="备注" align="center" prop="remark" width="200" />
-      <el-table-column label="操作" align="center" min-width="110" fixed="right">
-        <template #default="scope">
+      <el-form
+        class="-mb-15px"
+        :model="queryParams"
+        ref="queryFormRef"
+        :inline="true"
+        label-width="68px"
+      >
+        <el-form-item label="监控区域" prop="code">
+          <el-input
+            v-model="queryParams.location"
+            placeholder="请输入监控区域"
+            clearable
+            @keyup.enter="handleQuery"
+            class="!w-240px"
+          />
+        </el-form-item>
+        <el-form-item>
+          <el-button @click="handleQuery">
+            <Icon icon="ep:search" class="mr-5px"/>
+            搜索
+          </el-button>
+          <el-button @click="resetQuery">
+            <Icon icon="ep:refresh" class="mr-5px"/>
+            重置
+          </el-button>
           <el-button
-            link
             type="primary"
-            @click="openForm('update', scope.row.id)"
+            plain
+            @click="openForm('create')"
           >
-            编辑
+            <Icon icon="ep:plus" class="mr-5px"/>
+            新增
           </el-button>
           <el-button
-            link
-            type="danger"
-            @click="handleDelete(scope.row.id)"
+            type="success"
+            plain
+            @click="handleExport"
+            :loading="exportLoading"
+            v-hasPermi="['dev:camera:export']"
           >
-            删除
+            <Icon icon="ep:download" class="mr-5px"/>
+            导出
           </el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <!-- 分页 -->
-    <Pagination
-      :total="total"
-      v-model:page="queryParams.pageNo"
-      v-model:limit="queryParams.pageSize"
-      @pagination="getList"
-    />
+        </el-form-item>
+      </el-form>
+
+      <!-- 列表 -->
+      <el-table v-loading="loading" :data="list">
+        <el-table-column label="编码" align="center" prop="code" width="80"/>
+        <el-table-column label="抓图方式" align="center" prop="captureType" width="80">
+          <template #default="scope">
+            <dict-tag :type="DICT_TYPE.CAPTURE_TYPE" :value="scope.row.captureType"/>
+          </template>
+        </el-table-column>
+        <el-table-column label="通道" align="center" prop="channel" width="80"/>
+        <el-table-column label="监控区域" align="center" prop="location"/>
+        <el-table-column label="备注" align="center" prop="remark" width="200"/>
+        <el-table-column label="操作" align="center" min-width="110" fixed="right">
+          <template #default="scope">
+            <el-button
+              link
+              type="primary"
+              @click="openForm('update', scope.row.id)"
+            >
+              编辑
+            </el-button>
+            <el-button
+              link
+              type="danger"
+              @click="handleDelete(scope.row.id)"
+            >
+              删除
+            </el-button>
+            <el-button
+              link
+              type="success"
+              @click="imageHandle(scope.row.id)"
+              v-hasPermi="['video:image:query']"
+            >
+              查看截图
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <!-- 分页 -->
+      <Pagination
+        :total="total"
+        v-model:page="queryParams.pageNo"
+        v-model:limit="queryParams.pageSize"
+        @pagination="getList"
+      />
     </div>
   </el-drawer>
 
   <!-- 表单弹窗:添加/修改 -->
-  <NvrCameraForm ref="formRef" @success="getList" />
+  <NvrCameraForm ref="formRef" @success="getList"/>
 
+  <CameraImage ref="imageFormRef"/>
 
 </template>
 <script lang="ts" setup>
@@ -102,6 +111,7 @@
 import * as CameraApi from '@/api/data/video/camera'
 import NvrCameraForm from './NvrCameraForm.vue'
 import {DICT_TYPE} from "@/utils/dict";
+import CameraImage from "../camera/CameraImage.vue";
 
 defineOptions({name: 'NvrCamera'})
 
@@ -134,7 +144,7 @@
   await getList()
 }
 
-defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+defineExpose({open}) // 提供 open 方法,用于打开弹窗
 
 /** 查询列表 */
 const getList = async () => {
@@ -148,6 +158,12 @@
   }
 }
 
+/** 查看截图 */
+const imageFormRef = ref()
+const imageHandle = (id: string) => {
+  imageFormRef.value.open(id)
+}
+
 /** 搜索按钮操作 */
 const handleQuery = () => {
   queryParams.pageNo = 1
@@ -156,7 +172,7 @@
 
 /** 重置按钮操作 */
 const resetQuery = () => {
-  queryFormRef.value.resetFields()
+  queryParams.location = undefined
   handleQuery()
 }
 
diff --git a/src/views/data/video/nvr/index.vue b/src/views/data/video/nvr/index.vue
index 61d0163..b780a0e 100644
--- a/src/views/data/video/nvr/index.vue
+++ b/src/views/data/video/nvr/index.vue
@@ -52,11 +52,11 @@
       </el-form-item>
       <el-form-item>
         <el-button @click="handleQuery">
-          <Icon icon="ep:search" class="mr-5px" />
+          <Icon icon="ep:search" class="mr-5px"/>
           搜索
         </el-button>
         <el-button @click="resetQuery">
-          <Icon icon="ep:refresh" class="mr-5px" />
+          <Icon icon="ep:refresh" class="mr-5px"/>
           重置
         </el-button>
         <el-button
@@ -65,7 +65,7 @@
           @click="openForm('create')"
           v-hasPermi="['video:nvr:save']"
         >
-          <Icon icon="ep:plus" class="mr-5px" />
+          <Icon icon="ep:plus" class="mr-5px"/>
           新增
         </el-button>
         <el-button
@@ -75,7 +75,7 @@
           :loading="exportLoading"
           v-hasPermi="['video:nvr:export']"
         >
-          <Icon icon="ep:download" class="mr-5px" />
+          <Icon icon="ep:download" class="mr-5px"/>
           导出
         </el-button>
       </el-form-item>
@@ -87,20 +87,19 @@
     <el-table v-loading="loading" :data="list">
       <el-table-column label="品牌" align="center" prop="brand" width="80">
         <template #default="scope">
-          <dict-tag :type="DICT_TYPE.CAMERA_BRAND" :value="scope.row.brand" />
+          <dict-tag :type="DICT_TYPE.CAMERA_BRAND" :value="scope.row.brand"/>
         </template>
       </el-table-column>
       <el-table-column label="编码" align="center" prop="code" width="100"/>
       <el-table-column label="名称" align="center" prop="name"/>
-      <el-table-column label="IP" align="center" prop="ip" />
+      <el-table-column label="IP" align="center" prop="ip"/>
       <el-table-column label="端口" align="center" prop="port" width="100"/>
       <el-table-column label="用户名" align="center" prop="username" width="100"/>
       <el-table-column label="状态" prop="status" width="80">
         <template #default="scope">
-          <dict-tag :type="DICT_TYPE.NVR_ONLINE_STATUS" :value="scope.row.status" />
+          <dict-tag :type="DICT_TYPE.NVR_ONLINE_STATUS" :value="scope.row.status"/>
         </template>
       </el-table-column>
-      <el-table-column label="位置" align="center" prop="position" />
       <el-table-column label="备注" align="center" prop="remark" width="150"/>
       <el-table-column label="操作" align="center" min-width="110" fixed="right">
         <template #default="scope">
@@ -120,7 +119,8 @@
           >
             删除
           </el-button>
-          <el-button link type="success" size="small" @click="cameraHandle(scope.row.id)">摄像头</el-button>
+          <el-button link type="success" size="small" @click="cameraHandle(scope.row.id)">摄像头
+          </el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -134,7 +134,7 @@
   </ContentWrap>
 
   <!-- 表单弹窗:添加/修改 -->
-  <NvrForm ref="formRef" @success="getList" />
+  <NvrForm ref="formRef" @success="getList"/>
 
   <!-- 弹窗, 摄像头 -->
   <NvrCamera ref="videoCameraRef"/>
@@ -142,99 +142,100 @@
 </template>
 <script lang="ts" setup>
 import {DICT_TYPE, getIntDictOptions} from '@/utils/dict'
-  import download from '@/utils/download'
-  import * as NvrApi from '@/api/data/video/nvr'
-  import NvrForm from './NvrForm.vue'
-  import NvrCamera from './NvrCamera.vue'
+import download from '@/utils/download'
+import * as NvrApi from '@/api/data/video/nvr'
+import NvrForm from './NvrForm.vue'
+import NvrCamera from './NvrCamera.vue'
 
-  defineOptions({name: 'Nvr'})
+defineOptions({name: 'Nvr'})
 
-  const message = useMessage() // 消息弹窗
-  const {t} = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+const {t} = useI18n() // 国际化
 
-  const loading = ref(true) // 列表的加载中
-  const total = ref(0) // 列表的总页数
-  const list = ref([]) // 列表的数据
-  const queryParams = reactive({
-    pageNo: 1,
-    pageSize: 10,
-    brand: undefined,
-    ip: undefined,
-    code: undefined,
-    name: undefined,
-    status: undefined
-  })
-  const queryFormRef = ref() // 搜索的表单
-  const exportLoading = ref(false) // 导出的加载中
+const loading = ref(true) // 列表的加载中
+const total = ref(0) // 列表的总页数
+const list = ref([]) // 列表的数据
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  brand: undefined,
+  ip: undefined,
+  code: undefined,
+  name: undefined,
+  status: undefined
+})
+const queryFormRef = ref() // 搜索的表单
+const exportLoading = ref(false) // 导出的加载中
 
-  const videoCameraRef = ref()
+const videoCameraRef = ref()
 
-  /** 查询列表 */
-  const getList = async () => {
-    loading.value = true
-    try {
-      const data = await NvrApi.getNvrPage(queryParams)
-      list.value = data.list
-      total.value = data.total
-    } finally {
-      loading.value = false
-    }
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await NvrApi.getNvrPage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
   }
+}
 
-  const cameraHandle = (id: string) => {
-    // devCameraVisible.value = true
-    videoCameraRef.value.open(id)
-  }
+const cameraHandle = (id: string) => {
+  // devCameraVisible.value = true
+  videoCameraRef.value.open(id)
+}
 
-  /** 搜索按钮操作 */
-  const handleQuery = () => {
-    queryParams.pageNo = 1
-    getList()
-  }
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
+}
 
-  /** 重置按钮操作 */
-  const resetQuery = () => {
-    queryFormRef.value.resetFields()
-    handleQuery()
-  }
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value.resetFields()
+  queryParams.brand = undefined
+  handleQuery()
+}
 
-  /** 添加/修改操作 */
-  const formRef = ref()
-  const openForm = (type: string, id?: number) => {
-    formRef.value.open(type, id)
-  }
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (type: string, id?: number) => {
+  formRef.value.open(type, id)
+}
 
-  /** 删除按钮操作 */
-  const handleDelete = async (id: number) => {
-    try {
-      // 删除的二次确认
-      await message.delConfirm()
-      // 发起删除
-      await NvrApi.deleteNvr(id)
-      message.success(t('common.delSuccess'))
-      // 刷新列表
-      await getList()
-    } catch {
-    }
-  }
-
-  /** 导出按钮操作 */
-  const handleExport = async () => {
-    try {
-      // 导出的二次确认
-      await message.exportConfirm()
-      // 发起导出
-      exportLoading.value = true
-      const data = await NvrApi.exportNvr(queryParams)
-      download.excel(data, '录像机列表.xls')
-    } catch {
-    } finally {
-      exportLoading.value = false
-    }
-  }
-
-  /** 初始化 **/
-  onMounted(async () => {
+/** 删除按钮操作 */
+const handleDelete = async (id: number) => {
+  try {
+    // 删除的二次确认
+    await message.delConfirm()
+    // 发起删除
+    await NvrApi.deleteNvr(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
     await getList()
-  })
+  } catch {
+  }
+}
+
+/** 导出按钮操作 */
+const handleExport = async () => {
+  try {
+    // 导出的二次确认
+    await message.exportConfirm()
+    // 发起导出
+    exportLoading.value = true
+    const data = await NvrApi.exportNvr(queryParams)
+    download.excel(data, '录像机列表.xls')
+  } catch {
+  } finally {
+    exportLoading.value = false
+  }
+}
+
+/** 初始化 **/
+onMounted(async () => {
+  await getList()
+})
 </script>
diff --git a/src/views/model/pre/analysis/index.vue b/src/views/model/pre/analysis/index.vue
index b21627a..b0939c3 100644
--- a/src/views/model/pre/analysis/index.vue
+++ b/src/views/model/pre/analysis/index.vue
@@ -4,37 +4,42 @@
       <el-form :inline="true" :model="formData" label-width="80px">
         <el-form-item label="开始时间">
           <el-date-picker
-              size="mini"
-              v-model="formData.startTime"
-              type="datetime"
-              placeholder="选择日期时间"/>
+            v-model="formData.startTime"
+            type="datetime"
+            format="YYYY-MM-DD HH:mm:00"
+            value-format="YYYY-MM-DD HH:mm:00"
+            placeholder="选择日期时间"/>
         </el-form-item>
         <el-form-item label="结束时间">
           <el-date-picker
-              size="mini"
-              v-model="formData.endTime"
-              type="datetime"
-              placeholder="选择日期时间"/>
+            v-model="formData.endTime"
+            type="datetime"
+            format="YYYY-MM-DD HH:mm:00"
+            value-format="YYYY-MM-DD HH:mm:00"
+            placeholder="选择日期时间"/>
         </el-form-item>
         <el-form-item label="预测时间">
           <el-date-picker
-              size="mini"
-              v-model="formData.predictTime"
-              type="datetime"
-              placeholder="选择日期时间"/>
+            v-model="formData.predictTime"
+            type="datetime"
+            format="YYYY-MM-DD HH:mm:00"
+            value-format="YYYY-MM-DD HH:mm:00"
+            placeholder="选择日期时间"/>
         </el-form-item>
         <el-form-item label="预测频率">
-          <el-input-number size="mini" v-model="formData.predictFreq" controls-position="right" :min="1"
+          <el-input-number v-model="formData.predictFreq" controls-position="right"
+                           :min="1"
                            :max="10"/>
         </el-form-item>
         <el-form-item>
           <el-button-group>
-            <el-button size="mini" type="primary" plain :icon="ArrowLeft"
-                       v-loading="loading1" @click="leftSearchDataByRange()"/>
-            <el-button size="mini" type="primary" plain :icon="Search"
-                       v-loading="loading1" @click="getList()">查询</el-button>
-            <el-button size="mini" type="primary" plain :icon="ArrowRight"
-                       v-loading="loading1" @click="rightSearchDataByRange()"/>
+            <el-button type="primary" plain :icon="ArrowLeft"
+                       :loading="loading1" @click="leftSearchDataByRange()"/>
+            <el-button type="primary" plain :icon="Search"
+                       :loading="loading1" @click="getList()">查询
+            </el-button>
+            <el-button type="primary" plain :icon="ArrowRight"
+                       :loading="loading1" @click="rightSearchDataByRange()"/>
           </el-button-group>
         </el-form-item>
 
@@ -42,46 +47,52 @@
           <div class="his-body-left">
             <div class="his-body-tree">
               <el-tree
-                  :data="treeData"
-                  show-checkbox
-                  node-key="id"
-                  ref="tree"
-                  highlight-current
-                  :props="defaultProps"
-                  @check="onCheckTree"/>
+                :data="treeData"
+                show-checkbox
+                node-key="id"
+                ref="tree"
+                highlight-current
+                :props="defaultProps"
+                @check="onCheckTree"/>
             </div>
           </div>
           <div class="his-body-right">
             <div class="his-body-chart">
-              <el-form :inline="true" :model="calRateForm" :rules="formRules" ref="calRateForm" label-width="108px">
+              <el-form :inline="true" :model="calRateForm" :rules="formRules" ref="calRateFormRef"
+                       label-width="108px">
                 <el-row>
-                  <el-col :span="6" >
+                  <el-col :span="6">
                     <el-form-item label="预测项" prop="calItem" style="width: 90%">
-                      <el-select v-model="calRateForm.calItem" @change="calItemBaseVale" placeholder="请选择">
+                      <el-select size="small" v-model="calRateForm.calItem"
+                                 @change="calItemBaseVale"
+                                 placeholder="请选择">
                         <el-option
-                            v-for="item in formData.checkedItemData"
-                            :key="item.id"
-                            :label="item.label"
-                            :value="item.id"/>
+                          v-for="itemOut in formData.checkedItemData"
+                          :key="itemOut.id"
+                          :label="itemOut.label"
+                          :value="itemOut.id"/>
                       </el-select>
                     </el-form-item>
                   </el-col>
                   <el-col :span="6">
                     <el-form-item label="精准度偏差" prop="IN_DEVIATION">
-                      <el-input-number size="mini" v-model="calRateForm.IN_DEVIATION" controls-position="right" :min="1"
+                      <el-input-number size="small" v-model="calRateForm.IN_DEVIATION"
+                                       controls-position="right" :min="1"
                                        :max="10"/>
                     </el-form-item>
                   </el-col>
                   <el-col :span="6">
                     <el-form-item label="不可信率偏差" prop="OUT_DEVIATION">
-                      <el-input-number size="mini" v-model="calRateForm.OUT_DEVIATION" controls-position="right"
+                      <el-input-number size="small" v-model="calRateForm.OUT_DEVIATION"
+                                       controls-position="right"
                                        :min="1"
                                        :max="20"/>
                     </el-form-item>
                   </el-col>
                   <el-col :span="4">
                     <el-form-item>
-                      <el-button size="mini" type="primary" plain :loading="loading2" @click="calAccuracyRate">计算精准度
+                      <el-button size="small" type="primary" plain :loading="loading2"
+                                 @click="calAccuracyRate">计算精准度
                       </el-button>
                     </el-form-item>
                   </el-col>
@@ -89,54 +100,54 @@
                 <el-row>
                   <el-col :span="4">
                     <el-form-item label="精准度:">
-                      {{calRateForm.IN_ACCURACY_RATE}}%
+                      {{ calRateForm.IN_ACCURACY_RATE }}%
                     </el-form-item>
                   </el-col>
                   <el-col :span="4">
                     <el-form-item label="预测平均值:">
-                      {{calRateForm.itemPreAvg}}
+                      {{ calRateForm.itemPreAvg }}
                     </el-form-item>
                   </el-col>
                   <el-col :span="4">
                     <el-form-item label="预测最大值:">
-                      {{calRateForm.itemPreMax}}
+                      {{ calRateForm.itemPreMax }}
                     </el-form-item>
                   </el-col>
                   <el-col :span="4">
                     <el-form-item label="预测最小值:">
-                      {{calRateForm.itemPreMin}}
+                      {{ calRateForm.itemPreMin }}
                     </el-form-item>
                   </el-col>
                   <el-col :span="4">
                     <el-form-item label="预测累积量:">
-                      {{calRateForm.preCumulant}}
+                      {{ calRateForm.preCumulant }}
                     </el-form-item>
                   </el-col>
                 </el-row>
                 <el-row>
                   <el-col :span="4">
                     <el-form-item label="不可信率:">
-                      {{calRateForm.OUT_ACCURACY_RATE}}%
+                      {{ calRateForm.OUT_ACCURACY_RATE }}%
                     </el-form-item>
                   </el-col>
                   <el-col :span="4">
                     <el-form-item label="真实平均值:">
-                      {{calRateForm.itemAvg}}
+                      {{ calRateForm.itemAvg }}
                     </el-form-item>
                   </el-col>
                   <el-col :span="4">
                     <el-form-item label="真实最大值:">
-                      {{calRateForm.itemMax}}
+                      {{ calRateForm.itemMax }}
                     </el-form-item>
                   </el-col>
                   <el-col :span="4">
                     <el-form-item label="真实最小值:">
-                      {{calRateForm.itemMin}}
+                      {{ calRateForm.itemMin }}
                     </el-form-item>
                   </el-col>
                   <el-col :span="4">
                     <el-form-item label="真实累积量:">
-                      {{calRateForm.realCumulant}}
+                      {{ calRateForm.realCumulant }}
                     </el-form-item>
                   </el-col>
                 </el-row>
@@ -146,20 +157,25 @@
                   <el-col :span="12">
                     <el-form-item label="数据类型">
                       <el-checkbox-group v-model="formData.chartCheck" @change="changeChartCheck">
-                        <el-checkbox v-for="item in formData.chartOptions" :label="item" :key="item">{{item}}
+                        <el-checkbox v-for="item in formData.chartOptions" :label="item"
+                                     :key="item">{{ item }}
                         </el-checkbox>
                       </el-checkbox-group>
                     </el-form-item>
                   </el-col>
                   <el-col :span="6">
                     <el-form-item>
-                      <el-radio v-model="formData.isMultipleY" :label="false" @input="onChangeMultipleY">单坐标轴</el-radio>
-                      <el-radio v-model="formData.isMultipleY" :label="true" @input="onChangeMultipleY">多坐标轴</el-radio>
+                      <el-radio v-model="formData.isMultipleY" :label="false"
+                                @input="onChangeMultipleY">单坐标轴
+                      </el-radio>
+                      <el-radio v-model="formData.isMultipleY" :label="true"
+                                @input="onChangeMultipleY">多坐标轴
+                      </el-radio>
                     </el-form-item>
                   </el-col>
                 </el-row>
               </el-form>
-              <div id="data-analysis" style="height: 500px;"></div>
+              <div ref="dataAnalysisChart" style="height: 500px;"></div>
             </div>
           </div>
         </div>
@@ -168,31 +184,479 @@
   </el-card>
 </template>
 <script lang="ts" setup>
-  import {getYMDHMS} from "@/utils/dateUtil"
-  import * as CategoryApi from "@/api/data/ind/category";
-  import * as DmModule from '@/api/model/pre/dm'
-  import * as ItemApi from "@/api/data/ind/item/item";
-  import * as MmPredictItem from '@/api/model/pre/item'
-  import * as echarts from "echarts";
-  import { onMounted, ref } from 'vue';
-  import { Search, ArrowLeft, ArrowRight,} from '@element-plus/icons-vue'
+import {getYMDHMS} from "@/utils/dateUtil"
+import * as McsApi from '@/api/model/mcs'
+import * as echarts from "echarts";
+import {Search, ArrowLeft, ArrowRight,} from '@element-plus/icons-vue'
 
-  defineOptions({name: 'AnalysisformData'})
+defineOptions({name: 'AnalysisformData'})
 
-  const message = useMessage() // 消息弹窗
-  const { t } = useI18n() // 国际化
-  const dataCategoryList = ref([] as CategoryApi.IndItemCategoryVO[])
-  const loading1 = ref(false) // 列表的加载中
-  const loading2 = ref(false) // 列表的加载中
-  const total = ref(0) // 列表的总页数
-  const list = ref([]) // 字典表格数据
-  const queryParams = reactive({
-    pageNo: 1,
-    pageSize: 10,
-    itemno: '',
-    itemname: '',
+const message = useMessage() // 消息弹窗
+const {t} = useI18n() // 国际化
+const dataAnalysisChart = ref(null);
+const loading1 = ref(false) // 列表的加载中
+const loading2 = ref(false) // 列表的加载中
+const total = ref(0) // 列表的总页数
+const list = ref([]) // 字典表格数据
+let formData = ref({
+  rangeDate: '',
+  startTime: '',
+  endTime: '',
+  predictTime: '',
+  predictTimeStr: '',
+  startTimeStr: '',
+  endTimeStr: '',
+  predictTimeStamp: 0,
+  startTimeStamp: 0,
+  endTimeStamp: 0,
+  currentStamp: '',
+  currentStamp60: '',
+  predictStamp: '',
+  chartCheck: ['T+L', '真实值'],
+  chartOptions: ['T+N', 'T+L', '当时', '真实值', '调整值'],
+  checkedItemData: [],
+  backItem: '',
+  backValue: 0,
+  backCoe: 1,
+  preCumulant: 0,
+  realCumulant: 0,
+  queryStep: 2,
+  isMultipleYRadio: '单坐标轴',
+  isMultipleY: false,
+  predictFreq: 3,
+})
+const calRateFormRef = ref()
+const calRateForm = ref({
+  calItem: undefined,
+  IN_DEVIATION: 0,
+  OUT_DEVIATION: 0,
+  IN_ACCURACY_RATE: 0,
+  OUT_ACCURACY_RATE: 0,
+  itemAvg: 0,
+  itemMax: 0,
+  itemMin: 0,
+  itemPreAvg: 0,
+  itemPreMax: 0,
+  itemPreMin: 0,
+  preCumulant: 0,
+  realCumulant: 0
+})
+let itemData = ref({
+  currentTreeList: [],
+  chart: {},
+  option: {}
+})
+const treeData = ref([])
+const itemDataObject = ref()
+const timer = ref()
+let myChart = null;
+
+const formRules = reactive({
+  calItem: [{required: true, message: '预测项不能为空', trigger: 'blur'}],
+  IN_DEVIATION: [{required: true, message: '精准度偏差不能为空', trigger: 'blur'}],
+  OUT_DEVIATION: [{required: true, message: '不可信率偏差不能为空', trigger: 'blur'}],
+})
+
+/** 查询列表 */
+const getList = async () => {
+  loading1.value = true
+  try {
+    if (!formData.value.chartCheck) {
+      formData.value.chartCheck = ['真实值']
+    }
+    let chartCheckArray = formData.value.chartCheck;
+    if (!formData.value.checkedItemData || formData.value.checkedItemData.length == 0) {
+      itemData.value.option = {};
+      return;
+    }
+    let outIds = formData.value.checkedItemData.map(item => {
+      return item.id
+    })
+    const params = reactive({
+      outIds: outIds,
+      predictTime: formData.value.predictTime,
+      startTime: formData.value.startTime,
+      endTime: formData.value.endTime
+    })
+    const data = await McsApi.getPreDataCharts(params)
+    formData.value.predictTime = data.predictTime;
+    formData.value.startTime = data.startTime
+    formData.value.endTime = data.endTime
+
+    let xAxisData = data.categories;
+    let yAxisData = [];
+    let offset = 0;
+    let yAxisIndex = 0;
+    let legendData = [];
+    let yMaxArr = [];
+    let seriesData = [];
+    seriesData.push({
+      name: '',
+      data: [null],
+      type: 'line',
+      smooth: true,
+      color: 'green',
+      markLine: {
+        silent: true,
+        lineStyle: {
+          color: '#32a487',
+          width: 2
+        },
+        data: [{
+          xAxis: formData.value.predictTime
+        }],
+        label: {
+          normal: {
+            formatter: formData.value.predictTime
+          }
+        },
+        symbol: ['circle', 'none'],
+      },
+    });
+    itemDataObject.value = {}
+    for (let i = 0; i < data.dataViewList.length; i++) {
+      let dataView = data.dataViewList[i]
+      itemDataObject.value[dataView.outId] = dataView;
+      let maxValue = dataView.maxValue;
+      let minValue = dataView.minValue;
+      yAxisIndex = formData.value.isMultipleY ? i : 0;
+      let yMax = maxValue;
+      if (maxValue < 0) {
+        maxValue = 1;
+      } else if (maxValue < 10) {
+        yMax = (Math.ceil(maxValue * 11) / 10).toFixed(1);
+      } else if (maxValue < 100) {
+        yMax = (Math.ceil(maxValue * 1.1 / 5) * 5);
+      } else {
+        yMax = (Math.ceil(maxValue * 1.1 / 10) * 10);
+      }
+      yMaxArr.push(yMax);
+      let yMin = minValue;
+      if (minValue >= 0) {
+        yMin = 0;
+      } else if (minValue > -10) {
+        yMin = (Math.floor(minValue * 11) / 10).toFixed(1);
+      } else if (minValue > -100) {
+        yMin = (Math.floor(minValue * 1.1 / 5) * 5);
+      } else {
+        yMin = (Math.floor(minValue * 1.1 / 10) * 10);
+      }
+      yAxisData.push({
+        type: 'value',
+        name: "",
+        min: yMin,
+        max: yMax,
+        position: 'left',
+        offset: offset,
+        splitLine: {
+          show: false
+        },
+        axisLine: {
+          show: true,
+          lineStyle: {}
+        },
+        axisLabel: {
+          formatter: '{value}'
+        }
+      })
+      offset = offset + 40
+      if (chartCheckArray.indexOf('真实值') !== -1) {
+        let legendName = dataView.resultstr + '(真实)';
+        legendData.push(legendName);
+        seriesData.push({
+          name: legendName,
+          data: dataView.realData || [],
+          type: 'line',
+          yAxisIndex: yAxisIndex,
+          showSymbol: false,
+          smooth: true,
+          lineStyle: {
+            width: 2
+          }
+        });
+      }
+      if (chartCheckArray.indexOf('T+N') !== -1) {
+        let legendName = dataView.resultstr + '(T+N)';
+        seriesData.push({
+          name: legendName,
+          data: dataView.preDataN || [],
+          type: 'line',
+          yAxisIndex: yAxisIndex,
+          showSymbol: false,
+          smooth: true,
+          lineStyle: {
+            width: 2
+          }
+        });
+      }
+      if (chartCheckArray.indexOf('T+L') !== -1) {
+        let legendName = dataView.resultstr + '(T+L)';
+        legendData.push(legendName);
+        seriesData.push({
+          name: legendName,
+          data: dataView.preDataL || [],
+          type: 'line',
+          showSymbol: false,
+          connectNulls: true,
+          yAxisIndex: yAxisIndex,
+          smooth: true,
+          lineStyle: {
+            width: 2
+          }
+        });
+      }
+      if (chartCheckArray.indexOf('当时') !== -1) {
+        let legendName = dataView.resultstr + '(当时)';
+        legendData.push(legendName);
+        seriesData.push({
+          name: legendName,
+          data: dataView.curData || [],
+          type: 'line',
+          yAxisIndex: yAxisIndex,
+          showSymbol: false,
+          smooth: true,
+          lineStyle: {
+            width: 2
+          }
+        });
+      }
+      if (chartCheckArray.indexOf('调整值') !== -1) {
+        let legendName = dataView.resultstr + '(调整值)';
+        legendData.push(legendName);
+        seriesData.push({
+          name: legendName,
+          data: dataView.adjData || [],
+          type: 'line',
+          yAxisIndex: yAxisIndex,
+          showSymbol: false,
+          connectNulls: true,
+          smooth: true,
+          lineStyle: {
+            width: 2,
+            type: 'dashed'
+          }
+        });
+      }
+    }
+    //如果最大值相差不大,改成一致大小
+    if (yMaxArr.length > 1) {
+      let max = Math.max.apply(null, yMaxArr);
+      let min = Math.min.apply(null, yMaxArr);
+      if (Math.abs((max - min) / max) <= 0.2) {
+        for (let i = 0; i < yAxisData.length; i++) {
+          yAxisData[i].max = max;
+        }
+      }
+    }
+    myChart = echarts.init(dataAnalysisChart.value);
+    let option = {
+      title: {
+        text: ''
+      },
+      tooltip: {
+        trigger: 'axis'
+      },
+      legend: {
+        show: true,
+        data: legendData,
+        top: 10
+      },
+      grid: {
+        top: '20%',
+        left: '3%',
+        right: '6%',
+        bottom: '3%',
+        containLabel: true
+      },
+      xAxis: {
+        type: 'category',
+        boundaryGap: false,
+        data: xAxisData
+      },
+      yAxis: formData.value.isMultipleY ? yAxisData : {
+        type: 'value',
+        splitLine: {show: false},
+        axisLine: {show: true}
+      },
+      dataZoom: [
+        {
+          type: 'inside',
+          start: 0,
+          end: 100
+        },
+        {
+          start: 0,
+          end: 10
+        }
+      ],
+      series: seriesData
+    }
+    myChart.clear()
+    myChart.setOption(option)
+  } finally {
+    loading1.value = false
+  }
+}
+
+onMounted(() => {
+  resetForm()
+  getPreItemTree()
+})
+
+async function getPreItemTree() {
+  treeData.value = await McsApi.getPredictItemTree()
+}
+
+function leftSearchDataByRange() {
+  let mins = getRangeMins();
+  let startTime = formData.value.startTime;
+  let endTime = formData.value.endTime;
+  let predictTime = formData.value.predictTime;
+  if (predictTime) {
+    predictTime = getYMDHMS(new Date(predictTime) - 1000 * 60 * mins);
+    formData.value.predictTime = predictTime;
+  }
+  if (startTime) {
+    startTime = getYMDHMS(new Date(startTime) - 1000 * 60 * mins);
+    formData.value.startTime = startTime;
+  }
+  if (endTime) {
+    endTime = getYMDHMS(new Date(endTime) - 1000 * 60 * mins);
+    formData.value.endTime = endTime;
+  }
+  getList();
+}
+
+function getRangeMins() {
+  let result: string | number = 0;
+  if (formData.value.startTime && formData.value.endTime) {
+    let startStamp = new Date(formData.value.startTime).getTime();
+    let endStamp = new Date(formData.value.endTime).getTime();
+    let queryStep = ((endStamp - startStamp) / (1000 * 60)).toFixed(0);
+    result = queryStep >= 0 ? queryStep : 0;
+  }
+  return result;
+}
+
+function onCheckTree(data, checked, indeterminate) {
+  formData.value.checkedItemData = [];
+  if (checked.checkedNodes) {
+    formData.value.checkedItemData = [...checked.checkedNodes]
+  }
+  debounce(getList, 1000);
+}
+
+function debounce(func, wait) {
+  let args = [];
+  if (timer.value) {
+    clearTimeout(timer.value);
+  }
+  timer.value = setTimeout(() => {
+    func.apply(this, args);
+    timer.value = null;
+  }, wait)
+}
+
+function calItemBaseVale() {
+  if (!calRateForm.value.calItem) {
+    calRateForm.value.itemPreMax = 0;
+    calRateForm.value.itemPreMin = 0;
+    calRateForm.value.itemPreAvg = 0;
+    calRateForm.value.preCumulant = 0;
+    calRateForm.value.itemMax = 0;
+    calRateForm.value.itemMin = 0;
+    calRateForm.value.itemAvg = 0;
+    calRateForm.value.realCumulant = 0;
+  } else {
+    let dataView = itemDataObject.value[calRateForm.value.calItem]
+    calRateForm.value.itemPreMax = dataView.preMax;
+    calRateForm.value.itemPreMin = dataView.preMin;
+    calRateForm.value.itemPreAvg = dataView.preAvg;
+    calRateForm.value.preCumulant = dataView.preCumulant;
+    calRateForm.value.itemMax = dataView.hisMax;
+    calRateForm.value.itemMin = dataView.hisMin;
+    calRateForm.value.itemAvg = dataView.hisAvg;
+    calRateForm.value.realCumulant = dataView.hisCumulant;
+  }
+}
+
+function calAccuracyRate() {
+  this.$refs['calRateForm'].validate((valid) => {
+    if (!valid) {
+      return false
+    }
+    let dataView = itemDataObject[calRateForm.value.calItem]
+    let seriesReaData = dataView.realData;
+    let seriesPreData = dataView.preDataL;
+    if (seriesReaData == null || seriesPreData == null ||
+      seriesReaData.length === 0 || seriesPreData.length === 0) {
+      loading2.value = false;
+      return;
+    }
+    let predictValueMap = {};
+    seriesPreData.forEach(function (item) {
+      predictValueMap[item[0]] = item[1];
+    })
+    let pointValueMap = {};
+    seriesReaData.forEach(function (item) {
+      pointValueMap[item[0]] = item[1];
+    })
+    let inDeviation = Number(calRateForm.value.IN_DEVIATION);
+    let outDeviation = Number(calRateForm.value.OUT_DEVIATION);
+    if (inDeviation === 0 && outDeviation === 0) {
+      loading2.value = false;
+      return;
+    }
+    let inDeviationCount = 0;
+    let outDeviationCount = 0;
+    let totalCount = 0;
+    for (let key in predictValueMap) {
+      let predictValue = predictValueMap[key];
+      let pointValue = pointValueMap[key];
+      if (pointValue == null || "" === pointValue || predictValue == null || "" === predictValue) {
+        continue;
+      }
+      let deviationAbs = (predictValue - pointValue) >= 0 ? (predictValue - pointValue) : (predictValue - pointValue) * -1;
+      if (deviationAbs < inDeviation) {
+        inDeviationCount = inDeviationCount + 1;
+      }
+      if (deviationAbs > outDeviation) {
+        outDeviationCount = outDeviationCount + 1;
+      }
+      totalCount = totalCount + 1;
+    }
+
+    let rateIn = (inDeviationCount / totalCount * 100).toFixed(2);
+    let rateOut = (outDeviationCount / totalCount * 100).toFixed(2);
+    calRateForm.value.IN_ACCURACY_RATE = Number(rateIn);
+    calRateForm.value.OUT_ACCURACY_RATE = Number(rateOut);
+    loading2.value = false;
   })
-  let formData = ref({
+}
+
+function rightSearchDataByRange() {
+  let mins = getRangeMins();
+  let startTime = formData.value.startTime;
+  let endTime = formData.value.endTime;
+  let predictTime = formData.value.predictTime;
+  if (predictTime) {
+    predictTime = getYMDHMS(new Date(predictTime) - 0 + 1000 * 60 * mins);
+    formData.value.predictTime = predictTime;
+  }
+  if (startTime) {
+    startTime = getYMDHMS(new Date(startTime) - 0 + 1000 * 60 * mins);
+    formData.value.startTime = startTime;
+  }
+  if (endTime) {
+    endTime = getYMDHMS(new Date(endTime) - 0 + 1000 * 60 * mins);
+    formData.value.endTime = endTime;
+  }
+  getList();
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
     rangeDate: '',
     startTime: '',
     endTime: '',
@@ -218,9 +682,9 @@
     isMultipleYRadio: '单坐标轴',
     isMultipleY: false,
     predictFreq: 3,
-  })
-  let calRateForm = ref({
-    calItem: '',
+  }
+  calRateForm.value = {
+    calItem: undefined,
     IN_DEVIATION: 0,
     OUT_DEVIATION: 0,
     IN_ACCURACY_RATE: 0,
@@ -231,462 +695,47 @@
     itemPreAvg: 0,
     itemPreMax: 0,
     itemPreMin: 0,
-    preCumulant:0,
-    realCumulant:0
-  })
-  let itemData = ref({
-    currentTreeList: [],
-    chart: {},
-    option: {}
-  })
-  const chartContainer = ref(null);
-  const treeData = ref([])
-  const itemDataObject = ref()
-  const timer = ref()
-
-  const formRules = reactive({
-    calItem: [{required: true, message: '预测项不能为空', trigger: 'blur'}],
-    IN_DEVIATION: [{required: true, message: '精准度偏差不能为空', trigger: 'blur'}],
-    OUT_DEVIATION: [{required: true, message: '不可信率偏差不能为空', trigger: 'blur'}],
-  })
-  //const myChart = echarts.init(document.getElementById("data-analysis"));
-  /** 查询列表 */
-  const getList = async () => {
-    loading1.value = true
-    try {
-      const data = formData.value
-      if (!formData.value.chartCheck) {
-        formData.value.chartCheck = ['真实值']
-      }
-      let chartCheckArray = formData.value.chartCheck;
-      if (!formData.value.checkedItemData || formData.value.checkedItemData.length == 0) {
-        itemData.value.option = {};
-        return;
-      }
-      let itemIdList = formData.value.checkedItemData.map(item => {
-        return item.id
-      })
-      const params = ref({
-        itemIds: itemIdList.join(','),
-        predictTime: formData.value.predictTime,
-        startTime: formData.value.startTime,
-        endTime: formData.value.endTime
-      })
-      const res = await MmPredictItem.getViewCharts(params)
-      if (res.code !== 0) {
-        return message.error(res.msg)
-      }
-      formData.value.predictTime = res.data.predictTime;
-      formData.value.startTime = res.data.startTime
-      formData.value.endTime = res.data.endTime
-
-      let xAxisData = res.data.categories;
-      let yAxisData = [];
-      let offset = 0;
-      let yAxisIndex = 0;
-      let legendData = [];
-      let yMaxArr = [];
-      let seriesData = [];
-      seriesData.push({
-        name: '',
-        data: [null],
-        type: 'line',
-        smooth: true,
-        color: 'green',
-        markLine: {
-          silent: true,
-          lineStyle: {
-            color: '#32a487',
-            width: 2
-          },
-          data: [{
-            xAxis: formData.value.predictTime
-          }],
-          label: {
-            normal: {
-              formatter: formData.value.predictTime
-            }
-          },
-          symbol: ['circle', 'none'],
-        },
-      });
-      itemDataObject.value = {}
-      for (let i = 0; i < res.data.dataViewList.length; i++) {
-        let dataView = res.data.dataViewList[i]
-        itemDataObject.value.dataView.itemId = dataView;
-        let maxValue = dataView.maxValue;
-        let minValue = dataView.minValue;
-        yAxisIndex = formData.value.isMultipleY ? i : 0;
-        let yMax = maxValue;
-        if (maxValue < 0) {
-          maxValue = 1;
-        } else if (maxValue < 10) {
-          yMax = (Math.ceil(maxValue * 11) / 10).toFixed(1);
-        } else if (maxValue < 100) {
-          yMax = (Math.ceil(maxValue * 1.1 / 5) * 5);
-        } else {
-          yMax = (Math.ceil(maxValue * 1.1 / 10) * 10);
-        }
-        yMaxArr.push(yMax);
-        let yMin = minValue;
-        if (minValue >= 0) {
-          yMin = 0;
-        } else if (minValue > -10) {
-          yMin = (Math.floor(minValue * 11) / 10).toFixed(1);
-        } else if (minValue > -100) {
-          yMin = (Math.floor(minValue * 1.1 / 5) * 5);
-        } else {
-          yMin = (Math.floor(minValue * 1.1 / 10) * 10);
-        }
-        yAxisData.push({
-          type: 'value',
-          name: "",
-          min: yMin,
-          max: yMax,
-          position: 'left',
-          offset: offset,
-          splitLine: {
-            show: false
-          },
-          axisLine: {
-            show: true,
-            lineStyle: {}
-          },
-          axisLabel: {
-            formatter: '{value}'
-          }
-        })
-        offset = offset + 40
-        if (chartCheckArray.indexOf('真实值') !== -1) {
-          let legendName = dataView.itemName + '(真实)';
-          legendData.push(legendName);
-          seriesData.push({
-            name: legendName,
-            data: dataView.realData || [],
-            type: 'line',
-            yAxisIndex: yAxisIndex,
-            showSymbol: false,
-            smooth: true,
-            lineStyle: {
-              width: 3
-            }
-          });
-        }
-        if (chartCheckArray.indexOf('T+N') !== -1) {
-          let legendName = dataView.itemName + '(T+N)';
-          seriesData.push({
-            name: legendName,
-            data: dataView.preDataN || [],
-            type: 'line',
-            yAxisIndex: yAxisIndex,
-            showSymbol: false,
-            smooth: true,
-            lineStyle: {
-              width: 3
-            }
-          });
-        }
-        if (chartCheckArray.indexOf('T+L') !== -1) {
-          let legendName = dataView.itemName + '(T+L)';
-          legendData.push(legendName);
-          seriesData.push({
-            name: legendName,
-            data: dataView.preDataL || [],
-            type: 'line',
-            showSymbol: false,
-            connectNulls: true,
-            yAxisIndex: yAxisIndex,
-            smooth: true,
-            lineStyle: {
-              width: 3
-            }
-          });
-        }
-        if (chartCheckArray.indexOf('当时') !== -1) {
-          let legendName = dataView.itemName + '(当时)';
-          legendData.push(legendName);
-          seriesData.push({
-            name: legendName,
-            data: dataView.curData || [],
-            type: 'line',
-            yAxisIndex: yAxisIndex,
-            showSymbol: false,
-            smooth: true,
-            lineStyle: {
-              width: 3
-            }
-          });
-        }
-        if (chartCheckArray.indexOf('调整值') !== -1) {
-          let legendName = dataView.itemName + '(调整值)';
-          legendData.push(legendName);
-          seriesData.push({
-            name: legendName,
-            data: dataView.adjData || [],
-            type: 'line',
-            yAxisIndex: yAxisIndex,
-            showSymbol: false,
-            connectNulls: true,
-            smooth: true,
-            lineStyle: {
-              width: 3,
-              type: 'dashed'
-            }
-          });
-        }
-      }
-      //如果最大值相差不大,改成一致大小
-      if (yMaxArr.length > 1) {
-        let max = Math.max.apply(null, yMaxArr);
-        let min = Math.min.apply(null, yMaxArr);
-        if (Math.abs((max - min) / max) <= 0.2) {
-          for (let i = 0; i < yAxisData.length; i++) {
-            yAxisData[i].max = max;
-          }
-        }
-      }
-      let option = {
-        title: {
-          text: ''
-        },
-        tooltip: {
-          trigger: 'axis'
-        },
-        legend: {
-          show: true,
-          data: legendData,
-          top: 10
-        },
-        grid: {
-          top: 50,
-          left: '3%',
-          right: '6%',
-          bottom: '3%',
-          containLabel: true
-        },
-        xAxis: {
-          type: 'category',
-          boundaryGap: false,
-          data: xAxisData
-        },
-        yAxis: formData.value.isMultipleY ? yAxisData : {
-          type: 'value',
-          splitLine: {show: false},
-          axisLine: {show: true}
-        },
-        dataZoom: [
-          {
-            type: 'inside',
-            start: 0,
-            end: 100
-          },
-          {
-            start: 0,
-            end: 10
-          }
-        ],
-        series: seriesData
-      }
-      //chart.setOption(option)
-    } finally {
-      loading1.value = false
-    }
+    preCumulant: 0,
+    realCumulant: 0
   }
-
-  onMounted(() => {
-    getPreItemTree()
-    getList()
-  })
-
-  async function getPreItemTree() {
-    treeData.value = await MmPredictItem.getMmPredictItemTree()
-  }
-
-  function leftSearchDataByRange() {
-    let mins = getRangeMins();
-    let startTime = formData.value.startTime;
-    let endTime = formData.value.endTime;
-    let predictTime = formData.value.predictTime;
-    if (predictTime) {
-      predictTime = getYMDHMS(new Date(predictTime) - 1000 * 60 * mins);
-      formData.value.predictTime = predictTime;
-    }
-    if (startTime) {
-      startTime = getYMDHMS(new Date(startTime) - 1000 * 60 * mins);
-      formData.value.startTime = startTime;
-    }
-    if (endTime) {
-      endTime = getYMDHMS(new Date(endTime) - 1000 * 60 * mins);
-      formData.value.endTime = endTime;
-    }
-    getList();
-  }
-
-  function getRangeMins () {
-    let result: string | number = 0;
-    if(formData.value.startTime && formData.value.endTime) {
-      let startStamp = new Date(formData.value.startTime).getTime();
-      let endStamp = new Date(formData.value.endTime).getTime();
-      let queryStep = ((endStamp - startStamp) / (1000 * 60)).toFixed(0);
-      result = queryStep >= 0 ? queryStep : 0;
-    }
-    return result;
-  }
-
-  function onCheckTree(data, checked, indeterminate) {
-    formData.value.checkedItemData = [];
-    if (checked.checkedNodes) {
-      formData.value.checkedItemData = [...checked.checkedNodes]
-    }
-    //myChart.clear()
-    debounce(getList(), 1000);
-  }
-
-  function debounce(func, wait) {
-    let args = [];
-    if (timer.value) {
-      clearTimeout(timer.value);
-    }
-    timer.value = setTimeout(() => {
-      func.apply(this, args);
-      timer.value = null;
-    }, wait)
-  }
-
-  function calItemBaseVale() {
-    if (!calRateForm.value.calItem) {
-      calRateForm.value.itemPreMax = 0;
-      calRateForm.value.itemPreMin = 0;
-      calRateForm.value.itemPreAvg = 0;
-      calRateForm.value.preCumulant = 0;
-      calRateForm.value.itemMax = 0;
-      calRateForm.value.itemMin = 0;
-      calRateForm.value.itemAvg = 0;
-      calRateForm.value.realCumulant = 0;
-      return
-    } else {
-      let dataView = itemDataObject[calRateForm.value.calItem]
-      calRateForm.value.itemPreMax = dataView.preMax;
-      calRateForm.value.itemPreMin = dataView.preMin;
-      calRateForm.value.itemPreAvg = dataView.preAvg;
-      calRateForm.value.preCumulant = dataView.preCumulant;
-      calRateForm.value.itemMax = dataView.hisMax;
-      calRateForm.value.itemMin = dataView.hisMin;
-      calRateForm.value.itemAvg = dataView.hisAvg;
-      calRateForm.value.realCumulant = dataView.hisCumulant;
-    }
-  }
-
-  function calAccuracyRate() {
-    this.$refs['calRateForm'].validate((valid) => {
-      if (!valid) {
-        return false
-      }
-      let dataView = itemDataObject[calRateForm.value.calItem]
-      let seriesReaData = dataView.realData;
-      let seriesPreData = dataView.preDataL;
-      if (seriesReaData == null || seriesPreData == null ||
-        seriesReaData.length === 0 || seriesPreData.length === 0) {
-        loading2.value = false;
-        return;
-      }
-      let predictValueMap = {};
-      seriesPreData.forEach(function (item) {
-        predictValueMap[item[0]] = item[1];
-      })
-      let pointValueMap = {};
-      seriesReaData.forEach(function (item) {
-        pointValueMap[item[0]] = item[1];
-      })
-      let inDeviation = Number(calRateForm.value.IN_DEVIATION);
-      let outDeviation = Number(calRateForm.value.OUT_DEVIATION);
-      if (inDeviation === 0 && outDeviation === 0) {
-        loading2.value = false;
-        return;
-      }
-      let inDeviationCount = 0;
-      let outDeviationCount = 0;
-      let totalCount = 0;
-      for (let key in predictValueMap) {
-        let predictValue = predictValueMap[key];
-        let pointValue = pointValueMap[key];
-        if (pointValue == null || "" === pointValue || predictValue == null || "" === predictValue) {
-          continue;
-        }
-        let deviationAbs = (predictValue - pointValue) >= 0 ? (predictValue - pointValue) : (predictValue - pointValue) * -1;
-        if (deviationAbs < inDeviation) {
-          inDeviationCount = inDeviationCount + 1;
-        }
-        if (deviationAbs > outDeviation) {
-          outDeviationCount = outDeviationCount + 1;
-        }
-        totalCount = totalCount + 1;
-      }
-
-      let rateIn = (inDeviationCount / totalCount * 100).toFixed(2);
-      let rateOut = (outDeviationCount / totalCount * 100).toFixed(2);
-      calRateForm.value.IN_ACCURACY_RATE = Number(rateIn);
-      calRateForm.value.OUT_ACCURACY_RATE = Number(rateOut);
-      loading2.value = false;
-    })
-  }
-
-  function rightSearchDataByRange() {
-    let mins = getRangeMins();
-    let startTime = formData.value.startTime;
-    let endTime = formData.value.endTime;
-    let predictTime = formData.value.predictTime;
-    if (predictTime) {
-      predictTime = getYMDHMS(new Date(predictTime) - 0 + 1000 * 60 * mins);
-      formData.value.predictTime = predictTime;
-    }
-    if (startTime) {
-      startTime = getYMDHMS(new Date(startTime) - 0 + 1000 * 60 * mins);
-      formData.value.startTime = startTime;
-    }
-    if (endTime) {
-      endTime = getYMDHMS(new Date(endTime) - 0 + 1000 * 60 * mins);
-      formData.value.endTime = endTime;
-    }
-    getList();
-  }
-
+  calRateFormRef.value?.resetFields()
+}
 </script>
 <style scoped>
-  .el-form-item {
-    margin-bottom: 0 !important;
-  }
+.el-form-item {
+  margin-bottom: 0 !important;
+}
 
-  .his-body-chart {
-    height: 100%;
-    border: 1px solid lightgray;
-    padding: 10px;
-  }
+.his-body-chart {
+  height: 100%;
+  border: 1px solid lightgray;
+  padding: 10px;
+}
 
-  .his-body-tree {
-    height: 100%;
-    border: 1px solid lightgray;
-    padding: 10px;
-  }
+.his-body-tree {
+  height: 100%;
+  border: 1px solid lightgray;
+  padding: 10px;
+}
 
-  .his-body-right {
-    width: 80%;
-    height: 100%;
-    padding-top: 10px;
-  }
+.his-body-right {
+  width: 80%;
+  height: 100%;
+  padding-top: 10px;
+}
 
-  .his-body-left {
-    width: 20%;
-    height: 100%;
-    padding: 10px 10px 0 0;
-  }
+.his-body-left {
+  width: 20%;
+  height: 100%;
+  padding: 10px 10px 0 0;
+}
 
-  .his-body {
-    width: 100%;
-    height: calc(calc(100vh - 68px - 38px - 160px));
-    display: flex;
-    flex-direction: row;
-    justify-content: flex-start;
-    align-content: flex-start;
-  }
+.his-body {
+  width: 100%;
+  height: calc(calc(100vh - 68px - 38px - 160px));
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-content: flex-start;
+}
 </style>
diff --git a/src/views/model/pre/item/MmPredictItemForm.vue b/src/views/model/pre/item/MmPredictItemForm.vue
index e10af7d..cb01f79 100644
--- a/src/views/model/pre/item/MmPredictItemForm.vue
+++ b/src/views/model/pre/item/MmPredictItemForm.vue
@@ -17,7 +17,8 @@
         </el-col>
         <el-col :span="12">
           <el-form-item label="编号" prop="mmPredictItem.itemno">
-            <el-input v-model="dataForm.mmPredictItem.itemno" placeholder="编号" maxlength="50" readonly/>
+            <el-input v-model="dataForm.mmPredictItem.itemno" placeholder="编号" maxlength="50"
+                      readonly/>
           </el-form-item>
         </el-col>
       </el-row>
@@ -210,13 +211,13 @@
         :data="dataForm.mmItemOutputList"
         border
         style="width: 100%; margin-top: 5px;">
-        <el-table-column prop="outputorder" label="排序" align="center" width="80px" />
+        <el-table-column prop="outputorder" label="排序" align="center" width="80px"/>
         <el-table-column label="结果" align="center" width="150px">
           <template #default="scope">
             <el-input v-model="scope.row.resultstr" placeholder="请输入"/>
           </template>
         </el-table-column>
-        <el-table-column label="结果数据类型" align="center"  width="150px">
+        <el-table-column label="结果数据类型" align="center" width="150px">
           <template #default="scope">
             <el-select
               v-model="scope.row.resultType"
@@ -233,7 +234,9 @@
         </el-table-column>
         <el-table-column label="索引" align="center" width="120px">
           <template #default="scope">
-            <el-input-number style="width:100%;hight:100%" :disabled="scope.row.resultType !== 2" v-model="scope.row.resultIndex" :min="0" step-strictly controls-position="right"/>
+            <el-input-number style="width:100%;hight:100%" :disabled="scope.row.resultType !== 2"
+                             v-model="scope.row.resultIndex" :min="0" step-strictly
+                             controls-position="right"/>
           </template>
         </el-table-column>
         <el-table-column label="数据点" align="center">
@@ -290,7 +293,9 @@
         <el-table-column prop="modelparamorder" label="序号" width="60" align="center"/>
         <el-table-column prop="" label="类型" width="200" align="center">
           <template #default="scope">
-            <el-select v-model="scope.row.modelparamtype" placeholder="请选择">
+            <el-select v-model="scope.row.modelparamtype"
+                       @change="changeModelparamtype(scope.row)"
+                       placeholder="请选择">
               <el-option
                 v-for="dict in getStrDictOptions(DICT_TYPE.MODEL_PARAM_TYPE)"
                 :key="dict.value"
@@ -761,11 +766,11 @@
   dataForm.value.itemtypename = itemTypeMap[value]
 }
 
-function changeModelparamtype(value, row) {
+function changeModelparamtype(row) {
   row.modelparamid = ''
 }
 
-function changeOutputPoint(value,row) {
+function changeOutputPoint(value, row) {
   row.tagname = pointMap[value]
 }
 
@@ -792,10 +797,12 @@
   rows.splice(index, 0, row)
   orderRow(rows)
 }
+
 function addItemOutput(list) {
   list.push({})
   orderItemOutput(list)
 }
+
 function deleteItemOutput(index: string, rows) {
   if (!rows || rows.length === 1) {
     message.error('不能全部删除!')
@@ -804,6 +811,7 @@
   rows.splice(index, 1)
   orderItemOutput(rows)
 }
+
 function orderItemOutput(list) {
   list.sort((a, b) => a.outputorder - b.outputorder);
   let outputorder = 1
@@ -816,7 +824,7 @@
 function resultTypeChange(value, row) {
   if (value === 1) {
     row.resultIndex = undefined
-  }else if (value === 2) {
+  } else if (value === 2) {
     row.resultIndex = 0
   }
 }
diff --git a/types/env.d.ts b/types/env.d.ts
index 40ce343..82b4cd7 100644
--- a/types/env.d.ts
+++ b/types/env.d.ts
@@ -25,6 +25,7 @@
   readonly VITE_UPLOAD_URL: string
   readonly VITE_API_URL: string
   readonly VITE_BASE_PATH: string
+  readonly VITE_VIDEO_CAMERA_DOMAIN: string
   readonly VITE_DROP_DEBUGGER: string
   readonly VITE_DROP_CONSOLE: string
   readonly VITE_SOURCEMAP: string

--
Gitblit v1.9.3