Compare commits
39 Commits
2026-03
...
cd2be0f4aa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd2be0f4aa | ||
|
|
855c569535 | ||
| 6a84d28101 | |||
|
|
1a69be62a0 | ||
|
|
02caca969e | ||
|
|
3f1af5e4cc | ||
|
|
88e9812d5f | ||
|
|
83a827ba5b | ||
| 40b1092718 | |||
|
|
83a1128884 | ||
| 1a44a2f9e0 | |||
|
|
5044c88946 | ||
|
|
51a862ed00 | ||
|
|
1ca8e536dd | ||
|
|
2445cfbff3 | ||
|
|
21ac0611cd | ||
|
|
ff841cfa93 | ||
|
|
01cc29c8b2 | ||
|
|
a324f7afcf | ||
|
|
4272f7756e | ||
|
|
070e404bbb | ||
| ed60e2b7f3 | |||
| 7785d4f708 | |||
| 0c64711dd8 | |||
|
|
d85dba8bf8 | ||
|
|
56b8158f4a | ||
| 765507398e | |||
| 9224ea17b8 | |||
| dc08f7d1ac | |||
| 1652b5faf8 | |||
|
|
fae2a7d735 | ||
|
|
bf3a99cbf3 | ||
|
|
2e7c0b7f44 | ||
|
|
98e0f9de02 | ||
|
|
21756e05d4 | ||
|
|
abfdf29a38 | ||
|
|
120892808b | ||
|
|
0f5cb1d3c5 | ||
| dbaa42ff7e |
6
.env.LN
Normal file
6
.env.LN
Normal file
@@ -0,0 +1,6 @@
|
||||
# 辽宁嵌入
|
||||
NODE_ENV = LN
|
||||
VITE_NAME="LN"
|
||||
# 电网一张图 地图图层
|
||||
VITE_NARIMAP=null
|
||||
VITE_NRGISCOMMON=null
|
||||
6
.env.LNqr
Normal file
6
.env.LNqr
Normal file
@@ -0,0 +1,6 @@
|
||||
# 辽宁嵌入
|
||||
NODE_ENV = LNqr
|
||||
VITE_NAME="LNqr"
|
||||
# 电网一张图 地图图层
|
||||
VITE_NARIMAP=null
|
||||
VITE_NRGISCOMMON=null
|
||||
156
README.md
156
README.md
@@ -1,78 +1,78 @@
|
||||
#### 介绍
|
||||
|
||||
```
|
||||
Vue 3 + TypeScript + Vite这个模板可以帮助您开始使用Vue 3和TypeScript在Vite中进行开发。该模板使用了Vue 3的<script setup>单文件组件,请查看script setup文档了解更多信息。
|
||||
```
|
||||
|
||||
#### 安装依赖&运行项目
|
||||
|
||||
> node version:^18.17.0 || >=20.5.0"
|
||||
|
||||
```shell
|
||||
#项目使用pnpm包管理器
|
||||
npm i pnpm -g
|
||||
|
||||
#安装依赖
|
||||
pnpm i
|
||||
|
||||
#运行项目
|
||||
npm run dev
|
||||
|
||||
#冀北现场启动命令 区分是否加载现场电网一张图内网api
|
||||
npm run dev:jibei
|
||||
|
||||
#去除后台所有模块名 如除/xxxx-boot
|
||||
npm run dev:removeMode
|
||||
|
||||
|
||||
|
||||
#因海南和冀北技术监督不同 通过修改文件的方式来区分
|
||||
#海南打包 需要吧pqs目录下supervise_hn 文件夹改成supervise 原文件改成supervise_jb
|
||||
#冀北打包 需要吧pqs目录下supervise_jb 文件夹改成supervise 原文件改成supervise_hn
|
||||
```
|
||||
|
||||
#### 页面编写-示例
|
||||
|
||||
```
|
||||
基础页面写法请查看`src/template`下的readme.md
|
||||
```
|
||||
|
||||
#### 开发规范
|
||||
|
||||
> 初衷:养成合理的习惯,精力留在技术调研、业务开发中。
|
||||
>
|
||||
> 常见点如下描述,更多的规范待前端开发人员有时间后,慢慢丰富。
|
||||
|
||||
- 命名风格:所有的包(文件夹)、文件名以小驼峰的风格命名,比如 xxxAaa,禁止 XxxAaa 或者 xxx-aaa。
|
||||
- 命名语义:禁止中文命名或拼音,英文命名借用下工具,稍微准确一点,不要与实际业务相差太远。
|
||||
- 功能组件创建风格:以**功能名称**命名文件夹,每个功能下以**index.vue**作为该功能的组件入口。正确示例参考:/src/views/auth/menu/index.vue。
|
||||
|
||||

|
||||
|
||||
- todo...:待后续补充。
|
||||
|
||||
#### 开发助手
|
||||
|
||||
##### 1、表格系列
|
||||
|
||||
- 页面表格以及表格页面按钮的弹出等功能参考:/views/pqs/voltageSags/sagGovern/index.vue
|
||||
- 表格中需要替换数据:
|
||||
|
||||
```js
|
||||
// 通过formatter函数返回实际需要返回的值
|
||||
{
|
||||
title: '数据来源', field: 'dataSource', minWidth: '130',
|
||||
formatter: (row: any) => {
|
||||
return row.dataSource == 0 ? '离线导入' : '监测点同步'
|
||||
}
|
||||
}****
|
||||
```
|
||||
|
||||
##### 2、样式系列
|
||||
|
||||
- 获取当前主体的高度:import { mainHeight } from '@/utils/layout'
|
||||
- 弹框内输入框长度设置 1 行 1 个 class="form-one" 1 行 2 个 class="form-two"
|
||||
|
||||
#### 依赖变更记录
|
||||
|
||||
- 2024-04-25 新增 vform3,by 洪圣文,用于页面表单设计保存为 json,命令:pnpm i vform3-builds
|
||||
#### 介绍
|
||||
|
||||
```
|
||||
Vue 3 + TypeScript + Vite这个模板可以帮助您开始使用Vue 3和TypeScript在Vite中进行开发。该模板使用了Vue 3的<script setup>单文件组件,请查看script setup文档了解更多信息。
|
||||
```
|
||||
|
||||
#### 安装依赖&运行项目
|
||||
|
||||
> node version:^18.17.0 || >=20.5.0"
|
||||
|
||||
```shell
|
||||
#项目使用pnpm包管理器
|
||||
npm i pnpm -g
|
||||
|
||||
#安装依赖
|
||||
pnpm i
|
||||
|
||||
#运行项目
|
||||
npm run dev
|
||||
|
||||
#jb现场启动命令 区分是否加载现场电网一张图内网api
|
||||
npm run dev:jibei
|
||||
|
||||
#去除后台所有模块名 如除/xxxx-boot
|
||||
npm run dev:removeMode
|
||||
|
||||
|
||||
|
||||
#因海南和jb技术监督不同 通过修改文件的方式来区分
|
||||
#海南打包 需要吧pqs目录下supervise_hn 文件夹改成supervise 原文件改成supervise_jb
|
||||
#jb打包 需要吧pqs目录下supervise_jb 文件夹改成supervise 原文件改成supervise_hn
|
||||
```
|
||||
|
||||
#### 页面编写-示例
|
||||
|
||||
```
|
||||
基础页面写法请查看`src/template`下的readme.md
|
||||
```
|
||||
|
||||
#### 开发规范
|
||||
|
||||
> 初衷:养成合理的习惯,精力留在技术调研、业务开发中。
|
||||
>
|
||||
> 常见点如下描述,更多的规范待前端开发人员有时间后,慢慢丰富。
|
||||
|
||||
- 命名风格:所有的包(文件夹)、文件名以小驼峰的风格命名,比如 xxxAaa,禁止 XxxAaa 或者 xxx-aaa。
|
||||
- 命名语义:禁止中文命名或拼音,英文命名借用下工具,稍微准确一点,不要与实际业务相差太远。
|
||||
- 功能组件创建风格:以**功能名称**命名文件夹,每个功能下以**index.vue**作为该功能的组件入口。正确示例参考:/src/views/auth/menu/index.vue。
|
||||
|
||||

|
||||
|
||||
- todo...:待后续补充。
|
||||
|
||||
#### 开发助手
|
||||
|
||||
##### 1、表格系列
|
||||
|
||||
- 页面表格以及表格页面按钮的弹出等功能参考:/views/pqs/voltageSags/sagGovern/index.vue
|
||||
- 表格中需要替换数据:
|
||||
|
||||
```js
|
||||
// 通过formatter函数返回实际需要返回的值
|
||||
{
|
||||
title: '数据来源', field: 'dataSource', minWidth: '130',
|
||||
formatter: (row: any) => {
|
||||
return row.dataSource == 0 ? '离线导入' : '监测点同步'
|
||||
}
|
||||
}****
|
||||
```
|
||||
|
||||
##### 2、样式系列
|
||||
|
||||
- 获取当前主体的高度:import { mainHeight } from '@/utils/layout'
|
||||
- 弹框内输入框长度设置 1 行 1 个 class="form-one" 1 行 2 个 class="form-two"
|
||||
|
||||
#### 依赖变更记录
|
||||
|
||||
- 2024-04-25 新增 vform3,by 洪圣文,用于页面表单设计保存为 json,命令:pnpm i vform3-builds
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<script src="/static/luckysheet/plugin.js"></script>
|
||||
<script src="/static/luckysheet/luckysheet.umd.js"></script>
|
||||
|
||||
<!-- 冀北地图 -->
|
||||
<!-- jb地图 -->
|
||||
<!--引入样式文件-->
|
||||
<script src="%VITE_NARIMAP%"></script>
|
||||
<!-- <script src="%VITE_NRGISCOMMON%"></script> -->
|
||||
|
||||
8813
package-lock.json
generated
8813
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
207
package.json
207
package.json
@@ -1,103 +1,108 @@
|
||||
{
|
||||
"name": "canneng-admin",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite --mode dev",
|
||||
"dev:jibei": "vite --mode jibei",
|
||||
"dev:hainan": "vite --mode hainan",
|
||||
"dev:qujing": "vite --mode qujing",
|
||||
"dev:removeMode": "vite --mode removeMode",
|
||||
"build": "vite build --mode dev",
|
||||
"build:jibei": "vite build --mode jibei",
|
||||
"build:hainan": "vite build --mode hainan",
|
||||
"build:qujing": "vite build --mode qujing",
|
||||
"build:removeMode": "vite build --mode removeMode",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "^7.0.2",
|
||||
"@element-plus/icons-vue": "^2.3.1",
|
||||
"@form-create/designer": "^3.1.3",
|
||||
"@form-create/element-ui": "^3.1.24",
|
||||
"@fortawesome/fontawesome-free": "^6.5.1",
|
||||
"@kjgl77/datav-vue3": "^1.7.4",
|
||||
"@vue-office/docx": "^1.6.3",
|
||||
"@vue-office/excel": "^1.7.8",
|
||||
"@vue-office/pdf": "^2.0.2",
|
||||
"@vueuse/core": "^10.7.0",
|
||||
"@wangeditor/editor": "^5.1.23",
|
||||
"@wangeditor/editor-for-vue": "^5.1.12",
|
||||
"@wangeditor/plugin-formula": "^1.0.11",
|
||||
"axios": "^1.6.2",
|
||||
"bpmn-js": "8.9.0",
|
||||
"bpmn-js-properties-panel": "0.46.0",
|
||||
"bpmn-js-token-simulation": "^0.10.0",
|
||||
"bpmn-moddle": "^6.0.0",
|
||||
"camunda-bpmn-moddle": "^7.0.1",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dayjs": "^1.11.10",
|
||||
"diagram-js": "^11.4.1",
|
||||
"diagram-js-minimap": "^2.0.4",
|
||||
"echarts": "^5.4.3",
|
||||
"echarts-gl": "^2.0.9",
|
||||
"echarts-liquidfill": "^3.1.0",
|
||||
"echarts4": "npm:echarts@^4.9.0",
|
||||
"element-plus": "^2.9.11",
|
||||
"exceljs": "^4.4.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"grid-layout-plus": "^1.1.0",
|
||||
"html2canvas": "^1.4.1",
|
||||
"jquery": "^3.7.1",
|
||||
"js-pinyin": "^0.2.5",
|
||||
"jsencrypt": "^3.3.2",
|
||||
"katex": "^0.16.11",
|
||||
"less": "^4.2.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"luckyexcel": "^1.0.1",
|
||||
"luckysheet": "^2.1.13",
|
||||
"mathjax": "^3.2.2",
|
||||
"min-dash": "^4.2.1",
|
||||
"mitt": "^3.0.1",
|
||||
"mqtt": "^5.13.3",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.1.7",
|
||||
"pinia-plugin-persistedstate": "^3.2.1",
|
||||
"qs": "^6.12.0",
|
||||
"screenfull": "^6.0.2",
|
||||
"splitpanes": "^3.1.5",
|
||||
"steady-xml": "0.1.0",
|
||||
"svg-pan-zoom": "^3.6.2",
|
||||
"use-element-plus-theme": "^0.0.5",
|
||||
"vexip-ui": "^2.3.28",
|
||||
"vue": "^3.3.11",
|
||||
"vue-baidu-map-3x": "^1.0.35",
|
||||
"vue-baidu-map-offline": "^1.0.7",
|
||||
"vue-demi": "^0.14.8",
|
||||
"vue-draggable-resizable": "3.0.0-beta.2",
|
||||
"vue-i18n": "9.10.2",
|
||||
"vue-katex": "^0.5.0",
|
||||
"vue-router": "4",
|
||||
"vue-types": "^5.1.1",
|
||||
"vxe-table": "^4.5.17",
|
||||
"vxe-table-plugin-export-xlsx": "^4.0.1",
|
||||
"web-storage-cache": "^1.1.1",
|
||||
"xe-utils": "^3.5.14",
|
||||
"yarn": "^1.22.22"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@purge-icons/generated": "^0.9.0",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/node": "^20.10.5",
|
||||
"@types/splitpanes": "^2.2.6",
|
||||
"@vitejs/plugin-vue": "^4.5.2",
|
||||
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
||||
"sass": "^1.69.5",
|
||||
"typescript": "^5.2.2",
|
||||
"unplugin-auto-import": "^0.16.7",
|
||||
"vite": "^5.0.8",
|
||||
"vite-plugin-mkcert": "^1.17.3",
|
||||
"vue-tsc": "^1.8.25"
|
||||
}
|
||||
"name": "canneng-admin",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite --mode dev",
|
||||
"dev:jibei": "vite --mode jibei",
|
||||
"dev:hainan": "vite --mode hainan",
|
||||
"dev:qujing": "vite --mode qujing",
|
||||
"dev:LN": "vite --mode LN",
|
||||
"dev:LNqr": "vite --mode LNqr",
|
||||
"dev:removeMode": "vite --mode removeMode",
|
||||
"build": "vite build --mode dev",
|
||||
"build:jibei": "vite build --mode jibei",
|
||||
"build:hainan": "vite build --mode hainan",
|
||||
"build:qujing": "vite build --mode qujing",
|
||||
"build:LN": "vite build --mode LN",
|
||||
"build:LNqr": "vite build --mode LNqr",
|
||||
"build:removeMode": "vite build --mode removeMode",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "^7.0.2",
|
||||
"@element-plus/icons-vue": "^2.3.1",
|
||||
"@form-create/designer": "^3.1.3",
|
||||
"@form-create/element-ui": "^3.1.24",
|
||||
"@fortawesome/fontawesome-free": "^6.5.1",
|
||||
"@kjgl77/datav-vue3": "^1.7.4",
|
||||
"@vue-office/docx": "^1.6.3",
|
||||
"@vue-office/excel": "^1.7.8",
|
||||
"@vue-office/pdf": "^2.0.2",
|
||||
"@vueuse/core": "^10.7.0",
|
||||
"@wangeditor/editor": "^5.1.23",
|
||||
"@wangeditor/editor-for-vue": "^5.1.12",
|
||||
"@wangeditor/plugin-formula": "^1.0.11",
|
||||
"axios": "^1.6.2",
|
||||
"bpmn-js": "8.9.0",
|
||||
"bpmn-js-properties-panel": "0.46.0",
|
||||
"bpmn-js-token-simulation": "^0.10.0",
|
||||
"bpmn-moddle": "^6.0.0",
|
||||
"camunda-bpmn-moddle": "^7.0.1",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dayjs": "^1.11.10",
|
||||
"diagram-js": "^11.4.1",
|
||||
"diagram-js-minimap": "^2.0.4",
|
||||
"echarts": "^5.4.3",
|
||||
"echarts-gl": "^2.0.9",
|
||||
"echarts-liquidfill": "^3.1.0",
|
||||
"echarts4": "npm:echarts@^4.9.0",
|
||||
"element-plus": "^2.9.11",
|
||||
"exceljs": "^4.4.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"grid-layout-plus": "^1.1.0",
|
||||
"html2canvas": "^1.4.1",
|
||||
"jquery": "^3.7.1",
|
||||
"js-pinyin": "^0.2.5",
|
||||
"jsencrypt": "^3.3.2",
|
||||
"katex": "^0.16.11",
|
||||
"less": "^4.2.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"luckyexcel": "^1.0.1",
|
||||
"luckysheet": "^2.1.13",
|
||||
"mathjax": "^3.2.2",
|
||||
"min-dash": "^4.2.1",
|
||||
"mitt": "^3.0.1",
|
||||
"mqtt": "^5.13.3",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.1.7",
|
||||
"pinia-plugin-persistedstate": "^3.2.1",
|
||||
"qs": "^6.12.0",
|
||||
"screenfull": "^6.0.2",
|
||||
"splitpanes": "^3.1.5",
|
||||
"steady-xml": "0.1.0",
|
||||
"svg-pan-zoom": "^3.6.2",
|
||||
"use-element-plus-theme": "^0.0.5",
|
||||
"vexip-ui": "^2.3.28",
|
||||
"vue": "^3.3.11",
|
||||
"vue-baidu-map-3x": "^1.0.35",
|
||||
"vue-baidu-map-offline": "^1.0.7",
|
||||
"vue-demi": "^0.14.8",
|
||||
"vue-draggable-resizable": "3.0.0-beta.2",
|
||||
"vue-i18n": "9.10.2",
|
||||
"vue-katex": "^0.5.0",
|
||||
"vue-router": "4",
|
||||
"vue-types": "^5.1.1",
|
||||
"vxe-pc-ui": "~4.15.19",
|
||||
"vxe-table": "^4.19.22",
|
||||
"vxe-table-plugin-export-xlsx": "^4.0.7",
|
||||
"web-storage-cache": "^1.1.1",
|
||||
"xe-utils": "^3.5.14",
|
||||
"yarn": "^1.22.22"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@purge-icons/generated": "^0.9.0",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/node": "^20.10.5",
|
||||
"@types/splitpanes": "^2.2.6",
|
||||
"@vitejs/plugin-vue": "^4.5.2",
|
||||
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
||||
"sass": "^1.69.5",
|
||||
"typescript": "^5.2.2",
|
||||
"unplugin-auto-import": "^0.16.7",
|
||||
"vite": "^5.0.8",
|
||||
"vite-plugin-mkcert": "^1.17.3",
|
||||
"vue-tsc": "^1.8.25"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4747,10 +4747,11 @@ window.BMAP_AUTHENTIC_KEY = ''
|
||||
c.Nm
|
||||
? c.Nm.sa(b)
|
||||
: ((c.Nm = new U(b, {
|
||||
icon: new qc(G.qa + 'blank.gif', {
|
||||
width: 1,
|
||||
height: 1
|
||||
}),
|
||||
// icon: new qc(G.qa + 'blank.gif', {
|
||||
// width: 1,
|
||||
// height: 1
|
||||
// }),
|
||||
icon: '',
|
||||
offset: new O(0, 0),
|
||||
clickable: t
|
||||
})),
|
||||
@@ -5886,7 +5887,7 @@ window.BMAP_AUTHENTIC_KEY = ''
|
||||
Qc.prototype.co = function () {
|
||||
this.Gb.src =
|
||||
0 < z.ca.ia && 6 >= z.ca.ia && this.GJ
|
||||
? G.qa + 'blank.gif'
|
||||
? '' //G.qa + 'blank.gif'
|
||||
: '' !== this.src && this.Gb.src == this.src
|
||||
? this.src + '&t = ' + Date.now()
|
||||
: this.src
|
||||
|
||||
16
src/App.vue
16
src/App.vue
@@ -9,14 +9,20 @@ import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
|
||||
import useSetTheme from '@/utils/setTheme'
|
||||
import { onMounted } from 'vue'
|
||||
useSetTheme()
|
||||
onMounted(async () => {
|
||||
const fetchMqttUrl = async () => {
|
||||
const response = await fetch('/')
|
||||
const WebSocketUrl:any = response.headers.get('X-WebSocket-Url')
|
||||
const WebSocketUrl2:any = response.headers.get('X-WebSocket-Url2')
|
||||
const MqttUrl:any = response.headers.get('X-MqttUrl-Url')
|
||||
localStorage.setItem('WebSocketUrl2', WebSocketUrl2)
|
||||
const WebSocketUrl: any = response.headers.get('X-WebSocket-Url')
|
||||
const WebSocketUrl2: any = response.headers.get('X-WebSocket-Url2')
|
||||
const WebSocketUrl3: any = response.headers.get('X-WebSocket-Url3')
|
||||
const MqttUrl: any = response.headers.get('X-MqttUrl-Url')
|
||||
localStorage.setItem('WebSocketUrl', WebSocketUrl)
|
||||
localStorage.setItem('WebSocketUrl2', WebSocketUrl2)
|
||||
localStorage.setItem('WebSocketUrl3', WebSocketUrl3)
|
||||
localStorage.setItem('MqttUrl', MqttUrl)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchMqttUrl()
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 获取区域中断终端
|
||||
export function getAreaOffDev(data) {
|
||||
export function getAreaOffDev(data:any) {
|
||||
return request({
|
||||
url: '/device-boot/device/getAreaOffDev',
|
||||
method: 'post',
|
||||
@@ -9,10 +9,28 @@ export function getAreaOffDev(data) {
|
||||
})
|
||||
}
|
||||
// 获取区域中断终端
|
||||
export function getYwZtSubstation(data) {
|
||||
export function getYwZtSubstation(data:any) {
|
||||
return request({
|
||||
url: '/device-boot/ywZt/getYwZtSubstation',
|
||||
method: 'GET',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
|
||||
//终端周期检测
|
||||
export function terminalCheckPage(data:any) {
|
||||
return request({
|
||||
url: '/device-boot/alarm/terminalCheckPage',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function userCheckUpload(data:any) {
|
||||
return request({
|
||||
url: '/device-boot/userReport/userCheckUpload',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -4,6 +4,10 @@ import request from '@/utils/request'
|
||||
export function getSubLineGiveAnAlarm(data: any) {
|
||||
return request({ url: '/harmonic-boot/gridDiagram/getSubLineGiveAnAlarm', method: 'post', data })
|
||||
}
|
||||
|
||||
export function getAreaObjAlarm(data: any) {
|
||||
return request({ url: '/harmonic-boot/gridDiagram/getAreaObjAlarm', method: 'post', data })
|
||||
}
|
||||
// 变电站详细列表
|
||||
export function getPollutionAlarmPageData(data: any) {
|
||||
return request({ url: '/harmonic-boot/gridDiagram/getPollutionAlarmPageData', method: 'post', data })
|
||||
|
||||
@@ -1,215 +1,250 @@
|
||||
import request from '@/utils/request'
|
||||
import { LoginData } from '@/api/types'
|
||||
import { useAdminInfo } from '@/stores/adminInfo'
|
||||
import { sm3Digest } from '@/assets/commjs/sm3.js'
|
||||
import { sm2, encrypt } from '@/assets/commjs/sm2.js'
|
||||
|
||||
// 获取公钥
|
||||
export function gongkey(params?: any) {
|
||||
if (!params) {
|
||||
const adminInfo = useAdminInfo()
|
||||
params = {
|
||||
loginName: encrypt(adminInfo.$state.loginName)
|
||||
}
|
||||
}
|
||||
return request({
|
||||
url: '/user-boot/user/generateSm2Key',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export async function pwdSm3(pwd: any, loginName?: string) {
|
||||
let publicKey = await gongkey(
|
||||
loginName
|
||||
? {
|
||||
loginName: encrypt(loginName)
|
||||
}
|
||||
: false
|
||||
)
|
||||
let sm3Pwd = sm3Digest(pwd) //SM3加密
|
||||
return sm2(sm3Pwd + '|' + pwd, publicKey.data, 0)
|
||||
}
|
||||
|
||||
//登录获取token
|
||||
export async function login(params: any) {
|
||||
if (params.refresh_token == undefined) {
|
||||
params.password = await pwdSm3(params.password, params.username)
|
||||
}
|
||||
params.username = encrypt(params.username)
|
||||
return request({
|
||||
url: '/pqs-auth/oauth/token',
|
||||
method: 'post',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
//获取用户信息
|
||||
export function getUserById() {
|
||||
const adminInfo = useAdminInfo()
|
||||
return request({
|
||||
url: '/user-boot/user/getUserById?id=' + adminInfo.userIndex,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 刷新token
|
||||
// 导出一个名为refreshToken的函数,该函数返回一个Promise对象
|
||||
export function refreshToken(): Promise<any> {
|
||||
// 调用useAdminInfo函数获取管理员信息,并将其赋值给adminInfo变量
|
||||
const adminInfo = useAdminInfo()
|
||||
// 调用login函数,传入一个对象作为参数,该对象包含grant_type、refresh_token和username三个属性
|
||||
// grant_type设置为'refresh_token',表示使用刷新令牌的方式获取新的访问令牌
|
||||
// refresh_token使用adminInfo中的refresh_token属性
|
||||
// username使用adminInfo中的loginName属性
|
||||
// 返回login函数的调用结果,即一个Promise对象
|
||||
return login({
|
||||
grant_type: 'refresh_token',
|
||||
refresh_token: adminInfo.refresh_token,
|
||||
username: adminInfo.loginName
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取营销用户列表
|
||||
* @returns {AxiosPromise}
|
||||
*/
|
||||
export const getMarketList = () => {
|
||||
return request({
|
||||
url: '/user-boot/user/getMarketList',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
export function add(data: any) {
|
||||
return request({
|
||||
url: '/user-boot/user/add',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function edit(data: any) {
|
||||
return request({
|
||||
url: '/user-boot/user/update',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export async function passwordConfirm(pwd: string) {
|
||||
return request({
|
||||
url: '/user-boot/user/passwordConfirm?password=' + (await pwdSm3(pwd)),
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function deluser(data: any) {
|
||||
return request({
|
||||
url: '/user-boot/user/delete',
|
||||
method: 'delete',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
|
||||
export function activateUser(data: any) {
|
||||
return request({
|
||||
url: '/user-boot/user/activateUser',
|
||||
method: 'put',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
|
||||
export async function updatePassword(params: any) {
|
||||
return request({
|
||||
url: '/user-boot/user/updatePassword',
|
||||
method: 'put',
|
||||
params: {
|
||||
id: params.id,
|
||||
newPassword: await pwdSm3(params.newPassword)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export async function updateFirstPassword(params: any) {
|
||||
return request({
|
||||
url: '/user-boot/user/updateFirstPassword',
|
||||
method: 'put',
|
||||
data: {
|
||||
name: encrypt(params.name),
|
||||
password: await pwdSm3(params.password, params.name)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function checkUser(data: any) {
|
||||
return request({
|
||||
url: '/user-boot/user/check',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
export function existMonitorDeptTree() {
|
||||
return request({
|
||||
url: '/user-boot/dept/existMonitorDeptTree',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
// 获取用户
|
||||
export function getUserByRoleType(data: any) {
|
||||
return request({
|
||||
url: '/user-boot/user/getUserByRoleType?roleType=' + data,
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
||||
// 获取部门下所有用户
|
||||
export function listAllUserByDeptId(data: any) {
|
||||
return request({
|
||||
url: '/user-boot/user/listAllUserByDeptId?deptId=' + data,
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
||||
// 根据id获取所有用户信息
|
||||
export function getUserListByIds(data: any) {
|
||||
return request({
|
||||
url: '/user-boot/user/getUserListByIds',
|
||||
method: 'POST',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有用户不包括管理员
|
||||
*/
|
||||
export const getUserSimpleList = () => {
|
||||
return request({
|
||||
url: '/user-boot/user/simpleList',
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有用户包括管理员
|
||||
*/
|
||||
export const getAllUserSimpleList = () => {
|
||||
return request({
|
||||
url: '/user-boot/user/getAllUserSimpleList',
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
||||
export const getSysConfig = () => {
|
||||
return request({
|
||||
url: '/system-boot/config/getSysConfig',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
// 驾驶舱组件配置
|
||||
export const componentTree = () => {
|
||||
return request({
|
||||
url: '/user-boot/component/componentTree',
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
import request from '@/utils/request'
|
||||
import { LoginData } from '@/api/types'
|
||||
import { useAdminInfo } from '@/stores/adminInfo'
|
||||
import { sm3Digest } from '@/assets/commjs/sm3.js'
|
||||
import { sm2, encrypt } from '@/assets/commjs/sm2.js'
|
||||
|
||||
// 获取公钥
|
||||
export function gongkey(params?: any) {
|
||||
if (!params) {
|
||||
const adminInfo = useAdminInfo()
|
||||
params = {
|
||||
loginName: encrypt(adminInfo.$state.loginName)
|
||||
}
|
||||
}
|
||||
return request({
|
||||
url: '/user-boot/user/generateSm2Key',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export async function pwdSm3(pwd: any, loginName?: string) {
|
||||
let publicKey = await gongkey(
|
||||
loginName
|
||||
? {
|
||||
loginName: encrypt(loginName)
|
||||
}
|
||||
: false
|
||||
)
|
||||
let sm3Pwd = sm3Digest(pwd) //SM3加密
|
||||
return sm2(sm3Pwd + '|' + pwd, publicKey.data, 0)
|
||||
}
|
||||
|
||||
//登录获取token
|
||||
export async function login(params: any) {
|
||||
if (params.refresh_token == undefined) {
|
||||
params.password = await pwdSm3(params.password, params.username)
|
||||
}
|
||||
params.username = encrypt(params.username)
|
||||
return request({
|
||||
url: '/pqs-auth/oauth/token',
|
||||
method: 'post',
|
||||
params
|
||||
})
|
||||
}
|
||||
//辽宁嵌入登录获取token
|
||||
export async function loginLNqr(data: any) {
|
||||
return request({
|
||||
url: '/pqs-auth/oauth/lnLogin',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
|
||||
export async function lnRefreshToken(data: any) {
|
||||
return request({
|
||||
url: '/pqs-auth/oauth/lnRefreshToken',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
|
||||
export async function logout() {
|
||||
return request({
|
||||
url: '/pqs-auth/oauth/logout',
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//获取用户信息
|
||||
export function getUserById() {
|
||||
const adminInfo = useAdminInfo()
|
||||
return request({
|
||||
url: '/user-boot/user/getUserById?id=' + adminInfo.userIndex,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 刷新token
|
||||
// 导出一个名为refreshToken的函数,该函数返回一个Promise对象
|
||||
export function refreshToken(): Promise<any> {
|
||||
// 调用useAdminInfo函数获取管理员信息,并将其赋值给adminInfo变量
|
||||
const adminInfo = useAdminInfo()
|
||||
// 调用login函数,传入一个对象作为参数,该对象包含grant_type、refresh_token和username三个属性
|
||||
// grant_type设置为'refresh_token',表示使用刷新令牌的方式获取新的访问令牌
|
||||
// refresh_token使用adminInfo中的refresh_token属性
|
||||
// username使用adminInfo中的loginName属性
|
||||
// 返回login函数的调用结果,即一个Promise对象
|
||||
return login({
|
||||
grant_type: 'refresh_token',
|
||||
refresh_token: adminInfo.refresh_token,
|
||||
username: adminInfo.loginName
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function lnRefreshTokenTo(): Promise<any> {
|
||||
// 调用useAdminInfo函数获取管理员信息,并将其赋值给adminInfo变量
|
||||
const adminInfo = useAdminInfo()
|
||||
return lnRefreshToken({
|
||||
refreshToken: adminInfo.refresh_token,
|
||||
clientId: "njcn",
|
||||
clientSecret:"njcnpqs"
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取营销用户列表
|
||||
* @returns {AxiosPromise}
|
||||
*/
|
||||
export const getMarketList = () => {
|
||||
return request({
|
||||
url: '/user-boot/user/getMarketList',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
export function add(data: any) {
|
||||
return request({
|
||||
url: '/user-boot/user/add',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function edit(data: any) {
|
||||
return request({
|
||||
url: '/user-boot/user/update',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export async function passwordConfirm(pwd: string) {
|
||||
return request({
|
||||
url: '/user-boot/user/passwordConfirm?password=' + (await pwdSm3(pwd)),
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function deluser(data: any) {
|
||||
return request({
|
||||
url: '/user-boot/user/delete',
|
||||
method: 'delete',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
|
||||
export function activateUser(data: any) {
|
||||
return request({
|
||||
url: '/user-boot/user/activateUser',
|
||||
method: 'put',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
|
||||
export async function updatePassword(params: any) {
|
||||
return request({
|
||||
url: '/user-boot/user/updatePassword',
|
||||
method: 'put',
|
||||
params: {
|
||||
id: params.id,
|
||||
newPassword: await pwdSm3(params.newPassword)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export async function updateFirstPassword(params: any) {
|
||||
return request({
|
||||
url: '/user-boot/user/updateFirstPassword',
|
||||
method: 'put',
|
||||
data: {
|
||||
name: encrypt(params.name),
|
||||
password: await pwdSm3(params.password, params.name)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function checkUser(data: any) {
|
||||
return request({
|
||||
url: '/user-boot/user/check',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
export function existMonitorDeptTree() {
|
||||
return request({
|
||||
url: '/user-boot/dept/existMonitorDeptTree',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
// 获取用户
|
||||
export function getUserByRoleType(data: any) {
|
||||
return request({
|
||||
url: '/user-boot/user/getUserByRoleType?roleType=' + data,
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
||||
// 获取部门下所有用户
|
||||
export function listAllUserByDeptId(data: any) {
|
||||
return request({
|
||||
url: '/user-boot/user/listAllUserByDeptId?deptId=' + data,
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
||||
// 根据id获取所有用户信息
|
||||
export function getUserListByIds(data: any) {
|
||||
return request({
|
||||
url: '/user-boot/user/getUserListByIds',
|
||||
method: 'POST',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有用户不包括管理员
|
||||
*/
|
||||
export const getUserSimpleList = () => {
|
||||
return request({
|
||||
url: '/user-boot/user/simpleList',
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有用户包括管理员
|
||||
*/
|
||||
export const getAllUserSimpleList = () => {
|
||||
return request({
|
||||
url: '/user-boot/user/getAllUserSimpleList',
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
||||
export const getSysConfig = () => {
|
||||
return request({
|
||||
url: '/system-boot/config/getSysConfig',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
// 驾驶舱组件配置
|
||||
export const componentTree = () => {
|
||||
return request({
|
||||
url: '/user-boot/component/componentTree',
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
||||
BIN
src/assets/imgs/m0.png
Normal file
BIN
src/assets/imgs/m0.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
BIN
src/assets/imgs/m1.png
Normal file
BIN
src/assets/imgs/m1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.2 KiB |
BIN
src/assets/imgs/m2.png
Normal file
BIN
src/assets/imgs/m2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.9 KiB |
BIN
src/assets/imgs/m3.png
Normal file
BIN
src/assets/imgs/m3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.6 KiB |
BIN
src/assets/imgs/m4.png
Normal file
BIN
src/assets/imgs/m4.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
@@ -30,7 +30,7 @@ import { downloadFile } from '@/api/system-boot/file'
|
||||
import { previewFile } from '@/utils/fileDownLoad'
|
||||
|
||||
const { push, options, currentRoute } = useRouter()
|
||||
const VITE_FLAG = import.meta.env.VITE_NAME == 'jibei'
|
||||
const VITE_FLAG = false//import.meta.env.VITE_NAME == 'jibei'
|
||||
// const url = 'http://192.168.1.22:9009/excelreport' + currentRoute.value.href?.split('?')[1]
|
||||
const url = ref('')
|
||||
const excelOptions = ref({})
|
||||
|
||||
@@ -126,7 +126,8 @@ const prop = defineProps({
|
||||
width: { type: [String, Number] },
|
||||
height: { type: [String, Number] },
|
||||
timeKey: { type: [String, Number] },
|
||||
timeValue: { type: Object }
|
||||
timeValue: { type: Object },
|
||||
searchKey: { type: [String, Number] }
|
||||
})
|
||||
|
||||
const headerHeight = ref(57)
|
||||
@@ -347,22 +348,22 @@ onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
watch(
|
||||
() => prop.timeKey,
|
||||
() => prop.searchKey,
|
||||
val => {
|
||||
tableStore.index()
|
||||
}
|
||||
)
|
||||
watch(
|
||||
() => prop.timeValue,
|
||||
// watch(
|
||||
// () => prop.timeValue,
|
||||
|
||||
val => {
|
||||
tableStore.index()
|
||||
},
|
||||
// val => {
|
||||
// tableStore.index()
|
||||
// },
|
||||
|
||||
{
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
// {
|
||||
// deep: true
|
||||
// }
|
||||
// )
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import '@/assets/font/iconfont.css';
|
||||
|
||||
@@ -122,7 +122,8 @@ const prop = defineProps({
|
||||
width: { type: [String, Number] },
|
||||
height: { type: [String, Number] },
|
||||
timeKey: { type: [String, Number] },
|
||||
timeValue: { type: Object }
|
||||
timeValue: { type: Object },
|
||||
searchKey: { type: [String, Number] }
|
||||
})
|
||||
|
||||
const headerHeight = ref(57)
|
||||
@@ -183,7 +184,7 @@ const tableStore: any = new TableStore({
|
||||
if (tableStore.table.params.statisticalType.name == '终端厂家') {
|
||||
return k.citTotalNum != 0
|
||||
} else {
|
||||
return k.citName != '上送国网' && k.citName != '非上送国网'
|
||||
return !k.citName.includes('上送')
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -329,22 +330,22 @@ onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
watch(
|
||||
() => prop.timeKey,
|
||||
() => prop.searchKey,
|
||||
val => {
|
||||
tableStore.index()
|
||||
}
|
||||
)
|
||||
watch(
|
||||
() => prop.timeValue,
|
||||
// watch(
|
||||
// () => prop.timeValue,
|
||||
|
||||
val => {
|
||||
tableStore.index()
|
||||
},
|
||||
// val => {
|
||||
// tableStore.index()
|
||||
// },
|
||||
|
||||
{
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
// {
|
||||
// deep: true
|
||||
// }
|
||||
// )
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import '@/assets/font/iconfont.css';
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
@selectChange="selectChange"
|
||||
datePicker
|
||||
v-if="fullscreen"
|
||||
></TableHeader>
|
||||
>
|
||||
</TableHeader>
|
||||
<div
|
||||
class="monitoringPoints"
|
||||
:style="{
|
||||
@@ -120,7 +121,8 @@ const prop = defineProps({
|
||||
width: { type: [String, Number] },
|
||||
height: { type: [String, Number] },
|
||||
timeKey: { type: [String, Number] },
|
||||
timeValue: { type: Object }
|
||||
timeValue: { type: Object },
|
||||
searchKey: { type: [String, Number] }
|
||||
})
|
||||
|
||||
const headerHeight = ref(57)
|
||||
@@ -181,7 +183,7 @@ const tableStore: any = new TableStore({
|
||||
if (tableStore.table.params.statisticalType.name == '终端厂家') {
|
||||
return k.citTotalNum != 0
|
||||
} else {
|
||||
return k.citName != '上送国网' && k.citName != '非上送国网'
|
||||
return !k.citName.includes('上送')
|
||||
}
|
||||
})
|
||||
|
||||
@@ -328,22 +330,22 @@ onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
watch(
|
||||
() => prop.timeKey,
|
||||
() => prop.searchKey,
|
||||
val => {
|
||||
tableStore.index()
|
||||
}
|
||||
)
|
||||
watch(
|
||||
() => prop.timeValue,
|
||||
// watch(
|
||||
// () => prop.timeValue,
|
||||
|
||||
val => {
|
||||
tableStore.index()
|
||||
},
|
||||
// val => {
|
||||
// tableStore.index()
|
||||
// },
|
||||
|
||||
{
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
// {
|
||||
// deep: true
|
||||
// }
|
||||
// )
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import '@/assets/font/iconfont.css';
|
||||
|
||||
@@ -150,7 +150,8 @@ const prop = defineProps({
|
||||
width: { type: [String, Number] },
|
||||
height: { type: [String, Number] },
|
||||
timeKey: { type: [String, Number] },
|
||||
timeValue: { type: Object }
|
||||
timeValue: { type: Object },
|
||||
searchKey: { type: [String, Number] }
|
||||
})
|
||||
|
||||
const headerHeight = ref(57)
|
||||
@@ -233,7 +234,7 @@ const tableStore: any = new TableStore({
|
||||
if (tableStore.table.params.statisticalType.name == '终端厂家') {
|
||||
return k.count != 0
|
||||
} else {
|
||||
return k.name != '上送国网' && k.name != '非上送国网'
|
||||
return !k.name.includes('上送')
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -246,22 +247,28 @@ onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
watch(
|
||||
() => prop.timeKey,
|
||||
() => prop.searchKey,
|
||||
val => {
|
||||
tableStore.index()
|
||||
}
|
||||
)
|
||||
watch(
|
||||
() => prop.timeValue,
|
||||
// watch(
|
||||
// () => prop.timeKey,
|
||||
// val => {
|
||||
// tableStore.index()
|
||||
// }
|
||||
// )
|
||||
// watch(
|
||||
// () => prop.timeValue,
|
||||
|
||||
val => {
|
||||
tableStore.index()
|
||||
},
|
||||
// val => {
|
||||
// tableStore.index()
|
||||
// },
|
||||
|
||||
{
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
// {
|
||||
// deep: true
|
||||
// }
|
||||
// )
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import '@/assets/font/iconfont.css';
|
||||
|
||||
322
src/components/echarts/rmsWorker.js
Normal file
322
src/components/echarts/rmsWorker.js
Normal file
@@ -0,0 +1,322 @@
|
||||
// 辅助函数
|
||||
const getMax = (temp, tempA, tempB, tempC) => {
|
||||
temp = temp > tempA ? temp : tempA
|
||||
temp = temp > tempB ? temp : tempB
|
||||
if (tempC !== undefined) {
|
||||
temp = temp > tempC ? temp : tempC
|
||||
}
|
||||
return temp
|
||||
}
|
||||
|
||||
const getMaxTwo = (temp, tempA, tempB) => {
|
||||
temp = temp > tempA ? temp : tempA
|
||||
temp = temp > tempB ? temp : tempB
|
||||
return temp
|
||||
}
|
||||
|
||||
const getMin = (temp, tempA, tempB, tempC) => {
|
||||
temp = temp < tempA ? temp : tempA
|
||||
temp = temp < tempB ? temp : tempB
|
||||
if (tempC !== undefined) {
|
||||
temp = temp < tempC ? temp : tempC
|
||||
}
|
||||
return temp
|
||||
}
|
||||
|
||||
const getMinOpen = (temp, tempA, tempB) => {
|
||||
temp = temp < tempA ? temp : tempA
|
||||
temp = temp < tempB ? temp : tempB
|
||||
return temp
|
||||
}
|
||||
|
||||
// 数据处理函数
|
||||
const fliteWaveData = (wp, step, iphasicValue, isOpen) => {
|
||||
const rmsData = wp.listRmsData
|
||||
const pt = Number(wp.pt) / 1000
|
||||
const ct = Number(wp.ct)
|
||||
const titleList = wp.waveTitle
|
||||
let xishu = pt
|
||||
let aTitle = '',
|
||||
bTitle = '',
|
||||
cTitle = '',
|
||||
unit = '电压'
|
||||
let rmsvFirstX = 0,
|
||||
rmsvFirstY = 0,
|
||||
rmsvSecondX = 0,
|
||||
rmsvSecondY = 0,
|
||||
firstZhou = 'a',
|
||||
secondeZhou = 'a'
|
||||
let ifmax = 0,
|
||||
ifmin = 0,
|
||||
ismax = 0,
|
||||
ismin = 0,
|
||||
rfmax = 0,
|
||||
rfmin = 0,
|
||||
rsmax = 0,
|
||||
rsmin = 0
|
||||
|
||||
const shunshiFA = []
|
||||
const shunshiFB = []
|
||||
const shunshiFC = []
|
||||
const shunshiSA = []
|
||||
const shunshiSB = []
|
||||
const shunshiSC = []
|
||||
const rmsFA = []
|
||||
const rmsFB = []
|
||||
const rmsFC = []
|
||||
const rmsSA = []
|
||||
const rmsSB = []
|
||||
const rmsSC = []
|
||||
|
||||
if (titleList[iphasicValue * step + 1]?.substring(0, 1) !== 'U') {
|
||||
xishu = ct
|
||||
unit = '电流'
|
||||
}
|
||||
|
||||
for (let i = 1; i <= iphasicValue; i++) {
|
||||
switch (i) {
|
||||
case 1:
|
||||
aTitle = titleList[iphasicValue * step + i]?.substring(1) || ''
|
||||
break
|
||||
case 2:
|
||||
bTitle = titleList[iphasicValue * step + i]?.substring(1) || ''
|
||||
break
|
||||
case 3:
|
||||
cTitle = titleList[iphasicValue * step + i]?.substring(1) || ''
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (rmsData[0] && rmsData[0][iphasicValue * step + 1] !== undefined) {
|
||||
rfmax = rmsData[0][iphasicValue * step + 1] * xishu
|
||||
rfmin = rmsData[0][iphasicValue * step + 1] * xishu
|
||||
rmsvFirstY = rmsData[0][iphasicValue * step + 1] * xishu
|
||||
rmsvFirstX = rmsData[0][0]
|
||||
rsmax = rmsData[0][iphasicValue * step + 1]
|
||||
rsmin = rmsData[0][iphasicValue * step + 1]
|
||||
rmsvSecondY = rmsData[0][iphasicValue * step + 1]
|
||||
rmsvSecondX = rmsData[0][0]
|
||||
}
|
||||
|
||||
for (let rms = 0; rms < rmsData.length; rms++) {
|
||||
if (!rmsData[rms] || rmsData[rms][iphasicValue * step + 1] === undefined) {
|
||||
break
|
||||
}
|
||||
|
||||
switch (iphasicValue) {
|
||||
case 1:
|
||||
const rmsFirstA = rmsData[rms][iphasicValue * step + 1] * xishu
|
||||
rmsFA.push([rmsData[rms][0], rmsFirstA])
|
||||
rfmax = rfmax > rmsFirstA ? rfmax : rmsFirstA
|
||||
rfmin = rfmin < rmsFirstA ? rfmin : rmsFirstA
|
||||
if (rfmin < rmsvFirstY) {
|
||||
rmsvFirstY = rfmin
|
||||
firstZhou = 'a'
|
||||
rmsvFirstX = rmsData[rms][0]
|
||||
}
|
||||
|
||||
const rmsSecondA = rmsData[rms][iphasicValue * step + 1]
|
||||
rmsSA.push([rmsData[rms][0], rmsSecondA])
|
||||
rsmax = rsmax > rmsSecondA ? rsmax : rmsSecondA
|
||||
rsmin = rsmin < rmsSecondA ? rsmin : rmsSecondA
|
||||
if (rsmin < rmsvSecondY) {
|
||||
rmsvSecondY = rsmin
|
||||
secondeZhou = 'a'
|
||||
rmsvSecondX = rmsData[rms][0]
|
||||
}
|
||||
break
|
||||
case 2:
|
||||
const rmsFirstA2 = rmsData[rms][iphasicValue * step + 1] * xishu
|
||||
const rmsFirstB2 = rmsData[rms][iphasicValue * step + 2] * xishu
|
||||
rmsFA.push([rmsData[rms][0], rmsFirstA2])
|
||||
rmsFB.push([rmsData[rms][0], rmsFirstB2])
|
||||
rfmax = getMaxTwo(rfmax, rmsFirstA2, rmsFirstB2)
|
||||
rfmin = getMinOpen(rfmin, rmsFirstA2, rmsFirstB2)
|
||||
if (rfmin < rmsvFirstY) {
|
||||
rmsvFirstY = rfmin
|
||||
if (rfmin === rmsFirstA2) {
|
||||
firstZhou = 'a'
|
||||
} else if (rfmin === rmsFirstB2) {
|
||||
firstZhou = 'b'
|
||||
}
|
||||
rmsvFirstX = rmsData[rms][0]
|
||||
}
|
||||
|
||||
const rmsSecondA2 = rmsData[rms][iphasicValue * step + 1]
|
||||
const rmsSecondB2 = rmsData[rms][iphasicValue * step + 2]
|
||||
rmsSA.push([rmsData[rms][0], rmsSecondA2])
|
||||
rmsSB.push([rmsData[rms][0], rmsSecondB2])
|
||||
rsmax = getMaxTwo(rsmax, rmsSecondA2, rmsSecondB2)
|
||||
rsmin = getMinOpen(rsmin, rmsSecondA2, rmsSecondB2)
|
||||
if (rsmin < rmsvSecondY) {
|
||||
rmsvSecondY = rsmin
|
||||
if (rsmin === rmsSecondA2) {
|
||||
secondeZhou = 'a'
|
||||
} else if (rsmin === rmsSecondB2) {
|
||||
secondeZhou = 'b'
|
||||
}
|
||||
rmsvSecondX = rmsData[rms][0]
|
||||
}
|
||||
break
|
||||
case 3:
|
||||
const rmsFirstA3 = rmsData[rms][iphasicValue * step + 1] * xishu
|
||||
const rmsFirstB3 = rmsData[rms][iphasicValue * step + 2] * xishu
|
||||
const rmsFirstC3 = rmsData[rms][iphasicValue * step + 3] * xishu
|
||||
rmsFA.push([rmsData[rms][0], rmsFirstA3])
|
||||
rmsFB.push([rmsData[rms][0], rmsFirstB3])
|
||||
rmsFC.push([rmsData[rms][0], rmsFirstC3])
|
||||
rfmax = getMax(rfmax, rmsFirstA3, rmsFirstB3, rmsFirstC3)
|
||||
rfmin = isOpen
|
||||
? getMinOpen(rfmin, rmsFirstA3, rmsFirstC3)
|
||||
: getMin(rfmin, rmsFirstA3, rmsFirstB3, rmsFirstC3)
|
||||
if (rfmin < rmsvFirstY) {
|
||||
rmsvFirstY = rfmin
|
||||
if (rfmin === rmsFirstA3) {
|
||||
firstZhou = 'a'
|
||||
} else if (rfmin === rmsFirstB3) {
|
||||
firstZhou = 'b'
|
||||
} else {
|
||||
firstZhou = 'c'
|
||||
}
|
||||
rmsvFirstX = rmsData[rms][0]
|
||||
}
|
||||
|
||||
const rmsSecondA3 = rmsData[rms][iphasicValue * step + 1]
|
||||
const rmsSecondB3 = rmsData[rms][iphasicValue * step + 2]
|
||||
const rmsSecondC3 = rmsData[rms][iphasicValue * step + 3]
|
||||
rmsSA.push([rmsData[rms][0], rmsSecondA3])
|
||||
rmsSB.push([rmsData[rms][0], rmsSecondB3])
|
||||
rmsSC.push([rmsData[rms][0], rmsSecondC3])
|
||||
rsmax = getMax(rsmax, rmsSecondA3, rmsSecondB3, rmsSecondC3)
|
||||
rsmin = isOpen
|
||||
? getMinOpen(rsmin, rmsSecondA3, rmsSecondC3)
|
||||
: getMin(rsmin, rmsSecondA3, rmsSecondB3, rmsSecondC3)
|
||||
if (rsmin < rmsvSecondY) {
|
||||
rmsvSecondY = rsmin
|
||||
if (rsmin === rmsSecondA3) {
|
||||
secondeZhou = 'a'
|
||||
} else if (rsmin === rmsSecondB3) {
|
||||
secondeZhou = 'b'
|
||||
} else {
|
||||
secondeZhou = 'c'
|
||||
}
|
||||
rmsvSecondX = rmsData[rms][0]
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
const instantF = { max: ifmax, min: ifmin }
|
||||
const instantS = { max: ismax, min: ismin }
|
||||
const RMSF = { max: rfmax, min: rfmin }
|
||||
const RMSS = { max: rsmax, min: rsmin }
|
||||
const RMSFMinDetail = { rmsvFirstX, rmsvFirstY, firstZhou }
|
||||
const RMSSMinDetail = { rmsvSecondX, rmsvSecondY, secondeZhou }
|
||||
const shunshiF = { shunshiFA, shunshiFB, shunshiFC }
|
||||
const shunshiS = { shunshiSA, shunshiSB, shunshiSC }
|
||||
const RMSFWave = { rmsFA, rmsFB, rmsFC }
|
||||
const RMSSWave = { rmsSA, rmsSB, rmsSC }
|
||||
const title = { aTitle, bTitle, cTitle, unit }
|
||||
|
||||
return {
|
||||
instantF,
|
||||
instantS,
|
||||
RMSF,
|
||||
RMSS,
|
||||
RMSFMinDetail,
|
||||
RMSSMinDetail,
|
||||
shunshiF,
|
||||
shunshiS,
|
||||
RMSFWave,
|
||||
RMSSWave,
|
||||
title,
|
||||
unit
|
||||
}
|
||||
}
|
||||
|
||||
// 监听消息
|
||||
self.onmessage = function (e) {
|
||||
const { wp, isOpen, value, boxoList, requestId } = e.data
|
||||
|
||||
try {
|
||||
const iphasicValue = wp.iphasic || 1
|
||||
|
||||
const picCounts = (wp.waveTitle.length - 1) / iphasicValue
|
||||
const waveDatas = []
|
||||
|
||||
for (let i = 0; i < picCounts; i++) {
|
||||
const data = fliteWaveData(wp, i, iphasicValue, isOpen, boxoList)
|
||||
waveDatas.push(data)
|
||||
}
|
||||
// 处理标题
|
||||
let titles = ''
|
||||
if (boxoList.systemType == 'pms') {
|
||||
titles =
|
||||
'变电站名称:' +
|
||||
boxoList.powerStationName +
|
||||
' 监测点名称:' +
|
||||
boxoList.measurementPointName +
|
||||
' 发生时刻:' +
|
||||
boxoList.startTime +
|
||||
' 暂降(骤升)幅值:' +
|
||||
(boxoList.featureAmplitude * 100).toFixed(2) +
|
||||
'% 持续时间:' +
|
||||
boxoList.duration +
|
||||
's'
|
||||
} else if (boxoList.systemType == 'ZL') {
|
||||
titles =
|
||||
(boxoList.engineeringName == undefined ? '' : ' 项目名称:' + boxoList.engineeringName) +
|
||||
' 监测点名称:' +
|
||||
boxoList.equipmentName +
|
||||
' 发生时刻:' +
|
||||
boxoList.startTime +
|
||||
' 暂降(骤升)幅值:' +
|
||||
boxoList.evtParamVVaDepth +
|
||||
'% 持续时间:' +
|
||||
boxoList.evtParamTm +
|
||||
's'
|
||||
} else if (boxoList.systemType == 'YPT') {
|
||||
titles =
|
||||
(boxoList.engineeringName == undefined ? '' : ' 项目名称:' + boxoList.engineeringName) +
|
||||
' 监测点名称:' +
|
||||
boxoList.lineName +
|
||||
' 发生时刻:' +
|
||||
boxoList.startTime +
|
||||
' 暂降(骤升)幅值:' +
|
||||
(boxoList.featureAmplitude * 100).toFixed(2) +
|
||||
'% 持续时间:' +
|
||||
boxoList.persistTime +
|
||||
's'
|
||||
} else {
|
||||
titles =
|
||||
' 变电站名称:' +
|
||||
boxoList.subName +
|
||||
' 监测点名称:' +
|
||||
boxoList.lineName +
|
||||
' 发生时刻:' +
|
||||
boxoList.startTime +
|
||||
' 暂降(骤升)幅值:' +
|
||||
(boxoList.featureAmplitude * 100).toFixed(2) +
|
||||
'% 持续时间:' +
|
||||
boxoList.duration +
|
||||
's'
|
||||
}
|
||||
// 发送处理结果回主线程
|
||||
self.postMessage({
|
||||
requestId,
|
||||
titles: titles,
|
||||
success: true,
|
||||
waveDatas,
|
||||
time: wp.time,
|
||||
type: wp.waveType,
|
||||
severity: wp.yzd,
|
||||
iphasic: iphasicValue
|
||||
})
|
||||
} catch (error) {
|
||||
self.postMessage({
|
||||
requestId,
|
||||
success: false,
|
||||
error: error.message
|
||||
})
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
207
src/components/echarts/shuWorker.js
Normal file
207
src/components/echarts/shuWorker.js
Normal file
@@ -0,0 +1,207 @@
|
||||
// waveData.worker.js
|
||||
self.addEventListener('message', function (e) {
|
||||
const { wp, value, iphasic, isOpen, boxoList, requestId } = e.data
|
||||
|
||||
// 处理波形数据的函数
|
||||
const fliteWaveData = (wp, step) => {
|
||||
// 将原有的fliteWaveData函数实现复制到这里
|
||||
const shunData = wp.listWaveData
|
||||
const pt = Number(wp.pt) / 1000
|
||||
const ct = Number(wp.ct)
|
||||
const titleList = wp.waveTitle
|
||||
let xishu = pt
|
||||
let aTitle = '',
|
||||
bTitle = '',
|
||||
cTitle = '',
|
||||
unit = '电压'
|
||||
let ifmax = 0,
|
||||
ifmin = 0,
|
||||
ismax = 0,
|
||||
ismin = 0
|
||||
|
||||
const shunshiFA = []
|
||||
const shunshiFB = []
|
||||
const shunshiFC = []
|
||||
const shunshiSA = []
|
||||
const shunshiSB = []
|
||||
const shunshiSC = []
|
||||
|
||||
if (shunData.length > 0) {
|
||||
if (titleList[iphasic * step + 1]?.substring(0, 1) !== 'U') {
|
||||
xishu = ct
|
||||
unit = '电流'
|
||||
}
|
||||
|
||||
for (let i = 1; i <= iphasic; i++) {
|
||||
switch (i) {
|
||||
case 1:
|
||||
aTitle = titleList[iphasic * step + i]?.substring(1) || ''
|
||||
break
|
||||
case 2:
|
||||
bTitle = titleList[iphasic * step + i]?.substring(1) || ''
|
||||
break
|
||||
case 3:
|
||||
cTitle = titleList[iphasic * step + i]?.substring(1) || ''
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (shunData[0][iphasic * step + 1] !== undefined) {
|
||||
ifmax = shunData[0][iphasic * step + 1] * xishu
|
||||
ifmin = shunData[0][iphasic * step + 1] * xishu
|
||||
ismax = shunData[0][iphasic * step + 1]
|
||||
ismin = shunData[0][iphasic * step + 1]
|
||||
}
|
||||
|
||||
for (let shun = 0; shun < shunData.length; shun++) {
|
||||
if (shunData[shun][iphasic * step + 1] === undefined) {
|
||||
break
|
||||
}
|
||||
|
||||
switch (iphasic) {
|
||||
case 1:
|
||||
const shunFirstA = shunData[shun][iphasic * step + 1] * xishu
|
||||
shunshiFA.push([shunData[shun][0], shunFirstA])
|
||||
ifmax = Math.max(ifmax, shunFirstA)
|
||||
ifmin = Math.min(ifmin, shunFirstA)
|
||||
|
||||
const shunSecondA = shunData[shun][iphasic * step + 1]
|
||||
shunshiSA.push([shunData[shun][0], shunSecondA])
|
||||
ismax = Math.max(ismax, shunSecondA)
|
||||
ismin = Math.min(ismin, shunSecondA)
|
||||
break
|
||||
case 2:
|
||||
const shunFirstA2 = shunData[shun][iphasic * step + 1] * xishu
|
||||
const shunFirstB2 = shunData[shun][iphasic * step + 2] * xishu
|
||||
shunshiFA.push([shunData[shun][0], shunFirstA2])
|
||||
shunshiFB.push([shunData[shun][0], shunFirstB2])
|
||||
ifmax = Math.max(ifmax, shunFirstA2, shunFirstB2)
|
||||
ifmin = Math.min(ifmin, shunFirstA2, shunFirstB2)
|
||||
|
||||
const shunSecondA2 = shunData[shun][iphasic * step + 1]
|
||||
const shunSecondB2 = shunData[shun][iphasic * step + 2]
|
||||
shunshiSA.push([shunData[shun][0], shunSecondA2])
|
||||
shunshiSB.push([shunData[shun][0], shunSecondB2])
|
||||
ismax = Math.max(ismax, shunSecondA2, shunSecondB2)
|
||||
ismin = Math.min(ismin, shunSecondA2, shunSecondB2)
|
||||
break
|
||||
case 3:
|
||||
const shunFirstA3 = shunData[shun][iphasic * step + 1] * xishu
|
||||
const shunFirstB3 = shunData[shun][iphasic * step + 2] * xishu
|
||||
const shunFirstC3 = shunData[shun][iphasic * step + 3] * xishu
|
||||
shunshiFA.push([shunData[shun][0], shunFirstA3])
|
||||
shunshiFB.push([shunData[shun][0], shunFirstB3])
|
||||
shunshiFC.push([shunData[shun][0], shunFirstC3])
|
||||
ifmax = Math.max(ifmax, shunFirstA3, shunFirstB3, shunFirstC3)
|
||||
ifmin = isOpen
|
||||
? Math.min(ifmin, shunFirstA3, shunFirstC3)
|
||||
: Math.min(ifmin, shunFirstA3, shunFirstB3, shunFirstC3)
|
||||
|
||||
const shunSecondA3 = shunData[shun][iphasic * step + 1]
|
||||
const shunSecondB3 = shunData[shun][iphasic * step + 2]
|
||||
const shunSecondC3 = shunData[shun][iphasic * step + 3]
|
||||
shunshiSA.push([shunData[shun][0], shunSecondA3])
|
||||
shunshiSB.push([shunData[shun][0], shunSecondB3])
|
||||
shunshiSC.push([shunData[shun][0], shunSecondC3])
|
||||
ismax = Math.max(ismax, shunSecondA3, shunSecondB3, shunSecondC3)
|
||||
ismin = isOpen
|
||||
? Math.min(ismin, shunSecondA3, shunSecondC3)
|
||||
: Math.min(ismin, shunSecondA3, shunSecondB3, shunSecondC3)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const instantF = { max: ifmax, min: ifmin }
|
||||
const instantS = { max: ismax, min: ismin }
|
||||
const shunshiF = { shunshiFA, shunshiFB, shunshiFC }
|
||||
const shunshiS = { shunshiSA, shunshiSB, shunshiSC }
|
||||
const title = { aTitle, bTitle, cTitle, unit }
|
||||
|
||||
return { instantF, instantS, shunshiF, shunshiS, title, unit }
|
||||
}
|
||||
|
||||
// 处理标题
|
||||
let titles = ''
|
||||
if (boxoList.systemType == 'pms') {
|
||||
titles =
|
||||
'变电站名称:' +
|
||||
boxoList.powerStationName +
|
||||
' 监测点名称:' +
|
||||
boxoList.measurementPointName +
|
||||
' 发生时刻:' +
|
||||
boxoList.startTime +
|
||||
' 暂降(骤升)幅值:' +
|
||||
(boxoList.featureAmplitude * 100).toFixed(2) +
|
||||
'% 持续时间:' +
|
||||
boxoList.duration +
|
||||
's'
|
||||
} else if (boxoList.systemType == 'ZL') {
|
||||
titles =
|
||||
(boxoList.engineeringName == undefined ? '' : ' 项目名称:' + boxoList.engineeringName) +
|
||||
' 监测点名称:' +
|
||||
boxoList.equipmentName +
|
||||
' 发生时刻:' +
|
||||
boxoList.startTime +
|
||||
' 暂降(骤升)幅值:' +
|
||||
boxoList.evtParamVVaDepth +
|
||||
'% 持续时间:' +
|
||||
boxoList.evtParamTm +
|
||||
's'
|
||||
} else if (boxoList.systemType == 'YPT') {
|
||||
titles =
|
||||
(boxoList.engineeringName == undefined ? '' : ' 项目名称:' + boxoList.engineeringName) +
|
||||
' 监测点名称:' +
|
||||
boxoList.lineName +
|
||||
' 发生时刻:' +
|
||||
boxoList.startTime +
|
||||
' 暂降(骤升)幅值:' +
|
||||
(boxoList.featureAmplitude * 100).toFixed(2) +
|
||||
'% 持续时间:' +
|
||||
boxoList.persistTime +
|
||||
's'
|
||||
} else {
|
||||
titles =
|
||||
'变电站名称:' +
|
||||
boxoList.subName +
|
||||
' 监测点名称:' +
|
||||
boxoList.lineName +
|
||||
' 发生时刻:' +
|
||||
boxoList.startTime +
|
||||
' 暂降(骤升)幅值:' +
|
||||
(boxoList.featureAmplitude * 100).toFixed(2) +
|
||||
'% 持续时间:' +
|
||||
boxoList.duration +
|
||||
's'
|
||||
}
|
||||
|
||||
const iphasicValue = wp.iphasic || 1
|
||||
const picCounts = (wp.waveTitle.length - 1) / iphasicValue
|
||||
const waveDatas = []
|
||||
|
||||
for (let i = 0; i < picCounts; i++) {
|
||||
const data = fliteWaveData(wp, i)
|
||||
waveDatas.push(data)
|
||||
}
|
||||
|
||||
const time = wp.time
|
||||
const type = wp.waveType
|
||||
let severity = wp.yzd
|
||||
|
||||
if (severity < 0) {
|
||||
severity = '/'
|
||||
type = '/'
|
||||
}
|
||||
|
||||
// 将处理结果发送回主线程
|
||||
self.postMessage({
|
||||
requestId,
|
||||
success: true,
|
||||
waveDatas,
|
||||
time,
|
||||
type,
|
||||
severity,
|
||||
titles,
|
||||
iphasic: iphasicValue
|
||||
})
|
||||
})
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
<div v-if="view2">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<span style="font-size: 14px; line-height: 30px">值类型选择:</span>
|
||||
<!-- <span style="font-size: 14px; line-height: 30px">值类型选择:</span>
|
||||
<el-select
|
||||
style="min-width: 200px; width: 200px"
|
||||
@change="changeView"
|
||||
@@ -15,7 +15,11 @@
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-select> -->
|
||||
<el-radio-group v-model.trim="value" @change="changeView">
|
||||
<el-radio-button label="一次值" :value="1" />
|
||||
<el-radio-button label="二次值" :value="2" />
|
||||
</el-radio-group>
|
||||
<!-- <el-button v-if="view2 && senior" class="ml10" type="primary" @click="AdvancedAnalytics">
|
||||
高级分析
|
||||
</el-button> -->
|
||||
@@ -24,37 +28,18 @@
|
||||
<el-button @click="backbxlb" icon="el-icon-Back" style="float: right">返回</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div v-loading="loading" style="height: calc(100vh - 190px)">
|
||||
<el-tabs v-if="view4" class="default-main" v-model="bxactiveName" @tab-click="bxhandleClick">
|
||||
<el-tab-pane
|
||||
label="瞬时波形"
|
||||
name="ssbx"
|
||||
class="boxbx pt10 pb10"
|
||||
:style="'height:' + bxecharts + ';overflow-y: scroll;'"
|
||||
>
|
||||
<shushiboxi
|
||||
ref="shushiboxiRef"
|
||||
v-if="bxactiveName == 'ssbx' && showBoxi"
|
||||
:value="value"
|
||||
:parentHeight="parentHeight"
|
||||
:boxoList="boxoList"
|
||||
:wp="wp"
|
||||
></shushiboxi>
|
||||
<div v-loading="loading" style="height: calc(100vh - 190px)" class="mt10">
|
||||
<el-tabs v-if="view4" type="border-card" v-model="bxactiveName"
|
||||
@tab-click="bxhandleClick">
|
||||
<el-tab-pane label="瞬时波形" name="ssbx" class="boxbx pt10 pb10"
|
||||
:style="'height:' + bxecharts + ';overflow-y: scroll;'">
|
||||
<shushiboxi ref="shushiboxiRef" v-if="bxactiveName == 'ssbx' && showBoxi" :value="value"
|
||||
:parentHeight="parentHeight" :boxoList="boxoList" :wp="wp"></shushiboxi>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane
|
||||
label="RMS波形"
|
||||
class="boxbx pt10 pb10"
|
||||
name="rmsbx"
|
||||
:style="'height:' + bxecharts + ';overflow-y: scroll;'"
|
||||
>
|
||||
<rmsboxi
|
||||
ref="rmsboxiRef"
|
||||
v-if="bxactiveName == 'rmsbx' && showBoxi"
|
||||
:value="value"
|
||||
:parentHeight="parentHeight"
|
||||
:boxoList="boxoList"
|
||||
:wp="wp"
|
||||
></rmsboxi>
|
||||
<el-tab-pane label="RMS波形" class="boxbx pt10 pb10" name="rmsbx"
|
||||
:style="'height:' + bxecharts + ';overflow-y: scroll;'">
|
||||
<rmsboxi ref="rmsboxiRef" v-if="bxactiveName == 'rmsbx' && showBoxi" :value="value"
|
||||
:parentHeight="parentHeight" :boxoList="boxoList" :wp="wp"></rmsboxi>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<el-empty v-else description="暂无数据" style="height: calc(100vh - 190px)" />
|
||||
@@ -70,10 +55,12 @@
|
||||
import shushiboxi from '@/components/echarts/shushiboxi.vue'
|
||||
import rmsboxi from '@/components/echarts/rmsboxi.vue'
|
||||
import analytics from '@/components/echarts/analytics.vue'
|
||||
import { ref, reactive } from 'vue'
|
||||
import { ref, shallowRef } from 'vue'
|
||||
import { analysis } from '@/api/advance-boot/analyse'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import { getMonitorEventAnalyseWave, downloadWaveFile } from '@/api/event-boot/transient'
|
||||
import { buildWaveStoreKey, registerWaveRaw, buildSlimWp, releaseWaveRaw } from '@/utils/waveRawStore'
|
||||
import { clearWaveCache } from '@/utils/waveCache'
|
||||
const emit = defineEmits(['backbxlb'])
|
||||
interface Props {
|
||||
// boxoList: any
|
||||
@@ -100,10 +87,10 @@ const options = ref([
|
||||
}
|
||||
])
|
||||
const shushiboxiRef = ref()
|
||||
const bxecharts = ref(mainHeight(95).height as any)
|
||||
const bxecharts = ref(mainHeight(145).height as any)
|
||||
const view2 = ref(true)
|
||||
const boxoList: any = ref(null)
|
||||
const wp = ref(null)
|
||||
const wp = shallowRef<any>(null)
|
||||
const showBoxi = ref(true)
|
||||
const view3 = ref(false)
|
||||
const view4 = ref(false)
|
||||
@@ -117,7 +104,9 @@ const open = async (row: any) => {
|
||||
if (res != undefined) {
|
||||
boxoList.value = row
|
||||
boxoList.value.pt = res.data.pt
|
||||
wp.value = res.data
|
||||
const storeKey = buildWaveStoreKey(row)
|
||||
registerWaveRaw(storeKey, res.data)
|
||||
wp.value = buildSlimWp(res.data, storeKey)
|
||||
loading.value = false
|
||||
view4.value = true
|
||||
}
|
||||
@@ -128,9 +117,6 @@ const open = async (row: any) => {
|
||||
})
|
||||
}
|
||||
const bxhandleClick = (tab: any) => {
|
||||
if (shushiboxiRef.value) shushiboxiRef.value.backbxlb()
|
||||
if (rmsboxiRef.value) rmsboxiRef.value.backbxlb()
|
||||
|
||||
loading.value = true
|
||||
if (tab.name == 'ssbx') {
|
||||
bxactiveName.value = 'ssbx'
|
||||
@@ -143,10 +129,12 @@ const bxhandleClick = (tab: any) => {
|
||||
// console.log(tab, event);
|
||||
}
|
||||
const backbxlb = () => {
|
||||
const storeKey = wp.value?.waveStoreKey
|
||||
releaseWaveRaw(storeKey, 'all')
|
||||
clearWaveCache()
|
||||
boxoList.value = null
|
||||
wp.value = null
|
||||
if (shushiboxiRef.value) shushiboxiRef.value.backbxlb()
|
||||
if (rmsboxiRef.value) rmsboxiRef.value.backbxlb()
|
||||
|
||||
|
||||
emit('backbxlb')
|
||||
}
|
||||
@@ -173,8 +161,8 @@ const AdvancedAnalytics = () => {
|
||||
view2.value = false
|
||||
}
|
||||
const changeView = () => {
|
||||
if (shushiboxiRef.value) shushiboxiRef.value.backbxlb()
|
||||
if (rmsboxiRef.value) rmsboxiRef.value.backbxlb()
|
||||
shushiboxiRef.value?.backbxlb?.()
|
||||
rmsboxiRef.value?.backbxlb?.()
|
||||
showBoxi.value = false
|
||||
setTimeout(() => {
|
||||
showBoxi.value = true
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
<template>
|
||||
<div style="width: 540px">
|
||||
<div :style="{ width: isMinuteData ? '750px' : '610px' }">
|
||||
<el-select v-model="interval" style="min-width: 90px; width: 90px; margin-right: 10px" @change="timeChange">
|
||||
<el-option v-for="item in timeOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
|
||||
<el-date-picker
|
||||
v-model="timeValue"
|
||||
type="daterange"
|
||||
:type="pickerType"
|
||||
:disabled="disabledPicker"
|
||||
:disabled-date="isFutureDate"
|
||||
style="width: 220px; margin-right: 10px"
|
||||
:style="{ width: isMinuteData ? '360px' : '220px', marginRight: '10px' }"
|
||||
unlink-panels
|
||||
:clearable="false"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
value-format="YYYY-MM-DD"
|
||||
:shortcuts="shortcuts"
|
||||
:start-placeholder="isMinuteData ? '开始时间' : '开始日期'"
|
||||
:end-placeholder="isMinuteData ? '结束时间' : '结束日期'"
|
||||
:value-format="pickerValueFormat"
|
||||
:shortcuts="isMinuteData ? undefined : shortcuts"
|
||||
/>
|
||||
<el-button :disabled="backDisabled" type="primary" :icon="DArrowLeft" @click="preClick"></el-button>
|
||||
<el-button type="primary" :icon="VideoPause" @click="nowTime">当前</el-button>
|
||||
@@ -26,18 +26,41 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { DArrowLeft, VideoPause, DArrowRight } from '@element-plus/icons-vue'
|
||||
import { ref, onMounted, nextTick, watch } from 'vue'
|
||||
import { ref, onMounted, computed, watch } from 'vue'
|
||||
|
||||
interface Props {
|
||||
nextFlag?: boolean
|
||||
theCurrentTime?: boolean
|
||||
isStatisticData?: number | string
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
nextFlag: false,
|
||||
theCurrentTime: false
|
||||
theCurrentTime: false,
|
||||
isStatisticData: 0
|
||||
})
|
||||
|
||||
const isMinuteData = computed(() => Number(props.isStatisticData) === 1)
|
||||
const pickerType = computed(() => (isMinuteData.value ? 'datetimerange' : 'daterange'))
|
||||
const pickerValueFormat = computed(() => (isMinuteData.value ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD'))
|
||||
|
||||
const toDatePart = (value: string) => (value?.includes(' ') ? value.split(' ')[0] : value)
|
||||
|
||||
const toMinuteStart = (date: string) => `${toDatePart(date)} 00:00:00`
|
||||
|
||||
const toMinuteEnd = (date: string) => `${toDatePart(date)} 23:59:59`
|
||||
|
||||
const normalizeRange = (start: string, end: string) => {
|
||||
if (!isMinuteData.value) {
|
||||
return [toDatePart(start), toDatePart(end)]
|
||||
}
|
||||
return [toMinuteStart(start), toMinuteEnd(end)]
|
||||
}
|
||||
|
||||
const setRangeValue = (start: string, end: string) => {
|
||||
timeValue.value = normalizeRange(start, end)
|
||||
}
|
||||
|
||||
const interval = ref(3)
|
||||
const timeFlag = ref(1)
|
||||
const count = ref(0)
|
||||
@@ -95,13 +118,13 @@ const timeChange = (e: number) => {
|
||||
if (e == 1) {
|
||||
disabledPicker.value = true
|
||||
|
||||
timeValue.value = [setTime(1), setTime()]
|
||||
setRangeValue(setTime(1), setTime())
|
||||
} else if (e == 2) {
|
||||
disabledPicker.value = true
|
||||
timeValue.value = [setTime(2), setTime()]
|
||||
setRangeValue(setTime(2), setTime())
|
||||
} else if (e == 3) {
|
||||
disabledPicker.value = true
|
||||
timeValue.value = [setTime(3), setTime()]
|
||||
setRangeValue(setTime(3), setTime())
|
||||
} else if (e == 4) {
|
||||
let year = parseInt(setTime().substring(0, 4))
|
||||
let month = parseInt(setTime().substring(5, 7))
|
||||
@@ -111,12 +134,12 @@ const timeChange = (e: number) => {
|
||||
var dayOfWeek = start.getDay() == 0 ? 7 : start.getDay() - 1 // 如果为周日,则置为7天
|
||||
|
||||
disabledPicker.value = true
|
||||
timeValue.value = [setTime(0, dayOfWeek), setTime(0, -6 + dayOfWeek)]
|
||||
setRangeValue(setTime(0, dayOfWeek), setTime(0, -6 + dayOfWeek))
|
||||
} else if (e == 5) {
|
||||
disabledPicker.value = false
|
||||
backDisabled.value = true
|
||||
preDisabled.value = props.nextFlag ? false : true
|
||||
timeValue.value = [setTime(), setTime()]
|
||||
setRangeValue(setTime(), setTime())
|
||||
}
|
||||
if (e == 1 || e == 2) {
|
||||
timeFlag.value = 0
|
||||
@@ -186,7 +209,7 @@ const preClick = () => {
|
||||
startTime = year + '-01-01'
|
||||
endTime = year + '-12-31'
|
||||
}
|
||||
timeValue.value = [startTime, endTime]
|
||||
setRangeValue(startTime, endTime)
|
||||
|
||||
// 判断向后键的状态
|
||||
// var temp = NowgetEndTime()
|
||||
@@ -415,16 +438,27 @@ const next = () => {
|
||||
}
|
||||
if (!props.nextFlag) {
|
||||
if (
|
||||
new Date(endTime + ' 00:00:00').getTime() >=
|
||||
new Date(toDatePart(endTime) + ' 00:00:00').getTime() >=
|
||||
new Date(window.XEUtils.toDateString(new Date(), 'yyyy-MM-dd ') + ' 00:00:00').getTime()
|
||||
) {
|
||||
preDisabled.value = props.nextFlag ? false : true
|
||||
}
|
||||
}
|
||||
|
||||
timeValue.value = [startTime, endTime]
|
||||
setRangeValue(startTime, endTime)
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.isStatisticData,
|
||||
() => {
|
||||
if (timeValue.value?.length === 2) {
|
||||
setRangeValue(timeValue.value[0], timeValue.value[1])
|
||||
} else {
|
||||
timeChange(interval.value)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const setTime = (flag = 0, e = 0) => {
|
||||
let dd = window.XEUtils.toDateString(new Date().getTime() - e * 3600 * 1000 * 24, 'dd')
|
||||
|
||||
|
||||
@@ -9,11 +9,8 @@ export const defaultAttribute: VxeTableProps = {
|
||||
columnConfig: { resizable: true },
|
||||
rowConfig: { isCurrent: true, isHover: true },
|
||||
scrollX: { scrollToLeftOnChange: true },
|
||||
scrollY: { scrollToTopOnChange: true, enabled: true },
|
||||
treeConfig: {
|
||||
reserve: true
|
||||
},
|
||||
showOverflow: true,
|
||||
showFooter:true
|
||||
scrollY: { scrollToTopOnChange: true, enabled: true, gt: 100 },
|
||||
customConfig: { enabled: true, allowFixed: false, showFooter: false, immediate: true ,mode:'default'},
|
||||
showOverflow: 'tooltip',
|
||||
showHeaderOverflow: false
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,11 @@
|
||||
label-position="left"
|
||||
:inline="true"
|
||||
>
|
||||
<el-form-item v-if="datePicker" style="grid-column: span 2; max-width: 630px">
|
||||
<el-form-item
|
||||
v-if="datePicker"
|
||||
style="grid-column: span 2"
|
||||
:style="{ maxWidth: isStatisticData == 1 ? '750px' : '610px' }"
|
||||
>
|
||||
<template #label>
|
||||
<el-checkbox v-if="showTimeAll" v-model="timeAll" label="统计时间" />
|
||||
<span v-else>{{ dateLabel }}</span>
|
||||
@@ -19,11 +23,17 @@
|
||||
v-if="timeAll"
|
||||
:nextFlag="nextFlag"
|
||||
:theCurrentTime="theCurrentTime"
|
||||
:isStatisticData="isStatisticData"
|
||||
></DatePicker>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="区域" v-if="area">
|
||||
<Area ref="areaRef" v-model="tableStore.table.params.deptIndex" @change-value="onAreaChange" />
|
||||
<Area
|
||||
ref="areaRef"
|
||||
v-model="tableStore.table.params.deptIndex"
|
||||
@change-value="onAreaChange"
|
||||
style="width: 200px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<slot name="select"></slot>
|
||||
</el-form>
|
||||
@@ -60,6 +70,7 @@
|
||||
</el-button>
|
||||
</template>
|
||||
<slot name="operation"></slot>
|
||||
<el-button class="ml10" v-if="showCustomColumn" :icon="Setting" @click="openCustomColumn">列设置</el-button>
|
||||
</div>
|
||||
<el-form
|
||||
:style="showSelect && showUnfoldButton ? headerFormSecondStyleOpen : headerFormSecondStyleClose"
|
||||
@@ -79,9 +90,8 @@ import DatePicker from '@/components/form/datePicker/index.vue'
|
||||
import Area from '@/components/form/area/index.vue'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import { Search, RefreshLeft } from '@element-plus/icons-vue'
|
||||
import { defineProps } from 'vue'
|
||||
const emit = defineEmits(['selectChange','areaChange'])
|
||||
import { Search, RefreshLeft, Setting } from '@element-plus/icons-vue'
|
||||
const emit = defineEmits(['selectChange', 'areaChange'])
|
||||
const tableStore = inject('tableStore') as TableStore
|
||||
const tableHeader = ref()
|
||||
const datePickerRef = ref()
|
||||
@@ -100,6 +110,8 @@ interface Props {
|
||||
showExport?: boolean //导出控制
|
||||
showTimeAll?: boolean //控制时间是否显示
|
||||
dateLabel?: string //设置时间名称
|
||||
isStatisticData?: number | string // 0统计数据 1分钟数据
|
||||
showCustomColumn?: boolean // 列设置
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
@@ -111,7 +123,9 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
showReset: true,
|
||||
showExport: false,
|
||||
showTimeAll: false,
|
||||
dateLabel: '统计日期'
|
||||
dateLabel: '统计日期',
|
||||
isStatisticData: 0,
|
||||
showCustomColumn: false
|
||||
})
|
||||
// 动态计算table高度
|
||||
const resizeObserver = new ResizeObserver(entries => {
|
||||
@@ -132,9 +146,8 @@ const headerFormSecondStyleClose = {
|
||||
padding: '0'
|
||||
}
|
||||
|
||||
const onAreaChange = (data) => {
|
||||
|
||||
emit('areaChange', {label: data.label})
|
||||
const onAreaChange = data => {
|
||||
emit('areaChange', { label: data.label })
|
||||
}
|
||||
|
||||
watch(
|
||||
@@ -142,7 +155,6 @@ watch(
|
||||
newVal => {
|
||||
setTimeout(() => {
|
||||
areaRef.value && areaRef.value.change()
|
||||
|
||||
}, 0)
|
||||
}
|
||||
)
|
||||
@@ -155,7 +167,13 @@ watch(
|
||||
}, 500)
|
||||
}
|
||||
)
|
||||
const openCustomColumn = () => {
|
||||
tableStore?.table?.ref?.openCustom?.()
|
||||
}
|
||||
onMounted(() => {
|
||||
if (props.showCustomColumn && tableStore?.table) {
|
||||
tableStore.table.customColumnInHeader = true
|
||||
}
|
||||
timeAll.value = props.showTimeAll ? false : true
|
||||
if (props.datePicker && timeAll.value) {
|
||||
tableStore.table.params.searchBeginTime = datePickerRef.value.timeValue[0]
|
||||
@@ -238,14 +256,14 @@ const onResetForm = () => {
|
||||
//时间重置成默认值
|
||||
datePickerRef.value?.setTheDate(3)
|
||||
|
||||
if(props.showTimeAll){
|
||||
timeAll.value = false
|
||||
delete tableStore.table.params.searchBeginTime
|
||||
delete tableStore.table.params.searchEndTime
|
||||
delete tableStore.table.params.startTime
|
||||
delete tableStore.table.params.endTime
|
||||
delete tableStore.table.params.timeFlag
|
||||
delete tableStore.table.params.interval
|
||||
if (props.showTimeAll) {
|
||||
timeAll.value = false
|
||||
delete tableStore.table.params.searchBeginTime
|
||||
delete tableStore.table.params.searchEndTime
|
||||
delete tableStore.table.params.startTime
|
||||
delete tableStore.table.params.endTime
|
||||
delete tableStore.table.params.timeFlag
|
||||
delete tableStore.table.params.interval
|
||||
}
|
||||
|
||||
if (props.datePicker && timeAll.value) {
|
||||
@@ -264,7 +282,6 @@ const setTheDate = (val: any) => {
|
||||
}
|
||||
// 导出
|
||||
const onExport = () => {
|
||||
|
||||
tableStore.onTableAction('export', { showAllFlag: true })
|
||||
}
|
||||
|
||||
@@ -300,6 +317,7 @@ defineExpose({
|
||||
padding: 13px 15px;
|
||||
font-size: 14px;
|
||||
overflow: hidden;
|
||||
|
||||
.table-header-operate-text {
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
@@ -1,24 +1,46 @@
|
||||
<template>
|
||||
<div :style="{ height: typeof props.height === 'string' ? props.height : tableStore.table.height }">
|
||||
<vxe-table ref="tableRef" height="auto" :key="key" :data="tableStore.table.data"
|
||||
v-loading="tableStore.table.loading" v-bind="Object.assign({}, defaultAttribute, $attrs)"
|
||||
@checkbox-all="selectChangeEvent" @checkbox-change="selectChangeEvent" :showOverflow="showOverflow"
|
||||
@sort-change="handleSortChange">
|
||||
<div v-if="showCustomColumn && !tableStore?.table?.customColumnInHeader" class="table-custom-toolbar">
|
||||
<el-button icon="el-icon-Setting" @click="openCustomColumn">列设置</el-button>
|
||||
</div>
|
||||
<vxe-table
|
||||
ref="tableRef"
|
||||
height="auto"
|
||||
:key="key"
|
||||
:data="tableStore.table.data"
|
||||
v-loading="tableStore.table.loading"
|
||||
v-bind="tableBindProps"
|
||||
@checkbox-all="selectChangeEvent"
|
||||
@checkbox-change="selectChangeEvent"
|
||||
@cell-click="onCellClick"
|
||||
>
|
||||
<!-- @sort-change="handleSortChange" -->
|
||||
<!-- Column 组件内部是 el-table-column -->
|
||||
<template v-if="isGroup">
|
||||
<GroupColumn :column="tableStore.table.column" />
|
||||
</template>
|
||||
<template v-else>
|
||||
<Column :attr="item" :key="key + '-column'" v-for="(item, key) in tableStore.table.column"
|
||||
:tree-node="item.treeNode">
|
||||
<Column
|
||||
:attr="item"
|
||||
:key="key + '-column'"
|
||||
v-for="(item, key) in tableStore.table.column"
|
||||
:tree-node="item.treeNode"
|
||||
>
|
||||
<!-- tableStore 预设的列 render 方案 -->
|
||||
<template v-if="item.render" #default="scope">
|
||||
<FieldRender :field="item" :row="scope.row" :column="scope.column" :index="scope.rowIndex" :key="key +
|
||||
'-' +
|
||||
item.render +
|
||||
'-' +
|
||||
(item.field ? '-' + item.field + '-' + scope.row[item.field] : '')
|
||||
" />
|
||||
<FieldRender
|
||||
:field="item"
|
||||
:row="scope.row"
|
||||
:column="scope.column"
|
||||
:index="scope.rowIndex"
|
||||
:key="
|
||||
key +
|
||||
'-' +
|
||||
item.render +
|
||||
'-' +
|
||||
(item.field ? '-' + item.field + '-' + scope.row[item.field] : '')
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
</Column>
|
||||
</template>
|
||||
@@ -27,17 +49,22 @@
|
||||
</div>
|
||||
|
||||
<div v-if="tableStore.showPage" class="table-pagination">
|
||||
<el-pagination :currentPage="tableStore.table.params!.pageNum" :page-size="tableStore.table.params!.pageSize"
|
||||
:page-sizes="pageSizes" background
|
||||
<el-pagination
|
||||
:currentPage="tableStore.table.params!.pageNum"
|
||||
:page-size="tableStore.table.params!.pageSize"
|
||||
:page-sizes="pageSizes"
|
||||
background
|
||||
:layout="config.layout.shrink ? 'prev, next, jumper' : 'sizes,total, ->, prev, pager, next, jumper'"
|
||||
:total="tableStore.table.total" @size-change="onTableSizeChange"
|
||||
@current-change="onTableCurrentChange"></el-pagination>
|
||||
:total="tableStore.table.total"
|
||||
@size-change="onTableSizeChange"
|
||||
@current-change="onTableCurrentChange"
|
||||
></el-pagination>
|
||||
</div>
|
||||
<slot name="footer"></slot>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, nextTick, inject, computed, onMounted, watch } from 'vue'
|
||||
import { ref, nextTick, inject, computed, onMounted, watch, useAttrs } from 'vue'
|
||||
import type { ElTable } from 'element-plus'
|
||||
import { VxeTableEvents, VxeTableInstance } from 'vxe-table'
|
||||
import FieldRender from '@/components/table/fieldRender/index.vue'
|
||||
@@ -53,17 +80,32 @@ const tableRef = ref<VxeTableInstance>()
|
||||
const tableStore = inject('tableStore') as TableStoreClass
|
||||
const router = useRouter()
|
||||
const key = ref(0)
|
||||
const emit = defineEmits<{
|
||||
(e: 'cell-click', params: any): void
|
||||
}>()
|
||||
interface Props extends /* @vue-ignore */ Partial<InstanceType<typeof ElTable>> {
|
||||
isGroup?: boolean
|
||||
showOverflow?: boolean
|
||||
showOverflow?: boolean | 'ellipsis' | 'title' | 'tooltip'
|
||||
height?: string | number
|
||||
showCustomColumn?: boolean
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
isGroup: false,
|
||||
showOverflow: true,
|
||||
height: undefined
|
||||
showOverflow: 'tooltip',
|
||||
height: undefined,
|
||||
showCustomColumn: false
|
||||
})
|
||||
const attrs = useAttrs()
|
||||
const tableBindProps = computed(() => {
|
||||
return Object.assign({}, defaultAttribute, attrs, {
|
||||
showOverflow: props.showOverflow,
|
||||
showHeaderOverflow: false
|
||||
})
|
||||
})
|
||||
const onCellClick: VxeTableEvents.CellClick<any> = params => {
|
||||
emit('cell-click', params)
|
||||
}
|
||||
onMounted(() => {
|
||||
tableStore.table.ref = tableRef.value as VxeTableInstance
|
||||
})
|
||||
@@ -93,7 +135,9 @@ const selectChangeEvent: VxeTableEvents.CheckboxChange<any> = ({ checked }) => {
|
||||
const records = (tableRef.value as VxeTableInstance).getCheckboxRecords()
|
||||
tableStore.onTableAction('selection-change', records)
|
||||
}
|
||||
|
||||
const openCustomColumn = () => {
|
||||
tableRef.value?.openCustom?.()
|
||||
}
|
||||
const getRef = () => {
|
||||
return tableRef.value
|
||||
}
|
||||
|
||||
@@ -3,167 +3,177 @@
|
||||
<el-tabs type="border-card" v-model="activeName" @tab-click="handleClick">
|
||||
<el-tab-pane label="监测点详情" name="tab1">
|
||||
<el-descriptions :column="3" border label-width="150px">
|
||||
<el-descriptions-item label="项目工程">
|
||||
<el-descriptions-item label="项目工程">
|
||||
{{ details.areaName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="项目单位">
|
||||
<el-descriptions-item label="项目单位">
|
||||
{{ details.gdName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="所属变电站">
|
||||
<el-descriptions-item label="所属变电站">
|
||||
{{ details.bdName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="电压等级">
|
||||
{{ details.scale }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="终端厂家">
|
||||
{{ details.manufacturer }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="终端名称">
|
||||
{{ details.devName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="网络参数">
|
||||
{{ details.ip }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="监测点名称">
|
||||
<el-descriptions-item label="监测点名称">
|
||||
{{ details.lineName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="监测点序号">
|
||||
{{ details.id }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="通讯状态">
|
||||
{{ details.comFlag }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="干扰源类型">
|
||||
{{ details.loadType }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="监测点对象名称">
|
||||
<el-descriptions-item label="监测点对象名称">
|
||||
{{ details.objName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="接线方式">
|
||||
<el-descriptions-item label="监测点序号">
|
||||
{{ details.id }}
|
||||
</el-descriptions-item>
|
||||
|
||||
<el-descriptions-item label="终端厂家">
|
||||
{{ details.manufacturer }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="终端名称">
|
||||
{{ details.devName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="终端型号">
|
||||
{{ typeArr.find(item => item.id == details.devType)?.name }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="电压等级">
|
||||
{{ details.scale }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="网络参数">
|
||||
{{ details.ip }}
|
||||
</el-descriptions-item>
|
||||
|
||||
<el-descriptions-item label="通讯状态">
|
||||
{{ details.comFlag }}
|
||||
</el-descriptions-item>
|
||||
|
||||
<el-descriptions-item label="干扰源类型">
|
||||
{{ details.loadType }}
|
||||
</el-descriptions-item>
|
||||
|
||||
<el-descriptions-item label="接线方式">
|
||||
{{ details.ptType }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="PT变比">
|
||||
<el-descriptions-item label="统计间隔(分钟)">
|
||||
{{ details.timeInterval }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="PT变比">
|
||||
{{ details.pt }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="CT变比">
|
||||
<el-descriptions-item label="CT变比">
|
||||
{{ details.ct }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="基准容量(MVA)">
|
||||
<el-descriptions-item label="基准容量(MVA)">
|
||||
{{ details.standardCapacity }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="最小短路容量(MVA)">
|
||||
{{ details.shortCapacity }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="供电设备容量(MVA)">
|
||||
<el-descriptions-item label="供电设备容量(MVA)">
|
||||
{{ details.devCapacity }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="用户协议容量(MVA)">
|
||||
<el-descriptions-item label="最小短路容量(MW)">
|
||||
{{ details.shortCapacity }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="用户协议容量(MW)">
|
||||
{{ details.dealCapacity }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="监测点限值" name="tab2">
|
||||
<el-descriptions :column="3" border label-width="250px">
|
||||
<el-descriptions-item label="电压偏差上限值(%)">
|
||||
<el-descriptions :column="3" border label-width="250px">
|
||||
<el-descriptions-item label="电压偏差上限值(%)">
|
||||
{{ limitValue.voltageDev }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="电压偏差下限值(%)">
|
||||
<el-descriptions-item label="电压偏差下限值(%)">
|
||||
{{ limitValue.uvoltageDev }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="频率偏差限值(Hz)">
|
||||
<el-descriptions-item label="频率偏差限值(Hz)">
|
||||
{{ limitValue.freqDev }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="三相电压不平衡度限值(%)">
|
||||
<el-descriptions-item label="三相电压不平衡度限值(%)">
|
||||
{{ limitValue.ubalance }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="负序电流限值(A)">
|
||||
<el-descriptions-item label="负序电流限值(A)">
|
||||
{{ limitValue.ineg }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="长时闪变限值(%)">
|
||||
<el-descriptions-item label="长时闪变限值(%)">
|
||||
{{ limitValue.flicker }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="电压总畸变率限值(%)">
|
||||
<el-descriptions-item label="电压总畸变率限值(%)">
|
||||
{{ limitValue.uaberrance }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="奇次谐波电压含有率限值(%)">
|
||||
<el-descriptions-item label="奇次谐波电压含有率限值(%)">
|
||||
{{ limitValue.oddHarm }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="偶次谐波电压含有率限值(%)">
|
||||
<el-descriptions-item label="偶次谐波电压含有率限值(%)">
|
||||
{{ limitValue.evenHarm }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="3次谐波电流幅值限值(A)">
|
||||
<el-descriptions-item label="3次谐波电流幅值限值(A)">
|
||||
{{ limitValue.iharm3 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="4次谐波电流幅值限值(A)">
|
||||
<el-descriptions-item label="4次谐波电流幅值限值(A)">
|
||||
{{ limitValue.iharm4 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="5次谐波电流幅值限值(A)">
|
||||
<el-descriptions-item label="5次谐波电流幅值限值(A)">
|
||||
{{ limitValue.iharm5 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="6次谐波电流幅值限值(A)">
|
||||
<el-descriptions-item label="6次谐波电流幅值限值(A)">
|
||||
{{ limitValue.iharm6 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="7次谐波电流幅值限值(A)">
|
||||
<el-descriptions-item label="7次谐波电流幅值限值(A)">
|
||||
{{ limitValue.iharm7 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="8次谐波电流幅值限值(A)">
|
||||
<el-descriptions-item label="8次谐波电流幅值限值(A)">
|
||||
{{ limitValue.iharm8 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="9次谐波电流幅值限值(A)">
|
||||
<el-descriptions-item label="9次谐波电流幅值限值(A)">
|
||||
{{ limitValue.iharm9 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="10次谐波电流幅值限值(A)">
|
||||
<el-descriptions-item label="10次谐波电流幅值限值(A)">
|
||||
{{ limitValue.iharm10 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="11次谐波电流幅值限值(A)">
|
||||
<el-descriptions-item label="11次谐波电流幅值限值(A)">
|
||||
{{ limitValue.iharm11 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="12次谐波电流幅值限值(A)">
|
||||
<el-descriptions-item label="12次谐波电流幅值限值(A)">
|
||||
{{ limitValue.iharm12 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="13次谐波电流幅值限值(A)">
|
||||
<el-descriptions-item label="13次谐波电流幅值限值(A)">
|
||||
{{ limitValue.iharm13 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="14次谐波电流幅值限值(A)">
|
||||
<el-descriptions-item label="14次谐波电流幅值限值(A)">
|
||||
{{ limitValue.iharm14 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="15次谐波电流幅值限值(A)">
|
||||
<el-descriptions-item label="15次谐波电流幅值限值(A)">
|
||||
{{ limitValue.iharm15 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="16次谐波电流幅值限值(A)">
|
||||
<el-descriptions-item label="16次谐波电流幅值限值(A)">
|
||||
{{ limitValue.iharm16 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="17次谐波电流幅值限值(A)">
|
||||
<el-descriptions-item label="17次谐波电流幅值限值(A)">
|
||||
{{ limitValue.iharm17 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="18次谐波电流幅值限值(A)">
|
||||
<el-descriptions-item label="18次谐波电流幅值限值(A)">
|
||||
{{ limitValue.iharm18 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="19次谐波电流幅值限值(A)">
|
||||
<el-descriptions-item label="19次谐波电流幅值限值(A)">
|
||||
{{ limitValue.iharm19 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="20次谐波电流幅值限值(A)">
|
||||
<el-descriptions-item label="20次谐波电流幅值限值(A)">
|
||||
{{ limitValue.iharm20 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="21次谐波电流幅值限值(A)">
|
||||
<el-descriptions-item label="21次谐波电流幅值限值(A)">
|
||||
{{ limitValue.iharm21 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="22次谐波电流幅值限值(A)">
|
||||
<el-descriptions-item label="22次谐波电流幅值限值(A)">
|
||||
{{ limitValue.iharm22 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="23次谐波电流幅值限值(A)">
|
||||
<el-descriptions-item label="23次谐波电流幅值限值(A)">
|
||||
{{ limitValue.iharm23 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="24次谐波电流幅值限值(A)">
|
||||
<el-descriptions-item label="24次谐波电流幅值限值(A)">
|
||||
{{ limitValue.iharm24 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="25次谐波电流幅值限值(A)">
|
||||
<el-descriptions-item label="25次谐波电流幅值限值(A)">
|
||||
{{ limitValue.iharm25 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="0.5-1.5次间谐波电压含有率限值(%)">
|
||||
<el-descriptions-item label="0.5-1.5次间谐波电压含有率限值(%)">
|
||||
{{ limitValue.inUharm }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="2.5-15.5次谐波电压含有率限值(%)">
|
||||
<el-descriptions-item label="2.5-15.5次谐波电压含有率限值(%)">
|
||||
{{ limitValue.inUharm16 }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
@@ -174,11 +184,14 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, inject } from 'vue'
|
||||
import { getLineOverLimitData, getLineDetailData } from '@/api/device-boot/line'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
const dialogVisible = ref(false)
|
||||
const title = ref('')
|
||||
const activeName = ref('tab1')
|
||||
const details: any = ref([])
|
||||
const dictData = useDictData()
|
||||
const limitValue: any = ref([])
|
||||
const typeArr = dictData.getBasicData('Dev_Type')
|
||||
const open = (data: any) => {
|
||||
details.value = []
|
||||
limitValue.value = []
|
||||
@@ -187,7 +200,7 @@ const open = (data: any) => {
|
||||
|
||||
getLineDetailData(data.id).then(res => {
|
||||
details.value = res.data
|
||||
|
||||
res.data.objName ? (title.value = res.data.objName + '_' + title.value) : ''
|
||||
})
|
||||
getLineOverLimitData(data.id).then(res => {
|
||||
limitValue.value = res.data
|
||||
|
||||
@@ -28,66 +28,66 @@ const info = (id: any) => {
|
||||
expanded.value = [id]
|
||||
getTerminalTree().then(res => {
|
||||
// let arr: any[] = []
|
||||
if (VITE_FLAG) {
|
||||
res.data.forEach((item: any) => {
|
||||
item.icon = 'el-icon-Menu'
|
||||
item.plevel = item.level
|
||||
item.level = 0
|
||||
item.children.forEach((item2: any) => {
|
||||
item2.icon = 'el-icon-HomeFilled'
|
||||
// if (VITE_FLAG) {
|
||||
// res.data.forEach((item: any) => {
|
||||
// item.icon = 'el-icon-Menu'
|
||||
// item.plevel = item.level
|
||||
// item.level = 0
|
||||
// item.children.forEach((item2: any) => {
|
||||
// item2.icon = 'el-icon-HomeFilled'
|
||||
|
||||
item2.plevel = item2.level
|
||||
item2.level = 100
|
||||
expanded.value.push(item2.id)
|
||||
item2.children.forEach((item3: any) => {
|
||||
item3.icon = 'el-icon-CollectionTag'
|
||||
item3.plevel = item3.level
|
||||
item3.level = 200
|
||||
item3.children.forEach((item4: any) => {
|
||||
item4.icon = 'el-icon-Flag'
|
||||
item4.plevel = item4.level
|
||||
item4.level = 300
|
||||
// arr.push(item4)
|
||||
item4.children.forEach((item5: any) => {
|
||||
item5.icon = 'el-icon-OfficeBuilding'
|
||||
item5.plevel = item5.level
|
||||
item5.level = 300
|
||||
// item5.id = item4.id
|
||||
item5.children.forEach((item6: any) => {
|
||||
item6.icon = 'el-icon-HelpFilled'
|
||||
item6.plevel = 4
|
||||
if (item6.name == '电网侧' && item6.children.length == 0) {
|
||||
item6.level = 400
|
||||
} else {
|
||||
item6.level = 400
|
||||
}
|
||||
item6.children.forEach((item7: any) => {
|
||||
item7.icon = 'el-icon-Film'
|
||||
item7.plevel = item7.level
|
||||
item7.level = 400
|
||||
item7.children.forEach((item8: any) => {
|
||||
item8.icon = 'el-icon-Collection'
|
||||
item8.plevel = item8.level
|
||||
item8.level = 500
|
||||
item8.children.forEach((item9: any) => {
|
||||
item9.icon = 'el-icon-Share'
|
||||
item9.plevel = item9.level
|
||||
item9.level = 600
|
||||
item9.children.forEach((item10: any) => {
|
||||
item10.icon = 'el-icon-Location'
|
||||
item10.plevel = item10.level
|
||||
item10.level = 700
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
} else {
|
||||
// item2.plevel = item2.level
|
||||
// item2.level = 100
|
||||
// expanded.value.push(item2.id)
|
||||
// item2.children.forEach((item3: any) => {
|
||||
// item3.icon = 'el-icon-CollectionTag'
|
||||
// item3.plevel = item3.level
|
||||
// item3.level = 200
|
||||
// item3.children.forEach((item4: any) => {
|
||||
// item4.icon = 'el-icon-Flag'
|
||||
// item4.plevel = item4.level
|
||||
// item4.level = 300
|
||||
// // arr.push(item4)
|
||||
// item4.children.forEach((item5: any) => {
|
||||
// item5.icon = 'el-icon-OfficeBuilding'
|
||||
// item5.plevel = item5.level
|
||||
// item5.level = 300
|
||||
// // item5.id = item4.id
|
||||
// item5.children.forEach((item6: any) => {
|
||||
// item6.icon = 'el-icon-HelpFilled'
|
||||
// item6.plevel = 4
|
||||
// if (item6.name == '电网侧' && item6.children.length == 0) {
|
||||
// item6.level = 400
|
||||
// } else {
|
||||
// item6.level = 400
|
||||
// }
|
||||
// item6.children.forEach((item7: any) => {
|
||||
// item7.icon = 'el-icon-Film'
|
||||
// item7.plevel = item7.level
|
||||
// item7.level = 400
|
||||
// item7.children.forEach((item8: any) => {
|
||||
// item8.icon = 'el-icon-Collection'
|
||||
// item8.plevel = item8.level
|
||||
// item8.level = 500
|
||||
// item8.children.forEach((item9: any) => {
|
||||
// item9.icon = 'el-icon-Share'
|
||||
// item9.plevel = item9.level
|
||||
// item9.level = 600
|
||||
// item9.children.forEach((item10: any) => {
|
||||
// item10.icon = 'el-icon-Location'
|
||||
// item10.plevel = item10.level
|
||||
// item10.level = 700
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
// } else {
|
||||
res.data.forEach((item: any) => {
|
||||
item.icon = 'el-icon-Menu'
|
||||
item.plevel = item.level
|
||||
@@ -129,7 +129,7 @@ const info = (id: any) => {
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
// }
|
||||
|
||||
tree.value = res.data
|
||||
|
||||
|
||||
@@ -11,25 +11,25 @@
|
||||
:data="eventList.slice((pageNum - 1) * pageSize, pageNum * pageSize)"
|
||||
>
|
||||
<!-- <vxe-column type="seq" width="70px" title="序号"></vxe-column> -->
|
||||
<vxe-column field="time" width="180px" sortable title="发生时刻"></vxe-column>
|
||||
<vxe-column field="lineName" title="监测点"></vxe-column>
|
||||
<vxe-column field="powerCompany" title="变电站" width="100px"></vxe-column>
|
||||
<vxe-column field="powerCompany" title="供电公司" width="100px"></vxe-column>
|
||||
<vxe-column field="persistTime" width="120px" sortable title="持续时间(s)">
|
||||
<template #default="{ row }">
|
||||
{{ Math.floor(row.persistTime * 1000) / 1000 }}
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="time" width="180px" sortable title="暂降发生时刻"></vxe-column>
|
||||
<vxe-column field="eventValue" width="160px" sortable title="暂降(骤升)幅值(%)">
|
||||
<template #default="{ row }">
|
||||
{{ Math.floor(row.eventValue * 10000) / 100 }}
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="persistTime" width="120px" sortable title="持续时间(s)">
|
||||
<template #default="{ row }">
|
||||
{{ Math.floor(row.persistTime * 1000) / 1000 }}
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="eventType" width="100px" title="触发类型">
|
||||
<template #default="{ row }">
|
||||
{{ event.filter(item => item.id == row.eventType)[0]?.name || '/' }}
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="powerCompany" title="变电站" width="100px"></vxe-column>
|
||||
<vxe-column field="powerCompany" title="供电公司" width="100px"></vxe-column>
|
||||
<vxe-column field="lineName" title="监测点"></vxe-column>
|
||||
</vxe-table>
|
||||
<div class="table-pagination mt10">
|
||||
<el-pagination
|
||||
@@ -50,7 +50,8 @@ import { ref, reactive, onMounted } from 'vue'
|
||||
import { defaultAttribute } from '@/components/table/defaultAttribute'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import MQTT from '@/utils/mqtt'
|
||||
// import MQTT from '@/utils/mqtt'
|
||||
import socketClient from '@/utils/webSocketClient'
|
||||
const dictData = useDictData()
|
||||
const event = dictData.getBasicData('Event_Statis')
|
||||
import { useAdminInfo } from '@/stores/adminInfo'
|
||||
@@ -68,37 +69,71 @@ const handleClose = (done: any) => {
|
||||
drawer.value = false
|
||||
done()
|
||||
}
|
||||
const init = async () => {
|
||||
const mqttClient = new MQTT('/sendEvent')
|
||||
// 设置消息接收回调
|
||||
try {
|
||||
await mqttClient.init()
|
||||
const dataSocket = reactive({
|
||||
socketServe: socketClient.Instance
|
||||
})
|
||||
// const init = async () => {
|
||||
// const mqttClient = new MQTT('/sendEvent')
|
||||
// // 设置消息接收回调
|
||||
// try {
|
||||
// await mqttClient.init()
|
||||
|
||||
// 订阅主题
|
||||
await mqttClient.subscribe()
|
||||
// 设置消息接收回调
|
||||
mqttClient.onMessage((topic, message) => {
|
||||
const msg = JSON.parse(message.toString())
|
||||
// console.log('🚀 ~ init ~ msg:', msg)
|
||||
if (msg.deptList.includes(adminInfo.$state.deptId)) {
|
||||
drawer.value = true
|
||||
isLoading.value = true
|
||||
eventList.value.unshift(msg)
|
||||
setTimeout(() => {
|
||||
isLoading.value = false
|
||||
}, 500)
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
// console.error('MQTT 初始化失败:', error)
|
||||
}
|
||||
// // 订阅主题
|
||||
// await mqttClient.subscribe()
|
||||
// // 设置消息接收回调
|
||||
// mqttClient.onMessage((topic, message) => {
|
||||
// const msg = JSON.parse(message.toString())
|
||||
// // console.log('🚀 ~ init ~ msg:', msg)
|
||||
// if (msg.deptList.includes(adminInfo.$state.deptId)) {
|
||||
// drawer.value = true
|
||||
// isLoading.value = true
|
||||
// eventList.value.unshift(msg)
|
||||
// setTimeout(() => {
|
||||
// isLoading.value = false
|
||||
// }, 500)
|
||||
// }
|
||||
// })
|
||||
// } catch (error) {
|
||||
// // console.error('MQTT 初始化失败:', error)
|
||||
// }
|
||||
// }
|
||||
const socket = async () => {
|
||||
const url = localStorage.getItem('WebSocketUrl3') || 'null' //'ws://192.168.2.130:10203/event/'
|
||||
|
||||
// const url = 'ws://192.168.1.68:10203/event/'
|
||||
|
||||
await dataSocket.socketServe.connect(`${url}${adminInfo.id}`)
|
||||
|
||||
await dataSocket.socketServe.registerCallBack('message', (res: any) => {
|
||||
if (res.deptList.includes(adminInfo.$state.deptId)) {
|
||||
drawer.value = true
|
||||
isLoading.value = true
|
||||
eventList.value.unshift(res)
|
||||
setTimeout(() => {
|
||||
isLoading.value = false
|
||||
}, 500)
|
||||
}
|
||||
// logList.value.push({
|
||||
// type: res.code == 500 ? 'error' : '',
|
||||
// time: formatDate(new Date(), 'YYYY-MM-DD hh:mm:ss'),
|
||||
// name: res.message
|
||||
// })
|
||||
})
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
dataSocket.socketServe?.closeWs()
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
// startMqtt('/sendEvent', (topic, message) => {
|
||||
// const msg = JSON.parse(message.toString())
|
||||
// console.log(msg)
|
||||
// })
|
||||
init()
|
||||
|
||||
setTimeout(() => {
|
||||
socket()
|
||||
}, 3000)
|
||||
})
|
||||
defineExpose({
|
||||
open,
|
||||
|
||||
@@ -8,41 +8,14 @@
|
||||
name="el-icon-BellFilled"
|
||||
size="18"
|
||||
/>
|
||||
<span class="nav-menu-text" v-if="globalPopUpRef?.eventList.length != 0">
|
||||
{{ (globalPopUpRef?.eventList.length>99? '99+':globalPopUpRef?.eventList.length) || 0 }}
|
||||
<span class="nav-menu-text" v-if="globalPopUpRef?.eventList?.length > 0">
|
||||
{{ globalPopUpRef.eventList.length > 99 ? '99+' : globalPopUpRef.eventList.length }}
|
||||
</span>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<!-- <el-tooltip effect="dark" content="截图" placement="bottom">
|
||||
<div @click="savePng" class="nav-menu-item">
|
||||
<Icon
|
||||
:color="configStore.getColorVal('headerBarTabColor')"
|
||||
class="nav-menu-icon"
|
||||
name="el-icon-Camera"
|
||||
size="18"
|
||||
/>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<el-tooltip effect="dark" :content="state.isFullScreen ? '缩小' : '放大'" placement="bottom">
|
||||
<div @click="onFullScreen" class="nav-menu-item" :class="state.isFullScreen ? 'hover' : ''">
|
||||
<Icon
|
||||
:color="configStore.getColorVal('headerBarTabColor')"
|
||||
class="nav-menu-icon"
|
||||
v-if="state.isFullScreen"
|
||||
name="fa-solid fa-compress"
|
||||
size="18"
|
||||
/>
|
||||
<Icon
|
||||
:color="configStore.getColorVal('headerBarTabColor')"
|
||||
class="nav-menu-icon"
|
||||
v-else
|
||||
name="fa-solid fa-expand"
|
||||
size="18"
|
||||
/>
|
||||
</div>
|
||||
</el-tooltip> -->
|
||||
|
||||
<el-dropdown style="height: 100%" @command="handleCommand">
|
||||
<div class="admin-info" :class="state.currentNavMenu == 'adminInfo' ? 'hover' : ''">
|
||||
<div class="admin-info" :class="state.currentNavMenu === 'adminInfo' ? 'hover' : ''">
|
||||
<el-avatar :size="25" fit="fill">
|
||||
<img src="@/assets/avatar.png" alt="" />
|
||||
</el-avatar>
|
||||
@@ -51,105 +24,115 @@
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="adminInfo">个人资料</el-dropdown-item>
|
||||
<el-dropdown-item command="changePwd">修改密码</el-dropdown-item>
|
||||
<el-dropdown-item command="layout">退出登录</el-dropdown-item>
|
||||
<el-dropdown-item command="changePwd" v-if="!IS_LNQR">修改密码</el-dropdown-item>
|
||||
<el-dropdown-item command="logout">退出登录</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<!-- <div @click="configStore.setLayout('showDrawer', true)" class="nav-menu-item">
|
||||
<Icon
|
||||
:color="configStore.getColorVal('headerBarTabColor')"
|
||||
class="nav-menu-icon"
|
||||
name="fa fa-cogs"
|
||||
size="18"
|
||||
/>
|
||||
</div> -->
|
||||
|
||||
<Config />
|
||||
<PopupPwd ref="popupPwd" />
|
||||
<AdminInfo ref="popupAdminInfo" />
|
||||
<!-- <TerminalVue /> -->
|
||||
<!-- 全局暂降事件 -->
|
||||
<globalPopUp ref="globalPopUpRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import screenfull from 'screenfull'
|
||||
import { useConfig } from '@/stores/config'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import Config from './config.vue'
|
||||
import { useAdminInfo } from '@/stores/adminInfo'
|
||||
import router from '@/router'
|
||||
import globalPopUp from './globalPopUp.vue'
|
||||
import { routePush } from '@/utils/router'
|
||||
import html2canvas from 'html2canvas'
|
||||
import { useNavTabs } from '@/stores/navTabs'
|
||||
import { logout } from '@/api/user-boot/user'
|
||||
import Config from './config.vue'
|
||||
import PopupPwd from './popup/password.vue'
|
||||
import AdminInfo from './popup/adminInfo.vue'
|
||||
import { useNavTabs } from '@/stores/navTabs'
|
||||
import globalPopUp from './globalPopUp.vue'
|
||||
const { replace } = useRouter()
|
||||
// 环境标识
|
||||
const IS_LNQR = import.meta.env.VITE_NAME === 'LNqr'
|
||||
|
||||
const adminInfo = useAdminInfo()
|
||||
const navTabs = useNavTabs()
|
||||
const configStore = useConfig()
|
||||
|
||||
// 引用
|
||||
const popupPwd = ref()
|
||||
const popupAdminInfo = ref()
|
||||
const state = reactive({
|
||||
isFullScreen: false,
|
||||
currentNavMenu: '',
|
||||
showLayoutDrawer: false,
|
||||
showAdminInfoPopover: false
|
||||
})
|
||||
const globalPopUpRef = ref()
|
||||
const savePng = () => {
|
||||
html2canvas(document.body, {
|
||||
scale: 1,
|
||||
useCORS: true
|
||||
}).then(function (canvas) {
|
||||
var link = document.createElement('a')
|
||||
link.href = canvas.toDataURL('image/png')
|
||||
link.download = 'screenshot.png'
|
||||
link.click()
|
||||
})
|
||||
}
|
||||
const onFullScreen = () => {
|
||||
if (!screenfull.isEnabled) {
|
||||
ElMessage.warning('layouts.Full screen is not supported')
|
||||
return false
|
||||
|
||||
// 状态
|
||||
const state = reactive({
|
||||
currentNavMenu: ''
|
||||
})
|
||||
|
||||
// 打开暂降事件
|
||||
const temporaryLandingEvent = () => {
|
||||
if (globalPopUpRef.value) {
|
||||
globalPopUpRef.value.open()
|
||||
}
|
||||
screenfull.toggle()
|
||||
screenfull.onchange(() => {
|
||||
state.isFullScreen = screenfull.isFullscreen
|
||||
})
|
||||
}
|
||||
|
||||
const handleCommand = async(key: string) => {
|
||||
console.log(key)
|
||||
// 下拉菜单命令
|
||||
const handleCommand = async (key: string) => {
|
||||
switch (key) {
|
||||
case 'adminInfo':
|
||||
popupAdminInfo.value.open()
|
||||
popupAdminInfo.value?.open()
|
||||
break
|
||||
case 'changePwd':
|
||||
popupPwd.value.open()
|
||||
popupPwd.value?.open()
|
||||
break
|
||||
case 'layout':
|
||||
await window.location.reload()
|
||||
setTimeout(() => {
|
||||
navTabs.closeTabs()
|
||||
window.localStorage.clear()
|
||||
adminInfo.reset()
|
||||
router.push({ name: 'login' })
|
||||
}, 0)
|
||||
// navTabs.closeTabs()
|
||||
// window.localStorage.clear()
|
||||
// adminInfo.reset()
|
||||
// router.push({ name: 'login' })
|
||||
break
|
||||
default:
|
||||
case 'logout':
|
||||
await handleLogout()
|
||||
break
|
||||
}
|
||||
}
|
||||
const temporaryLandingEvent = () => {
|
||||
globalPopUpRef.value.open()
|
||||
|
||||
// 统一登出逻辑
|
||||
const handleLogout = async () => {
|
||||
try {
|
||||
// 1. 调用后端登出接口
|
||||
await logout()
|
||||
// console.log('✅ 后端登出成功')
|
||||
} catch (err) {
|
||||
// console.error('❌ 登出接口异常', err)
|
||||
} finally {
|
||||
// 2. 清理本地所有数据
|
||||
clearLocalData()
|
||||
|
||||
// 3. LNqr 环境跳 CAS 登出
|
||||
if (IS_LNQR) {
|
||||
redirectToCasLogout()
|
||||
} else {
|
||||
// 普通环境直接跳登录页
|
||||
replace('/login')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 清理本地数据
|
||||
const clearLocalData = () => {
|
||||
// 清空 localStorage
|
||||
window.localStorage.clear()
|
||||
|
||||
// 清空用户状态
|
||||
adminInfo.reset()
|
||||
|
||||
// 清空标签页
|
||||
navTabs.closeTabs()
|
||||
|
||||
console.log('✅ 本地数据已全部清空')
|
||||
}
|
||||
|
||||
// CAS 登出跳转
|
||||
const redirectToCasLogout = () => {
|
||||
const casLogoutUrl =
|
||||
'http://privilege-epri.dcloud.ln.dc.sgcc.com.cn/cas/logout?service=http://privilege-epri.dcloud.ln.dc.sgcc.com.cn/cas/login?service=http://PQMonitoring.dcloud.ln.dc.sgcc.com.cn'
|
||||
window.location.href = casLogoutUrl
|
||||
// 清 Cookie
|
||||
document.cookie.split(';').forEach(cookie => {
|
||||
const name = cookie.split('=')[0].trim()
|
||||
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -163,7 +146,6 @@ const temporaryLandingEvent = () => {
|
||||
height: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
// height: 100%;
|
||||
margin-left: auto;
|
||||
background-color: v-bind('configStore.getColorVal("headerBarBackground")');
|
||||
|
||||
@@ -219,37 +201,15 @@ const temporaryLandingEvent = () => {
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu-box :deep(.el-dropdown-menu__item) {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.admin-info-base {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
padding-top: 10px;
|
||||
|
||||
.admin-info-other {
|
||||
display: block;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
|
||||
.admin-info-name {
|
||||
font-size: var(--el-font-size-large);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.admin-info-footer {
|
||||
padding: 10px 0;
|
||||
margin: 0 -12px -12px -12px;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.pt2 {
|
||||
padding-top: 2px;
|
||||
.nav-menu-text {
|
||||
position: absolute;
|
||||
top: 13px;
|
||||
left: 20px;
|
||||
font-size: 12px;
|
||||
background: #ff0000;
|
||||
color: #fff;
|
||||
border-radius: 5px;
|
||||
padding: 0 3px;
|
||||
}
|
||||
|
||||
@keyframes twinkle {
|
||||
@@ -263,15 +223,4 @@ const temporaryLandingEvent = () => {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
.nav-menu-text {
|
||||
position: absolute;
|
||||
top: 13px;
|
||||
left: 20px;
|
||||
font-size: 12px;
|
||||
display: inline-block;
|
||||
background-color: #ff0000;
|
||||
color: #fff;
|
||||
border-radius: 5px;
|
||||
padding: 0 3px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -4,8 +4,10 @@ import router from './router'
|
||||
import pinia from '@/stores/index'
|
||||
import { registerIcons } from '@/utils/common'
|
||||
import mitt from 'mitt'
|
||||
import VxeUI from 'vxe-pc-ui'
|
||||
import VXETable from 'vxe-table'
|
||||
import XEUtils from 'xe-utils'
|
||||
import 'vxe-pc-ui/lib/style.css'
|
||||
import 'vxe-table/lib/style.css'
|
||||
import ElementPlus from 'element-plus'
|
||||
import 'element-plus/dist/index.css'
|
||||
@@ -61,6 +63,7 @@ const setupAll = async () => {
|
||||
await setupI18n(app)
|
||||
app.use(router)
|
||||
app.use(pinia)
|
||||
app.use(VxeUI)
|
||||
app.use(ElementPlus)
|
||||
app.use(VXETable)
|
||||
|
||||
|
||||
@@ -1,55 +1,22 @@
|
||||
import type { App } from 'vue'
|
||||
// 👇使用 form-create 需额外全局引入 element plus 组件
|
||||
import {
|
||||
ElAlert,
|
||||
ElAside,
|
||||
ElContainer,
|
||||
ElDivider,
|
||||
ElHeader,
|
||||
ElMain,
|
||||
ElPopconfirm,
|
||||
ElTable,
|
||||
ElTableColumn,
|
||||
ElTabPane,
|
||||
ElTabs,
|
||||
ElTransfer
|
||||
} from 'element-plus'
|
||||
import FcDesigner from '@form-create/designer'
|
||||
import formCreate from '@form-create/element-ui'
|
||||
import install from '@form-create/element-ui/auto-import'
|
||||
//======================= 自定义组件 =======================
|
||||
import { UploadFile, UploadImg, UploadImgs } from '@/components/UploadFile'
|
||||
import { DictSelect } from '@/components/DictSelect'
|
||||
import UserSelect from '@/views/system/auth/userList/UserSelect.vue'
|
||||
import { Editor } from '@/components/Editor'
|
||||
|
||||
const components = [
|
||||
ElAside,
|
||||
ElPopconfirm,
|
||||
ElHeader,
|
||||
ElMain,
|
||||
ElContainer,
|
||||
ElDivider,
|
||||
ElTransfer,
|
||||
ElAlert,
|
||||
ElTabs,
|
||||
ElTable,
|
||||
ElTableColumn,
|
||||
ElTabPane,
|
||||
UploadImg,
|
||||
UploadImgs,
|
||||
UploadFile,
|
||||
DictSelect,
|
||||
UserSelect,
|
||||
Editor
|
||||
]
|
||||
|
||||
// 参考 http://www.form-create.com/v3/element-ui/auto-import.html 文档
|
||||
export const setupFormCreate = (app: App<Element>) => {
|
||||
components.forEach((component) => {
|
||||
app.component(component.name, component)
|
||||
})
|
||||
formCreate.use(install)
|
||||
app.use(formCreate)
|
||||
app.use(FcDesigner)
|
||||
}
|
||||
import type { App } from 'vue'
|
||||
import FcDesigner from '@form-create/designer'
|
||||
import formCreate from '@form-create/element-ui'
|
||||
import install from '@form-create/element-ui/auto-import'
|
||||
//======================= 自定义组件 =======================
|
||||
import { UploadFile, UploadImg, UploadImgs } from '@/components/UploadFile'
|
||||
import { DictSelect } from '@/components/DictSelect'
|
||||
import UserSelect from '@/views/system/auth/userList/UserSelect.vue'
|
||||
import { Editor } from '@/components/Editor'
|
||||
|
||||
// Element Plus 已在 main.ts 通过 app.use(ElementPlus) 全局注册,此处仅注册 form-create 自定义组件
|
||||
const components = [UploadImg, UploadImgs, UploadFile, DictSelect, UserSelect, Editor]
|
||||
|
||||
// 参考 http://www.form-create.com/v3/element-ui/auto-import.html 文档
|
||||
export const setupFormCreate = (app: App<Element>) => {
|
||||
components.forEach((component) => {
|
||||
app.component(component.name!, component)
|
||||
})
|
||||
formCreate.use(install)
|
||||
app.use(formCreate)
|
||||
app.use(FcDesigner)
|
||||
}
|
||||
|
||||
@@ -404,6 +404,11 @@ body,
|
||||
.el-select__wrapper {
|
||||
height: 32px !important;
|
||||
}
|
||||
.BMap_center,
|
||||
.BMap_top,
|
||||
.BMap_bottom {
|
||||
background-color: #fff;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'AlimamaFangYuanTiVF';
|
||||
src: url('../assets/font/ali/AlimamaFangYuanTiVF-Thin.woff') format('woff'),
|
||||
|
||||
@@ -31,6 +31,8 @@ $border-color: map.merge(
|
||||
@include set-component-css-var('border-color', $border-color);
|
||||
--vxe-ui-table-row-current-background-color: var(--el-color-primary-light-8);
|
||||
--vxe-ui-table-row-hover-current-background-color: var(--el-color-primary-light-8);
|
||||
--vxe-ui-font-primary-color: var(--el-color-primary);
|
||||
--vxe-ui-font-primary-lighten-color: var(--el-color-primary);
|
||||
// --vxe-table-row-current-background-color: var(--el-color-primary-light-7);
|
||||
// --vxe-table-row-hover-background-color: var(--el-color-primary-light-9);
|
||||
// --vxe-table-row-hover-current-background-color: var(--el-color-primary-light-7);
|
||||
|
||||
@@ -70,7 +70,8 @@
|
||||
// .vxe-table--render-default .is--disabled.vxe-cell--checkbox .vxe-checkbox--icon{
|
||||
// color: #fff0;
|
||||
// }
|
||||
.vxe-table--tooltip-wrapper {
|
||||
.vxe-table--tooltip-wrapper,
|
||||
.vxe-tooltip--wrapper {
|
||||
z-index: 10000 !important;
|
||||
}
|
||||
.is--disabled {
|
||||
@@ -98,3 +99,8 @@
|
||||
background-color: #000 !important;
|
||||
}
|
||||
}
|
||||
.vxe-table-custom--panel-list > li {
|
||||
max-width: 28em;
|
||||
min-width: 15em;
|
||||
padding: 0.3em 1em 0.2em 1em;
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class='default-main'>
|
||||
<!-- 表头 -->
|
||||
<!-- date-picker 时间组件 area区域组件-->
|
||||
<TableHeader date-picker area>
|
||||
<TableHeader date-picker area showCustomColumn>
|
||||
<template v-slot:select>
|
||||
<el-form-item label='关键词:'>
|
||||
<el-input
|
||||
|
||||
59
src/utils/chartAxisHelper.ts
Normal file
59
src/utils/chartAxisHelper.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
const AXIS_DECIMALS = 2
|
||||
|
||||
export function roundAxisValue(val: number, decimals = AXIS_DECIMALS): number {
|
||||
if (!Number.isFinite(val)) return 0
|
||||
const factor = 10 ** decimals
|
||||
return Math.round(val * factor) / factor
|
||||
}
|
||||
|
||||
/** Y 轴刻度:最多 2 位小数,末尾 0 去掉(如 1.00 → 1,0.10 → 0.1) */
|
||||
export function formatAxisLabel(value: number): string {
|
||||
if (!Number.isFinite(value)) return '0'
|
||||
return String(Number(roundAxisValue(value).toFixed(AXIS_DECIMALS)))
|
||||
}
|
||||
|
||||
/** 瞬间波形 Y 轴范围 */
|
||||
export function calcShuYAxisRange(dataMin: number, dataMax: number): { min: number; max: number } {
|
||||
const min = Number(dataMin)
|
||||
const max = Number(dataMax)
|
||||
if (!Number.isFinite(min) || !Number.isFinite(max)) {
|
||||
return { min: 0, max: 1 }
|
||||
}
|
||||
|
||||
let axisMax = max * 1.1
|
||||
let axisMin = min > 0 ? min - min * 0.1 : min * 1.1
|
||||
|
||||
if (axisMax <= axisMin) {
|
||||
const pad = Math.abs(max) * 0.1 || 0.01
|
||||
axisMax = max + pad
|
||||
axisMin = min - pad
|
||||
}
|
||||
|
||||
return {
|
||||
min: roundAxisValue(axisMin),
|
||||
max: roundAxisValue(axisMax)
|
||||
}
|
||||
}
|
||||
|
||||
/** RMS 波形 Y 轴范围 */
|
||||
export function calcRmsYAxisRange(dataMin: number, dataMax: number): { min: number; max: number } {
|
||||
const min = Number(dataMin)
|
||||
const max = Number(dataMax)
|
||||
if (!Number.isFinite(min) || !Number.isFinite(max)) {
|
||||
return { min: 0, max: 1 }
|
||||
}
|
||||
|
||||
let axisMax = max * 1.06 * 1.1
|
||||
let axisMin = min - min * 0.2
|
||||
|
||||
if (axisMax <= axisMin) {
|
||||
const pad = Math.abs(max - min) * 0.1 || Math.abs(max) * 0.1 || 0.01
|
||||
axisMax = max + pad
|
||||
axisMin = min - pad
|
||||
}
|
||||
|
||||
return {
|
||||
min: roundAxisValue(axisMin),
|
||||
max: roundAxisValue(axisMax)
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
// 高级算法
|
||||
export const ADVANCE_BOOT = '/advance-boot'
|
||||
|
||||
//技术监督
|
||||
export const PROCESS_BOOT = '/process-boot'
|
||||
|
||||
//工作流模块
|
||||
export const BPM_BOOT = '/bpm-boot'
|
||||
|
||||
//冀北技术监督
|
||||
export const SUPERVISION_BOOT = '/supervision-boot'
|
||||
|
||||
//终端模块
|
||||
// 高级算法
|
||||
export const ADVANCE_BOOT = '/advance-boot'
|
||||
|
||||
//技术监督
|
||||
export const PROCESS_BOOT = '/process-boot'
|
||||
|
||||
//工作流模块
|
||||
export const BPM_BOOT = '/bpm-boot'
|
||||
|
||||
//网公司技术监督
|
||||
export const SUPERVISION_BOOT = '/supervision-boot'
|
||||
|
||||
//终端模块
|
||||
export const DEVICE_BOOT = '/device-boot'
|
||||
@@ -11,6 +11,7 @@ const calculateValue = (o: number, value: number, num: number, isMin: boolean) =
|
||||
} else if (value > -1 && value < 0 && isMin == false) {
|
||||
return 0
|
||||
}
|
||||
|
||||
let base
|
||||
if (Math.abs(o) >= 100) {
|
||||
base = 100
|
||||
@@ -19,8 +20,11 @@ const calculateValue = (o: number, value: number, num: number, isMin: boolean) =
|
||||
} else if (Math.abs(o) >= 1) {
|
||||
base = 1
|
||||
} else {
|
||||
base = 0.1
|
||||
const multiple = 1 / 0.1
|
||||
|
||||
base = Math.ceil(Math.abs(o) * multiple) / multiple
|
||||
}
|
||||
|
||||
let calculatedValue
|
||||
if (isMin) {
|
||||
if (value < 0) {
|
||||
@@ -35,98 +39,37 @@ const calculateValue = (o: number, value: number, num: number, isMin: boolean) =
|
||||
calculatedValue = value + num * value
|
||||
}
|
||||
}
|
||||
|
||||
if (base === 0.1) {
|
||||
return parseFloat(calculatedValue.toFixed(1))
|
||||
// return parseFloat(calculatedValue.toFixed(1))
|
||||
return Math.ceil(calculatedValue * 10) / 10
|
||||
} else if (isMin) {
|
||||
return Math.floor(calculatedValue / base) * base
|
||||
} else {
|
||||
return Math.ceil(calculatedValue / base) * base
|
||||
}
|
||||
}
|
||||
|
||||
// 处理y轴最大最小值
|
||||
export const yMethod = (arr: any) => {
|
||||
let num = 0.1
|
||||
let num = 0.2
|
||||
let numList = dataProcessing(arr)
|
||||
let maxValue = 0
|
||||
let minValue = 0
|
||||
let max = 0
|
||||
let min = 0
|
||||
maxValue = Math.max(...numList)
|
||||
minValue = Math.min(...numList)
|
||||
const o = maxValue - minValue
|
||||
if (Math.abs(o) >= 300) {
|
||||
num = 0.02
|
||||
if (numList.length === 0) {
|
||||
return [0, 0]
|
||||
}
|
||||
const maxValue = Math.max(...numList)
|
||||
const minValue = Math.min(...numList)
|
||||
let min = 0
|
||||
let max = 0
|
||||
|
||||
min = calculateValue(o, minValue, num, true)
|
||||
max = calculateValue(o, maxValue, num, false)
|
||||
// if (-100 >= minValue) {
|
||||
// min = Math.floor((minValue + num * minValue) / 100) * 100
|
||||
// } else if (-10 >= minValue && minValue > -100) {
|
||||
// min = Math.floor((minValue + num * minValue) / 10) * 10
|
||||
// } else if (-1 >= minValue && minValue > -10) {
|
||||
// min = Math.floor(minValue + num * minValue)
|
||||
// } else if (0 > minValue && minValue > -1) {
|
||||
// min = parseFloat((minValue + num * minValue).toFixed(1))
|
||||
// } else if (minValue == 0) {
|
||||
// min = 0
|
||||
// } else if (0 < minValue && minValue < 1) {
|
||||
// min = parseFloat((minValue - num * minValue).toFixed(1))
|
||||
// } else if (1 <= minValue && minValue < 10) {
|
||||
// min = Math.floor(minValue - num * minValue)
|
||||
// } else if (10 <= minValue && minValue < 100) {
|
||||
// min = Math.floor((minValue - num * minValue) / 10) * 10
|
||||
// } else if (100 <= minValue) {
|
||||
// min = Math.floor((minValue - num * minValue) / 100) * 100
|
||||
// }
|
||||
|
||||
// if (-100 >= maxValue) {
|
||||
// max = Math.ceil((maxValue - num * maxValue) / 100) * 100
|
||||
// } else if (-10 >= maxValue && maxValue > -100) {
|
||||
// max = Math.ceil((maxValue - num * maxValue) / 10) * 10
|
||||
// } else if (-1 >= maxValue && maxValue > -10) {
|
||||
// max = Math.ceil(maxValue - num * maxValue)
|
||||
// } else if (0 > maxValue && maxValue > -1) {
|
||||
// max = parseFloat((maxValue - num * maxValue).toFixed(1))
|
||||
// } else if (maxValue == 0) {
|
||||
// max = 0
|
||||
// } else if (0 < maxValue && maxValue < 1) {
|
||||
// max = parseFloat((maxValue + num * maxValue).toFixed(1))
|
||||
// } else if (1 <= maxValue && maxValue < 10) {
|
||||
// max = Math.ceil(maxValue + num * maxValue)
|
||||
// } else if (10 <= maxValue && maxValue < 100) {
|
||||
// max = Math.ceil((maxValue + num * maxValue) / 10) * 10
|
||||
// } else if (100 <= maxValue) {
|
||||
// max = Math.ceil((maxValue + num * maxValue) / 100) * 100
|
||||
// }
|
||||
|
||||
// if (maxValue > 1000 || minValue < -1000) {
|
||||
// max = Math.ceil(maxValue / 100) * 100
|
||||
// if (minValue == 0) {
|
||||
// min = 0
|
||||
// } else {
|
||||
// min = Math.floor(minValue / 100) * 100
|
||||
// }
|
||||
// } else if (maxValue < 60 && minValue > 40) {
|
||||
// max = 60
|
||||
// min = 40
|
||||
// } else if (maxValue == minValue && maxValue < 10 && minValue > 0) {
|
||||
// max = Math.ceil(maxValue / 10) * 10
|
||||
// min = Math.floor(minValue / 10) * 10
|
||||
// } else if (maxValue == minValue && maxValue != 0 && minValue != 0) {
|
||||
// max = Math.ceil(maxValue / 10 + 1) * 10
|
||||
// min = Math.floor(minValue / 10 - 1) * 10
|
||||
// } else {
|
||||
// max = Math.ceil(maxValue / 10) * 10
|
||||
// min = Math.floor(minValue / 10) * 10
|
||||
// }
|
||||
|
||||
// if (maxValue > 0 && maxValue < 1) {
|
||||
// max = 1
|
||||
// } else if (max == 0 && minValue > -1 && minValue < 0) {
|
||||
// min = -1
|
||||
// }
|
||||
// 一正一负时各自按绝对值范围计算,不用 max - min 作为跨度
|
||||
if (maxValue > 0 && minValue < 0) {
|
||||
min = calculateValue(Math.abs(minValue), minValue, num, true)
|
||||
max = calculateValue(Math.abs(maxValue), maxValue, num, false)
|
||||
} else {
|
||||
const o = maxValue - minValue === 0 ? maxValue : maxValue - minValue
|
||||
min = calculateValue(o, minValue, num, true)
|
||||
max = calculateValue(o, maxValue, num, false)
|
||||
}
|
||||
|
||||
return [min, max]
|
||||
}
|
||||
@@ -158,8 +101,6 @@ export const exportCSV = (title: object, data: any, filename: string) => {
|
||||
URL.revokeObjectURL(link.href)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 补全时间序列数据中缺失的条目
|
||||
* @param rawData 原始数据,格式为 [["时间字符串", "数值", "单位", "类型"], ...]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { downloadFile } from '@/api/system-boot/file'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
const sanitizeUrl = (url: string): string => {
|
||||
return url.replace(/\[/g, '(').replace(/\]/g, ')')
|
||||
@@ -7,7 +8,7 @@ const sanitizeUrl = (url: string): string => {
|
||||
// 下载文件
|
||||
export const download = (urls: string) => {
|
||||
//console.log('下载', urls)
|
||||
|
||||
ElMessage.info('下载中...')
|
||||
downloadFile({ filePath: urls })
|
||||
.then((res: any) => {
|
||||
// 1. 确定文件MIME类型(优化:用更简洁的方式)
|
||||
@@ -26,9 +27,9 @@ export const download = (urls: string) => {
|
||||
}
|
||||
return mimeMap[ext] || ''
|
||||
}
|
||||
|
||||
|
||||
const blob = new Blob([res], { type: getFileType(urls) })
|
||||
|
||||
|
||||
// 2. 提取文件名并保留原生后缀(核心修复点)
|
||||
const fileName = urls.split('/').at(-1) || '下载文件' // 先提取URL最后一段(文件名)
|
||||
|
||||
@@ -43,8 +44,12 @@ export const download = (urls: string) => {
|
||||
// 4. 清理资源(优化)
|
||||
link.remove()
|
||||
window.URL.revokeObjectURL(url) // 释放blob URL
|
||||
setTimeout(() => {
|
||||
ElMessage.success('下载成功')
|
||||
}, 1000)
|
||||
})
|
||||
.catch(err => {
|
||||
ElMessage.warning('下载失败:', err)
|
||||
console.error('下载失败:', err)
|
||||
// 可添加错误提示(如Toast)
|
||||
})
|
||||
@@ -61,7 +66,7 @@ export const previewFile = async (urls: any) => {
|
||||
//console.log('预览', urls)
|
||||
let url = ''
|
||||
await downloadFile({ filePath: decodeURI(urls) })
|
||||
.then((res: any) => {
|
||||
.then((res: any) => {
|
||||
// 1. 确定文件MIME类型(优化:用更简洁的方式)
|
||||
const getFileType = (url: string) => {
|
||||
const ext = url.split('.').pop()?.toLowerCase() || ''
|
||||
@@ -77,7 +82,7 @@ export const previewFile = async (urls: any) => {
|
||||
jpg: 'image/jpg'
|
||||
}
|
||||
return mimeMap[ext] || ''
|
||||
}
|
||||
}
|
||||
const blob = new Blob([res], { type: getFileType(decodeURI(urls)) })
|
||||
// 3. 创建下载链接
|
||||
url = window.URL.createObjectURL(blob)
|
||||
|
||||
@@ -27,8 +27,8 @@ class MQTT {
|
||||
clean: true,
|
||||
connectTimeout: 30 * 1000,
|
||||
clientId: `mqttjs_${Math.random().toString(16).substr(2, 8)}`,
|
||||
username: 't_user',
|
||||
password: 'njcnpqs',
|
||||
username: '',
|
||||
password: '',
|
||||
reconnectPeriod: 1000, // 默认1秒重试一次
|
||||
maxReconnectTimes: 3 // 默认最大重连5次
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import type { AxiosRequestConfig, Method } from 'axios'
|
||||
import axios from 'axios'
|
||||
import { ElLoading, ElNotification, type LoadingOptions } from 'element-plus'
|
||||
import { refreshToken } from '@/api/user-boot/user'
|
||||
import { lnRefreshToken, lnRefreshTokenTo, refreshToken } from '@/api/user-boot/user'
|
||||
import router from '@/router/index'
|
||||
import { useAdminInfo } from '@/stores/adminInfo'
|
||||
import { debounce } from 'lodash-es'
|
||||
const IS_LN_VERSION = import.meta.env.VITE_NAME === 'LNqr'
|
||||
let loginExpireTimer: any = null
|
||||
window.requests = []
|
||||
window.tokenRefreshing = false
|
||||
@@ -107,7 +108,12 @@ function createAxios<Data = any, T = ApiPromise<Data>>(
|
||||
config.headers.Authorization = 'Basic bmpjbjpuamNucHFz'
|
||||
}
|
||||
}
|
||||
if (config.url == '/user-boot/user/generateSm2Key' || config.url == '/pqs-auth/oauth/token') {
|
||||
if (
|
||||
config.url == '/user-boot/user/generateSm2Key' ||
|
||||
config.url == '/pqs-auth/oauth/token' ||
|
||||
config.url == '/pqs-auth/oauth/lnLogin' ||
|
||||
config.url == '/pqs-auth/oauth/lnRefreshToken'
|
||||
) {
|
||||
config.headers.Authorization = 'Basic bmpjbjpuamNucHFz'
|
||||
}
|
||||
|
||||
@@ -142,24 +148,46 @@ function createAxios<Data = any, T = ApiPromise<Data>>(
|
||||
if (!window.tokenRefreshing) {
|
||||
window.tokenRefreshing = true
|
||||
|
||||
return refreshToken()
|
||||
.then(res => {
|
||||
adminInfo.setToken(res.data.access_token, 'auth')
|
||||
adminInfo.setToken(res.data.refresh_token, 'refresh')
|
||||
window.requests.forEach(cb => cb(res.data.access_token))
|
||||
window.requests = []
|
||||
if (IS_LN_VERSION) {
|
||||
//辽宁版本
|
||||
return lnRefreshTokenTo()
|
||||
.then(res => {
|
||||
adminInfo.setToken(res.data.access_token, 'auth')
|
||||
adminInfo.setToken(res.data.refresh_token, 'refresh')
|
||||
window.requests.forEach(cb => cb(res.data.access_token))
|
||||
window.requests = []
|
||||
|
||||
return Axios(response.config)
|
||||
})
|
||||
.catch(err => {
|
||||
window.location.reload()
|
||||
adminInfo.removeToken()
|
||||
router.push({ name: 'login' })
|
||||
return Promise.reject(err)
|
||||
})
|
||||
.finally(() => {
|
||||
window.tokenRefreshing = false
|
||||
})
|
||||
return Axios(response.config)
|
||||
})
|
||||
.catch(err => {
|
||||
// refresh_token + CAS 都过期 → 重新走CAS登录
|
||||
//window.location.href = '/api/pqs-auth/oauth/lnCheck'
|
||||
return Promise.reject(err)
|
||||
})
|
||||
.finally(() => {
|
||||
window.tokenRefreshing = false
|
||||
})
|
||||
} else {
|
||||
//通用版本
|
||||
return refreshToken()
|
||||
.then(res => {
|
||||
adminInfo.setToken(res.data.access_token, 'auth')
|
||||
adminInfo.setToken(res.data.refresh_token, 'refresh')
|
||||
window.requests.forEach(cb => cb(res.data.access_token))
|
||||
window.requests = []
|
||||
|
||||
return Axios(response.config)
|
||||
})
|
||||
.catch(err => {
|
||||
window.location.reload()
|
||||
adminInfo.removeToken()
|
||||
router.push({ name: 'login' })
|
||||
return Promise.reject(err)
|
||||
})
|
||||
.finally(() => {
|
||||
window.tokenRefreshing = false
|
||||
})
|
||||
}
|
||||
} else {
|
||||
return new Promise(resolve => {
|
||||
// 用函数形式将 resolve 存入,等待刷新后再执行
|
||||
@@ -185,6 +213,17 @@ function createAxios<Data = any, T = ApiPromise<Data>>(
|
||||
loginExpireTimer = null // 执行后清空定时器
|
||||
}, 100) // 可根据实际情况调整延迟时间
|
||||
return Promise.reject(response.data)
|
||||
} else if (response.data.code == 'A0121') {
|
||||
//统一认证过期
|
||||
//const casLogoutUrl = 'http://privilege-epri.dcloud.ln.dc.sgcc.com.cn/cas/login?service=http://PQMonitoring.dcloud.ln.dc.sgcc.com.cn'
|
||||
// 1. 清空本地失效token、用户信息
|
||||
adminInfo.removeToken()
|
||||
adminInfo.reset()
|
||||
// 2. 跳转统一鉴权中转接口
|
||||
const authCheckUrl = '/api/pqs-auth/oauth/lnCheck'
|
||||
window.location.href = authCheckUrl
|
||||
// 中断请求
|
||||
return Promise.reject(response.data)
|
||||
} else {
|
||||
if (options.showCodeMessage) {
|
||||
ElNotification({
|
||||
|
||||
@@ -10,7 +10,6 @@ import { compact, isEmpty, reverse } from 'lodash-es'
|
||||
import { getRouteMenu, dictDataCache } from '@/api/auth'
|
||||
import { isAdminApp } from '@/utils/common'
|
||||
import { adminBaseRoutePath } from '@/router/static'
|
||||
const route:any = useRouter()
|
||||
/**
|
||||
* 导航失败有错误消息的路由push
|
||||
* @param to — 导航位置,同 router.push
|
||||
@@ -319,8 +318,9 @@ export const getMenu = () => {
|
||||
}
|
||||
handlerMenu(res.data)
|
||||
handleAdminRoute(res.data)
|
||||
if (route?.params.to) {
|
||||
const lastRoute = JSON.parse(route.params.to as string)
|
||||
const currentRoute = router.currentRoute.value
|
||||
if (currentRoute?.params.to) {
|
||||
const lastRoute = JSON.parse(currentRoute.params.to as string)
|
||||
if (lastRoute.path != adminBaseRoutePath) {
|
||||
let query = !isEmpty(lastRoute.query) ? lastRoute.query : {}
|
||||
routePush({ path: lastRoute.path, query: query })
|
||||
|
||||
@@ -48,6 +48,7 @@ export default class TableStore {
|
||||
filename: null,
|
||||
loading: true,
|
||||
exportLoading: false,
|
||||
customColumnInHeader: false,
|
||||
column: [],
|
||||
loadCallback: null,
|
||||
exportProcessingData: null,
|
||||
|
||||
@@ -1,400 +1,432 @@
|
||||
interface TreeHelperConfig {
|
||||
id: string
|
||||
children: string
|
||||
pid: string
|
||||
}
|
||||
|
||||
const DEFAULT_CONFIG: TreeHelperConfig = {
|
||||
id: 'id',
|
||||
children: 'children',
|
||||
pid: 'pid'
|
||||
}
|
||||
export const defaultProps = {
|
||||
children: 'children',
|
||||
label: 'name',
|
||||
value: 'id',
|
||||
isLeaf: 'leaf',
|
||||
emitPath: false // 用于 cascader 组件:在选中节点改变时,是否返回由该节点所在的各级菜单的值所组成的数组,若设置 false,则只返回该节点的值
|
||||
}
|
||||
|
||||
const getConfig = (config: Partial<TreeHelperConfig>) => Object.assign({}, DEFAULT_CONFIG, config)
|
||||
|
||||
// tree from list
|
||||
export const listToTree = <T = any>(list: any[], config: Partial<TreeHelperConfig> = {}): T[] => {
|
||||
const conf = getConfig(config) as TreeHelperConfig
|
||||
const nodeMap = new Map()
|
||||
const result: T[] = []
|
||||
const { id, children, pid } = conf
|
||||
|
||||
for (const node of list) {
|
||||
node[children] = node[children] || []
|
||||
nodeMap.set(node[id], node)
|
||||
}
|
||||
for (const node of list) {
|
||||
const parent = nodeMap.get(node[pid])
|
||||
;(parent ? parent.children : result).push(node)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export const treeToList = <T = any>(tree: any, config: Partial<TreeHelperConfig> = {}): T => {
|
||||
config = getConfig(config)
|
||||
const { children } = config
|
||||
const result: any = [...tree]
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
if (!result[i][children!]) continue
|
||||
result.splice(i + 1, 0, ...result[i][children!])
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export const findNode = <T = any>(
|
||||
tree: any,
|
||||
func: Fn,
|
||||
config: Partial<TreeHelperConfig> = {}
|
||||
): T | null => {
|
||||
config = getConfig(config)
|
||||
const { children } = config
|
||||
const list = [...tree]
|
||||
for (const node of list) {
|
||||
if (func(node)) return node
|
||||
node[children!] && list.push(...node[children!])
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export const findNodeAll = <T = any>(
|
||||
tree: any,
|
||||
func: Fn,
|
||||
config: Partial<TreeHelperConfig> = {}
|
||||
): T[] => {
|
||||
config = getConfig(config)
|
||||
const { children } = config
|
||||
const list = [...tree]
|
||||
const result: T[] = []
|
||||
for (const node of list) {
|
||||
func(node) && result.push(node)
|
||||
node[children!] && list.push(...node[children!])
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export const findPath = <T = any>(
|
||||
tree: any,
|
||||
func: Fn,
|
||||
config: Partial<TreeHelperConfig> = {}
|
||||
): T | T[] | null => {
|
||||
config = getConfig(config)
|
||||
const path: T[] = []
|
||||
const list = [...tree]
|
||||
const visitedSet = new Set()
|
||||
const { children } = config
|
||||
while (list.length) {
|
||||
const node = list[0]
|
||||
if (visitedSet.has(node)) {
|
||||
path.pop()
|
||||
list.shift()
|
||||
} else {
|
||||
visitedSet.add(node)
|
||||
node[children!] && list.unshift(...node[children!])
|
||||
path.push(node)
|
||||
if (func(node)) {
|
||||
return path
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export const findPathAll = (tree: any, func: Fn, config: Partial<TreeHelperConfig> = {}) => {
|
||||
config = getConfig(config)
|
||||
const path: any[] = []
|
||||
const list = [...tree]
|
||||
const result: any[] = []
|
||||
const visitedSet = new Set(),
|
||||
{ children } = config
|
||||
while (list.length) {
|
||||
const node = list[0]
|
||||
if (visitedSet.has(node)) {
|
||||
path.pop()
|
||||
list.shift()
|
||||
} else {
|
||||
visitedSet.add(node)
|
||||
node[children!] && list.unshift(...node[children!])
|
||||
path.push(node)
|
||||
func(node) && result.push([...path])
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export const filter = <T = any>(
|
||||
tree: T[],
|
||||
func: (n: T) => boolean,
|
||||
config: Partial<TreeHelperConfig> = {}
|
||||
): T[] => {
|
||||
config = getConfig(config)
|
||||
const children = config.children as string
|
||||
|
||||
function listFilter(list: T[]) {
|
||||
return list
|
||||
.map((node: any) => ({ ...node }))
|
||||
.filter((node) => {
|
||||
node[children] = node[children] && listFilter(node[children])
|
||||
return func(node) || (node[children] && node[children].length)
|
||||
})
|
||||
}
|
||||
|
||||
return listFilter(tree)
|
||||
}
|
||||
|
||||
export const forEach = <T = any>(
|
||||
tree: T[],
|
||||
func: (n: T) => any,
|
||||
config: Partial<TreeHelperConfig> = {}
|
||||
): void => {
|
||||
config = getConfig(config)
|
||||
const list: any[] = [...tree]
|
||||
const { children } = config
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
// func 返回true就终止遍历,避免大量节点场景下无意义循环,引起浏览器卡顿
|
||||
if (func(list[i])) {
|
||||
return
|
||||
}
|
||||
children && list[i][children] && list.splice(i + 1, 0, ...list[i][children])
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Extract tree specified structure
|
||||
*/
|
||||
export const treeMap = <T = any>(
|
||||
treeData: T[],
|
||||
opt: { children?: string; conversion: Fn }
|
||||
): T[] => {
|
||||
return treeData.map((item) => treeMapEach(item, opt))
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Extract tree specified structure
|
||||
*/
|
||||
export const treeMapEach = (
|
||||
data: any,
|
||||
{ children = 'children', conversion }: { children?: string; conversion: Fn }
|
||||
) => {
|
||||
const haveChildren = Array.isArray(data[children]) && data[children].length > 0
|
||||
const conversionData = conversion(data) || {}
|
||||
if (haveChildren) {
|
||||
return {
|
||||
...conversionData,
|
||||
[children]: data[children].map((i: number) =>
|
||||
treeMapEach(i, {
|
||||
children,
|
||||
conversion
|
||||
})
|
||||
)
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
...conversionData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归遍历树结构
|
||||
* @param treeDatas 树
|
||||
* @param callBack 回调
|
||||
* @param parentNode 父节点
|
||||
*/
|
||||
export const eachTree = (treeDatas: any[], callBack: Fn, parentNode = {}) => {
|
||||
treeDatas.forEach((element) => {
|
||||
const newNode = callBack(element, parentNode) || element
|
||||
if (element.children) {
|
||||
eachTree(element.children, callBack, newNode)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造树型结构数据
|
||||
* @param {*} data 数据源
|
||||
* @param {*} id id字段 默认 'id'
|
||||
* @param {*} parentId 父节点字段 默认 'parentId'
|
||||
* @param {*} children 孩子节点字段 默认 'children'
|
||||
*/
|
||||
export const handleTree = (data: any[], id?: string, parentId?: string, children?: string) => {
|
||||
if (!Array.isArray(data)) {
|
||||
console.warn('data must be an array')
|
||||
return []
|
||||
}
|
||||
const config = {
|
||||
id: id || 'id',
|
||||
parentId: parentId || 'parentId',
|
||||
childrenList: children || 'children'
|
||||
}
|
||||
|
||||
const childrenListMap = {}
|
||||
const nodeIds = {}
|
||||
const tree: any[] = []
|
||||
|
||||
for (const d of data) {
|
||||
const parentId = d[config.parentId]
|
||||
if (childrenListMap[parentId] == null) {
|
||||
childrenListMap[parentId] = []
|
||||
}
|
||||
nodeIds[d[config.id]] = d
|
||||
childrenListMap[parentId].push(d)
|
||||
}
|
||||
|
||||
for (const d of data) {
|
||||
const parentId = d[config.parentId]
|
||||
if (nodeIds[parentId] == null) {
|
||||
tree.push(d)
|
||||
}
|
||||
}
|
||||
|
||||
for (const t of tree) {
|
||||
adaptToChildrenList(t)
|
||||
}
|
||||
|
||||
function adaptToChildrenList(o) {
|
||||
if (childrenListMap[o[config.id]] !== null) {
|
||||
o[config.childrenList] = childrenListMap[o[config.id]]
|
||||
}
|
||||
if (o[config.childrenList]) {
|
||||
for (const c of o[config.childrenList]) {
|
||||
adaptToChildrenList(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tree
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造树型结构数据
|
||||
* @param {*} data 数据源
|
||||
* @param {*} id id字段 默认 'id'
|
||||
* @param {*} parentId 父节点字段 默认 'parentId'
|
||||
* @param {*} children 孩子节点字段 默认 'children'
|
||||
* @param {*} rootId 根Id 默认 0
|
||||
*/
|
||||
// @ts-ignore
|
||||
export const handleTree2 = (data, id, parentId, children, rootId) => {
|
||||
id = id || 'id'
|
||||
parentId = parentId || 'parentId'
|
||||
// children = children || 'children'
|
||||
rootId =
|
||||
rootId ||
|
||||
Math.min(
|
||||
...data.map((item) => {
|
||||
return item[parentId]
|
||||
})
|
||||
) ||
|
||||
0
|
||||
// 对源数据深度克隆
|
||||
const cloneData = JSON.parse(JSON.stringify(data))
|
||||
// 循环所有项
|
||||
const treeData = cloneData.filter((father) => {
|
||||
const branchArr = cloneData.filter((child) => {
|
||||
// 返回每一项的子级数组
|
||||
return father[id] === child[parentId]
|
||||
})
|
||||
branchArr.length > 0 ? (father.children = branchArr) : ''
|
||||
// 返回第一层
|
||||
return father[parentId] === rootId
|
||||
})
|
||||
return treeData !== '' ? treeData : data
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验选中的节点,是否为指定 level
|
||||
*
|
||||
* @param tree 要操作的树结构数据
|
||||
* @param nodeId 需要判断在什么层级的数据
|
||||
* @param level 检查的级别, 默认检查到二级
|
||||
* @return true 是;false 否
|
||||
*/
|
||||
export const checkSelectedNode = (tree: any[], nodeId: any, level = 2): boolean => {
|
||||
if (typeof tree === 'undefined' || !Array.isArray(tree) || tree.length === 0) {
|
||||
console.warn('tree must be an array')
|
||||
return false
|
||||
}
|
||||
|
||||
// 校验是否是一级节点
|
||||
if (tree.some((item) => item.id === nodeId)) {
|
||||
return false
|
||||
}
|
||||
|
||||
// 递归计数
|
||||
let count = 1
|
||||
|
||||
// 深层次校验
|
||||
function performAThoroughValidation(arr: any[]): boolean {
|
||||
count += 1
|
||||
for (const item of arr) {
|
||||
if (item.id === nodeId) {
|
||||
return true
|
||||
} else if (typeof item.children !== 'undefined' && item.children.length !== 0) {
|
||||
if (performAThoroughValidation(item.children)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
for (const item of tree) {
|
||||
count = 1
|
||||
if (performAThoroughValidation(item.children)) {
|
||||
// 找到后对比是否是期望的层级
|
||||
if (count >= level) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取节点的完整结构
|
||||
* @param tree 树数据
|
||||
* @param nodeId 节点 id
|
||||
*/
|
||||
export const treeToString = (tree: any[], nodeId) => {
|
||||
if (typeof tree === 'undefined' || !Array.isArray(tree) || tree.length === 0) {
|
||||
console.warn('tree must be an array')
|
||||
return ''
|
||||
}
|
||||
// 校验是否是一级节点
|
||||
const node = tree.find((item) => item.id === nodeId)
|
||||
if (typeof node !== 'undefined') {
|
||||
return node.name
|
||||
}
|
||||
let str = ''
|
||||
|
||||
function performAThoroughValidation(arr) {
|
||||
for (const item of arr) {
|
||||
if (item.id === nodeId) {
|
||||
str += ` / ${item.name}`
|
||||
return true
|
||||
} else if (typeof item.children !== 'undefined' && item.children.length !== 0) {
|
||||
str += ` / ${item.name}`
|
||||
if (performAThoroughValidation(item.children)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
for (const item of tree) {
|
||||
str = `${item.name}`
|
||||
if (performAThoroughValidation(item.children)) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return str
|
||||
}
|
||||
interface TreeHelperConfig {
|
||||
id: string
|
||||
children: string
|
||||
pid: string
|
||||
}
|
||||
|
||||
const DEFAULT_CONFIG: TreeHelperConfig = {
|
||||
id: 'id',
|
||||
children: 'children',
|
||||
pid: 'pid'
|
||||
}
|
||||
export const defaultProps = {
|
||||
children: 'children',
|
||||
label: 'name',
|
||||
value: 'id',
|
||||
isLeaf: 'leaf',
|
||||
emitPath: false // 用于 cascader 组件:在选中节点改变时,是否返回由该节点所在的各级菜单的值所组成的数组,若设置 false,则只返回该节点的值
|
||||
}
|
||||
|
||||
const getConfig = (config: Partial<TreeHelperConfig>) => Object.assign({}, DEFAULT_CONFIG, config)
|
||||
|
||||
// tree from list
|
||||
export const listToTree = <T = any>(list: any[], config: Partial<TreeHelperConfig> = {}): T[] => {
|
||||
const conf = getConfig(config) as TreeHelperConfig
|
||||
const nodeMap = new Map()
|
||||
const result: T[] = []
|
||||
const { id, children, pid } = conf
|
||||
|
||||
for (const node of list) {
|
||||
node[children] = node[children] || []
|
||||
nodeMap.set(node[id], node)
|
||||
}
|
||||
for (const node of list) {
|
||||
const parent = nodeMap.get(node[pid])
|
||||
;(parent ? parent.children : result).push(node)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export const treeToList = <T = any>(tree: any, config: Partial<TreeHelperConfig> = {}): T => {
|
||||
config = getConfig(config)
|
||||
const { children } = config
|
||||
const result: any = [...tree]
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
if (!result[i][children!]) continue
|
||||
result.splice(i + 1, 0, ...result[i][children!])
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export const findNode = <T = any>(
|
||||
tree: any,
|
||||
func: Fn,
|
||||
config: Partial<TreeHelperConfig> = {}
|
||||
): T | null => {
|
||||
config = getConfig(config)
|
||||
const { children } = config
|
||||
const list = [...tree]
|
||||
for (const node of list) {
|
||||
if (func(node)) return node
|
||||
node[children!] && list.push(...node[children!])
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export const findNodeAll = <T = any>(
|
||||
tree: any,
|
||||
func: Fn,
|
||||
config: Partial<TreeHelperConfig> = {}
|
||||
): T[] => {
|
||||
config = getConfig(config)
|
||||
const { children } = config
|
||||
const list = [...tree]
|
||||
const result: T[] = []
|
||||
for (const node of list) {
|
||||
func(node) && result.push(node)
|
||||
node[children!] && list.push(...node[children!])
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export const findPath = <T = any>(
|
||||
tree: any,
|
||||
func: Fn,
|
||||
config: Partial<TreeHelperConfig> = {}
|
||||
): T | T[] | null => {
|
||||
config = getConfig(config)
|
||||
const path: T[] = []
|
||||
const list = [...tree]
|
||||
const visitedSet = new Set()
|
||||
const { children } = config
|
||||
while (list.length) {
|
||||
const node = list[0]
|
||||
if (visitedSet.has(node)) {
|
||||
path.pop()
|
||||
list.shift()
|
||||
} else {
|
||||
visitedSet.add(node)
|
||||
node[children!] && list.unshift(...node[children!])
|
||||
path.push(node)
|
||||
if (func(node)) {
|
||||
return path
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export const findPathAll = (tree: any, func: Fn, config: Partial<TreeHelperConfig> = {}) => {
|
||||
config = getConfig(config)
|
||||
const path: any[] = []
|
||||
const list = [...tree]
|
||||
const result: any[] = []
|
||||
const visitedSet = new Set(),
|
||||
{ children } = config
|
||||
while (list.length) {
|
||||
const node = list[0]
|
||||
if (visitedSet.has(node)) {
|
||||
path.pop()
|
||||
list.shift()
|
||||
} else {
|
||||
visitedSet.add(node)
|
||||
node[children!] && list.unshift(...node[children!])
|
||||
path.push(node)
|
||||
func(node) && result.push([...path])
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export const filter = <T = any>(
|
||||
tree: T[],
|
||||
func: (n: T) => boolean,
|
||||
config: Partial<TreeHelperConfig> = {}
|
||||
): T[] => {
|
||||
config = getConfig(config)
|
||||
const children = config.children as string
|
||||
|
||||
function listFilter(list: T[]) {
|
||||
return list
|
||||
.map((node: any) => ({ ...node }))
|
||||
.filter((node) => {
|
||||
node[children] = node[children] && listFilter(node[children])
|
||||
return func(node) || (node[children] && node[children].length)
|
||||
})
|
||||
}
|
||||
|
||||
return listFilter(tree)
|
||||
}
|
||||
export const filterTree = <T = any>(
|
||||
tree: T[],
|
||||
func: (n: T) => boolean,
|
||||
config: Partial<TreeHelperConfig> = {}
|
||||
): T[] => {
|
||||
config = getConfig(config)
|
||||
const children = config.children as string
|
||||
|
||||
function listFilter(list: T[]) {
|
||||
return list
|
||||
.map((node: any) => ({ ...node }))
|
||||
.filter((node) => {
|
||||
// 1. 如果当前节点匹配 → 直接保留【所有子节点】,不再过滤下级
|
||||
if (func(node)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2. 如果当前节点不匹配,递归过滤子节点
|
||||
if (node[children]) {
|
||||
const filteredChildren = listFilter(node[children]);
|
||||
if (filteredChildren.length > 0) {
|
||||
node[children] = filteredChildren;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 都不匹配,过滤掉
|
||||
return false;
|
||||
})
|
||||
}
|
||||
|
||||
return listFilter(tree)
|
||||
}
|
||||
export const forEach = <T = any>(
|
||||
tree: T[],
|
||||
func: (n: T) => any,
|
||||
config: Partial<TreeHelperConfig> = {}
|
||||
): void => {
|
||||
config = getConfig(config)
|
||||
const list: any[] = [...tree]
|
||||
const { children } = config
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
// func 返回true就终止遍历,避免大量节点场景下无意义循环,引起浏览器卡顿
|
||||
if (func(list[i])) {
|
||||
return
|
||||
}
|
||||
children && list[i][children] && list.splice(i + 1, 0, ...list[i][children])
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Extract tree specified structure
|
||||
*/
|
||||
export const treeMap = <T = any>(
|
||||
treeData: T[],
|
||||
opt: { children?: string; conversion: Fn }
|
||||
): T[] => {
|
||||
return treeData.map((item) => treeMapEach(item, opt))
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Extract tree specified structure
|
||||
*/
|
||||
export const treeMapEach = (
|
||||
data: any,
|
||||
{ children = 'children', conversion }: { children?: string; conversion: Fn }
|
||||
) => {
|
||||
const haveChildren = Array.isArray(data[children]) && data[children].length > 0
|
||||
const conversionData = conversion(data) || {}
|
||||
if (haveChildren) {
|
||||
return {
|
||||
...conversionData,
|
||||
[children]: data[children].map((i: number) =>
|
||||
treeMapEach(i, {
|
||||
children,
|
||||
conversion
|
||||
})
|
||||
)
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
...conversionData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归遍历树结构
|
||||
* @param treeDatas 树
|
||||
* @param callBack 回调
|
||||
* @param parentNode 父节点
|
||||
*/
|
||||
export const eachTree = (treeDatas: any[], callBack: Fn, parentNode = {}) => {
|
||||
treeDatas.forEach((element) => {
|
||||
const newNode = callBack(element, parentNode) || element
|
||||
if (element.children) {
|
||||
eachTree(element.children, callBack, newNode)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造树型结构数据
|
||||
* @param {*} data 数据源
|
||||
* @param {*} id id字段 默认 'id'
|
||||
* @param {*} parentId 父节点字段 默认 'parentId'
|
||||
* @param {*} children 孩子节点字段 默认 'children'
|
||||
*/
|
||||
export const handleTree = (data: any[], id?: string, parentId?: string, children?: string) => {
|
||||
if (!Array.isArray(data)) {
|
||||
console.warn('data must be an array')
|
||||
return []
|
||||
}
|
||||
const config = {
|
||||
id: id || 'id',
|
||||
parentId: parentId || 'parentId',
|
||||
childrenList: children || 'children'
|
||||
}
|
||||
|
||||
const childrenListMap = {}
|
||||
const nodeIds = {}
|
||||
const tree: any[] = []
|
||||
|
||||
for (const d of data) {
|
||||
const parentId = d[config.parentId]
|
||||
if (childrenListMap[parentId] == null) {
|
||||
childrenListMap[parentId] = []
|
||||
}
|
||||
nodeIds[d[config.id]] = d
|
||||
childrenListMap[parentId].push(d)
|
||||
}
|
||||
|
||||
for (const d of data) {
|
||||
const parentId = d[config.parentId]
|
||||
if (nodeIds[parentId] == null) {
|
||||
tree.push(d)
|
||||
}
|
||||
}
|
||||
|
||||
for (const t of tree) {
|
||||
adaptToChildrenList(t)
|
||||
}
|
||||
|
||||
function adaptToChildrenList(o) {
|
||||
if (childrenListMap[o[config.id]] !== null) {
|
||||
o[config.childrenList] = childrenListMap[o[config.id]]
|
||||
}
|
||||
if (o[config.childrenList]) {
|
||||
for (const c of o[config.childrenList]) {
|
||||
adaptToChildrenList(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tree
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造树型结构数据
|
||||
* @param {*} data 数据源
|
||||
* @param {*} id id字段 默认 'id'
|
||||
* @param {*} parentId 父节点字段 默认 'parentId'
|
||||
* @param {*} children 孩子节点字段 默认 'children'
|
||||
* @param {*} rootId 根Id 默认 0
|
||||
*/
|
||||
// @ts-ignore
|
||||
export const handleTree2 = (data, id, parentId, children, rootId) => {
|
||||
id = id || 'id'
|
||||
parentId = parentId || 'parentId'
|
||||
// children = children || 'children'
|
||||
rootId =
|
||||
rootId ||
|
||||
Math.min(
|
||||
...data.map((item) => {
|
||||
return item[parentId]
|
||||
})
|
||||
) ||
|
||||
0
|
||||
// 对源数据深度克隆
|
||||
const cloneData = JSON.parse(JSON.stringify(data))
|
||||
// 循环所有项
|
||||
const treeData = cloneData.filter((father) => {
|
||||
const branchArr = cloneData.filter((child) => {
|
||||
// 返回每一项的子级数组
|
||||
return father[id] === child[parentId]
|
||||
})
|
||||
branchArr.length > 0 ? (father.children = branchArr) : ''
|
||||
// 返回第一层
|
||||
return father[parentId] === rootId
|
||||
})
|
||||
return treeData !== '' ? treeData : data
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验选中的节点,是否为指定 level
|
||||
*
|
||||
* @param tree 要操作的树结构数据
|
||||
* @param nodeId 需要判断在什么层级的数据
|
||||
* @param level 检查的级别, 默认检查到二级
|
||||
* @return true 是;false 否
|
||||
*/
|
||||
export const checkSelectedNode = (tree: any[], nodeId: any, level = 2): boolean => {
|
||||
if (typeof tree === 'undefined' || !Array.isArray(tree) || tree.length === 0) {
|
||||
console.warn('tree must be an array')
|
||||
return false
|
||||
}
|
||||
|
||||
// 校验是否是一级节点
|
||||
if (tree.some((item) => item.id === nodeId)) {
|
||||
return false
|
||||
}
|
||||
|
||||
// 递归计数
|
||||
let count = 1
|
||||
|
||||
// 深层次校验
|
||||
function performAThoroughValidation(arr: any[]): boolean {
|
||||
count += 1
|
||||
for (const item of arr) {
|
||||
if (item.id === nodeId) {
|
||||
return true
|
||||
} else if (typeof item.children !== 'undefined' && item.children.length !== 0) {
|
||||
if (performAThoroughValidation(item.children)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
for (const item of tree) {
|
||||
count = 1
|
||||
if (performAThoroughValidation(item.children)) {
|
||||
// 找到后对比是否是期望的层级
|
||||
if (count >= level) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取节点的完整结构
|
||||
* @param tree 树数据
|
||||
* @param nodeId 节点 id
|
||||
*/
|
||||
export const treeToString = (tree: any[], nodeId) => {
|
||||
if (typeof tree === 'undefined' || !Array.isArray(tree) || tree.length === 0) {
|
||||
console.warn('tree must be an array')
|
||||
return ''
|
||||
}
|
||||
// 校验是否是一级节点
|
||||
const node = tree.find((item) => item.id === nodeId)
|
||||
if (typeof node !== 'undefined') {
|
||||
return node.name
|
||||
}
|
||||
let str = ''
|
||||
|
||||
function performAThoroughValidation(arr) {
|
||||
for (const item of arr) {
|
||||
if (item.id === nodeId) {
|
||||
str += ` / ${item.name}`
|
||||
return true
|
||||
} else if (typeof item.children !== 'undefined' && item.children.length !== 0) {
|
||||
str += ` / ${item.name}`
|
||||
if (performAThoroughValidation(item.children)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
for (const item of tree) {
|
||||
str = `${item.name}`
|
||||
if (performAThoroughValidation(item.children)) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
50
src/utils/waveCache.ts
Normal file
50
src/utils/waveCache.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { getWaveRawList } from './waveRawStore'
|
||||
|
||||
const MAX_CACHE_SIZE = 6
|
||||
|
||||
const cache = new Map<string, unknown>()
|
||||
|
||||
function dataFingerprint(data: unknown[][] | undefined): string {
|
||||
if (!data?.length) return '0'
|
||||
const first = data[0]
|
||||
const last = data[data.length - 1]
|
||||
return `${data.length}:${first?.[0]}:${last?.[0]}`
|
||||
}
|
||||
|
||||
export function buildWaveCacheKey(
|
||||
type: 'shu' | 'rms',
|
||||
wp: Record<string, any> | undefined,
|
||||
value: number,
|
||||
isOpen: boolean,
|
||||
boxoList: Record<string, any>
|
||||
): string {
|
||||
if (!wp) return ''
|
||||
const rawList = wp.waveStoreKey
|
||||
? getWaveRawList(type, wp.waveStoreKey)
|
||||
: ((type === 'shu' ? wp.listWaveData : wp.listRmsData) as unknown[][] | undefined)
|
||||
const waveFp = dataFingerprint(rawList)
|
||||
const boxoFp = boxoList?.startTime ?? boxoList?.lineName ?? boxoList?.equipmentName ?? ''
|
||||
return `${type}|${wp.time}|${wp.waveType}|${wp.iphasic}|${value}|${isOpen}|${waveFp}|${boxoFp}`
|
||||
}
|
||||
|
||||
export function getWaveCache<T>(key: string): T | null {
|
||||
if (!key || !cache.has(key)) return null
|
||||
const value = cache.get(key) as T
|
||||
cache.delete(key)
|
||||
cache.set(key, value)
|
||||
return value
|
||||
}
|
||||
|
||||
export function setWaveCache(key: string, value: unknown): void {
|
||||
if (!key) return
|
||||
if (cache.has(key)) cache.delete(key)
|
||||
cache.set(key, value)
|
||||
while (cache.size > MAX_CACHE_SIZE) {
|
||||
const oldest = cache.keys().next().value
|
||||
if (oldest !== undefined) cache.delete(oldest)
|
||||
}
|
||||
}
|
||||
|
||||
export function clearWaveCache(): void {
|
||||
cache.clear()
|
||||
}
|
||||
59
src/utils/waveDisplayHelper.ts
Normal file
59
src/utils/waveDisplayHelper.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
const EMPTY_SERIES: number[][] = []
|
||||
|
||||
function ds(data: number[][] | undefined): number[][] {
|
||||
if (!data?.length) return EMPTY_SERIES
|
||||
return data
|
||||
}
|
||||
|
||||
/** Worker 完整计算后,剔除当前未使用的值类型,降低内存占用 */
|
||||
export function compactShuWaveResult(data: any, value: number) {
|
||||
const waveDatas = data.waveDatas.map((wd: any) => {
|
||||
if (value === 1) {
|
||||
return {
|
||||
...wd,
|
||||
shunshiF: {
|
||||
shunshiFA: ds(wd.shunshiF.shunshiFA),
|
||||
shunshiFB: ds(wd.shunshiF.shunshiFB),
|
||||
shunshiFC: ds(wd.shunshiF.shunshiFC)
|
||||
},
|
||||
shunshiS: { shunshiSA: EMPTY_SERIES, shunshiSB: EMPTY_SERIES, shunshiSC: EMPTY_SERIES }
|
||||
}
|
||||
}
|
||||
return {
|
||||
...wd,
|
||||
shunshiF: { shunshiFA: EMPTY_SERIES, shunshiFB: EMPTY_SERIES, shunshiFC: EMPTY_SERIES },
|
||||
shunshiS: {
|
||||
shunshiSA: ds(wd.shunshiS.shunshiSA),
|
||||
shunshiSB: ds(wd.shunshiS.shunshiSB),
|
||||
shunshiSC: ds(wd.shunshiS.shunshiSC)
|
||||
}
|
||||
}
|
||||
})
|
||||
return { ...data, waveDatas }
|
||||
}
|
||||
|
||||
export function compactRmsWaveResult(data: any, value: number) {
|
||||
const waveDatas = data.waveDatas.map((wd: any) => {
|
||||
if (value === 1) {
|
||||
return {
|
||||
...wd,
|
||||
RMSFWave: {
|
||||
rmsFA: ds(wd.RMSFWave.rmsFA),
|
||||
rmsFB: ds(wd.RMSFWave.rmsFB),
|
||||
rmsFC: ds(wd.RMSFWave.rmsFC)
|
||||
},
|
||||
RMSSWave: { rmsSA: EMPTY_SERIES, rmsSB: EMPTY_SERIES, rmsSC: EMPTY_SERIES }
|
||||
}
|
||||
}
|
||||
return {
|
||||
...wd,
|
||||
RMSFWave: { rmsFA: EMPTY_SERIES, rmsFB: EMPTY_SERIES, rmsFC: EMPTY_SERIES },
|
||||
RMSSWave: {
|
||||
rmsSA: ds(wd.RMSSWave.rmsSA),
|
||||
rmsSB: ds(wd.RMSSWave.rmsSB),
|
||||
rmsSC: ds(wd.RMSSWave.rmsSC)
|
||||
}
|
||||
}
|
||||
})
|
||||
return { ...data, waveDatas }
|
||||
}
|
||||
75
src/utils/waveRawStore.ts
Normal file
75
src/utils/waveRawStore.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
/** 原始波形数据存放于 Vue 响应式体系之外,避免大数组触发深度代理与重复持有 */
|
||||
|
||||
interface WaveRawEntry {
|
||||
listWaveData?: unknown[][]
|
||||
listRmsData?: unknown[][]
|
||||
waveTimeRange?: { min: number; max: number }
|
||||
}
|
||||
|
||||
const rawStore = new Map<string, WaveRawEntry>()
|
||||
|
||||
function calcTimeRange(data: unknown[][] | undefined): { min: number; max: number } | undefined {
|
||||
if (!data?.length) return undefined
|
||||
const first = data[0] as number[]
|
||||
const last = data[data.length - 1] as number[]
|
||||
return { min: first[0], max: last[0] + 1 }
|
||||
}
|
||||
|
||||
export function buildWaveStoreKey(boxoList: Record<string, any>): string {
|
||||
const id = boxoList?.eventId ?? boxoList?.id ?? ''
|
||||
return `${id}|${boxoList?.startTime ?? ''}`
|
||||
}
|
||||
|
||||
export function registerWaveRaw(storeKey: string, wp: Record<string, any>): void {
|
||||
if (!storeKey || !wp) return
|
||||
const entry: WaveRawEntry = rawStore.get(storeKey) ?? {}
|
||||
|
||||
if (wp.listWaveData?.length) {
|
||||
entry.listWaveData = wp.listWaveData
|
||||
entry.waveTimeRange = calcTimeRange(wp.listWaveData) ?? entry.waveTimeRange
|
||||
}
|
||||
if (wp.listRmsData?.length) {
|
||||
entry.listRmsData = wp.listRmsData
|
||||
entry.waveTimeRange = calcTimeRange(wp.listRmsData) ?? entry.waveTimeRange
|
||||
}
|
||||
|
||||
rawStore.set(storeKey, entry)
|
||||
}
|
||||
|
||||
export function getWaveRawList(type: 'shu' | 'rms', storeKey: string | undefined): unknown[][] | undefined {
|
||||
if (!storeKey) return undefined
|
||||
const entry = rawStore.get(storeKey)
|
||||
return type === 'shu' ? entry?.listWaveData : entry?.listRmsData
|
||||
}
|
||||
|
||||
export function getWaveTimeRange(storeKey: string | undefined): { min: number; max: number } | undefined {
|
||||
if (!storeKey) return undefined
|
||||
return rawStore.get(storeKey)?.waveTimeRange
|
||||
}
|
||||
|
||||
export function releaseWaveRaw(storeKey: string | undefined, type: 'shu' | 'rms' | 'all' = 'all'): void {
|
||||
if (!storeKey) return
|
||||
if (type === 'all') {
|
||||
rawStore.delete(storeKey)
|
||||
return
|
||||
}
|
||||
const entry = rawStore.get(storeKey)
|
||||
if (!entry) return
|
||||
if (type === 'shu') delete entry.listWaveData
|
||||
if (type === 'rms') delete entry.listRmsData
|
||||
if (!entry.listWaveData && !entry.listRmsData) {
|
||||
rawStore.delete(storeKey)
|
||||
} else {
|
||||
rawStore.set(storeKey, entry)
|
||||
}
|
||||
}
|
||||
|
||||
/** 构建不含大数组的 wp 对象,供子组件 props 使用 */
|
||||
export function buildSlimWp(wp: Record<string, any>, storeKey: string): Record<string, any> {
|
||||
const { listWaveData: _w, listRmsData: _r, ...rest } = wp
|
||||
return {
|
||||
...rest,
|
||||
waveStoreKey: storeKey,
|
||||
waveTimeRange: getWaveTimeRange(storeKey) ?? calcTimeRange(_w) ?? calcTimeRange(_r)
|
||||
}
|
||||
}
|
||||
98
src/utils/waveWorkerPool.ts
Normal file
98
src/utils/waveWorkerPool.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
import { toRaw } from 'vue'
|
||||
import { getWaveRawList } from './waveRawStore'
|
||||
|
||||
type WorkerMessageHandler = (data: any) => void
|
||||
|
||||
let shuWorker: Worker | null = null
|
||||
let rmsWorker: Worker | null = null
|
||||
|
||||
/** 递归剥离 Vue 响应式代理,得到可 structuredClone 的纯对象 */
|
||||
export function toPlainDeep<T>(value: T): T {
|
||||
const raw = toRaw(value as object) as T
|
||||
if (Array.isArray(raw)) {
|
||||
return raw.map(item => toPlainDeep(item)) as T
|
||||
}
|
||||
if (raw !== null && typeof raw === 'object') {
|
||||
const out: Record<string, unknown> = {}
|
||||
for (const [key, val] of Object.entries(raw)) {
|
||||
out[key] = toPlainDeep(val)
|
||||
}
|
||||
return out as T
|
||||
}
|
||||
return raw
|
||||
}
|
||||
|
||||
const BOXO_LIST_KEYS = [
|
||||
'systemType',
|
||||
'powerStationName',
|
||||
'measurementPointName',
|
||||
'startTime',
|
||||
'featureAmplitude',
|
||||
'duration',
|
||||
'engineeringName',
|
||||
'equipmentName',
|
||||
'evtParamVVaDepth',
|
||||
'evtParamTm',
|
||||
'lineName',
|
||||
'persistTime',
|
||||
'subName'
|
||||
] as const
|
||||
|
||||
export function buildWorkerPayload(
|
||||
type: 'shu' | 'rms',
|
||||
wp: Record<string, any>,
|
||||
boxoList: Record<string, any>,
|
||||
extras: { requestId: number; value: number; isOpen: boolean; iphasic?: number }
|
||||
) {
|
||||
const plainWp = toPlainDeep(wp)
|
||||
const wpPayload: Record<string, unknown> = {
|
||||
pt: plainWp.pt,
|
||||
ct: plainWp.ct,
|
||||
waveTitle: plainWp.waveTitle,
|
||||
iphasic: plainWp.iphasic,
|
||||
time: plainWp.time,
|
||||
waveType: plainWp.waveType,
|
||||
yzd: plainWp.yzd
|
||||
}
|
||||
const storeKey = plainWp.waveStoreKey as string | undefined
|
||||
if (type === 'shu') {
|
||||
wpPayload.listWaveData = getWaveRawList('shu', storeKey) ?? plainWp.listWaveData
|
||||
} else {
|
||||
wpPayload.listRmsData = getWaveRawList('rms', storeKey) ?? plainWp.listRmsData
|
||||
}
|
||||
|
||||
const plainBoxo: Record<string, unknown> = {}
|
||||
const rawBoxo = toPlainDeep(boxoList)
|
||||
for (const key of BOXO_LIST_KEYS) {
|
||||
if (rawBoxo[key] !== undefined) {
|
||||
plainBoxo[key] = rawBoxo[key]
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
requestId: extras.requestId,
|
||||
value: extras.value,
|
||||
isOpen: extras.isOpen,
|
||||
iphasic: extras.iphasic,
|
||||
wp: wpPayload,
|
||||
boxoList: plainBoxo
|
||||
}
|
||||
}
|
||||
|
||||
export function getShuWorker(onMessage: WorkerMessageHandler): Worker {
|
||||
if (!shuWorker) {
|
||||
shuWorker = new Worker(new URL('../components/echarts/shuWorker.js', import.meta.url))
|
||||
}
|
||||
shuWorker.onmessage = e => onMessage(e.data)
|
||||
shuWorker.onerror = error => console.error('Shu worker error:', error)
|
||||
return shuWorker
|
||||
}
|
||||
|
||||
export function getRmsWorker(onMessage: WorkerMessageHandler): Worker {
|
||||
if (!rmsWorker) {
|
||||
rmsWorker = new Worker(new URL('../components/echarts/rmsWorker.js', import.meta.url))
|
||||
}
|
||||
rmsWorker.onmessage = e => onMessage(e.data)
|
||||
rmsWorker.onerror = error => console.error('Rms worker error:', error)
|
||||
return rmsWorker
|
||||
}
|
||||
@@ -43,13 +43,11 @@ export default class SocketService {
|
||||
console.log('您的浏览器不支持WebSocket')
|
||||
return
|
||||
}
|
||||
|
||||
console.log("🚀 ~ SocketService ~ connect ~ url:", url)
|
||||
if (url === null || (typeof url === 'string' && url.includes('null'))) return;
|
||||
|
||||
setTimeout(() => {
|
||||
// ws://192.168.1.69:10407/mgtt
|
||||
// const url =
|
||||
// (localStorage.getItem('WebSocketUrl') == 'null'
|
||||
// ? 'ws://192.168.1.130:10405'
|
||||
// : localStorage.getItem('WebSocketUrl')) + id
|
||||
this.ws = new WebSocket(url)
|
||||
|
||||
this.ws.onopen = () => this.handleOpen()
|
||||
@@ -58,10 +56,9 @@ export default class SocketService {
|
||||
this.ws.onmessage = event => this.handleMessage(event)
|
||||
}, 0)
|
||||
}
|
||||
|
||||
// 处理连接成功事件
|
||||
private handleOpen(): void {
|
||||
ElMessage.success('webSocket连接服务端成功了')
|
||||
// ElMessage.success('webSocket连接服务端成功了')
|
||||
console.log('连接服务端成功了')
|
||||
this.connected = true
|
||||
this.connectRetryCount = 0
|
||||
@@ -90,7 +87,7 @@ export default class SocketService {
|
||||
|
||||
if (event.data == '连接成功') {
|
||||
this.sendHeartbeat()
|
||||
} else if (event.data == 'connect') {
|
||||
} else if (event.data == 'over') {
|
||||
} else if (event.data.length > 10) {
|
||||
let message: MessageType
|
||||
try {
|
||||
@@ -104,7 +101,7 @@ export default class SocketService {
|
||||
|
||||
// 通过接受服务端发送的type字段来回调函数
|
||||
|
||||
if ((message.key || message.code) && this.callBackMapping['message']) {
|
||||
if ((message.key || message.code || message.time) && this.callBackMapping['message']) {
|
||||
this.callBackMapping['message']!(message)
|
||||
} else {
|
||||
console.log('抛弃====>')
|
||||
@@ -112,6 +109,8 @@ export default class SocketService {
|
||||
// 丢弃或继续写你的逻辑
|
||||
}
|
||||
} else {
|
||||
this.callBackMapping['message']!({ Flag: false })
|
||||
if(event.data == 'connect')return
|
||||
ElMessage.error(event.data)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,423 +1,423 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader datePicker theCurrentTime area ref="header">
|
||||
<!-- <template v-slot:select>
|
||||
|
||||
</template> -->
|
||||
</TableHeader>
|
||||
<div v-loading="tableStore.table.loading">
|
||||
<el-row :gutter="10" class="pd10">
|
||||
<el-col :span="11" style="position: relative">
|
||||
<el-card>
|
||||
<el-radio-group
|
||||
v-model="tableStore.table.params.type"
|
||||
class="group"
|
||||
@change="tableStore.index()"
|
||||
>
|
||||
<el-radio-button label="风电场" value="1" />
|
||||
<el-radio-button label="光伏电站" value="2" />
|
||||
</el-radio-group>
|
||||
<MyEchartMap
|
||||
ref="EchartMap"
|
||||
:options="echartMapList"
|
||||
class="map"
|
||||
@eliminate="eliminate"
|
||||
@getRegionByRegion="getRegionByRegion"
|
||||
@clickMap="clickMap"
|
||||
/>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="13">
|
||||
<el-card>
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>暂降列表</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- <h3 class="mb10">暂降列表</h3> -->
|
||||
<div class="tall1">
|
||||
<vxe-table
|
||||
height="auto"
|
||||
auto-resize
|
||||
:data="distributionData"
|
||||
v-loading="loading"
|
||||
v-bind="defaultAttribute"
|
||||
>
|
||||
<vxe-column
|
||||
field="newStationName"
|
||||
title="新能源站名称"
|
||||
min-width="150px"
|
||||
show-overflow-tooltip
|
||||
></vxe-column>
|
||||
<vxe-column field="startTime" title="暂降发生时刻" min-width="150px"></vxe-column>
|
||||
<vxe-column
|
||||
field="featureAmplitude"
|
||||
title="暂降(骤升)幅值(%)"
|
||||
sortable
|
||||
min-width="150px"
|
||||
></vxe-column>
|
||||
<vxe-column
|
||||
field="advanceReason"
|
||||
title="暂降原因"
|
||||
sortable
|
||||
:formatter="formFilter"
|
||||
min-width="100px"
|
||||
></vxe-column>
|
||||
<vxe-column field="severity" title="严重度" min-width="100px" sortable></vxe-column>
|
||||
<vxe-column title="操作" width="80px">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
type="primary"
|
||||
v-if="row.wavePath != null"
|
||||
size="small"
|
||||
link
|
||||
@click="boxi(row)"
|
||||
>
|
||||
查看波形
|
||||
</el-button>
|
||||
<el-button v-else disabled size="small" link>暂无波形</el-button>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-card class="mt10">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>暂降波形</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="tall" v-loading="loading1">
|
||||
<!-- <h3 class="mb10">暂降波形</h3> -->
|
||||
<div v-if="wp != null">
|
||||
<rmsboxi :value="1" :height="height" :boxoList="boxoList" :wp="wp" />
|
||||
</div>
|
||||
<el-empty v-else description="暂无数据" class="custom-empty" />
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import { defaultAttribute } from '@/components/table/defaultAttribute'
|
||||
import MyEchartMap from '@/components/echarts/MyEchartMap.vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import { voltageRideThroughEventQueryPage } from '@/api/event-boot/highAndLowPressure'
|
||||
import { getMonitorEventAnalyseWave, getTransientDetailById } from '@/api/event-boot/transient'
|
||||
import rmsboxi from '@/components/echarts/rmsboxi.vue'
|
||||
import { ref, onMounted, provide } from 'vue'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import { FormItem } from 'vxe-table'
|
||||
defineOptions({
|
||||
name: 'newEnergy/highAndLowPressure'
|
||||
})
|
||||
const EchartMap = ref()
|
||||
const dictData = useDictData()
|
||||
const reason = dictData.getBasicData('Event_Reason')
|
||||
const triggerType = dictData.getBasicData('Event_Statis')
|
||||
const echartMapList: any = ref({})
|
||||
const header = ref()
|
||||
const distributionData: any = ref([])
|
||||
const loading = ref(false)
|
||||
const loading1 = ref(false)
|
||||
const boxoList = ref(null)
|
||||
const wp = ref(null)
|
||||
const tableStore = new TableStore({
|
||||
url: '/event-boot/voltageRideThrough/view',
|
||||
method: 'POST',
|
||||
column: [],
|
||||
beforeSearchFun: () => {
|
||||
tableStore.table.params.areaId = tableStore.table.params.deptIndex
|
||||
},
|
||||
loadCallback: () => {
|
||||
// 处理地图数据
|
||||
map(tableStore.table.data)
|
||||
// tabulation(tableStore.table.data)
|
||||
EchartMap.value.GetEchar(header.value.areaRef.areaName)
|
||||
if (tableStore.table.data.length > 0) {
|
||||
tabulation({ data: tableStore.table.data[0], seriesName: '高压' })
|
||||
}
|
||||
}
|
||||
})
|
||||
const height = mainHeight(200, 2).height
|
||||
provide('tableStore', tableStore)
|
||||
tableStore.table.params.type = '1'
|
||||
|
||||
// 地图点击事件
|
||||
const getRegionByRegion = (list: any) => {
|
||||
tableStore.table.params.deptIndex = list.id
|
||||
tableStore.onTableAction('search', {})
|
||||
}
|
||||
// 消除点
|
||||
const eliminate = (name: string) => {
|
||||
echartMapList.value.options.series = []
|
||||
EchartMap.value.GetEchar(name)
|
||||
}
|
||||
|
||||
// 地图数处理
|
||||
const map = (res: any) => {
|
||||
echartMapList.value = {
|
||||
title: {
|
||||
text: '高/低电压穿越'
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: function (params) {
|
||||
if (params.seriesType == 'bar3D') {
|
||||
return [params.seriesName, params.name + ':' + params.value[2] + (params.value[3] || '')].join(
|
||||
'<br />'
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
legend: {
|
||||
selectedMode: false
|
||||
},
|
||||
geo3D: {
|
||||
show: true,
|
||||
// name: '浙江',
|
||||
itemStyle: {
|
||||
color: getComputedStyle(document.documentElement).getPropertyValue('--el-color-primary-light-3'),
|
||||
borderWidth: 1,
|
||||
borderColor: '#fff'
|
||||
},
|
||||
emphasis: {
|
||||
label: { show: true, fontSize: 16 },
|
||||
itemStyle: {
|
||||
color: getComputedStyle(document.documentElement).getPropertyValue('--el-color-primary-light-7')
|
||||
}
|
||||
},
|
||||
viewControl: {
|
||||
alpha: 60,
|
||||
distance: 120,
|
||||
panMouseButton: 'right', //平移操作使用的鼠标按键
|
||||
rotateMouseButton: 'left' //旋转操作使用的鼠标按键
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
color: '#000',
|
||||
fontSize: 14,
|
||||
distance: 0,
|
||||
textStyle: {
|
||||
color: '#000',
|
||||
backgroundColor: '#000'
|
||||
}
|
||||
},
|
||||
|
||||
data: [
|
||||
{ name: '低压', field: 'lowPressure', unit: '次' },
|
||||
{ name: '高压', field: 'highPressure', unit: '次' }
|
||||
]
|
||||
},
|
||||
options: {
|
||||
series: [
|
||||
{
|
||||
name: '低压',
|
||||
type: 'bar3D',
|
||||
coordinateSystem: 'geo3D',
|
||||
shading: 'lambert',
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
formatter: params => {
|
||||
return params.value[2]
|
||||
}
|
||||
},
|
||||
|
||||
data:
|
||||
res.length == 0
|
||||
? []
|
||||
: res.map((item: any) => {
|
||||
return {
|
||||
...item,
|
||||
value: [item.lng, item.lat, item.lowPressure || 0]
|
||||
}
|
||||
}),
|
||||
// data:[],
|
||||
barSize: 1,
|
||||
minHeight: 1,
|
||||
itemStyle: {
|
||||
color: '#77DA63'
|
||||
},
|
||||
emphasis: {
|
||||
label: { show: true }
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '高压',
|
||||
type: 'bar3D',
|
||||
coordinateSystem: 'geo3D',
|
||||
shading: 'lambert',
|
||||
label: {
|
||||
show: true,
|
||||
// position: 'top',
|
||||
formatter: params => {
|
||||
return params.value[2]
|
||||
}
|
||||
},
|
||||
|
||||
data:
|
||||
res.length == 0
|
||||
? []
|
||||
: res.map((item: any) => {
|
||||
return {
|
||||
...item,
|
||||
value: [item.lng - 0.1, item.lat, item.highPressure || 0]
|
||||
}
|
||||
}),
|
||||
// [
|
||||
|
||||
// {
|
||||
// adcode: 330400,
|
||||
// name: '大连',
|
||||
|
||||
// wcs: 10,
|
||||
// mbs: 40,
|
||||
// wcl: 100,
|
||||
// value: [121.67391, 38.947468, 40, '']
|
||||
// }
|
||||
// ],
|
||||
barSize: 1,
|
||||
minHeight: 1,
|
||||
itemStyle: {
|
||||
color: '#FFBF00'
|
||||
},
|
||||
emphasis: {
|
||||
label: { show: true }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 点击地图
|
||||
const clickMap = (e: any) => {
|
||||
tabulation(e)
|
||||
}
|
||||
// 表格数据处理
|
||||
const tabulation = (e: any) => {
|
||||
console.log()
|
||||
|
||||
loading.value = true
|
||||
voltageRideThroughEventQueryPage({
|
||||
...tableStore.table.params,
|
||||
areaId: e.data.id,
|
||||
frequencyType:
|
||||
e.seriesName == '高压'
|
||||
? triggerType.filter(item => item.code == 'Voltage_Rise')[0].id
|
||||
: triggerType.filter(item => item.code == 'Voltage_Dip')[0].id
|
||||
})
|
||||
.then(res => {
|
||||
distributionData.value = res.data
|
||||
|
||||
for (let i = 0; i < res.data.length; i++) {
|
||||
if (res.data[i].wavePath != null) {
|
||||
boxi(res.data[i])
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// res.data.forEach((item: any) => {
|
||||
// if (item.wavePath != null) {
|
||||
// boxi(item)
|
||||
// return
|
||||
// }
|
||||
// })
|
||||
// 。wavePath
|
||||
loading.value = false
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
const formFilter = (row: any) => {
|
||||
if (row.column.property == 'advanceReason') {
|
||||
let title = ''
|
||||
reason.forEach(item => {
|
||||
if (item.id == row.row.advanceReason) {
|
||||
title = item.name
|
||||
} else if (row.row.advanceReason == null || row.row.advanceReason == '') {
|
||||
title = '/'
|
||||
}
|
||||
})
|
||||
return title
|
||||
} else {
|
||||
return row.row[row.column.property]
|
||||
}
|
||||
}
|
||||
// 查看波形数据
|
||||
const boxi = async (row: any) => {
|
||||
loading1.value = true
|
||||
wp.value = null
|
||||
await getTransientDetailById({
|
||||
eventId: row.eventId,
|
||||
sysType: 0,
|
||||
smallType: 0
|
||||
}).then(res => {
|
||||
boxoList.value = res.data
|
||||
})
|
||||
|
||||
await getMonitorEventAnalyseWave({
|
||||
id: row.eventId,
|
||||
systemType: 0,
|
||||
type: 0
|
||||
}).then(res => {
|
||||
if (res != undefined) {
|
||||
wp.value = res.data
|
||||
}
|
||||
loading1.value = false
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
const layout = mainHeight(83) as any
|
||||
const layout1 = mainHeight(93) as any
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.map {
|
||||
height: calc(v-bind('layout1.height') - 30px);
|
||||
}
|
||||
.tall {
|
||||
height: calc((v-bind('layout1.height') - 100px) / 2);
|
||||
}
|
||||
.tall1 {
|
||||
height: calc((v-bind('layout1.height') - 100px) / 2 - 50px);
|
||||
}
|
||||
|
||||
.group {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: 20px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
:deep(.el-card__body) {
|
||||
padding: 10px;
|
||||
}
|
||||
/* 自定义 el-empty 的样式 */
|
||||
:deep(.custom-empty) {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%; /* 调整高度 */
|
||||
padding: 20px; /* 调整内边距 */
|
||||
.el-empty__image {
|
||||
display: none; /* 隐藏默认图片 */
|
||||
}
|
||||
.el-empty__description {
|
||||
font-size: 14px; /* 调整字体大小 */
|
||||
color: var(--vxe-font-color);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader datePicker theCurrentTime area ref="header">
|
||||
<!-- <template v-slot:select>
|
||||
|
||||
</template> -->
|
||||
</TableHeader>
|
||||
<div v-loading="tableStore.table.loading">
|
||||
<el-row :gutter="10" class="pd10">
|
||||
<el-col :span="11" style="position: relative">
|
||||
<el-card>
|
||||
<el-radio-group
|
||||
v-model="tableStore.table.params.type"
|
||||
class="group"
|
||||
@change="tableStore.index()"
|
||||
>
|
||||
<el-radio-button label="风电场" value="1" />
|
||||
<el-radio-button label="光伏电站" value="2" />
|
||||
</el-radio-group>
|
||||
<MyEchartMap
|
||||
ref="EchartMap"
|
||||
:options="echartMapList"
|
||||
class="map"
|
||||
@eliminate="eliminate"
|
||||
@getRegionByRegion="getRegionByRegion"
|
||||
@clickMap="clickMap"
|
||||
/>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="13">
|
||||
<el-card>
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>暂降列表</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- <h3 class="mb10">暂降列表</h3> -->
|
||||
<div class="tall1">
|
||||
<vxe-table
|
||||
height="auto"
|
||||
auto-resize
|
||||
:data="distributionData"
|
||||
v-loading="loading"
|
||||
v-bind="defaultAttribute"
|
||||
>
|
||||
<vxe-column
|
||||
field="newStationName"
|
||||
title="新能源站名称"
|
||||
min-width="150px"
|
||||
show-overflow-tooltip
|
||||
></vxe-column>
|
||||
<vxe-column field="startTime" title="暂降发生时刻" min-width="180px" sortable></vxe-column>
|
||||
<vxe-column
|
||||
field="featureAmplitude"
|
||||
title="暂降(骤升)幅值(%)"
|
||||
sortable
|
||||
min-width="160px"
|
||||
></vxe-column>
|
||||
<vxe-column
|
||||
field="advanceReason"
|
||||
title="暂降原因"
|
||||
sortable
|
||||
:formatter="formFilter"
|
||||
min-width="100px"
|
||||
></vxe-column>
|
||||
<vxe-column field="severity" title="严重度" min-width="100px" sortable></vxe-column>
|
||||
<vxe-column title="操作" width="80px">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
type="primary"
|
||||
v-if="row.wavePath != null"
|
||||
size="small"
|
||||
link
|
||||
@click="boxi(row)"
|
||||
>
|
||||
查看波形
|
||||
</el-button>
|
||||
<el-button v-else disabled size="small" link>暂无波形</el-button>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-card class="mt10">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>暂降波形</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="tall" v-loading="loading1">
|
||||
<!-- <h3 class="mb10">暂降波形</h3> -->
|
||||
<div v-if="wp != null">
|
||||
<rmsboxi :value="1" :height="height" :boxoList="boxoList" :wp="wp" />
|
||||
</div>
|
||||
<el-empty v-else description="暂无数据" class="custom-empty" />
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import { defaultAttribute } from '@/components/table/defaultAttribute'
|
||||
import MyEchartMap from '@/components/echarts/MyEchartMap.vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import { voltageRideThroughEventQueryPage } from '@/api/event-boot/highAndLowPressure'
|
||||
import { getMonitorEventAnalyseWave, getTransientDetailById } from '@/api/event-boot/transient'
|
||||
import rmsboxi from '@/components/echarts/rmsboxi.vue'
|
||||
import { ref, onMounted, provide } from 'vue'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import { FormItem } from 'vxe-table'
|
||||
defineOptions({
|
||||
name: 'newEnergy/highAndLowPressure'
|
||||
})
|
||||
const EchartMap = ref()
|
||||
const dictData = useDictData()
|
||||
const reason = dictData.getBasicData('Event_Reason')
|
||||
const triggerType = dictData.getBasicData('Event_Statis')
|
||||
const echartMapList: any = ref({})
|
||||
const header = ref()
|
||||
const distributionData: any = ref([])
|
||||
const loading = ref(false)
|
||||
const loading1 = ref(false)
|
||||
const boxoList = ref(null)
|
||||
const wp = ref(null)
|
||||
const tableStore = new TableStore({
|
||||
url: '/event-boot/voltageRideThrough/view',
|
||||
method: 'POST',
|
||||
column: [],
|
||||
beforeSearchFun: () => {
|
||||
tableStore.table.params.areaId = tableStore.table.params.deptIndex
|
||||
},
|
||||
loadCallback: () => {
|
||||
// 处理地图数据
|
||||
map(tableStore.table.data)
|
||||
// tabulation(tableStore.table.data)
|
||||
EchartMap.value.GetEchar(header.value.areaRef.areaName)
|
||||
if (tableStore.table.data.length > 0) {
|
||||
tabulation({ data: tableStore.table.data[0], seriesName: '高压' })
|
||||
}
|
||||
}
|
||||
})
|
||||
const height = mainHeight(200, 2).height
|
||||
provide('tableStore', tableStore)
|
||||
tableStore.table.params.type = '1'
|
||||
|
||||
// 地图点击事件
|
||||
const getRegionByRegion = (list: any) => {
|
||||
tableStore.table.params.deptIndex = list.id
|
||||
tableStore.onTableAction('search', {})
|
||||
}
|
||||
// 消除点
|
||||
const eliminate = (name: string) => {
|
||||
echartMapList.value.options.series = []
|
||||
EchartMap.value.GetEchar(name)
|
||||
}
|
||||
|
||||
// 地图数处理
|
||||
const map = (res: any) => {
|
||||
echartMapList.value = {
|
||||
title: {
|
||||
text: '高/低电压穿越'
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: function (params) {
|
||||
if (params.seriesType == 'bar3D') {
|
||||
return [params.seriesName, params.name + ':' + params.value[2] + (params.value[3] || '')].join(
|
||||
'<br />'
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
legend: {
|
||||
selectedMode: false
|
||||
},
|
||||
geo3D: {
|
||||
show: true,
|
||||
// name: '浙江',
|
||||
itemStyle: {
|
||||
color: getComputedStyle(document.documentElement).getPropertyValue('--el-color-primary-light-3'),
|
||||
borderWidth: 1,
|
||||
borderColor: '#fff'
|
||||
},
|
||||
emphasis: {
|
||||
label: { show: true, fontSize: 16 },
|
||||
itemStyle: {
|
||||
color: getComputedStyle(document.documentElement).getPropertyValue('--el-color-primary-light-7')
|
||||
}
|
||||
},
|
||||
viewControl: {
|
||||
alpha: 60,
|
||||
distance: 120,
|
||||
panMouseButton: 'right', //平移操作使用的鼠标按键
|
||||
rotateMouseButton: 'left' //旋转操作使用的鼠标按键
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
color: '#000',
|
||||
fontSize: 14,
|
||||
distance: 0,
|
||||
textStyle: {
|
||||
color: '#000',
|
||||
backgroundColor: '#000'
|
||||
}
|
||||
},
|
||||
|
||||
data: [
|
||||
{ name: '低压', field: 'lowPressure', unit: '次' },
|
||||
{ name: '高压', field: 'highPressure', unit: '次' }
|
||||
]
|
||||
},
|
||||
options: {
|
||||
series: [
|
||||
{
|
||||
name: '低压',
|
||||
type: 'bar3D',
|
||||
coordinateSystem: 'geo3D',
|
||||
shading: 'lambert',
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
formatter: params => {
|
||||
return params.value[2]
|
||||
}
|
||||
},
|
||||
|
||||
data:
|
||||
res.length == 0
|
||||
? []
|
||||
: res.map((item: any) => {
|
||||
return {
|
||||
...item,
|
||||
value: [item.lng, item.lat, item.lowPressure || 0]
|
||||
}
|
||||
}),
|
||||
// data:[],
|
||||
barSize: 1,
|
||||
minHeight: 1,
|
||||
itemStyle: {
|
||||
color: '#77DA63'
|
||||
},
|
||||
emphasis: {
|
||||
label: { show: true }
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '高压',
|
||||
type: 'bar3D',
|
||||
coordinateSystem: 'geo3D',
|
||||
shading: 'lambert',
|
||||
label: {
|
||||
show: true,
|
||||
// position: 'top',
|
||||
formatter: params => {
|
||||
return params.value[2]
|
||||
}
|
||||
},
|
||||
|
||||
data:
|
||||
res.length == 0
|
||||
? []
|
||||
: res.map((item: any) => {
|
||||
return {
|
||||
...item,
|
||||
value: [item.lng - 0.1, item.lat, item.highPressure || 0]
|
||||
}
|
||||
}),
|
||||
// [
|
||||
|
||||
// {
|
||||
// adcode: 330400,
|
||||
// name: '大连',
|
||||
|
||||
// wcs: 10,
|
||||
// mbs: 40,
|
||||
// wcl: 100,
|
||||
// value: [121.67391, 38.947468, 40, '']
|
||||
// }
|
||||
// ],
|
||||
barSize: 1,
|
||||
minHeight: 1,
|
||||
itemStyle: {
|
||||
color: '#FFBF00'
|
||||
},
|
||||
emphasis: {
|
||||
label: { show: true }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 点击地图
|
||||
const clickMap = (e: any) => {
|
||||
tabulation(e)
|
||||
}
|
||||
// 表格数据处理
|
||||
const tabulation = (e: any) => {
|
||||
console.log()
|
||||
|
||||
loading.value = true
|
||||
voltageRideThroughEventQueryPage({
|
||||
...tableStore.table.params,
|
||||
areaId: e.data.id,
|
||||
frequencyType:
|
||||
e.seriesName == '高压'
|
||||
? triggerType.filter(item => item.code == 'Voltage_Rise')[0].id
|
||||
: triggerType.filter(item => item.code == 'Voltage_Dip')[0].id
|
||||
})
|
||||
.then(res => {
|
||||
distributionData.value = res.data
|
||||
|
||||
for (let i = 0; i < res.data.length; i++) {
|
||||
if (res.data[i].wavePath != null) {
|
||||
boxi(res.data[i])
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// res.data.forEach((item: any) => {
|
||||
// if (item.wavePath != null) {
|
||||
// boxi(item)
|
||||
// return
|
||||
// }
|
||||
// })
|
||||
// 。wavePath
|
||||
loading.value = false
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
const formFilter = (row: any) => {
|
||||
if (row.column.property == 'advanceReason') {
|
||||
let title = ''
|
||||
reason.forEach(item => {
|
||||
if (item.id == row.row.advanceReason) {
|
||||
title = item.name
|
||||
} else if (row.row.advanceReason == null || row.row.advanceReason == '') {
|
||||
title = '/'
|
||||
}
|
||||
})
|
||||
return title
|
||||
} else {
|
||||
return row.row[row.column.property]
|
||||
}
|
||||
}
|
||||
// 查看波形数据
|
||||
const boxi = async (row: any) => {
|
||||
loading1.value = true
|
||||
wp.value = null
|
||||
await getTransientDetailById({
|
||||
eventId: row.eventId,
|
||||
sysType: 0,
|
||||
smallType: 0
|
||||
}).then(res => {
|
||||
boxoList.value = res.data
|
||||
})
|
||||
|
||||
await getMonitorEventAnalyseWave({
|
||||
id: row.eventId,
|
||||
systemType: 0,
|
||||
type: 0
|
||||
}).then(res => {
|
||||
if (res != undefined) {
|
||||
wp.value = res.data
|
||||
}
|
||||
loading1.value = false
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
const layout = mainHeight(83) as any
|
||||
const layout1 = mainHeight(93) as any
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.map {
|
||||
height: calc(v-bind('layout1.height') - 30px);
|
||||
}
|
||||
.tall {
|
||||
height: calc((v-bind('layout1.height') - 100px) / 2);
|
||||
}
|
||||
.tall1 {
|
||||
height: calc((v-bind('layout1.height') - 100px) / 2 - 50px);
|
||||
}
|
||||
|
||||
.group {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: 20px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
:deep(.el-card__body) {
|
||||
padding: 10px;
|
||||
}
|
||||
/* 自定义 el-empty 的样式 */
|
||||
:deep(.custom-empty) {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%; /* 调整高度 */
|
||||
padding: 20px; /* 调整内边距 */
|
||||
.el-empty__image {
|
||||
display: none; /* 隐藏默认图片 */
|
||||
}
|
||||
.el-empty__description {
|
||||
font-size: 14px; /* 调整字体大小 */
|
||||
color: var(--vxe-font-color);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,119 +1,119 @@
|
||||
<template>
|
||||
<div class="dictiontary-list-detail child-router">
|
||||
<TableHeader :showSearch="false">
|
||||
<template #select>
|
||||
<el-form-item label="">
|
||||
<span class="text-large font-600 mr-3">{{ props.timePopUpBox.time }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-radio-group v-model="radio2" @change="tableStore.index()">
|
||||
<el-radio-button label="基础数据" value="1" />
|
||||
<el-radio-button label="谐波电压" value="2" />
|
||||
<el-radio-button label="谐波电流" value="3" />
|
||||
<el-radio-button label="间谐波电压" value="4" />
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template #operation>
|
||||
<el-button icon="el-icon-Back" @click="$emit('close')">返回</el-button>
|
||||
</template>
|
||||
</TableHeader>
|
||||
<Table ref="tableRef" isGroup />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, provide } from 'vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { dictDataDelete } from '@/api/system-boot/dicData'
|
||||
|
||||
defineOptions({
|
||||
name: 'setting/dictionary/list/detail'
|
||||
})
|
||||
const radio2 = ref('1')
|
||||
interface Props {
|
||||
timePopUpBox: anyObj
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
timePopUpBox: () => {
|
||||
return {}
|
||||
}
|
||||
})
|
||||
const popupEditRef = ref()
|
||||
const tableStore = new TableStore({
|
||||
url: '/harmonic-boot/powerStatistics/getTargetByTime',
|
||||
method: 'POST',
|
||||
showPage: false,
|
||||
column: [
|
||||
{
|
||||
title: '指标',
|
||||
field: 'anotherName',
|
||||
minWidth: '120px',
|
||||
formatter: row => {
|
||||
row.column.title =
|
||||
radio2.value == '1' ? '指标' : (row.column.title = radio2.value == '4' ? '间谐波次数' : '谐波次数')
|
||||
return row.cellValue
|
||||
}
|
||||
},
|
||||
{ title: '单位', field: 'unit' },
|
||||
{
|
||||
title: '最小值',
|
||||
field: 'min',
|
||||
children: [
|
||||
{
|
||||
title: 'A',
|
||||
field: 'minphaseA',
|
||||
formatter: row => formatter(row)
|
||||
},
|
||||
{ title: 'B', field: 'minphaseB', formatter: row => formatter(row) },
|
||||
{ title: 'C', field: 'minphaseC', formatter: row => formatter(row) }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '最大值',
|
||||
field: 'max',
|
||||
children: [
|
||||
{ title: 'A', field: 'maxphaseA', formatter: row => formatter(row) },
|
||||
{ title: 'B', field: 'maxphaseB', formatter: row => formatter(row) },
|
||||
{ title: 'C', field: 'maxphaseC', formatter: row => formatter(row) }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '平均值',
|
||||
field: 'avg',
|
||||
children: [
|
||||
{ title: 'A', field: 'avgphaseA', formatter: row => formatter(row) },
|
||||
{ title: 'B', field: 'avgphaseB', formatter: row => formatter(row) },
|
||||
{ title: 'C', field: 'avgphaseC', formatter: row => formatter(row) }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'cp95值',
|
||||
field: 'cp95',
|
||||
children: [
|
||||
{ title: 'A', field: 'cp95PhaseA', formatter: row => formatter(row) },
|
||||
{ title: 'B', field: 'cp95PhaseB', formatter: row => formatter(row) },
|
||||
{ title: 'C', field: 'cp95PhaseC', formatter: row => formatter(row) }
|
||||
]
|
||||
}
|
||||
],
|
||||
beforeSearchFun: () => {
|
||||
tableStore.table.params.field = props.timePopUpBox.field
|
||||
tableStore.table.params.lineId = props.timePopUpBox.lineId
|
||||
tableStore.table.params.searchBeginTime = props.timePopUpBox.time
|
||||
tableStore.table.params.searchEndTime = props.timePopUpBox.time
|
||||
tableStore.table.params.statisticalId = radio2.value
|
||||
},
|
||||
loadCallback: () => {}
|
||||
})
|
||||
|
||||
provide('tableStore', tableStore)
|
||||
const formatter = (row: any) => {
|
||||
return row.cellValue || '/'
|
||||
}
|
||||
onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<div class="dictiontary-list-detail child-router">
|
||||
<TableHeader :showSearch="false" showCustomColumn>
|
||||
<template #select>
|
||||
<el-form-item label="">
|
||||
<span class="text-large font-600 mr-3">{{ props.timePopUpBox.time }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-radio-group v-model="radio2" @change="tableStore.index()">
|
||||
<el-radio-button label="基础数据" value="1" />
|
||||
<el-radio-button label="谐波电压" value="2" />
|
||||
<el-radio-button label="谐波电流" value="3" />
|
||||
<el-radio-button label="间谐波电压" value="4" />
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template #operation>
|
||||
<el-button icon="el-icon-Back" @click="$emit('close')">返回</el-button>
|
||||
</template>
|
||||
</TableHeader>
|
||||
<Table ref="tableRef" isGroup />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, provide } from 'vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { dictDataDelete } from '@/api/system-boot/dicData'
|
||||
|
||||
defineOptions({
|
||||
name: 'setting/dictionary/list/detail'
|
||||
})
|
||||
const radio2 = ref('1')
|
||||
interface Props {
|
||||
timePopUpBox: anyObj
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
timePopUpBox: () => {
|
||||
return {}
|
||||
}
|
||||
})
|
||||
const popupEditRef = ref()
|
||||
const tableStore = new TableStore({
|
||||
url: '/harmonic-boot/powerStatistics/getTargetByTime',
|
||||
method: 'POST',
|
||||
showPage: false,
|
||||
column: [
|
||||
{
|
||||
title: '指标',
|
||||
field: 'anotherName',
|
||||
minWidth: '120px',
|
||||
formatter: row => {
|
||||
row.column.title =
|
||||
radio2.value == '1' ? '指标' : (row.column.title = radio2.value == '4' ? '间谐波次数' : '谐波次数')
|
||||
return row.cellValue
|
||||
}
|
||||
},
|
||||
{ title: '单位', field: 'unit' },
|
||||
{
|
||||
title: '最小值',
|
||||
field: 'min',
|
||||
children: [
|
||||
{
|
||||
title: 'A',
|
||||
field: 'minphaseA',
|
||||
formatter: row => formatter(row)
|
||||
},
|
||||
{ title: 'B', field: 'minphaseB', formatter: row => formatter(row) },
|
||||
{ title: 'C', field: 'minphaseC', formatter: row => formatter(row) }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '最大值',
|
||||
field: 'max',
|
||||
children: [
|
||||
{ title: 'A', field: 'maxphaseA', formatter: row => formatter(row) },
|
||||
{ title: 'B', field: 'maxphaseB', formatter: row => formatter(row) },
|
||||
{ title: 'C', field: 'maxphaseC', formatter: row => formatter(row) }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '平均值',
|
||||
field: 'avg',
|
||||
children: [
|
||||
{ title: 'A', field: 'avgphaseA', formatter: row => formatter(row) },
|
||||
{ title: 'B', field: 'avgphaseB', formatter: row => formatter(row) },
|
||||
{ title: 'C', field: 'avgphaseC', formatter: row => formatter(row) }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'cp95值',
|
||||
field: 'cp95',
|
||||
children: [
|
||||
{ title: 'A', field: 'cp95PhaseA', formatter: row => formatter(row) },
|
||||
{ title: 'B', field: 'cp95PhaseB', formatter: row => formatter(row) },
|
||||
{ title: 'C', field: 'cp95PhaseC', formatter: row => formatter(row) }
|
||||
]
|
||||
}
|
||||
],
|
||||
beforeSearchFun: () => {
|
||||
tableStore.table.params.field = props.timePopUpBox.field
|
||||
tableStore.table.params.lineId = props.timePopUpBox.lineId
|
||||
tableStore.table.params.searchBeginTime = props.timePopUpBox.time
|
||||
tableStore.table.params.searchEndTime = props.timePopUpBox.time
|
||||
tableStore.table.params.statisticalId = radio2.value
|
||||
},
|
||||
loadCallback: () => {}
|
||||
})
|
||||
|
||||
provide('tableStore', tableStore)
|
||||
const formatter = (row: any) => {
|
||||
return row.cellValue || '/'
|
||||
}
|
||||
onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -779,6 +779,7 @@ const analyseList = (e: string) => {
|
||||
provide('tableStore', tableStore)
|
||||
|
||||
onMounted(() => {
|
||||
TableHeaderRef.value.setTheDate(4)
|
||||
const dom = document.getElementById('navigation-splitpanes')
|
||||
if (dom) {
|
||||
size.value = Math.round((180 / dom.offsetHeight) * 120)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader ref="TableHeaderRef">
|
||||
<TableHeader ref="TableHeaderRef" showCustomColumn>
|
||||
<template #select>
|
||||
<el-form-item label="新能源场站名称">
|
||||
<el-input v-model="tableStore.table.params.name" clearable placeholder="输入关键字筛选" />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<div v-show="flg">
|
||||
<TableHeader datePicker showExport ref="TableHeaderRef">
|
||||
<TableHeader datePicker showExport ref="TableHeaderRef" showCustomColumn>
|
||||
<template v-slot:select>
|
||||
<el-form :inline="true" label-width="90px" class="">
|
||||
<el-form-item label="用户名:">
|
||||
@@ -90,7 +90,6 @@ const loading = ref(false)
|
||||
const statistics = ref()
|
||||
|
||||
const flg = ref(true)
|
||||
const showMqtt = ref(false)
|
||||
const zoom = ref('') //图表焦点校验
|
||||
|
||||
const resultList = ref([
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<div v-show="addedShow">
|
||||
<TableHeader datePicker showExport ref="TableHeaderRef">
|
||||
<TableHeader datePicker showExport ref="TableHeaderRef" showCustomColumn>
|
||||
<template #select>
|
||||
<el-form-item label="评估类型">
|
||||
<el-select
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<div>
|
||||
<TableHeader :showTimeAll="false" showExport ref="TableHeaderRef">
|
||||
<TableHeader :showTimeAll="false" showExport ref="TableHeaderRef" showCustomColumn>
|
||||
<template #select>
|
||||
<el-form-item label="用户类型">
|
||||
<el-select
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<!-- 新增 -->
|
||||
<el-dialog draggable title="详情" v-model="dialogVisible" width="1200px">
|
||||
<TableHeader datePicker showExport :showReset="false">
|
||||
<TableHeader datePicker showExport :showReset="false" >
|
||||
<template v-slot:select>
|
||||
<el-form-item label="筛选数据">
|
||||
<el-input v-model="tableStore.table.params.searchValue" placeholder="请输入筛选数据" clearable maxlength="32" show-word-limit/>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader datePicker showExport>
|
||||
<TableHeader datePicker showExport showCustomColumn>
|
||||
<template v-slot:select>
|
||||
<el-form-item label="筛选数据">
|
||||
<el-input v-model="tableStore.table.params.searchValue" placeholder="请输入筛选数据" clearable maxlength="32" show-word-limit/>
|
||||
|
||||
@@ -462,7 +462,7 @@ const currentChangeEvent = () => {
|
||||
hasDevices.value = hasAnyDevices
|
||||
|
||||
dataSource.value = res.data.processDeviceList.filter(item => {
|
||||
item.name = item.processNo + ''
|
||||
item.name = item.processNo + '号进程'
|
||||
return true // 保持原有的过滤逻辑
|
||||
})
|
||||
} else {
|
||||
|
||||
@@ -1107,7 +1107,7 @@
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
class="form-item"
|
||||
label="测量点性质:"
|
||||
label="电网标志:"
|
||||
:prop="
|
||||
'deviceParam.' +
|
||||
[deviceIndex] +
|
||||
@@ -1119,14 +1119,14 @@
|
||||
"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: '请选择测量点性质',
|
||||
message: '请选择电网标志',
|
||||
trigger: 'blur'
|
||||
}"
|
||||
>
|
||||
<el-select
|
||||
filterable
|
||||
v-model="lineItem.powerFlag"
|
||||
placeholder="请选择测量点性质"
|
||||
placeholder="请选择电网标志"
|
||||
:disabled="pageStatus == 1"
|
||||
@change="lineItem.objId = ''"
|
||||
>
|
||||
@@ -1140,14 +1140,15 @@
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
class="form-item"
|
||||
label="用户名称:"
|
||||
label="监测对象名称:"
|
||||
v-if="lineItem.powerFlag == 1"
|
||||
>
|
||||
<el-select
|
||||
filterable
|
||||
v-model="lineItem.objId"
|
||||
placeholder="请选择用户名称"
|
||||
placeholder="请选择对象名称"
|
||||
:disabled="pageStatus == 1"
|
||||
@change="(val) => handleSelect(lineItem, val)"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
@@ -1355,7 +1356,7 @@
|
||||
lIndex +
|
||||
'.bigObjType'
|
||||
"
|
||||
:rules="{ required: true, message: '请选择对象大类', trigger: 'blur' }"
|
||||
|
||||
>
|
||||
<el-select
|
||||
filterable
|
||||
@@ -1384,7 +1385,7 @@
|
||||
lIndex +
|
||||
'.smallObjType'
|
||||
"
|
||||
:rules="{ required: true, message: '请选择对象小类', trigger: 'blur' }"
|
||||
|
||||
>
|
||||
<el-select
|
||||
filterable
|
||||
@@ -2202,6 +2203,22 @@ const category = () => {
|
||||
bigList.value = convertToTree(res.data)
|
||||
})
|
||||
}
|
||||
|
||||
//用户对象chage事件
|
||||
const handleSelect = (item, selectedId) => {
|
||||
// 清空选择
|
||||
if (!selectedId) {
|
||||
item.projectName = ''
|
||||
return
|
||||
}
|
||||
// 过滤当前下拉数据源
|
||||
|
||||
const options = newStationIdArr.value.find(i => i.id === selectedId)
|
||||
if (options) {
|
||||
item.objName = options.projectName
|
||||
}
|
||||
}
|
||||
|
||||
// 组装用户大小类
|
||||
const convertToTree = (data: any) => {
|
||||
const nodeMap: any = {}
|
||||
@@ -2911,7 +2928,7 @@ const selectChanged = async (value: any) => {
|
||||
capacity = 750
|
||||
break
|
||||
case '35':
|
||||
capacity = 259
|
||||
capacity = 250
|
||||
break
|
||||
case '10':
|
||||
capacity = 100
|
||||
@@ -2931,9 +2948,9 @@ const selectChanged = async (value: any) => {
|
||||
case '750':
|
||||
capacity = 7000
|
||||
break
|
||||
case '800':
|
||||
capacity = 7000
|
||||
break
|
||||
// case '800':
|
||||
// capacity = 7000
|
||||
// break
|
||||
case '1000':
|
||||
capacity = 9000
|
||||
break
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader :showReset="false" showExport>
|
||||
<TableHeader :showReset="false" showExport showCustomColumn>
|
||||
<template #select>
|
||||
<el-form-item label="关键字筛选">
|
||||
<el-form-item label="筛选数据">
|
||||
<el-input
|
||||
maxlength="32"
|
||||
show-word-limit
|
||||
|
||||
185
src/views/pqs/business/terminal/terminaCkeck/components/form.vue
Normal file
185
src/views/pqs/business/terminal/terminaCkeck/components/form.vue
Normal file
@@ -0,0 +1,185 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:title="dialogMode === 'detail' ? '定检详情' : '上传周期检测报告'"
|
||||
:width="dialogMode === 'detail' ? '1000px' : '600px'"
|
||||
v-model="dialogShow"
|
||||
v-if="dialogShow"
|
||||
>
|
||||
<!-- 详情区域 -->
|
||||
<div v-if="dialogMode === 'detail'">
|
||||
</div>
|
||||
<!-- 上传报告表单区域 -->
|
||||
<div v-if="dialogMode === 'upload'">
|
||||
<el-form ref="uploadFormRef" :model="uploadForm" :rules="uploadRules" label-width="120px">
|
||||
<el-form-item label="定检日期" prop="thisCheckTime">
|
||||
<el-date-picker
|
||||
v-model="uploadForm.thisCheckTime"
|
||||
type="date"
|
||||
placeholder="请选择定检日期"
|
||||
@change="calcNextCheckTime"
|
||||
style="width:100%"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="下次定检日期" prop="nextCheckTime">
|
||||
<el-date-picker
|
||||
v-model="uploadForm.nextCheckTime"
|
||||
type="date"
|
||||
placeholder="请选择下次定检日期"
|
||||
style="width:100%"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item class="uploadFile" for="-" label="设备检测报告:">
|
||||
<el-upload
|
||||
v-model:file-list="uploadForm.checkUrl"
|
||||
ref="uploadRef"
|
||||
action=""
|
||||
:accept="acceptType"
|
||||
:limit="1"
|
||||
:on-change="(file) => choose(file, 'checkUrl')"
|
||||
:auto-upload="false"
|
||||
:on-remove="removeFile('checkUrl')"
|
||||
>
|
||||
<template #trigger>
|
||||
<el-button type="primary">上传文件</el-button>
|
||||
</template>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<el-button v-if="dialogMode === 'upload'" @click="dialogShow = false">取消</el-button>
|
||||
<el-button
|
||||
v-if="dialogMode === 'upload'"
|
||||
type="primary"
|
||||
:loading="submitLoading"
|
||||
@click="submitUploadReport"
|
||||
>
|
||||
提交
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, nextTick } from 'vue'
|
||||
import type { UploadFile } from 'element-plus'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { uploadFile } from '@/api/system-boot/file'
|
||||
import { userCheckUpload } from '@/api/device-boot/device'
|
||||
|
||||
const emit = defineEmits(['onSubmit'])
|
||||
|
||||
const acceptType = '.pdf,.docx'
|
||||
|
||||
const detailId = ref('')
|
||||
const dialogShow = ref(false)
|
||||
const dialogMode = ref<'detail' | 'upload'>('detail')
|
||||
const submitLoading = ref(false)
|
||||
|
||||
const uploadFormRef = ref()
|
||||
const uploadForm = reactive({
|
||||
thisCheckTime: '',
|
||||
nextCheckTime: '',
|
||||
checkUrl: [] as any[],
|
||||
devId: '',
|
||||
objId: ''
|
||||
})
|
||||
const checkUrlFile = ref('')
|
||||
|
||||
const calcNextCheckTime = (dateVal: string) => {
|
||||
if (!dateVal) {
|
||||
uploadForm.nextCheckTime = ''
|
||||
return
|
||||
}
|
||||
const date = new Date(dateVal)
|
||||
date.setFullYear(date.getFullYear() + 3)
|
||||
const y = date.getFullYear()
|
||||
const m = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const d = String(date.getDate()).padStart(2, '0')
|
||||
uploadForm.nextCheckTime = `${y}-${m}-${d}`
|
||||
}
|
||||
|
||||
const uploadRules = reactive({
|
||||
thisCheckTime: [{ required: true, message: '请选择定检日期', trigger: 'change' }],
|
||||
checkUrl: [{ required: true, message: '请上传设备检测报告', trigger: 'change' }]
|
||||
})
|
||||
|
||||
const submitUploadReport = async () => {
|
||||
await uploadFormRef.value?.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
submitLoading.value = true
|
||||
try {
|
||||
const params = {
|
||||
devId: uploadForm.devId,
|
||||
objId: uploadForm.objId,
|
||||
thisCheckTime: uploadForm.thisCheckTime,
|
||||
nextCheckTime: uploadForm.nextCheckTime,
|
||||
checkUrl: checkUrlFile.value
|
||||
}
|
||||
const res = await userCheckUpload(params)
|
||||
if (res.code === 'A0000') {
|
||||
ElMessage.success('提交成功')
|
||||
dialogShow.value = false
|
||||
emit('onSubmit')
|
||||
}
|
||||
} catch (err: any) {
|
||||
ElMessage.error(err.msg || '提交失败')
|
||||
} finally {
|
||||
submitLoading.value = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getFileName = (filePath: string) => {
|
||||
if (!filePath) return ''
|
||||
const parts = filePath.split('/')
|
||||
return parts[parts.length - 1] || filePath.replace(/^.*?\/(.*?)\//, '')
|
||||
}
|
||||
|
||||
const openUpload = (row: any) => {
|
||||
uploadForm.devId = row.devId
|
||||
uploadForm.objId = row.objId
|
||||
uploadForm.thisCheckTime = row.thisCheckTime || ''
|
||||
uploadForm.nextCheckTime = row.nextCheckTime || ''
|
||||
if (row.checkUrl) {
|
||||
checkUrlFile.value = row.checkUrl
|
||||
uploadForm.checkUrl = [{ name: getFileName(row.checkUrl), url: row.checkUrl }]
|
||||
} else {
|
||||
checkUrlFile.value = ''
|
||||
uploadForm.checkUrl = []
|
||||
}
|
||||
dialogMode.value = 'upload'
|
||||
dialogShow.value = true
|
||||
nextTick(() => {
|
||||
uploadFormRef.value?.clearValidate()
|
||||
})
|
||||
}
|
||||
|
||||
const openDetail = (id: string) => {
|
||||
detailId.value = id
|
||||
dialogMode.value = 'detail'
|
||||
dialogShow.value = true
|
||||
}
|
||||
|
||||
const removeFile = (val: string) => {
|
||||
return (_file: UploadFile, fileList: UploadFile[]) => {
|
||||
if (val === 'checkUrl') {
|
||||
checkUrlFile.value = ''
|
||||
}
|
||||
uploadForm[val] = fileList
|
||||
}
|
||||
}
|
||||
|
||||
const choose = (e: any, field: string) => {
|
||||
uploadFile(e.raw, '/supervision/').then(res => {
|
||||
if (field === 'checkUrl') {
|
||||
checkUrlFile.value = res.data.name
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({ openUpload, openDetail })
|
||||
</script>
|
||||
205
src/views/pqs/business/terminal/terminaCkeck/index.vue
Normal file
205
src/views/pqs/business/terminal/terminaCkeck/index.vue
Normal file
@@ -0,0 +1,205 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader ref="TableHeaderRef" showExport>
|
||||
<template #select>
|
||||
<el-form-item label="地市">
|
||||
<el-select v-model="tableStore.table.params.city" clearable placeholder="请选择地市">
|
||||
<el-option
|
||||
v-for="item in areaOptionList"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.name"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="监测对象">
|
||||
<el-input
|
||||
style="width: 200px"
|
||||
placeholder="请输入监测对象名称"
|
||||
v-model="tableStore.table.params.searchValue"
|
||||
clearable
|
||||
maxlength="32"
|
||||
show-word-limit
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template #operation>
|
||||
<!-- <el-button icon="el-icon-Plus" type="primary" @click="addFormModel">新增定检记录</el-button>-->
|
||||
</template>
|
||||
</TableHeader>
|
||||
<Table ref="tableRef" @cell-click="cellClickEvent" />
|
||||
|
||||
<checkForm ref="checkFormRef" @onSubmit="tableStore.index()" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, provide, watch } from 'vue'
|
||||
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import checkForm from './components/form.vue'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import { useAdminInfo } from '@/stores/adminInfo'
|
||||
import { download } from '@/utils/fileDownLoad'
|
||||
defineOptions({
|
||||
name: 'terminal/terminaCkeck'
|
||||
})
|
||||
|
||||
// 公共依赖
|
||||
const TableHeaderRef = ref()
|
||||
const checkFormRef = ref()
|
||||
const dictData = useDictData()
|
||||
const adminInfo = useAdminInfo()
|
||||
// 地区字典(和你原有地市下拉同源)
|
||||
const areaOptionList = dictData.getBasicData('jibei_area')
|
||||
|
||||
// TableStore 表格配置(仅修改字段映射,其余不动)
|
||||
const tableStore = new TableStore({
|
||||
url: '/device-boot/alarm/terminalCheckPage',
|
||||
method: 'POST',
|
||||
column: [
|
||||
// 多选框
|
||||
{
|
||||
width: '60',
|
||||
type: 'checkbox'
|
||||
},
|
||||
// 序号(分页自增,和你现有逻辑一致)
|
||||
{
|
||||
title: '序号',
|
||||
width: 70,
|
||||
formatter: (row: any) => {
|
||||
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
|
||||
}
|
||||
},
|
||||
{ field: 'areaName', title: '所在地市', minWidth: 100 },
|
||||
{ field: 'bdName', title: '变电站', minWidth: 150 },
|
||||
{ field: 'objName', title: '监测对象', minWidth: 180 },
|
||||
{ field: 'devName', title: '终端名称', minWidth: 180 },
|
||||
{ field: 'loginDate', title: '投运时间', minWidth: 120 },
|
||||
{ field: 'thisCheckTime', title: '本次定检时间', minWidth: 120 },
|
||||
{ field: 'nextCheckTime', title: '下次定检时间', minWidth: 120 },
|
||||
{
|
||||
title: '是否逾期',
|
||||
field: 'checkStatus',
|
||||
align: 'center',
|
||||
width: 80,
|
||||
render: 'customRender',
|
||||
customRender: props => {
|
||||
const val = props.renderValue
|
||||
let text = ''
|
||||
let color = ''
|
||||
if (val === 1) {
|
||||
text = '是'
|
||||
color = '#f56c6c'
|
||||
} else if (val === 0) {
|
||||
text = '否'
|
||||
color = '#67c23a'
|
||||
}
|
||||
return h('span', { style: { color, fontWeight: 'bold' } }, text)
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'overdueDay',
|
||||
title: '逾期天数',
|
||||
minWidth: 80,
|
||||
render: 'customRender',
|
||||
customRender: props => {
|
||||
const val = props.renderValue
|
||||
let text = ''
|
||||
let color = ''
|
||||
if (val > 0) {
|
||||
text = val
|
||||
color = '#f56c6c'
|
||||
} else if (val > -30) {
|
||||
text = Math.abs(val).toString() + '天后将逾期'
|
||||
color = '#e6a23c'
|
||||
} else {
|
||||
text = '/'
|
||||
}
|
||||
return h('span', { style: { color, fontWeight: 'bold' } }, text)
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'checkUrl',
|
||||
title: '周期检测报告',
|
||||
minWidth: 160,
|
||||
render: 'customRender',
|
||||
customRender: props => {
|
||||
const val = props.renderValue?.replace(/^.*?\/(.*?)\//, '') || ''
|
||||
return val ? h('span', { style: { color: 'var(--el-color-primary)', cursor: 'pointer' } }, val) : '/'
|
||||
}
|
||||
},
|
||||
// 操作列固定右侧
|
||||
{
|
||||
title: '操作',
|
||||
fixed: 'right',
|
||||
minWidth: 160,
|
||||
render: 'buttons',
|
||||
buttons: [
|
||||
// {
|
||||
// name: 'detail',
|
||||
// title: '详情',
|
||||
// type: 'primary',
|
||||
// icon: 'el-icon-EditPen',
|
||||
// render: 'basicButton',
|
||||
// click: row => {
|
||||
// checkFormRef.value.openDetail(row.devId)
|
||||
// }
|
||||
// },
|
||||
{
|
||||
name: 'edit',
|
||||
title: '上传周期检测报告',
|
||||
type: 'primary',
|
||||
icon: 'el-icon-Open',
|
||||
render: 'basicButton',
|
||||
click: row => {
|
||||
checkFormRef.value.openUpload(row)
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
beforeSearchFun: () => {
|
||||
// 携带当前登录人部门ID
|
||||
tableStore.table.params.orgId = adminInfo.$state.deptId
|
||||
}
|
||||
})
|
||||
|
||||
// 初始化查询参数
|
||||
tableStore.table.params.city = ''
|
||||
tableStore.table.params.substation = ''
|
||||
tableStore.table.params.terminalName = ''
|
||||
tableStore.table.params.orgId = adminInfo.$state.deptId
|
||||
|
||||
// 路由跳转带ID回显编辑(复用你原有路由传参逻辑)
|
||||
const props = defineProps({
|
||||
id: { type: String, default: 'null' }
|
||||
})
|
||||
watch(
|
||||
() => props.id,
|
||||
async newVal => {
|
||||
if (newVal === 'null') return
|
||||
const fullId = newVal.split('@')[0]
|
||||
const routeTime = Number(newVal.split('@')[1])
|
||||
if (isNaN(routeTime) || Date.now() - routeTime > import.meta.env.VITE_ROUTE_TIME_OUT) return
|
||||
const res = await getPqCheckById(fullId)
|
||||
if (res.code === 'A0000') {
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
// 点击行
|
||||
const cellClickEvent = ({ row, column }: any) => {
|
||||
if (column.field == 'checkUrl') {
|
||||
row.checkUrl ? download(row.checkUrl) : ''
|
||||
}
|
||||
}
|
||||
provide('tableStore', tableStore)
|
||||
onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -41,7 +41,7 @@
|
||||
</el-col>
|
||||
<el-col :span="19">
|
||||
<div class="mt10">
|
||||
<TableHeader showExport :showSearch="false" ref="TableHeaderRef">
|
||||
<TableHeader showExport :showSearch="false" ref="TableHeaderRef" showCustomColumn>
|
||||
<template v-slot:select>
|
||||
<span style="font-size: 14px; line-height: 40px; color: red;">
|
||||
所选变电站:
|
||||
@@ -504,14 +504,16 @@ const maintenance = (val: any) => {
|
||||
id: val.tfIndex,
|
||||
subId: val.subIndex
|
||||
}).then(res => {
|
||||
|
||||
bind.value = res.data.bind
|
||||
treeMenuLeftData.value = res.data.upNode
|
||||
treeMenuRightData.value = res.data.downNode
|
||||
|
||||
setDisabled(treeMenuRightData.value)
|
||||
setDisabled(treeMenuLeftData.value)
|
||||
isLoading3.value = false
|
||||
if (treeMenuLeftData.value && treeMenuLeftData.value.length > 0) {
|
||||
treeMenuLeftData.value[0].children?.forEach(item => {
|
||||
/* treeMenuLeftData.value[0].children?.forEach(item => {
|
||||
item.children?.forEach(item1 => {
|
||||
item1.children?.forEach(item2 => {
|
||||
item2.children?.forEach(item3 => {
|
||||
@@ -523,21 +525,25 @@ const maintenance = (val: any) => {
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})*/
|
||||
menuTreeLeft.value?.setCheckedKeys([bind.value[0]])
|
||||
maintenanceData.upNode = bind.value[0]
|
||||
bindLevel.value = 5
|
||||
}
|
||||
if (treeMenuRightData.value && treeMenuRightData.value.length > 0) {
|
||||
treeMenuRightData.value[0].children?.forEach(item => {
|
||||
/* treeMenuRightData.value[0].children?.forEach(item => {
|
||||
item.children?.forEach(item1 => {
|
||||
item1.children?.forEach(item2 => {
|
||||
item2.children?.forEach(item3 => {
|
||||
if (item3.level != null) {
|
||||
menuTreeRight.value?.setCheckedKeys([item3.id])
|
||||
maintenanceData.downNode = item3.id
|
||||
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})*/
|
||||
menuTreeRight.value?.setCheckedKeys([bind.value[1]])
|
||||
maintenanceData.downNode = bind.value[1]
|
||||
}
|
||||
nodemaintenanceInformation.value = true
|
||||
})
|
||||
|
||||
@@ -212,7 +212,7 @@
|
||||
<el-form-item for="-" v-if="form.userType != '0' && form.userType != '1'" label="PCC点:">
|
||||
<el-input v-model.trim="form.pccPoint" autocomplete="off" placeholder="请输入PCC点" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
<!-- <el-form-item
|
||||
for="-"
|
||||
v-if="form.userType == '2' || form.userType == '3' || form.userType == '4' || form.userType == '5'"
|
||||
label="基准短路容量:"
|
||||
@@ -273,7 +273,7 @@
|
||||
>
|
||||
<template #append>MVA</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-form-item>-->
|
||||
<el-form-item for="-" v-if="form.userType == '6'" label="行业:">
|
||||
<el-select v-model="form.industry" placeholder="请选择行业">
|
||||
<el-option v-for="(item, index) in industryList" :label="item.name" :value="item.id" :key="index" />
|
||||
@@ -368,6 +368,48 @@
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
class="uploadFile"
|
||||
for="-"
|
||||
label="设备检测报告:"
|
||||
prop="checkUrl"
|
||||
>
|
||||
<el-upload
|
||||
v-model:file-list="form.checkUrl"
|
||||
ref="uploadRef"
|
||||
action=""
|
||||
:accept="acceptType"
|
||||
:limit="1"
|
||||
:on-change="(file) => choose(file, 'checkUrl')"
|
||||
:auto-upload="false"
|
||||
:on-remove="removeFile('checkUrl')"
|
||||
>
|
||||
<template #trigger>
|
||||
<el-button type="primary" >上传文件</el-button>
|
||||
</template>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
class="uploadFile"
|
||||
for="-"
|
||||
label="电能质量评估报告:"
|
||||
prop="evaluation"
|
||||
>
|
||||
<el-upload
|
||||
v-model:file-list="form.assessUrl"
|
||||
ref="uploadRef"
|
||||
action=""
|
||||
:accept="acceptType"
|
||||
:limit="1"
|
||||
:on-change="(file) => choose(file, 'assessUrl')"
|
||||
:auto-upload="false"
|
||||
:on-remove="removeFile('assessUrl')"
|
||||
>
|
||||
<template #trigger>
|
||||
<el-button type="primary">上传文件</el-button>
|
||||
</template>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
<el-form-item for="-" label="预测评估结论:" style="width: 100%">
|
||||
<el-input
|
||||
type="textarea"
|
||||
@@ -390,7 +432,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, reactive, defineExpose, defineProps, defineEmits, watch, onUnmounted } from 'vue'
|
||||
// import { upload, insertTerminal, updateTerminal } from '@/api/process-boot/terminal'
|
||||
import type { UploadInstance, UploadProps, UploadRawFile } from 'element-plus'
|
||||
import type { UploadFile, UploadInstance, UploadProps, UploadRawFile } from 'element-plus'
|
||||
import { genFileId, ElMessage } from 'element-plus'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import type { ComponentSize, FormInstance, FormRules } from 'element-plus'
|
||||
@@ -435,10 +477,11 @@ const props = defineProps({
|
||||
}
|
||||
})
|
||||
const emits = defineEmits(['onSubmit'])
|
||||
const IS_LN = import.meta.env.VITE_NAME == 'LN' || import.meta.env.VITE_NAME == 'LNqr'
|
||||
const dictData = useDictData()
|
||||
const dialogFormVisible = ref(false)
|
||||
// .doc,.docx,.xlsx,.xls,.pdf
|
||||
const acceptType = ''
|
||||
const acceptType = '.pdf,.docx'
|
||||
const form: any = ref({})
|
||||
const loading = ref(false)
|
||||
const control: any = ref(true)
|
||||
@@ -532,6 +575,10 @@ const defaultProps = {
|
||||
const nonlinearDeviceTypeList: any = ref('')
|
||||
//获取登陆用户姓名和部门
|
||||
const adminInfo = useAdminInfo()
|
||||
// 电能质量检测报告
|
||||
const checkUrlFile = ref('')
|
||||
// 电能质量评估报告
|
||||
const evaluationFile = ref('')
|
||||
const resetForm = () => {
|
||||
form.value = {
|
||||
reporter: '', //填报人 1
|
||||
@@ -558,6 +605,8 @@ const resetForm = () => {
|
||||
pccPoint: '', //PCC点 1
|
||||
evaluationType: evaluationTypeList[0].id, //评估类型 1
|
||||
evaluationChekDept: '', //预测评估审单位 1
|
||||
checkUrl: [], //电能质量检测报告
|
||||
assessUrl: [], //电能质量评估报告
|
||||
minShortCircuitCapacity: '', //系统最小短路容量(MVA) 1
|
||||
userAgreementCapacity: '', //用户用电协议容量(MVA) 1
|
||||
needGovernance: 0, //是否需要治理 1
|
||||
@@ -581,6 +630,8 @@ const resetForm = () => {
|
||||
delete form.value.loadLevel
|
||||
delete form.value.powerSupplyInfo
|
||||
}
|
||||
checkUrlFile.value = ''
|
||||
evaluationFile.value = ''
|
||||
}
|
||||
//初始化数据
|
||||
resetForm()
|
||||
@@ -694,7 +745,7 @@ const rules = ref({
|
||||
reporter: [{ required: true, message: '请输入填报人', trigger: 'blur' }],
|
||||
reportDate: [{ required: true, message: '请选择填报日期', trigger: 'change' }],
|
||||
orgId: [{ required: true, message: '请选择填报部门', trigger: 'change' }],
|
||||
stationId: [{ required: true, message: '请选择所属电站', trigger: 'change' }],
|
||||
//stationId: [{ required: true, message: '请选择所属电站', trigger: 'change' }],
|
||||
expectedProductionDate: [{ required: true, message: '请选择工程预期投产日期', trigger: 'change' }],
|
||||
userType: [{ required: true, message: '清选择用户性质', trigger: 'change' }],
|
||||
city: [{ required: true, message: '请选择所在地市', trigger: 'change' }],
|
||||
@@ -900,6 +951,10 @@ const open = async (row: any) => {
|
||||
} else {
|
||||
resendId.value = ''
|
||||
form.value.userType = userTypeList.value[0].value
|
||||
checkUrlFile.value = ''
|
||||
evaluationFile.value = ''
|
||||
form.value.checkUrl = []
|
||||
form.value.evaluation = []
|
||||
}
|
||||
await getSubstationSelect().then(res => {
|
||||
stationList.value = res.data
|
||||
@@ -917,18 +972,36 @@ async function handleResponse(data: any) {
|
||||
// userType logic is commented out; if needed, implement accordingly
|
||||
if (data.userReportProjectPO) {
|
||||
form.value = { ...data, ...data.userReportProjectPO }
|
||||
fileRaw(data, 'userReportProjectPO')
|
||||
} else if (data.userReportSubstationPO) {
|
||||
form.value = { ...data, ...data.userReportSubstationPO }
|
||||
fileRaw(data, 'userReportSubstationPO')
|
||||
} else if (data.userReportSensitivePO) {
|
||||
form.value = {
|
||||
...data,
|
||||
...data.userReportSensitivePO,
|
||||
energyQualityIndex: data.userReportSensitivePO.energyQualityIndex.split(', ')
|
||||
}
|
||||
fileRaw(data, 'userReportSensitivePO')
|
||||
}
|
||||
form.value.orgId = adminInfo.$state.deptName
|
||||
}
|
||||
|
||||
// 处理上传文件回显
|
||||
const fileRaw = (row: any, key: string) => {
|
||||
const fileFields = ['checkUrl', 'assessUrl']
|
||||
for (const field of fileFields) {
|
||||
const filePath = row[key]?.[field] ?? row[field]
|
||||
if (filePath != null && filePath.length > 0) {
|
||||
form.value[field] = [{ name: filePath.split('/')[2] }]
|
||||
} else {
|
||||
form.value[field] = []
|
||||
}
|
||||
}
|
||||
checkUrlFile.value = row[key]?.checkUrl ?? row.checkUrl ?? ''
|
||||
evaluationFile.value = row[key]?.assessUrl ?? row.assessUrl ?? ''
|
||||
}
|
||||
|
||||
const close = () => {
|
||||
//重置表单内容
|
||||
//取消表单校验状态
|
||||
@@ -947,14 +1020,25 @@ const handleExceed: UploadProps['onExceed'] = files => {
|
||||
file.uid = genFileId()
|
||||
uploadRef.value!.handleStart(file)
|
||||
}
|
||||
let uploadName = ref('')
|
||||
//上传报告字段名称
|
||||
const uploadFileName = (val: any) => {
|
||||
uploadName.value = val
|
||||
}
|
||||
//移除文件上传
|
||||
const removeFile = (file: any, uploadFiles: any) => {
|
||||
console.log(file, uploadFiles)
|
||||
const removeFile = (val: string) => {
|
||||
return (_file: UploadFile, fileList: UploadFile[]) => {
|
||||
if (val === 'checkUrl') {
|
||||
checkUrlFile.value = ''
|
||||
} else if (val === 'assessUrl') {
|
||||
evaluationFile.value = ''
|
||||
}
|
||||
form.value[val] = fileList
|
||||
}
|
||||
}
|
||||
const choose = (e: any, field: string) => {
|
||||
uploadFile(e.raw, '/supervision/').then(res => {
|
||||
if (field === 'checkUrl') {
|
||||
checkUrlFile.value = res.data.name
|
||||
} else if (field === 'assessUrl') {
|
||||
evaluationFile.value = res.data.name
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 关联终端
|
||||
@@ -981,12 +1065,16 @@ const confirmForm = async (flag: boolean) => {
|
||||
subForm.value.reporter = adminInfo.$state.id
|
||||
subForm.value.orgId = adminInfo.$state.deptId
|
||||
let confirmFormData = JSON.parse(JSON.stringify(subForm.value))
|
||||
confirmFormData.checkUrl = checkUrlFile.value
|
||||
confirmFormData.assessUrl = evaluationFile.value
|
||||
//1.判断是否上传
|
||||
if (subForm.value.userType == '0' || subForm.value.userType == '1') {
|
||||
{
|
||||
//其他报告非必填
|
||||
confirmFormData.userReportProjectPO = {
|
||||
...confirmFormData.userReportProjectPO
|
||||
...confirmFormData.userReportProjectPO,
|
||||
checkUrl: checkUrlFile.value,
|
||||
assessUrl: evaluationFile.value
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -999,7 +1087,9 @@ const confirmForm = async (flag: boolean) => {
|
||||
) {
|
||||
{
|
||||
confirmFormData.userReportSubstationPO = {
|
||||
...confirmFormData.userReportSubstationPO
|
||||
...confirmFormData.userReportSubstationPO,
|
||||
checkUrl: checkUrlFile.value,
|
||||
assessUrl: evaluationFile.value
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1008,7 +1098,9 @@ const confirmForm = async (flag: boolean) => {
|
||||
{
|
||||
confirmFormData.userReportSensitivePO = {
|
||||
...confirmFormData.userReportSensitivePO,
|
||||
energyQualityIndex: confirmFormData.userReportSensitivePO.energyQualityIndex.join(', ')
|
||||
energyQualityIndex: confirmFormData.userReportSensitivePO.energyQualityIndex.join(', '),
|
||||
checkUrl: checkUrlFile.value,
|
||||
assessUrl: evaluationFile.value
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1060,8 +1152,6 @@ const filterUsers = (arr: any) => {
|
||||
userTypeList.value = userTypeList.value.filter(item => !arr.includes(item.value))
|
||||
}
|
||||
const setcontroFlag = () => {
|
||||
|
||||
|
||||
controFlag.value = true
|
||||
}
|
||||
defineExpose({ open, filterUsers, setcontroFlag })
|
||||
|
||||
@@ -212,12 +212,21 @@
|
||||
})?.name
|
||||
}}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="敏感电能质量指标" v-if="detailData.userType == 6">
|
||||
{{
|
||||
energyQualityIndexList.find(item => {
|
||||
return item.id == proviteData.energyQualityIndex
|
||||
})?.name
|
||||
}}
|
||||
<el-descriptions-item :span="2" label="电能质量设备检测报告">
|
||||
<el-icon class="elView" v-if="detailData?.checkUrl">
|
||||
<View @click="openFile(detailData?.checkUrl)" />
|
||||
</el-icon>
|
||||
<span class="aLoad" @click="download(detailData.checkUrl)" target="_blank">
|
||||
{{ detailData.checkUrl?.replace(/^.*?\/(.*?)\//, '') || '' }}
|
||||
</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span="2" label="电能质量评估报告">
|
||||
<el-icon class="elView" v-if="detailData?.assessUrl">
|
||||
<View @click="openFile(detailData?.assessUrl)" />
|
||||
</el-icon>
|
||||
<span class="aLoad" @click="download(detailData.assessUrl)" target="_blank">
|
||||
{{ detailData.assessUrl?.replace(/^.*?\/(.*?)\//, '') || '' }}
|
||||
</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
@@ -233,7 +242,7 @@ import { getDictTreeById } from '@/api/system-boot/dictTree'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import { getFileNameAndFilePath } from '@/api/system-boot/file'
|
||||
import { Link, View } from '@element-plus/icons-vue'
|
||||
import PreviewFile from '@/components/PreviewFile/index.vue'
|
||||
import { download } from '@/utils/fileDownLoad'
|
||||
// import { addOrUpdateFile, getFileById } from '@/api/supervision-boot/interfere/index'
|
||||
defineOptions({ name: 'BpmUserReportDetail' })
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader ref="TableHeaderRef">
|
||||
<TableHeader ref="TableHeaderRef" showExport showCustomColumn>
|
||||
<template #select>
|
||||
<el-form-item label="项目名称">
|
||||
<el-input
|
||||
@@ -32,7 +32,7 @@
|
||||
<el-button icon="el-icon-Upload" type="primary" @click="importUserData">批量导入</el-button> -->
|
||||
</template>
|
||||
</TableHeader>
|
||||
<Table ref="tableRef" />
|
||||
<Table ref="tableRef" @cell-click="cellClickEvent" />
|
||||
|
||||
<el-dialog title="详情" width="1000px" v-model="dialogShow" v-if="dialogShow">
|
||||
<DetailInfo :id="userId" :openType="'sourcesOfInterference'"></DetailInfo>
|
||||
@@ -45,7 +45,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, provide, nextTick, watch } from 'vue'
|
||||
import { ref, onMounted, reactive, provide, nextTick, watch, onUnmounted } from 'vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
@@ -58,6 +58,7 @@ import { downloadSensitiveReportTemplate } from '@/api/supervision-boot/userRepo
|
||||
import DetailInfo from './components/detail.vue'
|
||||
import { cancelFormData, getUserReportById } from '@/api/supervision-boot/interfere/index'
|
||||
import { deleteUserReport } from '@/api/device-boot/sensitiveLoadMange'
|
||||
import { download } from '@/utils/fileDownLoad'
|
||||
const addForms = ref()
|
||||
const dictData = useDictData()
|
||||
const sensitiveUserPopup = ref()
|
||||
@@ -88,13 +89,13 @@ const tableStore = new TableStore({
|
||||
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
|
||||
}
|
||||
},
|
||||
{ field: 'city', title: '所在地市', minWidth: 80 },
|
||||
{ field: 'substation', title: '厂站名称', minWidth: 100 },
|
||||
{ field: 'projectName', title: '项目名称', minWidth: 170 },
|
||||
{ field: 'city', title: '所在地市', minWidth: 100 },
|
||||
/* { field: 'substation', title: '厂站名称', minWidth: 100 },*/
|
||||
{ field: 'projectName', title: '项目名称', minWidth: 150 },
|
||||
{
|
||||
field: 'userType',
|
||||
title: '用户性质',
|
||||
minWidth: 150,
|
||||
minWidth: 180,
|
||||
formatter: (obj: any) => {
|
||||
const userType = obj.row.userType
|
||||
return getUserTypeName(userType)
|
||||
@@ -102,19 +103,42 @@ const tableStore = new TableStore({
|
||||
},
|
||||
|
||||
// { field: 'responsibleDepartment', title: '归口管理部门', minWidth: 130 },
|
||||
{ field: 'ratePower', title: '装机容量(MW)', minWidth: 130 },
|
||||
{ field: 'ratePower', title: '装机容量(MW)', minWidth: 80 },
|
||||
{ field: 'stationId', title: '所属电站', minWidth: 150 },
|
||||
{
|
||||
field: 'checkUrl',
|
||||
title: '电能质量设备检测报告',
|
||||
minWidth: 160,
|
||||
render: 'customRender',
|
||||
customRender: props => {
|
||||
const val = props.renderValue?.replace(/^.*?\/(.*?)\//, '') || ''
|
||||
return val ? h('span', { style: { color: 'var(--el-color-primary)', cursor: 'pointer' } }, val) : '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'assessUrl',
|
||||
title: '电能质量评估报告',
|
||||
minWidth: 160,
|
||||
render: 'customRender',
|
||||
customRender: props => {
|
||||
const val = props.renderValue?.replace(/^.*?\/(.*?)\//, '') || ''
|
||||
return val ? h('span', { style: { color: 'var(--el-color-primary)', cursor: 'pointer' } }, val) : '/'
|
||||
}
|
||||
},
|
||||
|
||||
/* {
|
||||
field: 'createBy',
|
||||
title: '创建人',
|
||||
minWidth: 80,
|
||||
formatter: (row: any) => {
|
||||
return dictData.state.userList.filter(item => item.id == row.cellValue)[0]?.name
|
||||
}
|
||||
},
|
||||
},*/
|
||||
{
|
||||
title: '操作',fixed: 'right',
|
||||
title: '操作',
|
||||
fixed: 'right',
|
||||
minWidth: 150,
|
||||
|
||||
|
||||
render: 'buttons',
|
||||
buttons: [
|
||||
{
|
||||
@@ -137,7 +161,6 @@ const tableStore = new TableStore({
|
||||
disabled: row => {
|
||||
return !(row.status == 0)
|
||||
},
|
||||
|
||||
|
||||
click: row => {
|
||||
addForms.value.filterUsers([6])
|
||||
@@ -147,9 +170,7 @@ const tableStore = new TableStore({
|
||||
row: row
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -208,27 +229,13 @@ const deleteEven = () => {
|
||||
})
|
||||
}
|
||||
}
|
||||
/**取消流程操作*/
|
||||
const cancelLeave = async (row: any) => {
|
||||
// 二次确认
|
||||
const { value } = await ElMessageBox.prompt('请输入取消原因', '取消流程', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
inputType: 'textarea',
|
||||
inputPattern: /^[\s\S]*.*\S[\s\S]*$/, // 判断非空,且非空格
|
||||
inputErrorMessage: '取消原因不能为空'
|
||||
})
|
||||
// 发起取消
|
||||
let data = {
|
||||
id: row.id,
|
||||
processInstanceId: row.processInstanceId,
|
||||
dataType: 1,
|
||||
reason: value
|
||||
// 点击行
|
||||
const cellClickEvent = ({ row, column }: any) => {
|
||||
if (column.field == 'checkUrl') {
|
||||
row.checkUrl ? download(row.checkUrl) : ''
|
||||
} else if (column.field == 'assessUrl') {
|
||||
row.assessUrl ? download(row.assessUrl) : ''
|
||||
}
|
||||
await cancelFormData(data)
|
||||
ElMessage.success('取消成功')
|
||||
// 加载数据
|
||||
tableStore.index()
|
||||
}
|
||||
|
||||
// 新增
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader date-picker>
|
||||
<TableHeader date-picker showCustomColumn>
|
||||
<template v-slot:select>
|
||||
<!-- <el-form-item label="用户名">
|
||||
<el-select v-model="value" class="m-2" placeholder="Select" size="large">
|
||||
@@ -33,14 +33,22 @@ const tableStore = new TableStore({
|
||||
url: '/system-boot/audit/getAuditLog',
|
||||
method: 'POST',
|
||||
column: [
|
||||
{ title: '操作时间', field: 'time', align: 'center', width: 200 },
|
||||
{ title: '操作人员', field: 'userName', align: 'center', width: 120 },
|
||||
{ title: '操作类型', field: 'operate', align: 'center', width: 220 },
|
||||
{ title: '事件描述', field: 'describe', align: 'center', showOverflow: true,minWidth: 200 },
|
||||
{ title: '事件类型', field: 'type', align: 'center', width: 160 },
|
||||
{ title: '操作结果', field: 'type', align: 'center', width: 100 },
|
||||
{ title: '操作IP', field: 'ip', align: 'center', width: 120 },
|
||||
{ title: '事件等级', field: 'level', align: 'center', width: 100 }
|
||||
{
|
||||
title: '序号',
|
||||
field: 'index',
|
||||
minWidth: 80,
|
||||
formatter: (row: any) => {
|
||||
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
|
||||
}
|
||||
},
|
||||
{ title: '操作时间', field: 'time', align: 'center', minWidth: 200 },
|
||||
{ title: '操作人员', field: 'userName', align: 'center', minWidth: 120 },
|
||||
{ title: '操作类型', field: 'operate', align: 'center', minWidth: 220 },
|
||||
{ title: '事件描述', field: 'describe', align: 'center', minWidth: 200 },
|
||||
{ title: '事件类型', field: 'type', align: 'center', minWidth: 160 },
|
||||
{ title: '操作结果', field: 'type', align: 'center', minWidth: 100 },
|
||||
{ title: '操作IP', field: 'ip', align: 'center', minWidth: 120 },
|
||||
{ title: '事件等级', field: 'level', align: 'center', minWidth: 100 }
|
||||
]
|
||||
})
|
||||
tableStore.table.params.loginName = ''
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
</div>
|
||||
<el-collapse v-model="activeName" accordion>
|
||||
<!-- <el-collapse-item title="典型电能质量干扰源" name="1"></el-collapse-item> -->
|
||||
<el-collapse-item title="国家电网有限公司企业标准" name="2">
|
||||
<el-collapse-item title="电网有限公司企业标准" name="2">
|
||||
<!-- <el-empty description="暂无数据" class="custom-empty iframe" /> -->
|
||||
<div :style="`overflow: auto;`" class="iframe">
|
||||
<vue-office-docx v-if="urlKey.includes('.doc') || urlKey.includes('.docx')" :src="url" />
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<!-- 案例库 -->
|
||||
<TableHeader ref="TableHeaderRef">
|
||||
<template #select>
|
||||
<el-form-item label="名称">
|
||||
<el-form-item label="筛选数据">
|
||||
<el-input v-model="tableStore.table.params.searchValue" clearable placeholder="请输入搜索名称" maxlength="32" show-word-limit/>
|
||||
</el-form-item>
|
||||
|
||||
|
||||
@@ -2,32 +2,39 @@
|
||||
<div class="default-main" :style="height">
|
||||
<!-- 标准库 -->
|
||||
|
||||
<splitpanes style="height: 100%" class="default-theme" id="navigation-splitpanes">
|
||||
<splitpanes
|
||||
style="height: 100%"
|
||||
class="default-theme"
|
||||
id="navigation-splitpanes"
|
||||
@resize="onPaneResize"
|
||||
@resized="onPaneResized"
|
||||
>
|
||||
<pane :size="size">
|
||||
<standardTree ref="treeRef"
|
||||
:default-expanded-keys="monitoringPoint.state.lineId ? [monitoringPoint.state.lineId] : []"
|
||||
:current-node-key="monitoringPoint.state.lineId" @node-click="handleNodeClick"
|
||||
@init="handleNodeClick"></standardTree>
|
||||
</pane>
|
||||
<pane style="background: #fff" :style="height">
|
||||
<div class="pd10" style="display: flex; justify-content: end">
|
||||
<pane style="background: #fff" class="standard-pane">
|
||||
<div class="pd10 standard-pane__toolbar" style="display: flex; justify-content: end">
|
||||
<el-button icon="el-icon-Plus" type="primary" @click="addUser" v-if="information">新增</el-button>
|
||||
<el-button icon="el-icon-Edit" type="primary" @click="editUser" v-if="information">修改</el-button>
|
||||
<el-button icon="el-icon-Delete" type="primary" @click="deleteEven"
|
||||
v-if="information">删除</el-button>
|
||||
<el-button icon="el-icon-Download" type="primary" @click="download" v-if="flag">下载</el-button>
|
||||
</div>
|
||||
<el-empty v-if="url.length == 0" description="暂无数据" class="custom-empty"
|
||||
:style="`height: calc(${height.height} - 60px);`" />
|
||||
<div :style="`height: calc(${height.height} - 60px);overflow: auto;`" v-else>
|
||||
<vue-office-docx v-if="urlKey.includes('.doc') || urlKey.includes('.docx')" :src="url" />
|
||||
<vue-office-excel v-if="urlKey.includes('.xls') || urlKey.includes('.xlsx')" :src="url"
|
||||
:options="excelOptions" />
|
||||
<!-- <vue-office-pdf v-if="url.includes('.pdf')" :src="url"/> -->
|
||||
<iframe v-if="urlKey.includes('.pdf')" :src="url" style="width: 100%; height: 99%"></iframe>
|
||||
<img v-if="
|
||||
urlKey.includes('.png') || urlKey.includes('.jpg') || urlKey.includes('.gif') || urlKey.includes('.bmp')
|
||||
" :src="url" />
|
||||
<el-empty v-if="url.length == 0" description="暂无数据" class="custom-empty standard-pane__content" />
|
||||
<div v-else class="standard-pane__content">
|
||||
<div v-show="!isPaneResizing" class="standard-preview">
|
||||
<vue-office-docx v-if="urlKey.includes('.doc') || urlKey.includes('.docx')" :src="url" />
|
||||
<vue-office-excel v-if="urlKey.includes('.xls') || urlKey.includes('.xlsx')" :src="url"
|
||||
:options="excelOptions" />
|
||||
<!-- <vue-office-pdf v-if="url.includes('.pdf')" :src="url"/> -->
|
||||
<iframe v-if="urlKey.includes('.pdf')" :src="url" style="width: 100%; height: 100%"></iframe>
|
||||
<img v-if="
|
||||
urlKey.includes('.png') || urlKey.includes('.jpg') || urlKey.includes('.gif') || urlKey.includes('.bmp')
|
||||
" :src="url" />
|
||||
</div>
|
||||
</div>
|
||||
</pane>
|
||||
</splitpanes>
|
||||
@@ -70,7 +77,16 @@ const addTreeRef = ref()
|
||||
const url = ref('')
|
||||
const dotList: any = ref({})
|
||||
const flag: any = ref(false)
|
||||
const isPaneResizing = ref(false)
|
||||
const information = adminInfo.roleCode.includes('information_info')
|
||||
const onPaneResize = () => {
|
||||
isPaneResizing.value = true
|
||||
}
|
||||
const onPaneResized = () => {
|
||||
requestAnimationFrame(() => {
|
||||
isPaneResizing.value = false
|
||||
})
|
||||
}
|
||||
onMounted(() => {
|
||||
const dom = document.getElementById('navigation-splitpanes')
|
||||
if (dom) {
|
||||
@@ -79,7 +95,7 @@ onMounted(() => {
|
||||
})
|
||||
|
||||
const urlKey=ref('')
|
||||
const VITE_FLAG = import.meta.env.VITE_NAME == 'jibei'
|
||||
const VITE_FLAG = false//import.meta.env.VITE_NAME == 'jibei'
|
||||
const handleNodeClick = (data: any, node: any) => {
|
||||
// console.log("🚀 ~ handleNodeClick ~ data:", data)
|
||||
dotList.value = data
|
||||
@@ -166,6 +182,36 @@ const download = () => {
|
||||
background: #eaeef1;
|
||||
}
|
||||
|
||||
:deep(.splitpanes__pane) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.standard-pane {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.standard-pane__toolbar {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.standard-pane__content {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.standard-preview {
|
||||
height: 99%;
|
||||
min-height: 99%;
|
||||
}
|
||||
|
||||
:deep(.splitpanes--dragging) .standard-preview {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.grid-content {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<!-- 模版 -->
|
||||
<TableHeader ref="TableHeaderRef" >
|
||||
<template #select>
|
||||
<el-form-item label="名称">
|
||||
<el-form-item label="筛选数据">
|
||||
<el-input v-model="tableStore.table.params.searchValue" clearable
|
||||
placeholder="请输入搜索名称" maxlength="32" show-word-limit/>
|
||||
</el-form-item>
|
||||
|
||||
@@ -1,274 +1,289 @@
|
||||
<template>
|
||||
<div class="default-main online">
|
||||
<div class="online_header">
|
||||
<TableHeader date-picker area ref="tableHeaderRef">
|
||||
<template #select>
|
||||
<el-form-item label="统计类型:">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.statisticalType"
|
||||
placeholder="请选择统计类型"
|
||||
value-key="id"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in classificationData"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="电压等级:">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.scale"
|
||||
multiple
|
||||
collapse-tags
|
||||
clearable
|
||||
placeholder="请选择电压等级"
|
||||
style="width: 100%"
|
||||
value-key="id"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in voltageleveloption"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="电网标识">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.powerFlag"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
placeholder="请选择电网标识"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in powerFlagList"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.algoDescribe"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="终端厂家:">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.manufacturer"
|
||||
multiple
|
||||
collapse-tags
|
||||
clearable
|
||||
placeholder="请选择终端厂家"
|
||||
style="width: 100%"
|
||||
value-key="id"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, index) in terminaloption"
|
||||
:key="index"
|
||||
:label="item.name"
|
||||
:value="item"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="干扰源类型:">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.loadType"
|
||||
multiple
|
||||
collapse-tags
|
||||
clearable
|
||||
placeholder="请选择干扰源类型"
|
||||
style="width: 100%"
|
||||
value-key="id"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, index) in interfereoption"
|
||||
:key="index"
|
||||
:label="item.name"
|
||||
:value="item"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</TableHeader>
|
||||
</div>
|
||||
<div class="online_main">
|
||||
<el-tabs v-model="activeName" type="border-card" @tab-click="handleClick">
|
||||
<el-tab-pane :name="0" :lazy="true" label="稳态指标符合性占比表格">
|
||||
<Table
|
||||
ref="tableRef"
|
||||
:tree-config="{ transform: true, parentField: 'uPid', rowField: 'uId' }"
|
||||
:scroll-y="{ enabled: true }"
|
||||
v-if="activeName == 0"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :name="1" :lazy="true" label="稳态指标符合性占比图">
|
||||
<charts v-if="activeName == 1" ref="chartsRef" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, watch } from 'vue'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import DatePicker from '@/components/form/datePicker/index.vue'
|
||||
import { getAreaDept } from '@/api/harmonic-boot/area'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import charts from './components/charts.vue'
|
||||
defineOptions({
|
||||
name: 'harmonic-boot/area/SteadyState'
|
||||
})
|
||||
const tableRef = ref()
|
||||
const onlineChartsRef = ref()
|
||||
const dictData = useDictData()
|
||||
//字典获取电压等级
|
||||
const voltageleveloption = dictData.getBasicData('Dev_Voltage_Stand')
|
||||
//字典获取终端厂家
|
||||
const terminaloption = dictData.getBasicData('Dev_Manufacturers')
|
||||
//字典获取干扰源类型
|
||||
const interfereoption = dictData.getBasicData('Interference_Source')
|
||||
//字典获取统计类型
|
||||
const classificationData = dictData.getBasicData('Statistical_Type', ['Report_Type'])
|
||||
//字典获取监督对象类型
|
||||
const powerFlagList = dictData.getBasicData('power_flag')
|
||||
//调用区域接口获取区域
|
||||
const treeData = ref([])
|
||||
const idArr = ref([])
|
||||
const activeName = ref(0)
|
||||
const getTreeData = async () => {
|
||||
await getAreaDept().then(res => {
|
||||
var data = res.data
|
||||
data.forEach(element => {
|
||||
idArr.value.push(element.id)
|
||||
})
|
||||
treeData.value = JSON.parse(JSON.stringify(res.data))
|
||||
})
|
||||
}
|
||||
getTreeData()
|
||||
|
||||
const chartsRef = ref()
|
||||
const handleClick = (tab: any, e: any) => {
|
||||
// console.log(tab,e,"??????????");
|
||||
// if(activeName.value===1){
|
||||
tableStore.index()
|
||||
// }
|
||||
}
|
||||
|
||||
// const datePickerRef = ref()
|
||||
const tableHeaderRef = ref()
|
||||
const tableStore = new TableStore({
|
||||
publicHeight: 60,
|
||||
showPage: false,
|
||||
url: '/harmonic-boot/steadyExceedRate/getSteadyExceedRateData',
|
||||
method: 'POST',
|
||||
column: [
|
||||
{
|
||||
title: '',
|
||||
field: 'name',
|
||||
align: 'left',
|
||||
treeNode: true,
|
||||
width: 350
|
||||
},
|
||||
{
|
||||
title: '电压等级',
|
||||
field: 'voltageLevel',
|
||||
|
||||
formatter: function (row) {
|
||||
return row.cellValue ? row.cellValue : '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '厂家',
|
||||
field: 'factoryName',
|
||||
|
||||
formatter: function (row) {
|
||||
return row.cellValue ? row.cellValue : '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '网络参数',
|
||||
field: 'networkParam',
|
||||
|
||||
formatter: function (row) {
|
||||
return row.cellValue ? row.cellValue : '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '监测点名称',
|
||||
field: 'lineName',
|
||||
|
||||
formatter: function (row) {
|
||||
return row.cellValue ? row.cellValue : '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '符合性占比(%)',
|
||||
field: 'steadyExceedRate',
|
||||
|
||||
formatter: function (row) {
|
||||
return row.cellValue == 3.14159 ? '暂无数据' : row.cellValue
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
loadCallback: () => {
|
||||
tableStore.table.data = tree2List(tableStore.table.data, Math.random() * 1000)
|
||||
tableStore.table.column[0].title = tableStore.table.params.statisticalType.name
|
||||
|
||||
chartsRef.value && chartsRef.value.getTableStoreParams(tableStore.table.params)
|
||||
setTimeout(() => {
|
||||
activeName.value == 0 && tableRef.value && tableRef.value.getRef().setAllTreeExpand(true)
|
||||
}, 0)
|
||||
}
|
||||
})
|
||||
|
||||
tableStore.table.params.statisticalType = classificationData[0]
|
||||
tableStore.table.params.scale = []
|
||||
tableStore.table.params.manufacturer = []
|
||||
tableStore.table.params.loadType = []
|
||||
tableStore.table.params.powerFlag = 2
|
||||
tableStore.table.params.serverName = 'harmonicBoot'
|
||||
provide('tableStore', tableStore)
|
||||
const tree2List = (list: any, id?: string) => {
|
||||
//存储结果的数组
|
||||
let arr: any = []
|
||||
// 遍历 tree 数组
|
||||
list.forEach((item: any) => {
|
||||
item.uPid = id
|
||||
item.uId = Math.random() * 1000
|
||||
item.valueOver == 3.14159 ? 0 : item.valueOver >= 90 ? 1 : item.valueOver && item.valueOver < 90 ? 2 : 3
|
||||
// 判断item是否存在children
|
||||
if (!item.children) return arr.push(item)
|
||||
// 函数递归,对children数组进行tree2List的转换
|
||||
const children = tree2List(item.children, item.uId)
|
||||
// 删除item的children属性
|
||||
delete item.children
|
||||
// 把item和children数组添加至结果数组
|
||||
//..children: 意思是把children数组展开
|
||||
arr.push(item, ...children)
|
||||
})
|
||||
// 返回结果数组
|
||||
return arr
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
// .online {
|
||||
// width: 100%;
|
||||
// height: 100%;
|
||||
// .online_header {
|
||||
// width: 100%;
|
||||
// max-height: 140px;
|
||||
// padding: 10px;
|
||||
// box-sizing: border-box;
|
||||
// }
|
||||
// .online_main {
|
||||
// padding: 0 10px;
|
||||
// }
|
||||
// }
|
||||
</style>
|
||||
<template>
|
||||
<div class="default-main online">
|
||||
<div class="online_header">
|
||||
<TableHeader date-picker area ref="tableHeaderRef">
|
||||
<template #select>
|
||||
<el-form-item label="统计类型">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.statisticalType"
|
||||
placeholder="请选择统计类型"
|
||||
value-key="id"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in classificationData"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="电压等级">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.scale"
|
||||
multiple
|
||||
collapse-tags
|
||||
clearable
|
||||
placeholder="请选择电压等级"
|
||||
style="width: 100%"
|
||||
value-key="id"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in voltageleveloption"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="电网标识">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.powerFlag"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
placeholder="请选择电网标识"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in powerFlagList"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.algoDescribe"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="终端厂家">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.manufacturer"
|
||||
multiple
|
||||
collapse-tags
|
||||
clearable
|
||||
placeholder="请选择终端厂家"
|
||||
style="width: 100%"
|
||||
value-key="id"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, index) in terminaloption"
|
||||
:key="index"
|
||||
:label="item.name"
|
||||
:value="item"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="干扰源类型:">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.loadType"
|
||||
multiple
|
||||
collapse-tags
|
||||
clearable
|
||||
placeholder="请选择干扰源类型"
|
||||
style="width: 100%"
|
||||
value-key="id"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, index) in interfereoption"
|
||||
:key="index"
|
||||
:label="item.name"
|
||||
:value="item"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="筛选数据">
|
||||
<el-input
|
||||
v-model.trim="tableStore.table.params.searchValue"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
placeholder="请输入关键字筛选"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</TableHeader>
|
||||
</div>
|
||||
<div class="online_main">
|
||||
<el-tabs v-model="activeName" type="border-card" @tab-click="handleClick">
|
||||
<el-tab-pane :name="0" :lazy="true" label="稳态指标符合性占比表格">
|
||||
<Table
|
||||
ref="tableRef"
|
||||
:tree-config="{ transform: true, parentField: 'uPid', rowField: 'uId' }"
|
||||
:scroll-y="{ enabled: true }"
|
||||
v-if="activeName == 0"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :name="1" :lazy="true" label="稳态指标符合性占比图">
|
||||
<charts v-if="activeName == 1" ref="chartsRef" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, watch } from 'vue'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import DatePicker from '@/components/form/datePicker/index.vue'
|
||||
import { getAreaDept } from '@/api/harmonic-boot/area'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import charts from './components/charts.vue'
|
||||
import { filterTree } from '@/utils/tree'
|
||||
defineOptions({
|
||||
name: 'harmonic-boot/area/SteadyState'
|
||||
})
|
||||
const tableRef = ref()
|
||||
const onlineChartsRef = ref()
|
||||
const dictData = useDictData()
|
||||
//字典获取电压等级
|
||||
const voltageleveloption = dictData.getBasicData('Dev_Voltage_Stand')
|
||||
//字典获取终端厂家
|
||||
const terminaloption = dictData.getBasicData('Dev_Manufacturers')
|
||||
//字典获取干扰源类型
|
||||
const interfereoption = dictData.getBasicData('Interference_Source')
|
||||
//字典获取统计类型
|
||||
const classificationData = dictData.getBasicData('Statistical_Type', ['Report_Type'])
|
||||
//字典获取监督对象类型
|
||||
const powerFlagList = dictData.getBasicData('power_flag')
|
||||
//调用区域接口获取区域
|
||||
const treeData = ref([])
|
||||
const idArr = ref([])
|
||||
const activeName = ref(0)
|
||||
const getTreeData = async () => {
|
||||
await getAreaDept().then(res => {
|
||||
var data = res.data
|
||||
data.forEach(element => {
|
||||
idArr.value.push(element.id)
|
||||
})
|
||||
treeData.value = JSON.parse(JSON.stringify(res.data))
|
||||
})
|
||||
}
|
||||
getTreeData()
|
||||
|
||||
const chartsRef = ref()
|
||||
const handleClick = (tab: any, e: any) => {
|
||||
// console.log(tab,e,"??????????");
|
||||
// if(activeName.value===1){
|
||||
tableStore.index()
|
||||
// }
|
||||
}
|
||||
|
||||
// const datePickerRef = ref()
|
||||
const tableHeaderRef = ref()
|
||||
const tableStore = new TableStore({
|
||||
publicHeight: 60,
|
||||
showPage: false,
|
||||
url: '/harmonic-boot/steadyExceedRate/getSteadyExceedRateData',
|
||||
method: 'POST',
|
||||
column: [
|
||||
{
|
||||
title: '',
|
||||
field: 'name',
|
||||
align: 'left',
|
||||
treeNode: true,
|
||||
width: 350
|
||||
},
|
||||
{
|
||||
title: '电压等级',
|
||||
field: 'voltageLevel',
|
||||
|
||||
formatter: function (row) {
|
||||
return row.cellValue ? row.cellValue : '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '厂家',
|
||||
field: 'factoryName',
|
||||
|
||||
formatter: function (row) {
|
||||
return row.cellValue ? row.cellValue : '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '网络参数',
|
||||
field: 'networkParam',
|
||||
|
||||
formatter: function (row) {
|
||||
return row.cellValue ? row.cellValue : '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '监测点名称',
|
||||
field: 'lineName',
|
||||
|
||||
formatter: function (row) {
|
||||
return row.cellValue ? row.cellValue : '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '符合性占比(%)',
|
||||
field: 'steadyExceedRate',
|
||||
|
||||
formatter: function (row) {
|
||||
return row.cellValue == 3.14159 ? '暂无数据' : row.cellValue
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
loadCallback: () => {
|
||||
tableStore.table.data = tree2List(
|
||||
filterTree(tableStore.table.data, node => {
|
||||
return node.name.includes(tableStore.table.params.searchValue)
|
||||
}),
|
||||
Math.random() * 1000
|
||||
)
|
||||
tableStore.table.column[0].title = tableStore.table.params.statisticalType.name
|
||||
|
||||
chartsRef.value && chartsRef.value.getTableStoreParams(tableStore.table.params)
|
||||
setTimeout(() => {
|
||||
activeName.value == 0 && tableRef.value && tableRef.value.getRef().setAllTreeExpand(true)
|
||||
}, 0)
|
||||
}
|
||||
})
|
||||
|
||||
tableStore.table.params.statisticalType = classificationData[0]
|
||||
tableStore.table.params.scale = []
|
||||
tableStore.table.params.manufacturer = []
|
||||
tableStore.table.params.loadType = []
|
||||
tableStore.table.params.powerFlag = 2
|
||||
tableStore.table.params.serverName = 'harmonicBoot'
|
||||
tableStore.table.params.searchValue = ''
|
||||
provide('tableStore', tableStore)
|
||||
const tree2List = (list: any, id?: string) => {
|
||||
//存储结果的数组
|
||||
let arr: any = []
|
||||
// 遍历 tree 数组
|
||||
list.forEach((item: any) => {
|
||||
item.uPid = id
|
||||
item.uId = Math.random() * 1000
|
||||
item.valueOver == 3.14159 ? 0 : item.valueOver >= 90 ? 1 : item.valueOver && item.valueOver < 90 ? 2 : 3
|
||||
// 判断item是否存在children
|
||||
if (!item.children) return arr.push(item)
|
||||
// 函数递归,对children数组进行tree2List的转换
|
||||
const children = tree2List(item.children, item.uId)
|
||||
// 删除item的children属性
|
||||
delete item.children
|
||||
// 把item和children数组添加至结果数组
|
||||
//..children: 意思是把children数组展开
|
||||
arr.push(item, ...children)
|
||||
})
|
||||
// 返回结果数组
|
||||
return arr
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
// .online {
|
||||
// width: 100%;
|
||||
// height: 100%;
|
||||
// .online_header {
|
||||
// width: 100%;
|
||||
// max-height: 140px;
|
||||
// padding: 10px;
|
||||
// box-sizing: border-box;
|
||||
// }
|
||||
// .online_main {
|
||||
// padding: 0 10px;
|
||||
// }
|
||||
// }
|
||||
</style>
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<div v-show="view">
|
||||
<TableHeader datePicker area showExport>
|
||||
<TableHeader datePicker area showExport showCustomColumn>
|
||||
<template #select>
|
||||
<el-form-item label="筛选数据">
|
||||
<el-input v-model="tableStore.table.params.searchValue" placeholder="输入关键字筛选" clearable maxlength="32" show-word-limit/>
|
||||
<el-input
|
||||
v-model="tableStore.table.params.searchValue"
|
||||
placeholder="输入关键字筛选"
|
||||
clearable
|
||||
maxlength="32"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="统计类型:">
|
||||
<el-form-item label="统计类型">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.statisticalType"
|
||||
value-key="id"
|
||||
@@ -21,7 +27,7 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="电压等级:">
|
||||
<el-form-item label="电压等级">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.scale"
|
||||
multiple
|
||||
@@ -38,7 +44,7 @@
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="终端厂家:">
|
||||
<el-form-item label="终端厂家">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.manufacturer"
|
||||
multiple
|
||||
@@ -55,7 +61,7 @@
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="干扰源类型:">
|
||||
<el-form-item label="干扰源类型">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.loadType"
|
||||
multiple
|
||||
@@ -127,7 +133,7 @@ const tableStore = new TableStore({
|
||||
{ field: 'lineName', title: '监测点名称', minWidth: '180' },
|
||||
{ field: 'gdName', title: '供电公司', minWidth: '120' },
|
||||
{ field: 'subName', title: '变电站', minWidth: '150' },
|
||||
{ field: 'ip', title: '网络参数' ,width:'120px' },
|
||||
{ field: 'ip', title: '网络参数', width: '120px' },
|
||||
{ field: 'scale', title: '电压等级', minWidth: '110' },
|
||||
{
|
||||
field: 'advanceType',
|
||||
@@ -137,7 +143,7 @@ const tableStore = new TableStore({
|
||||
return row.cellValue || '其他'
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
field: 'eventType',
|
||||
title: '触发类型',
|
||||
minWidth: '120',
|
||||
@@ -153,7 +159,7 @@ const tableStore = new TableStore({
|
||||
return row.cellValue || '其他'
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// {
|
||||
// field: 'severity', title: '严重度', minWidth: "80", formatter: (row: any) => {
|
||||
// return row.cellValue.toFixed(2)
|
||||
@@ -180,7 +186,8 @@ const tableStore = new TableStore({
|
||||
{ field: 'duration', title: '持续时间(s)', minWidth: '100' },
|
||||
|
||||
{
|
||||
title: '操作',fixed: 'right',
|
||||
title: '操作',
|
||||
fixed: 'right',
|
||||
width: '120',
|
||||
render: 'buttons',
|
||||
buttons: [
|
||||
@@ -278,6 +285,7 @@ const download = () => {
|
||||
document.body.appendChild(link)
|
||||
link.click() //执行下载
|
||||
document.body.removeChild(link) //释放标签
|
||||
ElMessage.success('波形下载成功')
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
<template>
|
||||
<div class="default-main online">
|
||||
|
||||
<div class="online_header">
|
||||
<TableHeader date-picker ref="tableHeaderRef">
|
||||
<TableHeader date-picker ref="tableHeaderRef" showCustomColumn>
|
||||
<template #select>
|
||||
<el-form-item label="统计类型:">
|
||||
<el-form-item label="统计类型">
|
||||
<el-select v-model="formData.statisticalType" placeholder="请选择统计类型" value-key="id"
|
||||
style="width: 100%">
|
||||
<el-option v-for="item in classificationData" :key="item.id" :label="item.name"
|
||||
:value="item"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="区域选择:">
|
||||
<el-form-item label="区域选择">
|
||||
<!-- <el-select ref="select1" v-model="deptName" placeholder="请选择所属部门区域" style="width: 100%">
|
||||
<el-option :value="formData.deptIndex" style="height: auto"> -->
|
||||
<!-- {{ formData.deptIndex }} -->
|
||||
@@ -33,29 +34,38 @@
|
||||
<!-- </el-option>
|
||||
</el-select> -->
|
||||
</el-form-item>
|
||||
<el-form-item label="电压等级:">
|
||||
<el-form-item label="电压等级">
|
||||
<el-select v-model="formData.scale" multiple collapse-tags clearable placeholder="请选择电压等级"
|
||||
style="width: 100%" value-key="id">
|
||||
<el-option v-for="item in voltageleveloption" :key="item.id" :label="item.name"
|
||||
:value="item"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="终端厂家:">
|
||||
<el-form-item label="终端厂家">
|
||||
<el-select v-model="formData.manufacturer" multiple collapse-tags clearable
|
||||
placeholder="请选择终端厂家" style="width: 100%" value-key="id">
|
||||
<el-option v-for="(item, index) in terminaloption" :key="index" :label="item.name"
|
||||
:value="item"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="干扰源类型:">
|
||||
<el-form-item label="干扰源类型">
|
||||
<el-select v-model="formData.loadType" multiple collapse-tags clearable placeholder="请选择干扰源类型"
|
||||
style="width: 100%" value-key="id">
|
||||
<el-option v-for="(item, index) in interfereoption" :key="index" :label="item.name"
|
||||
:value="item"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="关键字筛选:">
|
||||
<el-input v-model="tableStore.table.params.searchValue" clearable placeholder="请输入关键字"></el-input>
|
||||
<el-form-item label="通讯状态">
|
||||
<el-select v-model="tableStore.table.params.comFlagStatus" clearable placeholder="请选择通讯状态"
|
||||
style="width: 100%">
|
||||
<el-option label="正常" value="1" />
|
||||
<el-option label="中断" value="0" />
|
||||
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="筛选数据">
|
||||
<el-input v-model="tableStore.table.params.searchValue" clearable
|
||||
placeholder="请输入关键字"></el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template #operation>
|
||||
@@ -77,9 +87,10 @@
|
||||
</div>
|
||||
<el-dialog v-model="timePopUp" draggable title="补招" width="500">
|
||||
补招时间:
|
||||
<el-date-picker v-model="timeData" type="datetimerange" format="YYYY-MM-DD HH:mm:00"
|
||||
value-format="YYYY-MM-DD HH:mm:00" range-separator="至" date-format="YYYY-MM-DD" time-format="HH:mm:00"
|
||||
start-placeholder="开始日期" end-placeholder="结束日期" style="width: 400px" :disabledDate="disabledDate" />
|
||||
<el-date-picker v-model="timeData" type="datetimerange" format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss" range-separator="至" date-format="YYYY-MM-DD" time-format="HH:mm:ss"
|
||||
start-placeholder="开始日期" end-placeholder="结束日期" style="width: 400px" :disabledDate="disabledDate"
|
||||
:default-time="defaultTimeRange" />
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="timePopUp = false">取消</el-button>
|
||||
@@ -139,6 +150,10 @@ const classificationData = dictData.getBasicData('Statistical_Type', ['Report_Ty
|
||||
const treeData = ref([])
|
||||
const idArr = ref([])
|
||||
const timeData = ref([])
|
||||
const defaultTimeRange: [Date, Date] = [
|
||||
new Date(2000, 0, 1, 0, 0, 0),
|
||||
new Date(2000, 0, 1, 23, 59, 59)
|
||||
]
|
||||
const logList: any = ref([])
|
||||
const activeName = ref(0)
|
||||
const getTreeData = async () => {
|
||||
@@ -198,7 +213,7 @@ const tableStore = new TableStore({
|
||||
{
|
||||
title: '网络参数',
|
||||
field: 'ip',
|
||||
align: 'center',width:'120px',
|
||||
align: 'center', width: '120px',
|
||||
formatter: function (row) {
|
||||
return row.cellValue ? row.cellValue : '/'
|
||||
}
|
||||
@@ -288,7 +303,7 @@ const tableStore = new TableStore({
|
||||
// tableStore.table.params.searchEndTime = tableHeaderRef.value.datePickerRef.timeValue[1]
|
||||
},
|
||||
loadCallback: () => {
|
||||
tableStore.table.data = tree2List(filterTreeByKeyword( tableStore.table.data,tableStore.table.params.searchValue), Math.random() * 1000)
|
||||
tableStore.table.data = tree2List(filterTreeByKeyword(tableStore.table.data, tableStore.table.params.searchValue), Math.random() * 1000)
|
||||
tableStore.table.column[0].title = formData.value.statisticalType.name
|
||||
|
||||
chartsRef.value && chartsRef.value.getTableStoreParams(tableStore.table.params)
|
||||
@@ -313,6 +328,7 @@ tableStore.table.params.statisticalType = []
|
||||
tableStore.table.params.scale = []
|
||||
tableStore.table.params.manufacturer = []
|
||||
tableStore.table.params.loadType = []
|
||||
tableStore.table.params.comFlagStatus = ''
|
||||
provide('tableStore', tableStore)
|
||||
const tree2List = (list: any, id?: string) => {
|
||||
//存储结果的数组
|
||||
@@ -353,65 +369,65 @@ const tree2List = (list: any, id?: string) => {
|
||||
* @returns {Array} 筛选后的嵌套树形数据,保持原层级
|
||||
*/
|
||||
function filterTreeByKeyword(treeData, keyword) {
|
||||
// 关键词为空,直接返回原树(深拷贝,避免修改原数据)
|
||||
if (!keyword || keyword.trim() === '') {
|
||||
return JSON.parse(JSON.stringify(treeData));
|
||||
}
|
||||
const targetKey = keyword.trim();
|
||||
// 存储需要保留的节点ID(匹配节点+所有上级+所有下级)
|
||||
const keepIdSet = new Set();
|
||||
// 关键词为空,直接返回原树(深拷贝,避免修改原数据)
|
||||
if (!keyword || keyword.trim() === '') {
|
||||
return JSON.parse(JSON.stringify(treeData));
|
||||
}
|
||||
const targetKey = keyword.trim();
|
||||
// 存储需要保留的节点ID(匹配节点+所有上级+所有下级)
|
||||
const keepIdSet = new Set();
|
||||
|
||||
// 第一步:递归遍历树形,标记所有需要保留的节点ID
|
||||
const markKeepNodes = (node, parentNodes = []) => {
|
||||
// 1. 若当前节点名称包含关键词,标记自身+所有上级+所有下级
|
||||
const isMatch = node.name && node.name.includes(targetKey);
|
||||
if (isMatch) {
|
||||
// 标记自身
|
||||
keepIdSet.add(node.id);
|
||||
// 标记所有上级父节点
|
||||
parentNodes.forEach(pNode => keepIdSet.add(pNode.id));
|
||||
// 标记所有下级子节点(递归)
|
||||
const markChildren = (childNode) => {
|
||||
keepIdSet.add(childNode.id);
|
||||
if (childNode.children && childNode.children.length) {
|
||||
childNode.children.forEach(markChildren);
|
||||
// 第一步:递归遍历树形,标记所有需要保留的节点ID
|
||||
const markKeepNodes = (node, parentNodes = []) => {
|
||||
// 1. 若当前节点名称包含关键词,标记自身+所有上级+所有下级
|
||||
const isMatch = node.name && node.name.includes(targetKey);
|
||||
if (isMatch) {
|
||||
// 标记自身
|
||||
keepIdSet.add(node.id);
|
||||
// 标记所有上级父节点
|
||||
parentNodes.forEach(pNode => keepIdSet.add(pNode.id));
|
||||
// 标记所有下级子节点(递归)
|
||||
const markChildren = (childNode) => {
|
||||
keepIdSet.add(childNode.id);
|
||||
if (childNode.children && childNode.children.length) {
|
||||
childNode.children.forEach(markChildren);
|
||||
}
|
||||
};
|
||||
if (node.children && node.children.length) {
|
||||
node.children.forEach(markChildren);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (node.children && node.children.length) {
|
||||
node.children.forEach(markChildren);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 递归遍历子节点,传递当前节点的上级链(parentNodes + 当前节点)
|
||||
if (node.children && node.children.length) {
|
||||
node.children.forEach(child => markKeepNodes(child, [...parentNodes, node]));
|
||||
}
|
||||
};
|
||||
// 2. 递归遍历子节点,传递当前节点的上级链(parentNodes + 当前节点)
|
||||
if (node.children && node.children.length) {
|
||||
node.children.forEach(child => markKeepNodes(child, [...parentNodes, node]));
|
||||
}
|
||||
};
|
||||
|
||||
// 遍历根节点,开始标记
|
||||
treeData.forEach(rootNode => markKeepNodes(rootNode));
|
||||
// 遍历根节点,开始标记
|
||||
treeData.forEach(rootNode => markKeepNodes(rootNode));
|
||||
|
||||
// 第二步:递归重构树形,只保留标记过的节点,保持层级
|
||||
const rebuildTree = (node) => {
|
||||
// 若当前节点无需保留,直接返回null
|
||||
if (!keepIdSet.has(node.id)) {
|
||||
return null;
|
||||
}
|
||||
// 深拷贝当前节点,避免修改原数据
|
||||
const newNode = { ...node };
|
||||
// 递归处理子节点,过滤掉无需保留的,只保留有效子节点
|
||||
if (newNode.children && newNode.children.length) {
|
||||
const newChildren = newNode.children.map(child => rebuildTree(child)).filter(Boolean);
|
||||
newNode.children = newChildren;
|
||||
} else {
|
||||
newNode.children = [];
|
||||
}
|
||||
return newNode;
|
||||
};
|
||||
// 第二步:递归重构树形,只保留标记过的节点,保持层级
|
||||
const rebuildTree = (node) => {
|
||||
// 若当前节点无需保留,直接返回null
|
||||
if (!keepIdSet.has(node.id)) {
|
||||
return null;
|
||||
}
|
||||
// 深拷贝当前节点,避免修改原数据
|
||||
const newNode = { ...node };
|
||||
// 递归处理子节点,过滤掉无需保留的,只保留有效子节点
|
||||
if (newNode.children && newNode.children.length) {
|
||||
const newChildren = newNode.children.map(child => rebuildTree(child)).filter(Boolean);
|
||||
newNode.children = newChildren;
|
||||
} else {
|
||||
newNode.children = [];
|
||||
}
|
||||
return newNode;
|
||||
};
|
||||
|
||||
// 重构根节点,过滤掉null的根节点
|
||||
const filteredTree = treeData.map(rootNode => rebuildTree(rootNode)).filter(Boolean);
|
||||
return filteredTree;
|
||||
// 重构根节点,过滤掉null的根节点
|
||||
const filteredTree = treeData.map(rootNode => rebuildTree(rootNode)).filter(Boolean);
|
||||
return filteredTree;
|
||||
}
|
||||
|
||||
|
||||
@@ -429,7 +445,7 @@ const makeUp = () => {
|
||||
.getCheckboxRecords()
|
||||
.filter((item: any) => item.level == '6') || []
|
||||
|
||||
|
||||
|
||||
|
||||
if (list.length == 0) {
|
||||
return ElMessage({
|
||||
@@ -468,24 +484,29 @@ const makeUpSubmit = () => {
|
||||
reCallStartTime: timeData.value[0]
|
||||
}
|
||||
|
||||
socket(form)
|
||||
timePopUp.value = false
|
||||
logPopUp.value = true
|
||||
setTimeout(() => {
|
||||
socket(form)
|
||||
timePopUp.value = false
|
||||
logPopUp.value = true
|
||||
}, 500)
|
||||
}
|
||||
const socket = async (form: any) => {
|
||||
const url = (localStorage.getItem('WebSocketUrl2') || 'ws://192.168.1.67:10405/api/recell/')
|
||||
const url = (localStorage.getItem('WebSocketUrl2') || 'null')//'ws://192.168.1.68:10405/api/recell/')
|
||||
logList.value = []
|
||||
await dataSocket.socketServe.connect(`${url}${adminInfo.id}`)
|
||||
await dataSocket.socketServe.send(form)
|
||||
setTimeout(() => {
|
||||
dataSocket.socketServe.send(form)
|
||||
}, 500)
|
||||
logList.value.push({
|
||||
type: '',
|
||||
time: formatDate(new Date(), 'YYYY-MM-DD hh:mm:ss'),
|
||||
time: formatDate(new Date(), 'YYYY-MM-DD HH:mm:ss'),
|
||||
name: '开始补召,请稍等...',
|
||||
})
|
||||
await dataSocket.socketServe.registerCallBack('message', (res: any) => {
|
||||
if (res.code == undefined) return
|
||||
logList.value.push({
|
||||
type: res.code == 500 ? 'error' : '',
|
||||
time: formatDate(new Date(), 'YYYY-MM-DD hh:mm:ss'),
|
||||
time: formatDate(new Date(), 'YYYY-MM-DD HH:mm:ss'),
|
||||
name: res.message
|
||||
})
|
||||
|
||||
|
||||
@@ -1,259 +1,275 @@
|
||||
<template>
|
||||
<div class="default-main online">
|
||||
<div class="online_header">
|
||||
<TableHeader date-picker area ref="tableHeaderRef">
|
||||
<template #select>
|
||||
<el-form-item label="统计类型:">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.statisticalType"
|
||||
placeholder="请选择统计类型"
|
||||
value-key="id"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in classificationData"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="电压等级:">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.scale"
|
||||
multiple
|
||||
collapse-tags
|
||||
clearable
|
||||
placeholder="请选择电压等级"
|
||||
style="width: 100%"
|
||||
value-key="id"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in voltageleveloption"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="终端厂家:">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.manufacturer"
|
||||
multiple
|
||||
collapse-tags
|
||||
clearable
|
||||
placeholder="请选择终端厂家"
|
||||
style="width: 100%"
|
||||
value-key="id"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, index) in terminaloption"
|
||||
:key="index"
|
||||
:label="item.name"
|
||||
:value="item"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="干扰源类型:">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.loadType"
|
||||
multiple
|
||||
collapse-tags
|
||||
clearable
|
||||
placeholder="请选择干扰源类型"
|
||||
style="width: 100%"
|
||||
value-key="id"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, index) in interfereoption"
|
||||
:key="index"
|
||||
:label="item.name"
|
||||
:value="item"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="电网标志">
|
||||
<el-select v-model="tableStore.table.params.powerFlag" placeholder="请选择电网标志">
|
||||
<el-option
|
||||
v-for="item in sign"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.algoDescribe"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</TableHeader>
|
||||
</div>
|
||||
<div class="online_main">
|
||||
<el-tabs v-model="activeName" type="border-card" @tab-click="handleClick">
|
||||
<el-tab-pane :name="0" :lazy="true" label="谐波畸变率统计表">
|
||||
<Table
|
||||
ref="tableRef"
|
||||
:tree-config="{ transform: true, parentField: 'uPid', rowField: 'uId' }"
|
||||
:scroll-y="{ enabled: true }"
|
||||
v-if="activeName == 0"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :name="1" :lazy="true" label="谐波畸变率统计图">
|
||||
<charts v-if="activeName == 1" ref="chartsRef" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, watch } from 'vue'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import DatePicker from '@/components/form/datePicker/index.vue'
|
||||
import { getAreaDept } from '@/api/harmonic-boot/area'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import charts from './components/charts.vue'
|
||||
defineOptions({
|
||||
name: 'harmonic-boot/area/harmonicDistortionRate'
|
||||
})
|
||||
const tableRef = ref()
|
||||
const onlineChartsRef = ref()
|
||||
const dictData = useDictData()
|
||||
//字典获取电压等级
|
||||
const voltageleveloption = dictData.getBasicData('Dev_Voltage_Stand')
|
||||
//字典获取终端厂家
|
||||
const terminaloption = dictData.getBasicData('Dev_Manufacturers')
|
||||
//字典获取干扰源类型
|
||||
const interfereoption = dictData.getBasicData('Interference_Source')
|
||||
//字典获取统计类型
|
||||
const classificationData = dictData.getBasicData('Statistical_Type', ['Report_Type'])
|
||||
//调用区域接口获取区域
|
||||
const sign = dictData.getBasicData('power_flag')
|
||||
const treeData = ref([])
|
||||
const idArr = ref([])
|
||||
const activeName = ref(0)
|
||||
const getTreeData = async () => {
|
||||
await getAreaDept().then(res => {
|
||||
var data = res.data
|
||||
data.forEach(element => {
|
||||
idArr.value.push(element.id)
|
||||
})
|
||||
treeData.value = JSON.parse(JSON.stringify(res.data))
|
||||
})
|
||||
}
|
||||
getTreeData()
|
||||
|
||||
const chartsRef = ref()
|
||||
const handleClick = (tab: any, e: any) => {
|
||||
// console.log(tab,e,"??????????");
|
||||
// if(activeName.value===1){
|
||||
tableStore.index()
|
||||
// }
|
||||
}
|
||||
|
||||
// const datePickerRef = ref()
|
||||
const tableHeaderRef = ref()
|
||||
const tableStore = new TableStore({
|
||||
publicHeight: 60,
|
||||
showPage: false,
|
||||
url: '/harmonic-boot/tHDistortion/getTHDistortionData',
|
||||
method: 'POST',
|
||||
column: [
|
||||
{
|
||||
title: '',
|
||||
field: 'name',
|
||||
align: 'left',
|
||||
treeNode: true,
|
||||
width: 350
|
||||
},
|
||||
{
|
||||
title: '电压等级',
|
||||
field: 'voltageLevel',
|
||||
align: 'center',
|
||||
formatter: function (row) {
|
||||
return row.cellValue ? row.cellValue : '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '网络参数',
|
||||
field: 'networkParam',
|
||||
align: 'center',
|
||||
formatter: function (row) {
|
||||
return row.cellValue ? row.cellValue : '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '监测点名称',
|
||||
field: 'lineName',
|
||||
align: 'center',
|
||||
formatter: function (row) {
|
||||
return row.cellValue ? row.cellValue : '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '总谐波畸变率(%)',
|
||||
field: 'distortion',
|
||||
align: 'center',
|
||||
formatter: function (row) {
|
||||
return row.cellValue == 3.14159 ? '暂无数据' : row.cellValue
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
loadCallback: () => {
|
||||
tableStore.table.data = tree2List(tableStore.table.data, Math.random() * 1000)
|
||||
tableStore.table.column[0].title = tableStore.table.params.statisticalType.name
|
||||
chartsRef.value && chartsRef.value.getTableStoreParams(tableStore.table.params)
|
||||
setTimeout(() => {
|
||||
activeName.value == 0 && tableRef.value && tableRef.value.getRef().setAllTreeExpand(true)
|
||||
}, 0)
|
||||
}
|
||||
})
|
||||
|
||||
tableStore.table.params.statisticalType = classificationData[0]
|
||||
tableStore.table.params.scale = []
|
||||
tableStore.table.params.manufacturer = []
|
||||
tableStore.table.params.loadType = []
|
||||
tableStore.table.params.powerFlag = sign[0]?.algoDescribe || 0
|
||||
tableStore.table.params.serverName = 'harmonicBoot'
|
||||
provide('tableStore', tableStore)
|
||||
const tree2List = (list: any, id?: string) => {
|
||||
//存储结果的数组
|
||||
let arr: any = []
|
||||
// 遍历 tree 数组
|
||||
list.forEach((item: any) => {
|
||||
item.uPid = id
|
||||
item.uId = Math.random() * 1000
|
||||
item.valueOver == 3.14159 ? 0 : item.valueOver >= 90 ? 1 : item.valueOver && item.valueOver < 90 ? 2 : 3
|
||||
// 判断item是否存在children
|
||||
if (!item.children) return arr.push(item)
|
||||
// 函数递归,对children数组进行tree2List的转换
|
||||
const children = tree2List(item.children, item.uId)
|
||||
// 删除item的children属性
|
||||
delete item.children
|
||||
// 把item和children数组添加至结果数组
|
||||
//..children: 意思是把children数组展开
|
||||
arr.push(item, ...children)
|
||||
})
|
||||
// 返回结果数组
|
||||
return arr
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
// .online {
|
||||
// width: 100%;
|
||||
// height: 100%;
|
||||
// .online_header {
|
||||
// width: 100%;
|
||||
// max-height: 140px;
|
||||
// padding: 10px;
|
||||
// box-sizing: border-box;
|
||||
// }
|
||||
// .online_main {
|
||||
// padding: 0 10px;
|
||||
// }
|
||||
// }
|
||||
</style>
|
||||
<template>
|
||||
<div class="default-main online">
|
||||
<div class="online_header">
|
||||
<TableHeader date-picker area ref="tableHeaderRef">
|
||||
<template #select>
|
||||
<el-form-item label="统计类型">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.statisticalType"
|
||||
placeholder="请选择统计类型"
|
||||
value-key="id"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in classificationData"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="电压等级">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.scale"
|
||||
multiple
|
||||
collapse-tags
|
||||
clearable
|
||||
placeholder="请选择电压等级"
|
||||
style="width: 100%"
|
||||
value-key="id"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in voltageleveloption"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="终端厂家">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.manufacturer"
|
||||
multiple
|
||||
collapse-tags
|
||||
clearable
|
||||
placeholder="请选择终端厂家"
|
||||
style="width: 100%"
|
||||
value-key="id"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, index) in terminaloption"
|
||||
:key="index"
|
||||
:label="item.name"
|
||||
:value="item"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="干扰源类型">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.loadType"
|
||||
multiple
|
||||
collapse-tags
|
||||
clearable
|
||||
placeholder="请选择干扰源类型"
|
||||
style="width: 100%"
|
||||
value-key="id"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, index) in interfereoption"
|
||||
:key="index"
|
||||
:label="item.name"
|
||||
:value="item"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="电网标志">
|
||||
<el-select v-model="tableStore.table.params.powerFlag" placeholder="请选择电网标志">
|
||||
<el-option
|
||||
v-for="item in sign"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.algoDescribe"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="筛选数据">
|
||||
<el-input
|
||||
v-model.trim="tableStore.table.params.searchValue"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
placeholder="请输入关键字筛选"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</TableHeader>
|
||||
</div>
|
||||
<div class="online_main">
|
||||
<el-tabs v-model="activeName" type="border-card" @tab-click="handleClick">
|
||||
<el-tab-pane :name="0" :lazy="true" label="谐波畸变率统计表">
|
||||
<Table
|
||||
ref="tableRef"
|
||||
:tree-config="{ transform: true, parentField: 'uPid', rowField: 'uId' }"
|
||||
:scroll-y="{ enabled: true }"
|
||||
v-if="activeName == 0"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :name="1" :lazy="true" label="谐波畸变率统计图">
|
||||
<charts v-if="activeName == 1" ref="chartsRef" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, watch } from 'vue'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import DatePicker from '@/components/form/datePicker/index.vue'
|
||||
import { getAreaDept } from '@/api/harmonic-boot/area'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import charts from './components/charts.vue'
|
||||
import { filterTree } from '@/utils/tree'
|
||||
defineOptions({
|
||||
name: 'harmonic-boot/area/harmonicDistortionRate'
|
||||
})
|
||||
const tableRef = ref()
|
||||
const onlineChartsRef = ref()
|
||||
const dictData = useDictData()
|
||||
//字典获取电压等级
|
||||
const voltageleveloption = dictData.getBasicData('Dev_Voltage_Stand')
|
||||
//字典获取终端厂家
|
||||
const terminaloption = dictData.getBasicData('Dev_Manufacturers')
|
||||
//字典获取干扰源类型
|
||||
const interfereoption = dictData.getBasicData('Interference_Source')
|
||||
//字典获取统计类型
|
||||
const classificationData = dictData.getBasicData('Statistical_Type', ['Report_Type'])
|
||||
//调用区域接口获取区域
|
||||
const sign = dictData.getBasicData('power_flag')
|
||||
const treeData = ref([])
|
||||
const idArr = ref([])
|
||||
const activeName = ref(0)
|
||||
const getTreeData = async () => {
|
||||
await getAreaDept().then(res => {
|
||||
var data = res.data
|
||||
data.forEach(element => {
|
||||
idArr.value.push(element.id)
|
||||
})
|
||||
treeData.value = JSON.parse(JSON.stringify(res.data))
|
||||
})
|
||||
}
|
||||
getTreeData()
|
||||
|
||||
const chartsRef = ref()
|
||||
const handleClick = (tab: any, e: any) => {
|
||||
// console.log(tab,e,"??????????");
|
||||
// if(activeName.value===1){
|
||||
tableStore.index()
|
||||
// }
|
||||
}
|
||||
|
||||
// const datePickerRef = ref()
|
||||
const tableHeaderRef = ref()
|
||||
const tableStore = new TableStore({
|
||||
publicHeight: 60,
|
||||
showPage: false,
|
||||
url: '/harmonic-boot/tHDistortion/getTHDistortionData',
|
||||
method: 'POST',
|
||||
column: [
|
||||
{
|
||||
title: '',
|
||||
field: 'name',
|
||||
align: 'left',
|
||||
treeNode: true,
|
||||
width: 350
|
||||
},
|
||||
{
|
||||
title: '电压等级',
|
||||
field: 'voltageLevel',
|
||||
align: 'center',
|
||||
formatter: function (row) {
|
||||
return row.cellValue ? row.cellValue : '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '网络参数',
|
||||
field: 'networkParam',
|
||||
align: 'center',
|
||||
formatter: function (row) {
|
||||
return row.cellValue ? row.cellValue : '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '监测点名称',
|
||||
field: 'lineName',
|
||||
align: 'center',
|
||||
formatter: function (row) {
|
||||
return row.cellValue ? row.cellValue : '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '总谐波畸变率(%)',
|
||||
field: 'distortion',
|
||||
align: 'center',
|
||||
formatter: function (row) {
|
||||
return row.cellValue == 3.14159 ? '暂无数据' : row.cellValue
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
loadCallback: () => {
|
||||
tableStore.table.data = tree2List(
|
||||
filterTree(tableStore.table.data, node => {
|
||||
// 筛选条件:name 包含关键词
|
||||
return node.name.includes(tableStore.table.params.searchValue)
|
||||
}),
|
||||
Math.random() * 1000
|
||||
)
|
||||
tableStore.table.column[0].title = tableStore.table.params.statisticalType.name
|
||||
chartsRef.value && chartsRef.value.getTableStoreParams(tableStore.table.params)
|
||||
setTimeout(() => {
|
||||
activeName.value == 0 && tableRef.value && tableRef.value.getRef().setAllTreeExpand(true)
|
||||
}, 0)
|
||||
}
|
||||
})
|
||||
|
||||
tableStore.table.params.statisticalType = classificationData[0]
|
||||
tableStore.table.params.scale = []
|
||||
tableStore.table.params.manufacturer = []
|
||||
tableStore.table.params.loadType = []
|
||||
tableStore.table.params.powerFlag = sign[0]?.algoDescribe || 0
|
||||
tableStore.table.params.serverName = 'harmonicBoot'
|
||||
tableStore.table.params.searchValue = ''
|
||||
provide('tableStore', tableStore)
|
||||
const tree2List = (list: any, id?: string) => {
|
||||
//存储结果的数组
|
||||
let arr: any = []
|
||||
// 遍历 tree 数组
|
||||
list.forEach((item: any) => {
|
||||
item.uPid = id
|
||||
item.uId = Math.random() * 1000
|
||||
item.valueOver == 3.14159 ? 0 : item.valueOver >= 90 ? 1 : item.valueOver && item.valueOver < 90 ? 2 : 3
|
||||
// 判断item是否存在children
|
||||
if (!item.children) return arr.push(item)
|
||||
// 函数递归,对children数组进行tree2List的转换
|
||||
const children = tree2List(item.children, item.uId)
|
||||
// 删除item的children属性
|
||||
delete item.children
|
||||
// 把item和children数组添加至结果数组
|
||||
//..children: 意思是把children数组展开
|
||||
arr.push(item, ...children)
|
||||
})
|
||||
// 返回结果数组
|
||||
return arr
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
// .online {
|
||||
// width: 100%;
|
||||
// height: 100%;
|
||||
// .online_header {
|
||||
// width: 100%;
|
||||
// max-height: 140px;
|
||||
// padding: 10px;
|
||||
// box-sizing: border-box;
|
||||
// }
|
||||
// .online_main {
|
||||
// padding: 0 10px;
|
||||
// }
|
||||
// }
|
||||
</style>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader date-picker area showExport>
|
||||
<TableHeader date-picker area showExport showCustomColumn>
|
||||
<template #select>
|
||||
<el-form-item label="统计类型:" v-if="false">
|
||||
<el-form-item label="统计类型" v-if="false">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.statisticalType"
|
||||
placeholder="请选择统计类型"
|
||||
@@ -18,7 +18,7 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="电压等级:" v-if="false">
|
||||
<el-form-item label="电压等级" v-if="false">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.scale"
|
||||
multiple
|
||||
@@ -36,7 +36,7 @@
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="终端厂家:" v-if="false">
|
||||
<el-form-item label="终端厂家" v-if="false">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.manufacturer"
|
||||
multiple
|
||||
@@ -55,7 +55,7 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="干扰源类型:">
|
||||
<el-form-item label="干扰源类型">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.loadType"
|
||||
multiple
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div class="online_header">
|
||||
<TableHeader date-picker ref="tableHeaderRef">
|
||||
<template #select>
|
||||
<el-form-item label="统计类型:">
|
||||
<el-form-item label="统计类型">
|
||||
<el-select
|
||||
v-model="formData.statisticalType"
|
||||
placeholder="请选择统计类型"
|
||||
@@ -18,7 +18,7 @@
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="区域选择:">
|
||||
<el-form-item label="区域选择">
|
||||
<!-- <el-select ref="select1" v-model="deptName" placeholder="请选择所属部门区域" style="width: 100%">
|
||||
<el-option :value="formData.deptIndex" style="height: auto"> -->
|
||||
<!-- {{ formData.deptIndex }} -->
|
||||
@@ -48,7 +48,7 @@
|
||||
<!-- </el-option>
|
||||
</el-select> -->
|
||||
</el-form-item>
|
||||
<el-form-item label="电压等级:">
|
||||
<el-form-item label="电压等级">
|
||||
<el-select
|
||||
v-model="formData.scale"
|
||||
multiple
|
||||
@@ -66,7 +66,7 @@
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="终端厂家:">
|
||||
<el-form-item label="终端厂家">
|
||||
<el-select
|
||||
v-model="formData.manufacturer"
|
||||
multiple
|
||||
@@ -84,7 +84,7 @@
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="干扰源类型:">
|
||||
<el-form-item label="干扰源类型">
|
||||
<el-select
|
||||
v-model="formData.loadType"
|
||||
multiple
|
||||
@@ -102,7 +102,7 @@
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="关键字筛选:">
|
||||
<el-form-item label="筛选数据">
|
||||
<el-input
|
||||
v-model="tableStore.table.params.searchValue"
|
||||
clearable
|
||||
|
||||
@@ -1,305 +1,305 @@
|
||||
<template>
|
||||
<div class="charts" style="position: relative; width: 100%">
|
||||
<div style="position: absolute; right: 60px; top: 5px; font-weight: bold">
|
||||
<el-tag
|
||||
style="
|
||||
background: #A52a2a;
|
||||
width: 30px;
|
||||
height: 15px;
|
||||
border: 1px solid #A52a2a;
|
||||
float: left;
|
||||
margin-top: 2px;
|
||||
"
|
||||
></el-tag>
|
||||
<span style="color: #A52a2a; font-weight: 400; float: left">  在线率<60%   </span>
|
||||
<el-tag
|
||||
size="small"
|
||||
style="
|
||||
background: #ffcc33;
|
||||
width: 30px;
|
||||
height: 15px;
|
||||
border: 1px solid #ffcc33;
|
||||
float: left;
|
||||
margin-top: 2px;
|
||||
"
|
||||
></el-tag>
|
||||
<span style="color: #ffcc33; font-weight: 400; float: left">  60%≤在线率<90%   </span>
|
||||
<el-tag
|
||||
style="
|
||||
background: #339966;
|
||||
width: 30px;
|
||||
height: 15px;
|
||||
border: 1px solid #339966;
|
||||
float: left;
|
||||
margin-top: 2px;
|
||||
"
|
||||
></el-tag>
|
||||
<span style="color: #339966; font-weight: 400; float: left">  在线率≥90%</span>
|
||||
</div>
|
||||
<my-echart
|
||||
v-loading="loading"
|
||||
class="mt10"
|
||||
:style="`height: calc(${tableStore.table.height} - 135px)`"
|
||||
:options="options"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, provide, nextTick } from 'vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import * as echarts from 'echarts/core'
|
||||
const dictData = useDictData()
|
||||
const options = ref({})
|
||||
|
||||
const TableHeaderRef = ref()
|
||||
const tableStoreParams: any = ref({})
|
||||
const loading = ref(false)
|
||||
const getTableStoreParams = async (val: any) => {
|
||||
tableStoreParams.value = val
|
||||
loading.value = true
|
||||
setTimeout(() => {
|
||||
tableStore.index()
|
||||
}, 1500)
|
||||
}
|
||||
const itemStyle = {
|
||||
normal: {
|
||||
// 随机显示
|
||||
//color:function(d){return "#"+Math.floor(Math.random()*(256*256*256-1)).toString(16);}
|
||||
|
||||
// 定制显示(按顺序)
|
||||
color: function (params) {
|
||||
if (params.value >= 90) {
|
||||
return new echarts.graphic.LinearGradient(
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
[
|
||||
{
|
||||
offset: 1,
|
||||
color: '#339966'
|
||||
}
|
||||
],
|
||||
false
|
||||
)
|
||||
} else if (params.value >= 60 && params.value <= 90) {
|
||||
return new echarts.graphic.LinearGradient(
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
[
|
||||
{
|
||||
offset: 1,
|
||||
color: '#FFCC33'
|
||||
}
|
||||
],
|
||||
false
|
||||
)
|
||||
} else if (params.value <= 60 && params.value !== 3.14159) {
|
||||
return new echarts.graphic.LinearGradient(
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
[
|
||||
{
|
||||
offset: 1,
|
||||
color: '#A52a2a'
|
||||
}
|
||||
],
|
||||
false
|
||||
)
|
||||
} else if (params.value == 3.14159) {
|
||||
return new echarts.graphic.LinearGradient(
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
[
|
||||
{
|
||||
offset: 1,
|
||||
color: '#cccccc'
|
||||
}
|
||||
],
|
||||
false
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const tableStore = new TableStore({
|
||||
url: '/harmonic-boot/steadyQualify/getSteadyQualifyCensus',
|
||||
showPage: false,
|
||||
method: 'POST',
|
||||
// publicHeight: 10,
|
||||
column: [],
|
||||
beforeSearchFun: () => {
|
||||
tableStore.table.params = tableStoreParams.value
|
||||
},
|
||||
loadCallback: () => {
|
||||
let code = tableStore.table.params.statisticalType.code
|
||||
let title = '',
|
||||
titleX = ''
|
||||
if (code == 'Power_Network') {
|
||||
title = '区域'
|
||||
titleX = '区域'
|
||||
} else if (code == 'Manufacturer') {
|
||||
title = '终端厂家'
|
||||
titleX = '终端\n厂家'
|
||||
} else if (code == 'Voltage_Level') {
|
||||
title = '电压等级'
|
||||
titleX = '电压\n等级'
|
||||
} else if (code == 'Load_Type') {
|
||||
title = '干扰源类型'
|
||||
titleX = '干扰\n源类型'
|
||||
} else if (code == 'Report_Type') {
|
||||
title = '上报类型'
|
||||
titleX = '上报\n类型'
|
||||
}
|
||||
options.value = {
|
||||
title: {
|
||||
text: title
|
||||
},
|
||||
legend: {
|
||||
show: false
|
||||
},
|
||||
|
||||
tooltip: {
|
||||
|
||||
formatter: function (params: any) {
|
||||
let tips = `<strong>${params[0]?.name}</strong></br>` // 标题加粗
|
||||
params.forEach((item: any) => {
|
||||
const value = item.value === 3.14159 ? '暂无数据' : item.value // 处理特殊值
|
||||
tips += `<div style=" display: flex;justify-content: space-between;">
|
||||
<span>${item.marker}
|
||||
${item.seriesName}:
|
||||
</span> ${value}
|
||||
</div>` // 统一格式
|
||||
})
|
||||
return tips
|
||||
}
|
||||
},
|
||||
|
||||
xAxis: {
|
||||
name: titleX,
|
||||
data: tableStore.table.data.type
|
||||
},
|
||||
yAxis: {
|
||||
name: '%',
|
||||
max: 100
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '频率偏差',
|
||||
type: 'bar',
|
||||
itemStyle: itemStyle,
|
||||
data: tableStore.table.data.freqOffset,
|
||||
markLine: {
|
||||
silent: false,
|
||||
symbol: 'circle',
|
||||
data: [
|
||||
{
|
||||
name: '',
|
||||
yAxis: 100,
|
||||
lineStyle: {
|
||||
color: '#339966'
|
||||
},
|
||||
label: {
|
||||
// position: "middle",
|
||||
formatter: '{b}',
|
||||
textStyle: {
|
||||
color: '#339966'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
yAxis: 90,
|
||||
lineStyle: {
|
||||
color: '#FFCC33'
|
||||
},
|
||||
label: {
|
||||
// position: "middle",
|
||||
formatter: '{b}',
|
||||
textStyle: {
|
||||
color: '#FFCC33'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
yAxis: 60,
|
||||
lineStyle: {
|
||||
color: '#A52a2a'
|
||||
},
|
||||
label: {
|
||||
// position: "middle",
|
||||
formatter: '{b}',
|
||||
textStyle: {
|
||||
color: '#A52a2a'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '闪变',
|
||||
type: 'bar',
|
||||
itemStyle: itemStyle,
|
||||
data: tableStore.table.data.flicker
|
||||
},
|
||||
{
|
||||
name: '三相电压不平衡',
|
||||
type: 'bar',
|
||||
itemStyle: itemStyle,
|
||||
data: tableStore.table.data.voltageUnbalance
|
||||
},
|
||||
{
|
||||
name: '谐波电压',
|
||||
type: 'bar',
|
||||
itemStyle: itemStyle,
|
||||
data: tableStore.table.data.harmonicVoltage
|
||||
},
|
||||
{
|
||||
name: '电压偏差',
|
||||
type: 'bar',
|
||||
itemStyle: itemStyle,
|
||||
data: tableStore.table.data.voltageOffset
|
||||
},
|
||||
{
|
||||
name: '谐波电流',
|
||||
type: 'bar',
|
||||
itemStyle: itemStyle,
|
||||
data: tableStore.table.data.harmonicCurrent
|
||||
},
|
||||
{
|
||||
name: '负序电流',
|
||||
type: 'bar',
|
||||
itemStyle: itemStyle,
|
||||
data: tableStore.table.data.negativeCurrent
|
||||
},
|
||||
{
|
||||
name: '间谐波电压含有率',
|
||||
type: 'bar',
|
||||
itemStyle: itemStyle,
|
||||
data: tableStore.table.data.interHarmonic
|
||||
}
|
||||
]
|
||||
}
|
||||
loading.value = false
|
||||
}
|
||||
})
|
||||
|
||||
provide('tableStore', tableStore)
|
||||
|
||||
onMounted(() => {})
|
||||
defineExpose({ getTableStoreParams })
|
||||
</script>
|
||||
<style scoped lang="scss"></style>
|
||||
<template>
|
||||
<div class="charts" style="position: relative; width: 100%">
|
||||
<div style="position: absolute; right: 60px; top: 5px; font-weight: bold">
|
||||
<el-tag
|
||||
style="
|
||||
background: #A52a2a;
|
||||
width: 30px;
|
||||
height: 15px;
|
||||
border: 1px solid #A52a2a;
|
||||
float: left;
|
||||
margin-top: 2px;
|
||||
"
|
||||
></el-tag>
|
||||
<span style="color: #A52a2a; font-weight: 400; float: left">  合格率<60%   </span>
|
||||
<el-tag
|
||||
size="small"
|
||||
style="
|
||||
background: #ffcc33;
|
||||
width: 30px;
|
||||
height: 15px;
|
||||
border: 1px solid #ffcc33;
|
||||
float: left;
|
||||
margin-top: 2px;
|
||||
"
|
||||
></el-tag>
|
||||
<span style="color: #ffcc33; font-weight: 400; float: left">  60%≤合格率<90%   </span>
|
||||
<el-tag
|
||||
style="
|
||||
background: #339966;
|
||||
width: 30px;
|
||||
height: 15px;
|
||||
border: 1px solid #339966;
|
||||
float: left;
|
||||
margin-top: 2px;
|
||||
"
|
||||
></el-tag>
|
||||
<span style="color: #339966; font-weight: 400; float: left">  合格率≥90%</span>
|
||||
</div>
|
||||
<my-echart
|
||||
v-loading="loading"
|
||||
class="mt10"
|
||||
:style="`height: calc(${tableStore.table.height} - 135px)`"
|
||||
:options="options"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, provide, nextTick } from 'vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import * as echarts from 'echarts/core'
|
||||
const dictData = useDictData()
|
||||
const options = ref({})
|
||||
|
||||
const TableHeaderRef = ref()
|
||||
const tableStoreParams: any = ref({})
|
||||
const loading = ref(false)
|
||||
const getTableStoreParams = async (val: any) => {
|
||||
tableStoreParams.value = val
|
||||
loading.value = true
|
||||
setTimeout(() => {
|
||||
tableStore.index()
|
||||
}, 1500)
|
||||
}
|
||||
const itemStyle = {
|
||||
normal: {
|
||||
// 随机显示
|
||||
//color:function(d){return "#"+Math.floor(Math.random()*(256*256*256-1)).toString(16);}
|
||||
|
||||
// 定制显示(按顺序)
|
||||
color: function (params) {
|
||||
if (params.value >= 90) {
|
||||
return new echarts.graphic.LinearGradient(
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
[
|
||||
{
|
||||
offset: 1,
|
||||
color: '#339966'
|
||||
}
|
||||
],
|
||||
false
|
||||
)
|
||||
} else if (params.value >= 60 && params.value <= 90) {
|
||||
return new echarts.graphic.LinearGradient(
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
[
|
||||
{
|
||||
offset: 1,
|
||||
color: '#FFCC33'
|
||||
}
|
||||
],
|
||||
false
|
||||
)
|
||||
} else if (params.value <= 60 && params.value !== 3.14159) {
|
||||
return new echarts.graphic.LinearGradient(
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
[
|
||||
{
|
||||
offset: 1,
|
||||
color: '#A52a2a'
|
||||
}
|
||||
],
|
||||
false
|
||||
)
|
||||
} else if (params.value == 3.14159) {
|
||||
return new echarts.graphic.LinearGradient(
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
[
|
||||
{
|
||||
offset: 1,
|
||||
color: '#cccccc'
|
||||
}
|
||||
],
|
||||
false
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const tableStore = new TableStore({
|
||||
url: '/harmonic-boot/steadyQualify/getSteadyQualifyCensus',
|
||||
showPage: false,
|
||||
method: 'POST',
|
||||
// publicHeight: 10,
|
||||
column: [],
|
||||
beforeSearchFun: () => {
|
||||
tableStore.table.params = tableStoreParams.value
|
||||
},
|
||||
loadCallback: () => {
|
||||
let code = tableStore.table.params.statisticalType.code
|
||||
let title = '',
|
||||
titleX = ''
|
||||
if (code == 'Power_Network') {
|
||||
title = '区域'
|
||||
titleX = '区域'
|
||||
} else if (code == 'Manufacturer') {
|
||||
title = '终端厂家'
|
||||
titleX = '终端\n厂家'
|
||||
} else if (code == 'Voltage_Level') {
|
||||
title = '电压等级'
|
||||
titleX = '电压\n等级'
|
||||
} else if (code == 'Load_Type') {
|
||||
title = '干扰源类型'
|
||||
titleX = '干扰\n源类型'
|
||||
} else if (code == 'Report_Type') {
|
||||
title = '上报类型'
|
||||
titleX = '上报\n类型'
|
||||
}
|
||||
options.value = {
|
||||
title: {
|
||||
text: title
|
||||
},
|
||||
legend: {
|
||||
show: false
|
||||
},
|
||||
|
||||
tooltip: {
|
||||
|
||||
formatter: function (params: any) {
|
||||
let tips = `<strong>${params[0]?.name}</strong></br>` // 标题加粗
|
||||
params.forEach((item: any) => {
|
||||
const value = item.value === 3.14159 ? '暂无数据' : item.value // 处理特殊值
|
||||
tips += `<div style=" display: flex;justify-content: space-between;">
|
||||
<span>${item.marker}
|
||||
${item.seriesName}:
|
||||
</span> ${value}
|
||||
</div>` // 统一格式
|
||||
})
|
||||
return tips
|
||||
}
|
||||
},
|
||||
|
||||
xAxis: {
|
||||
name: titleX,
|
||||
data: tableStore.table.data.type
|
||||
},
|
||||
yAxis: {
|
||||
name: '%',
|
||||
max: 100
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '频率偏差',
|
||||
type: 'bar',
|
||||
itemStyle: itemStyle,
|
||||
data: tableStore.table.data.freqOffset,
|
||||
markLine: {
|
||||
silent: false,
|
||||
symbol: 'circle',
|
||||
data: [
|
||||
{
|
||||
name: '',
|
||||
yAxis: 100,
|
||||
lineStyle: {
|
||||
color: '#339966'
|
||||
},
|
||||
label: {
|
||||
// position: "middle",
|
||||
formatter: '{b}',
|
||||
textStyle: {
|
||||
color: '#339966'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
yAxis: 90,
|
||||
lineStyle: {
|
||||
color: '#FFCC33'
|
||||
},
|
||||
label: {
|
||||
// position: "middle",
|
||||
formatter: '{b}',
|
||||
textStyle: {
|
||||
color: '#FFCC33'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
yAxis: 60,
|
||||
lineStyle: {
|
||||
color: '#A52a2a'
|
||||
},
|
||||
label: {
|
||||
// position: "middle",
|
||||
formatter: '{b}',
|
||||
textStyle: {
|
||||
color: '#A52a2a'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '闪变',
|
||||
type: 'bar',
|
||||
itemStyle: itemStyle,
|
||||
data: tableStore.table.data.flicker
|
||||
},
|
||||
{
|
||||
name: '三相电压不平衡',
|
||||
type: 'bar',
|
||||
itemStyle: itemStyle,
|
||||
data: tableStore.table.data.voltageUnbalance
|
||||
},
|
||||
{
|
||||
name: '谐波电压',
|
||||
type: 'bar',
|
||||
itemStyle: itemStyle,
|
||||
data: tableStore.table.data.harmonicVoltage
|
||||
},
|
||||
{
|
||||
name: '电压偏差',
|
||||
type: 'bar',
|
||||
itemStyle: itemStyle,
|
||||
data: tableStore.table.data.voltageOffset
|
||||
},
|
||||
{
|
||||
name: '谐波电流',
|
||||
type: 'bar',
|
||||
itemStyle: itemStyle,
|
||||
data: tableStore.table.data.harmonicCurrent
|
||||
},
|
||||
{
|
||||
name: '负序电流',
|
||||
type: 'bar',
|
||||
itemStyle: itemStyle,
|
||||
data: tableStore.table.data.negativeCurrent
|
||||
},
|
||||
{
|
||||
name: '间谐波电压含有率',
|
||||
type: 'bar',
|
||||
itemStyle: itemStyle,
|
||||
data: tableStore.table.data.interHarmonic
|
||||
}
|
||||
]
|
||||
}
|
||||
loading.value = false
|
||||
}
|
||||
})
|
||||
|
||||
provide('tableStore', tableStore)
|
||||
|
||||
onMounted(() => {})
|
||||
defineExpose({ getTableStoreParams })
|
||||
</script>
|
||||
<style scoped lang="scss"></style>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div class="online_header">
|
||||
<TableHeader date-picker area ref="tableHeaderRef">
|
||||
<template #select>
|
||||
<el-form-item label="统计类型:">
|
||||
<el-form-item label="统计类型">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.statisticalType"
|
||||
placeholder="请选择统计类型"
|
||||
@@ -19,7 +19,7 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="电压等级:">
|
||||
<el-form-item label="电压等级">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.scale"
|
||||
multiple
|
||||
@@ -37,7 +37,7 @@
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="终端厂家:">
|
||||
<el-form-item label="终端厂家">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.manufacturer"
|
||||
multiple
|
||||
@@ -55,7 +55,7 @@
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="干扰源类型:">
|
||||
<el-form-item label="干扰源类型">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.loadType"
|
||||
multiple
|
||||
@@ -83,6 +83,14 @@
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="筛选数据">
|
||||
<el-input
|
||||
v-model.trim="tableStore.table.params.searchValue"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
placeholder="请输入关键字筛选"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</TableHeader>
|
||||
</div>
|
||||
@@ -113,6 +121,7 @@ import TableHeader from '@/components/table/header/index.vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import charts from './components/charts.vue'
|
||||
import { filterTree } from '@/utils/tree'
|
||||
defineOptions({
|
||||
name: 'harmonic-boot/area/qualifiedRate'
|
||||
})
|
||||
@@ -272,7 +281,13 @@ const tableStore = new TableStore({
|
||||
],
|
||||
|
||||
loadCallback: () => {
|
||||
tableStore.table.data = tree2List(tableStore.table.data, Math.random() * 1000)
|
||||
tableStore.table.data = tree2List(
|
||||
filterTree(tableStore.table.data, node => {
|
||||
// 筛选条件:name 包含关键词
|
||||
return node.name.includes(tableStore.table.params.searchValue)
|
||||
}),
|
||||
Math.random() * 1000
|
||||
)
|
||||
tableStore.table.column[0].title = tableStore.table.params.statisticalType.name
|
||||
|
||||
chartsRef.value && chartsRef.value.getTableStoreParams(tableStore.table.params)
|
||||
@@ -288,6 +303,7 @@ tableStore.table.params.manufacturer = []
|
||||
tableStore.table.params.loadType = []
|
||||
tableStore.table.params.serverName = 'harmonicBoot'
|
||||
tableStore.table.params.powerFlag = sign[0]?.algoDescribe || 0
|
||||
tableStore.table.params.searchValue = ''
|
||||
provide('tableStore', tableStore)
|
||||
// const tree2List = (list: any, pid?: string) => {
|
||||
// //存储结果的数组
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader date-picker area showExport>
|
||||
<TableHeader date-picker area showExport showCustomColumn>
|
||||
<template #select>
|
||||
<el-form-item label="统计类型:" v-if="false">
|
||||
<el-select
|
||||
|
||||
@@ -1,365 +1,379 @@
|
||||
<template>
|
||||
<div class="default-main online">
|
||||
<div class="online_header">
|
||||
<TableHeader date-picker area ref="tableHeaderRef">
|
||||
<template #select>
|
||||
<el-form-item label="统计类型:">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.statisticalType"
|
||||
placeholder="请选择统计类型"
|
||||
value-key="id"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in classificationData"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="终端厂家:">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.manufacturer"
|
||||
multiple
|
||||
collapse-tags
|
||||
clearable
|
||||
placeholder="请选择终端厂家"
|
||||
style="width: 100%"
|
||||
value-key="id"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, index) in terminaloption"
|
||||
:key="index"
|
||||
:label="item.name"
|
||||
:value="item"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</TableHeader>
|
||||
</div>
|
||||
<div class="online_main">
|
||||
<el-tabs v-model="activeName" type="border-card" @tab-click="handleClick">
|
||||
<el-tab-pane :name="0" :lazy="true" label="终端状态统计表">
|
||||
<div class="table_legend">
|
||||
<ul>
|
||||
<li>
|
||||
<p style="background: #339966">
|
||||
<svg
|
||||
t="1722910570852"
|
||||
class="icon"
|
||||
viewBox="0 0 1336 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="6243"
|
||||
width="16"
|
||||
height="16"
|
||||
>
|
||||
<path
|
||||
d="M49.588224 883.816448M1139.531776 883.816448M86.939648 862.977024M538.459136 960.381952c109.876224-153.544704 223.55968-289.842176 308.03968-385.787904 49.87392-56.639488 96.715776-108.155904 141.549568-154.500096 40.576-41.945088 80.805888-80.405504 119.478272-116.59264 65.92-61.693952 142.984192-130.034688 191.446016-159.30368l-61.891584-82.050048c-89.732096 56.139776-176.10752 116.103168-242.799616 162.18112-38.863872 26.855424-74.928128 52.667392-108.915712 77.252608-33.668096 24.356864-68.429824 51.106816-105.081856 79.166464-63.633408 48.712704-145.388544 114.194432-224.555008 181.860352L357.07904 374.989824 123.885568 558.770176 538.459136 960.381952zM1335.92064 862.977024"
|
||||
fill="#ffffff"
|
||||
p-id="6244"
|
||||
></path>
|
||||
</svg>
|
||||
</p>
|
||||
<span style="color: #339966">投运状态</span>
|
||||
</li>
|
||||
<li>
|
||||
<p style="background: #ffcc33">
|
||||
<svg
|
||||
t="1722910570852"
|
||||
class="icon"
|
||||
viewBox="0 0 1336 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="6243"
|
||||
width="16"
|
||||
height="16"
|
||||
>
|
||||
<path
|
||||
d="M49.588224 883.816448M1139.531776 883.816448M86.939648 862.977024M538.459136 960.381952c109.876224-153.544704 223.55968-289.842176 308.03968-385.787904 49.87392-56.639488 96.715776-108.155904 141.549568-154.500096 40.576-41.945088 80.805888-80.405504 119.478272-116.59264 65.92-61.693952 142.984192-130.034688 191.446016-159.30368l-61.891584-82.050048c-89.732096 56.139776-176.10752 116.103168-242.799616 162.18112-38.863872 26.855424-74.928128 52.667392-108.915712 77.252608-33.668096 24.356864-68.429824 51.106816-105.081856 79.166464-63.633408 48.712704-145.388544 114.194432-224.555008 181.860352L357.07904 374.989824 123.885568 558.770176 538.459136 960.381952zM1335.92064 862.977024"
|
||||
fill="#ffffff"
|
||||
p-id="6244"
|
||||
></path>
|
||||
</svg>
|
||||
</p>
|
||||
<span style="color: #ffcc33">检修状态</span>
|
||||
</li>
|
||||
<li>
|
||||
<p style="background: #A52a2a">
|
||||
<svg
|
||||
t="1722910570852"
|
||||
class="icon"
|
||||
viewBox="0 0 1336 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="6243"
|
||||
width="16"
|
||||
height="16"
|
||||
>
|
||||
<path
|
||||
d="M49.588224 883.816448M1139.531776 883.816448M86.939648 862.977024M538.459136 960.381952c109.876224-153.544704 223.55968-289.842176 308.03968-385.787904 49.87392-56.639488 96.715776-108.155904 141.549568-154.500096 40.576-41.945088 80.805888-80.405504 119.478272-116.59264 65.92-61.693952 142.984192-130.034688 191.446016-159.30368l-61.891584-82.050048c-89.732096 56.139776-176.10752 116.103168-242.799616 162.18112-38.863872 26.855424-74.928128 52.667392-108.915712 77.252608-33.668096 24.356864-68.429824 51.106816-105.081856 79.166464-63.633408 48.712704-145.388544 114.194432-224.555008 181.860352L357.07904 374.989824 123.885568 558.770176 538.459136 960.381952zM1335.92064 862.977024"
|
||||
fill="#ffffff"
|
||||
p-id="6244"
|
||||
></path>
|
||||
</svg>
|
||||
</p>
|
||||
<span style="color: #A52a2a">停运状态</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<Table
|
||||
ref="tableRef"
|
||||
:tree-config="{ transform: true, parentField: 'uPid', rowField: 'uId' }"
|
||||
:scroll-y="{ enabled: true }"
|
||||
v-if="activeName == 0"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :name="1" :lazy="true" label="终端状态统计图">
|
||||
<charts v-if="activeName == 1" ref="chartsRef" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, watch } from 'vue'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import DatePicker from '@/components/form/datePicker/index.vue'
|
||||
import { getAreaDept } from '@/api/harmonic-boot/area'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import charts from './components/charts.vue'
|
||||
defineOptions({
|
||||
name: 'harmonic-boot/area/terminalonlinerate'
|
||||
})
|
||||
const tableRef = ref()
|
||||
const chartsRef = ref()
|
||||
const dictData = useDictData()
|
||||
//字典获取电压等级
|
||||
const voltageleveloption = dictData.getBasicData('Dev_Voltage_Stand')
|
||||
//字典获取终端厂家
|
||||
const terminaloption = dictData.getBasicData('Dev_Manufacturers')
|
||||
//字典获取干扰源类型
|
||||
const interfereoption = dictData.getBasicData('Interference_Source')
|
||||
//字典获取统计类型
|
||||
const classificationData = dictData.getBasicData('Statistical_Type', ['Report_Type', 'Voltage_Level', 'Load_Type'])
|
||||
//调用区域接口获取区域
|
||||
const treeData = ref([])
|
||||
const idArr = ref([])
|
||||
const activeName = ref(0)
|
||||
const getTreeData = async () => {
|
||||
await getAreaDept().then(res => {
|
||||
var data = res.data
|
||||
data.forEach(element => {
|
||||
idArr.value.push(element.id)
|
||||
})
|
||||
treeData.value = JSON.parse(JSON.stringify(res.data))
|
||||
})
|
||||
}
|
||||
getTreeData()
|
||||
|
||||
const formData = ref({
|
||||
statisticalType: classificationData[0], //统计类型
|
||||
deptIndex: treeData.value[0]?.id, //区域选择
|
||||
scale: voltageleveloption, //电压等级
|
||||
manufacturer: terminaloption, //终端厂家
|
||||
loadType: interfereoption //干扰源类型
|
||||
// searchBeginTime: '',
|
||||
// searchEndTime: ''
|
||||
})
|
||||
formData.value.deptIndex = treeData.value[0]?.id
|
||||
const defaultProps = ref({
|
||||
label: 'name',
|
||||
value: 'id',
|
||||
checkStrictly: true,
|
||||
emitPath: false,
|
||||
expandTrigger: 'click' as const
|
||||
})
|
||||
const handleClick = (tab: any, e: any) => {
|
||||
// if(activeName.value===1){
|
||||
tableStore.index()
|
||||
// }
|
||||
}
|
||||
|
||||
// const datePickerRef = ref()
|
||||
const tableHeaderRef = ref()
|
||||
const tableStore = new TableStore({
|
||||
publicHeight: 100,
|
||||
showPage: false,
|
||||
url: '/harmonic-boot/terminal/getTerminalData',
|
||||
method: 'POST',
|
||||
|
||||
column: [
|
||||
{
|
||||
title: formData.value.statisticalType.name,
|
||||
field: 'name',
|
||||
align: 'left',
|
||||
width: 350,
|
||||
treeNode: true
|
||||
},
|
||||
{
|
||||
title: '终端个数(台)',
|
||||
field: 'number',
|
||||
align: 'center',
|
||||
formatter: function (row) {
|
||||
return row.cellValue != 0 ? row.cellValue : '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '投运(台)',
|
||||
field: 'runFlag',
|
||||
type: 'html',
|
||||
align: 'center',
|
||||
formatter: function (row) {
|
||||
return row.cellValue == 0
|
||||
? '/'
|
||||
: row.cellValue !== 0 && row.row.level !== 4
|
||||
? row.cellValue
|
||||
: row.cellValue !== 0 && row.row.level == 4 && row.row.reaFlag == 0 && row.row.stopFlag == 0
|
||||
? "<p class='table_icon' style='width: 18px;height: 18px;margin: 0 auto;display: flex;align-items: center;justify-content: center;border-radius: 50%;background: #339966'><svg t='1722910570852' class='icon' viewBox='0 0 1336 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='6243' width='16' height='16'><path d='M49.588224 883.816448M1139.531776 883.816448M86.939648 862.977024M538.459136 960.381952c109.876224-153.544704 223.55968-289.842176 308.03968-385.787904 49.87392-56.639488 96.715776-108.155904 141.549568-154.500096 40.576-41.945088 80.805888-80.405504 119.478272-116.59264 65.92-61.693952 142.984192-130.034688 191.446016-159.30368l-61.891584-82.050048c-89.732096 56.139776-176.10752 116.103168-242.799616 162.18112-38.863872 26.855424-74.928128 52.667392-108.915712 77.252608-33.668096 24.356864-68.429824 51.106816-105.081856 79.166464-63.633408 48.712704-145.388544 114.194432-224.555008 181.860352L357.07904 374.989824 123.885568 558.770176 538.459136 960.381952zM1335.92064 862.977024' fill='#ffffff' p-id='6244'></path></svg> </p>"
|
||||
: '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '检修(台)',
|
||||
field: 'reaFlag',
|
||||
type: 'html',
|
||||
align: 'center',
|
||||
formatter: function (row) {
|
||||
return row.cellValue == 0
|
||||
? '/'
|
||||
: row.cellValue !== 0 && row.row.level !== 4
|
||||
? row.cellValue
|
||||
: row.cellValue !== 0 && row.row.level == 4 && row.row.runFlag == 0 && row.row.stopFlag == 0
|
||||
? "<p class='table_icon' style='width: 18px;height: 18px;margin: 0 auto;display: flex;align-items: center;justify-content: center;border-radius: 50%;background: #ffcc33'><svg t='1722910570852' class='icon' viewBox='0 0 1336 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='6243' width='16' height='16'><path d='M49.588224 883.816448M1139.531776 883.816448M86.939648 862.977024M538.459136 960.381952c109.876224-153.544704 223.55968-289.842176 308.03968-385.787904 49.87392-56.639488 96.715776-108.155904 141.549568-154.500096 40.576-41.945088 80.805888-80.405504 119.478272-116.59264 65.92-61.693952 142.984192-130.034688 191.446016-159.30368l-61.891584-82.050048c-89.732096 56.139776-176.10752 116.103168-242.799616 162.18112-38.863872 26.855424-74.928128 52.667392-108.915712 77.252608-33.668096 24.356864-68.429824 51.106816-105.081856 79.166464-63.633408 48.712704-145.388544 114.194432-224.555008 181.860352L357.07904 374.989824 123.885568 558.770176 538.459136 960.381952zM1335.92064 862.977024' fill='#ffffff' p-id='6244'></path></svg> </p>"
|
||||
: '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '停运(台)',
|
||||
field: 'stopFlag',
|
||||
type: 'html',
|
||||
align: 'center',
|
||||
formatter: function (row) {
|
||||
return row.cellValue == 0
|
||||
? '/'
|
||||
: row.cellValue !== 0 && row.row.level !== 4
|
||||
? row.cellValue
|
||||
: row.cellValue !== 0 && row.row.level == 4 && row.row.runFlag == 0 && row.row.reaFlag == 0
|
||||
? "<p class='table_icon' style='width: 18px;height: 18px;margin: 0 auto;display: flex;align-items: center;justify-content: center;border-radius: 50%;background: #A52a2a'><svg t='1722910570852' class='icon' viewBox='0 0 1336 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='6243' width='16' height='16'><path d='M49.588224 883.816448M1139.531776 883.816448M86.939648 862.977024M538.459136 960.381952c109.876224-153.544704 223.55968-289.842176 308.03968-385.787904 49.87392-56.639488 96.715776-108.155904 141.549568-154.500096 40.576-41.945088 80.805888-80.405504 119.478272-116.59264 65.92-61.693952 142.984192-130.034688 191.446016-159.30368l-61.891584-82.050048c-89.732096 56.139776-176.10752 116.103168-242.799616 162.18112-38.863872 26.855424-74.928128 52.667392-108.915712 77.252608-33.668096 24.356864-68.429824 51.106816-105.081856 79.166464-63.633408 48.712704-145.388544 114.194432-224.555008 181.860352L357.07904 374.989824 123.885568 558.770176 538.459136 960.381952zM1335.92064 862.977024' fill='#ffffff' p-id='6244'></path></svg> </p>"
|
||||
: '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '在线率(%)',
|
||||
field: 'onlineRateData',
|
||||
align: 'center',
|
||||
formatter: function (row) {
|
||||
return row.cellValue == 3.14159 ? '暂无数据' : row.cellValue.toFixed(2)
|
||||
}
|
||||
}
|
||||
],
|
||||
// beforeSearchFun: () => {
|
||||
// tableStore.table.params.deptIndex = formData.value.deptIndex
|
||||
// tableStore.table.params.statisticalType = formData.value.statisticalType
|
||||
// tableStore.table.params.scale = formData.value.scale
|
||||
// tableStore.table.params.manufacturer = formData.value.manufacturer
|
||||
// tableStore.table.params.loadType = formData.value.loadType
|
||||
// tableStore.table.params.serverName = 'harmonicBoot'
|
||||
// // delete tableStore.table.params.timeFlag
|
||||
// // delete tableStore.table.params.startTime
|
||||
// // delete tableStore.table.params.endTime
|
||||
// // delete tableStore.table.params.pageNum
|
||||
// // delete tableStore.table.params.pageSize
|
||||
// // tableStore.table.params.searchBeginTime = tableHeaderRef.value.datePickerRef.timeValue[0]
|
||||
// // tableStore.table.params.searchEndTime = tableHeaderRef.value.datePickerRef.timeValue[1]
|
||||
// },
|
||||
loadCallback: () => {
|
||||
tableStore.table.data = tree2List(tableStore.table.data, Math.random() * 1000)
|
||||
tableStore.table.column[0].title = formData.value.statisticalType.name
|
||||
|
||||
chartsRef.value && chartsRef.value.getTableStoreParams(tableStore.table.params)
|
||||
setTimeout(() => {
|
||||
activeName.value == 0 && tableRef.value && tableRef.value.getRef().setAllTreeExpand(true)
|
||||
}, 0)
|
||||
}
|
||||
})
|
||||
tableStore.table.params.deptIndex = treeData.value[0]?.id
|
||||
tableStore.table.params.statisticalType = classificationData[0]
|
||||
tableStore.table.params.scale = voltageleveloption
|
||||
tableStore.table.params.manufacturer = terminaloption
|
||||
tableStore.table.params.loadType = interfereoption
|
||||
tableStore.table.params.serverName = 'harmonicBoot'
|
||||
|
||||
|
||||
provide('tableStore', tableStore)
|
||||
const tree2List = (list: any, id?: string) => {
|
||||
//存储结果的数组
|
||||
let arr: any = []
|
||||
// 遍历 tree 数组
|
||||
list.forEach((item: any) => {
|
||||
item.uPid = id
|
||||
item.uId = Math.random() * 1000
|
||||
item.valueOver == 3.14159 ? 0 : item.valueOver >= 90 ? 1 : item.valueOver && item.valueOver < 90 ? 2 : 3
|
||||
// 判断item是否存在children
|
||||
if (!item.children) return arr.push(item)
|
||||
// 函数递归,对children数组进行tree2List的转换
|
||||
const children = tree2List(item.children, item.uId)
|
||||
// 删除item的children属性
|
||||
delete item.children
|
||||
// 把item和children数组添加至结果数组
|
||||
//..children: 意思是把children数组展开
|
||||
arr.push(item, ...children)
|
||||
})
|
||||
// 返回结果数组
|
||||
return arr
|
||||
}
|
||||
|
||||
onMounted(() => {})
|
||||
|
||||
watch(
|
||||
() => treeData.value,
|
||||
(val, oldVal) => {
|
||||
if (val && val.length != 0) {
|
||||
formData.value.deptIndex = val[0].id
|
||||
tableStore.index()
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.table_legend {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
ul {
|
||||
width: 280px;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
li {
|
||||
flex: 1;
|
||||
list-style-type: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
p {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<div class="default-main online">
|
||||
<div class="online_header">
|
||||
<TableHeader date-picker area ref="tableHeaderRef">
|
||||
<template #select>
|
||||
<el-form-item label="统计类型">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.statisticalType"
|
||||
placeholder="请选择统计类型"
|
||||
value-key="id"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in classificationData"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="终端厂家">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.manufacturer"
|
||||
multiple
|
||||
collapse-tags
|
||||
clearable
|
||||
placeholder="请选择终端厂家"
|
||||
style="width: 100%"
|
||||
value-key="id"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, index) in terminaloption"
|
||||
:key="index"
|
||||
:label="item.name"
|
||||
:value="item"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="筛选数据">
|
||||
<el-input
|
||||
v-model.trim="tableStore.table.params.searchValue"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
placeholder="请输入关键字筛选"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</TableHeader>
|
||||
</div>
|
||||
<div class="online_main">
|
||||
<el-tabs v-model="activeName" type="border-card" @tab-click="handleClick">
|
||||
<el-tab-pane :name="0" :lazy="true" label="终端状态统计表">
|
||||
<div class="table_legend">
|
||||
<ul>
|
||||
<li>
|
||||
<p style="background: #339966">
|
||||
<svg
|
||||
t="1722910570852"
|
||||
class="icon"
|
||||
viewBox="0 0 1336 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="6243"
|
||||
width="16"
|
||||
height="16"
|
||||
>
|
||||
<path
|
||||
d="M49.588224 883.816448M1139.531776 883.816448M86.939648 862.977024M538.459136 960.381952c109.876224-153.544704 223.55968-289.842176 308.03968-385.787904 49.87392-56.639488 96.715776-108.155904 141.549568-154.500096 40.576-41.945088 80.805888-80.405504 119.478272-116.59264 65.92-61.693952 142.984192-130.034688 191.446016-159.30368l-61.891584-82.050048c-89.732096 56.139776-176.10752 116.103168-242.799616 162.18112-38.863872 26.855424-74.928128 52.667392-108.915712 77.252608-33.668096 24.356864-68.429824 51.106816-105.081856 79.166464-63.633408 48.712704-145.388544 114.194432-224.555008 181.860352L357.07904 374.989824 123.885568 558.770176 538.459136 960.381952zM1335.92064 862.977024"
|
||||
fill="#ffffff"
|
||||
p-id="6244"
|
||||
></path>
|
||||
</svg>
|
||||
</p>
|
||||
<span style="color: #339966">投运状态</span>
|
||||
</li>
|
||||
<li>
|
||||
<p style="background: #ffcc33">
|
||||
<svg
|
||||
t="1722910570852"
|
||||
class="icon"
|
||||
viewBox="0 0 1336 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="6243"
|
||||
width="16"
|
||||
height="16"
|
||||
>
|
||||
<path
|
||||
d="M49.588224 883.816448M1139.531776 883.816448M86.939648 862.977024M538.459136 960.381952c109.876224-153.544704 223.55968-289.842176 308.03968-385.787904 49.87392-56.639488 96.715776-108.155904 141.549568-154.500096 40.576-41.945088 80.805888-80.405504 119.478272-116.59264 65.92-61.693952 142.984192-130.034688 191.446016-159.30368l-61.891584-82.050048c-89.732096 56.139776-176.10752 116.103168-242.799616 162.18112-38.863872 26.855424-74.928128 52.667392-108.915712 77.252608-33.668096 24.356864-68.429824 51.106816-105.081856 79.166464-63.633408 48.712704-145.388544 114.194432-224.555008 181.860352L357.07904 374.989824 123.885568 558.770176 538.459136 960.381952zM1335.92064 862.977024"
|
||||
fill="#ffffff"
|
||||
p-id="6244"
|
||||
></path>
|
||||
</svg>
|
||||
</p>
|
||||
<span style="color: #ffcc33">检修状态</span>
|
||||
</li>
|
||||
<li>
|
||||
<p style="background: #a52a2a">
|
||||
<svg
|
||||
t="1722910570852"
|
||||
class="icon"
|
||||
viewBox="0 0 1336 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="6243"
|
||||
width="16"
|
||||
height="16"
|
||||
>
|
||||
<path
|
||||
d="M49.588224 883.816448M1139.531776 883.816448M86.939648 862.977024M538.459136 960.381952c109.876224-153.544704 223.55968-289.842176 308.03968-385.787904 49.87392-56.639488 96.715776-108.155904 141.549568-154.500096 40.576-41.945088 80.805888-80.405504 119.478272-116.59264 65.92-61.693952 142.984192-130.034688 191.446016-159.30368l-61.891584-82.050048c-89.732096 56.139776-176.10752 116.103168-242.799616 162.18112-38.863872 26.855424-74.928128 52.667392-108.915712 77.252608-33.668096 24.356864-68.429824 51.106816-105.081856 79.166464-63.633408 48.712704-145.388544 114.194432-224.555008 181.860352L357.07904 374.989824 123.885568 558.770176 538.459136 960.381952zM1335.92064 862.977024"
|
||||
fill="#ffffff"
|
||||
p-id="6244"
|
||||
></path>
|
||||
</svg>
|
||||
</p>
|
||||
<span style="color: #a52a2a">停运状态</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<Table
|
||||
ref="tableRef"
|
||||
:tree-config="{ transform: true, parentField: 'uPid', rowField: 'uId' }"
|
||||
:scroll-y="{ enabled: true }"
|
||||
v-if="activeName == 0"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :name="1" :lazy="true" label="终端状态统计图">
|
||||
<charts v-if="activeName == 1" ref="chartsRef" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, watch } from 'vue'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import DatePicker from '@/components/form/datePicker/index.vue'
|
||||
import { getAreaDept } from '@/api/harmonic-boot/area'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import charts from './components/charts.vue'
|
||||
import { filterTree } from '@/utils/tree'
|
||||
defineOptions({
|
||||
name: 'harmonic-boot/area/terminalonlinerate'
|
||||
})
|
||||
const tableRef = ref()
|
||||
const chartsRef = ref()
|
||||
const dictData = useDictData()
|
||||
//字典获取电压等级
|
||||
const voltageleveloption = dictData.getBasicData('Dev_Voltage_Stand')
|
||||
//字典获取终端厂家
|
||||
const terminaloption = dictData.getBasicData('Dev_Manufacturers')
|
||||
//字典获取干扰源类型
|
||||
const interfereoption = dictData.getBasicData('Interference_Source')
|
||||
//字典获取统计类型
|
||||
const classificationData = dictData.getBasicData('Statistical_Type', ['Report_Type', 'Voltage_Level', 'Load_Type'])
|
||||
//调用区域接口获取区域
|
||||
const treeData = ref([])
|
||||
const idArr = ref([])
|
||||
const activeName = ref(0)
|
||||
const getTreeData = async () => {
|
||||
await getAreaDept().then(res => {
|
||||
var data = res.data
|
||||
data.forEach(element => {
|
||||
idArr.value.push(element.id)
|
||||
})
|
||||
treeData.value = JSON.parse(JSON.stringify(res.data))
|
||||
})
|
||||
}
|
||||
getTreeData()
|
||||
|
||||
const formData = ref({
|
||||
statisticalType: classificationData[0], //统计类型
|
||||
deptIndex: treeData.value[0]?.id, //区域选择
|
||||
scale: voltageleveloption, //电压等级
|
||||
manufacturer: terminaloption, //终端厂家
|
||||
loadType: interfereoption //干扰源类型
|
||||
// searchBeginTime: '',
|
||||
// searchEndTime: ''
|
||||
})
|
||||
formData.value.deptIndex = treeData.value[0]?.id
|
||||
const defaultProps = ref({
|
||||
label: 'name',
|
||||
value: 'id',
|
||||
checkStrictly: true,
|
||||
emitPath: false,
|
||||
expandTrigger: 'click' as const
|
||||
})
|
||||
const handleClick = (tab: any, e: any) => {
|
||||
// if(activeName.value===1){
|
||||
tableStore.index()
|
||||
// }
|
||||
}
|
||||
|
||||
// const datePickerRef = ref()
|
||||
const tableHeaderRef = ref()
|
||||
const tableStore = new TableStore({
|
||||
publicHeight: 100,
|
||||
showPage: false,
|
||||
url: '/harmonic-boot/terminal/getTerminalData',
|
||||
method: 'POST',
|
||||
|
||||
column: [
|
||||
{
|
||||
title: formData.value.statisticalType.name,
|
||||
field: 'name',
|
||||
align: 'left',
|
||||
width: 350,
|
||||
treeNode: true
|
||||
},
|
||||
{
|
||||
title: '终端个数(台)',
|
||||
field: 'number',
|
||||
align: 'center',
|
||||
formatter: function (row) {
|
||||
return row.cellValue != 0 ? row.cellValue : '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '投运(台)',
|
||||
field: 'runFlag',
|
||||
type: 'html',
|
||||
align: 'center',
|
||||
formatter: function (row) {
|
||||
return row.cellValue == 0
|
||||
? '/'
|
||||
: row.cellValue !== 0 && row.row.level !== 4
|
||||
? row.cellValue
|
||||
: row.cellValue !== 0 && row.row.level == 4 && row.row.reaFlag == 0 && row.row.stopFlag == 0
|
||||
? "<p class='table_icon' style='width: 18px;height: 18px;margin: 0 auto;display: flex;align-items: center;justify-content: center;border-radius: 50%;background: #339966'><svg t='1722910570852' class='icon' viewBox='0 0 1336 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='6243' width='16' height='16'><path d='M49.588224 883.816448M1139.531776 883.816448M86.939648 862.977024M538.459136 960.381952c109.876224-153.544704 223.55968-289.842176 308.03968-385.787904 49.87392-56.639488 96.715776-108.155904 141.549568-154.500096 40.576-41.945088 80.805888-80.405504 119.478272-116.59264 65.92-61.693952 142.984192-130.034688 191.446016-159.30368l-61.891584-82.050048c-89.732096 56.139776-176.10752 116.103168-242.799616 162.18112-38.863872 26.855424-74.928128 52.667392-108.915712 77.252608-33.668096 24.356864-68.429824 51.106816-105.081856 79.166464-63.633408 48.712704-145.388544 114.194432-224.555008 181.860352L357.07904 374.989824 123.885568 558.770176 538.459136 960.381952zM1335.92064 862.977024' fill='#ffffff' p-id='6244'></path></svg> </p>"
|
||||
: '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '检修(台)',
|
||||
field: 'reaFlag',
|
||||
type: 'html',
|
||||
align: 'center',
|
||||
formatter: function (row) {
|
||||
return row.cellValue == 0
|
||||
? '/'
|
||||
: row.cellValue !== 0 && row.row.level !== 4
|
||||
? row.cellValue
|
||||
: row.cellValue !== 0 && row.row.level == 4 && row.row.runFlag == 0 && row.row.stopFlag == 0
|
||||
? "<p class='table_icon' style='width: 18px;height: 18px;margin: 0 auto;display: flex;align-items: center;justify-content: center;border-radius: 50%;background: #ffcc33'><svg t='1722910570852' class='icon' viewBox='0 0 1336 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='6243' width='16' height='16'><path d='M49.588224 883.816448M1139.531776 883.816448M86.939648 862.977024M538.459136 960.381952c109.876224-153.544704 223.55968-289.842176 308.03968-385.787904 49.87392-56.639488 96.715776-108.155904 141.549568-154.500096 40.576-41.945088 80.805888-80.405504 119.478272-116.59264 65.92-61.693952 142.984192-130.034688 191.446016-159.30368l-61.891584-82.050048c-89.732096 56.139776-176.10752 116.103168-242.799616 162.18112-38.863872 26.855424-74.928128 52.667392-108.915712 77.252608-33.668096 24.356864-68.429824 51.106816-105.081856 79.166464-63.633408 48.712704-145.388544 114.194432-224.555008 181.860352L357.07904 374.989824 123.885568 558.770176 538.459136 960.381952zM1335.92064 862.977024' fill='#ffffff' p-id='6244'></path></svg> </p>"
|
||||
: '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '停运(台)',
|
||||
field: 'stopFlag',
|
||||
type: 'html',
|
||||
align: 'center',
|
||||
formatter: function (row) {
|
||||
return row.cellValue == 0
|
||||
? '/'
|
||||
: row.cellValue !== 0 && row.row.level !== 4
|
||||
? row.cellValue
|
||||
: row.cellValue !== 0 && row.row.level == 4 && row.row.runFlag == 0 && row.row.reaFlag == 0
|
||||
? "<p class='table_icon' style='width: 18px;height: 18px;margin: 0 auto;display: flex;align-items: center;justify-content: center;border-radius: 50%;background: #A52a2a'><svg t='1722910570852' class='icon' viewBox='0 0 1336 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='6243' width='16' height='16'><path d='M49.588224 883.816448M1139.531776 883.816448M86.939648 862.977024M538.459136 960.381952c109.876224-153.544704 223.55968-289.842176 308.03968-385.787904 49.87392-56.639488 96.715776-108.155904 141.549568-154.500096 40.576-41.945088 80.805888-80.405504 119.478272-116.59264 65.92-61.693952 142.984192-130.034688 191.446016-159.30368l-61.891584-82.050048c-89.732096 56.139776-176.10752 116.103168-242.799616 162.18112-38.863872 26.855424-74.928128 52.667392-108.915712 77.252608-33.668096 24.356864-68.429824 51.106816-105.081856 79.166464-63.633408 48.712704-145.388544 114.194432-224.555008 181.860352L357.07904 374.989824 123.885568 558.770176 538.459136 960.381952zM1335.92064 862.977024' fill='#ffffff' p-id='6244'></path></svg> </p>"
|
||||
: '/'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '在线率(%)',
|
||||
field: 'onlineRateData',
|
||||
align: 'center',
|
||||
formatter: function (row) {
|
||||
return row.cellValue == 3.14159 ? '暂无数据' : row.cellValue.toFixed(2)
|
||||
}
|
||||
}
|
||||
],
|
||||
// beforeSearchFun: () => {
|
||||
// tableStore.table.params.deptIndex = formData.value.deptIndex
|
||||
// tableStore.table.params.statisticalType = formData.value.statisticalType
|
||||
// tableStore.table.params.scale = formData.value.scale
|
||||
// tableStore.table.params.manufacturer = formData.value.manufacturer
|
||||
// tableStore.table.params.loadType = formData.value.loadType
|
||||
// tableStore.table.params.serverName = 'harmonicBoot'
|
||||
// // delete tableStore.table.params.timeFlag
|
||||
// // delete tableStore.table.params.startTime
|
||||
// // delete tableStore.table.params.endTime
|
||||
// // delete tableStore.table.params.pageNum
|
||||
// // delete tableStore.table.params.pageSize
|
||||
// // tableStore.table.params.searchBeginTime = tableHeaderRef.value.datePickerRef.timeValue[0]
|
||||
// // tableStore.table.params.searchEndTime = tableHeaderRef.value.datePickerRef.timeValue[1]
|
||||
// },
|
||||
loadCallback: () => {
|
||||
tableStore.table.data = tree2List(
|
||||
filterTree(tableStore.table.data, node => {
|
||||
return node.name.includes(tableStore.table.params.searchValue)
|
||||
}),
|
||||
Math.random() * 1000
|
||||
)
|
||||
tableStore.table.column[0].title = formData.value.statisticalType.name
|
||||
|
||||
chartsRef.value && chartsRef.value.getTableStoreParams(tableStore.table.params)
|
||||
setTimeout(() => {
|
||||
activeName.value == 0 && tableRef.value && tableRef.value.getRef().setAllTreeExpand(true)
|
||||
}, 0)
|
||||
}
|
||||
})
|
||||
tableStore.table.params.deptIndex = treeData.value[0]?.id
|
||||
tableStore.table.params.statisticalType = classificationData[0]
|
||||
tableStore.table.params.scale = voltageleveloption
|
||||
tableStore.table.params.manufacturer = terminaloption
|
||||
tableStore.table.params.loadType = interfereoption
|
||||
tableStore.table.params.serverName = 'harmonicBoot'
|
||||
tableStore.table.params.searchValue = ''
|
||||
|
||||
provide('tableStore', tableStore)
|
||||
const tree2List = (list: any, id?: string) => {
|
||||
//存储结果的数组
|
||||
let arr: any = []
|
||||
// 遍历 tree 数组
|
||||
list.forEach((item: any) => {
|
||||
item.uPid = id
|
||||
item.uId = Math.random() * 1000
|
||||
item.valueOver == 3.14159 ? 0 : item.valueOver >= 90 ? 1 : item.valueOver && item.valueOver < 90 ? 2 : 3
|
||||
// 判断item是否存在children
|
||||
if (!item.children) return arr.push(item)
|
||||
// 函数递归,对children数组进行tree2List的转换
|
||||
const children = tree2List(item.children, item.uId)
|
||||
// 删除item的children属性
|
||||
delete item.children
|
||||
// 把item和children数组添加至结果数组
|
||||
//..children: 意思是把children数组展开
|
||||
arr.push(item, ...children)
|
||||
})
|
||||
// 返回结果数组
|
||||
return arr
|
||||
}
|
||||
|
||||
onMounted(() => {})
|
||||
|
||||
watch(
|
||||
() => treeData.value,
|
||||
(val, oldVal) => {
|
||||
if (val && val.length != 0) {
|
||||
formData.value.deptIndex = val[0].id
|
||||
tableStore.index()
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.table_legend {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
ul {
|
||||
width: 280px;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
li {
|
||||
flex: 1;
|
||||
list-style-type: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
p {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
|
||||
<TableHeader date-picker area showExport>
|
||||
<TableHeader date-picker area showExport showCustomColumn>
|
||||
<template #select>
|
||||
<!-- <el-form-item label="统计类型:">
|
||||
<el-select v-model="tableStore.table.params.statisticalType" placeholder="请选择统计类型" value-key="id">
|
||||
@@ -9,21 +9,21 @@
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="电压等级:">
|
||||
<el-form-item label="电压等级">
|
||||
<el-select v-model="tableStore.table.params.scale" filterable multiple collapse-tags clearable
|
||||
placeholder="请选择电压等级" value-key="id">
|
||||
<el-option v-for="item in voltageleveloption" :key="item.id" :label="item.name" :value="item">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="终端厂家:">
|
||||
<el-form-item label="终端厂家">
|
||||
<el-select v-model="tableStore.table.params.manufacturer" filterable multiple collapse-tags
|
||||
clearable placeholder="请选择终端厂家" value-key="id">
|
||||
<el-option v-for="item in terminaloption" :key="item.id" :label="item.name" :value="item">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="干扰源类型:">
|
||||
<el-form-item label="干扰源类型">
|
||||
<el-select v-model="tableStore.table.params.loadType" filterable multiple collapse-tags clearable
|
||||
placeholder="请选择干扰源类型" value-key="id">
|
||||
<el-option v-for="item in interfereoption" :key="item.id" :label="item.name" :value="item">
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
用采数据列表
|
||||
<back-component />
|
||||
</div>
|
||||
<TableHeader :showReset="false" ref="TableHeaderRef">
|
||||
<TableHeader :showReset="false" ref="TableHeaderRef" showCustomColumn>
|
||||
<template #select>
|
||||
<el-form-item label="关键字">
|
||||
<el-form-item label="筛选数据">
|
||||
<el-input v-model="tableStore.table.params.searchValue" clearable placeholder="请输入关键字" maxlength="32" show-word-limit/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
@@ -63,6 +63,10 @@ const tableStore = new TableStore({
|
||||
method: 'POST',
|
||||
publicHeight: 52,
|
||||
column: [
|
||||
{ title: '序号', field: 'index', width: 80, formatter: (row: any) => {
|
||||
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
|
||||
}
|
||||
},
|
||||
{ title: '表名', field: 'name' },
|
||||
{ title: '起始时间', field: 'startTime' },
|
||||
{ title: '截止时间', field: 'endTime' },
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<el-dialog v-model="dialogVisible" draggable title="完整性不足详情" width="1000">
|
||||
<TableHeader :showReset="false" ref="TableHeaderRef">
|
||||
<TableHeader :showReset="false" ref="TableHeaderRef" showCustomColumn>
|
||||
<template #select>
|
||||
<el-form-item label="关键字">
|
||||
<el-form-item label="筛选数据">
|
||||
<el-input v-model="tableStore.table.params.searchValue" clearable placeholder="请输入关键字" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
@@ -27,6 +27,10 @@ const tableStore = new TableStore({
|
||||
method: 'POST',
|
||||
publicHeight: 547,
|
||||
column: [
|
||||
{ title: '序号', field: 'index', width: 80, formatter: (row: any) => {
|
||||
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
|
||||
}
|
||||
},
|
||||
{ title: '数据名', field: 'name' },
|
||||
{ title: '用户名', field: 'userName' },
|
||||
{ title: '测量点局号', field: 'lineNo' },
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<!-- 模版 -->
|
||||
<TableHeader datePicker showExport :showReset="false" ref="TableHeaderRef">
|
||||
<TableHeader datePicker showExport :showReset="false" ref="TableHeaderRef" showCustomColumn>
|
||||
<template #select>
|
||||
<!-- <el-form-item label="关键字">
|
||||
<!-- <el-form-item label="筛选数据">
|
||||
<el-input v-model="tableStore.table.params.searchValue" clearable placeholder="请输入关键字" />
|
||||
</el-form-item> -->
|
||||
</template>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
|
||||
<TableHeader datePicker area showExport>
|
||||
<TableHeader datePicker area showExport showCustomColumn>
|
||||
<template #select>
|
||||
<!-- <el-form-item label="统计类型:">
|
||||
<el-select v-model="tableStore.table.params.statisticalType" placeholder="请选择统计类型" value-key="id">
|
||||
@@ -9,26 +9,31 @@
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="电压等级:">
|
||||
<el-form-item label="电压等级">
|
||||
<el-select v-model="tableStore.table.params.scale" filterable multiple collapse-tags clearable
|
||||
placeholder="请选择电压等级" value-key="id">
|
||||
<el-option v-for="item in voltageleveloption" :key="item.id" :label="item.name" :value="item">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="终端厂家:">
|
||||
<el-form-item label="终端厂家">
|
||||
<el-select v-model="tableStore.table.params.manufacturer" filterable multiple collapse-tags
|
||||
clearable placeholder="请选择终端厂家" value-key="id">
|
||||
<el-option v-for="item in terminaloption" :key="item.id" :label="item.name" :value="item">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="干扰源类型:">
|
||||
<el-form-item label="干扰源类型">
|
||||
<el-select v-model="tableStore.table.params.loadType" filterable multiple collapse-tags clearable
|
||||
placeholder="请选择干扰源类型" value-key="id">
|
||||
<el-option v-for="item in interfereoption" :key="item.id" :label="item.name" :value="item">
|
||||
</el-option>
|
||||
</el-select>
|
||||
|
||||
</el-form-item>
|
||||
<el-form-item label="筛选数据">
|
||||
<el-input v-model="tableStore.table.params.searchValue" clearable style="width: 240px;"
|
||||
placeholder="请输入变电站、监测点、监测对象" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
@@ -62,20 +67,20 @@ const tableStore = new TableStore({
|
||||
|
||||
column: [
|
||||
{ field: 'index', title: '序号', width: '80', formatter: (row: any) => { return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1 } },
|
||||
{ field: 'provinceCompany', title: '地级区', minWidth: "150px", },
|
||||
{ field: 'cityCompany', title: '供电公司', minWidth: "150px", },
|
||||
{ field: 'provinceCompany', title: '地级市', minWidth: "150px", },
|
||||
/* { field: 'cityCompany', title: '供电公司', minWidth: "150px", },*/
|
||||
{ field: 'subName', title: '变电站', minWidth: "150px", },
|
||||
{ field: 'lineScale', title: '电压等级', minWidth: "120px", },
|
||||
{ field: 'lineObjectName', title: '监测点对象名称', minWidth: "180px", formatter: (row: any) => { return row.cellValue == null ? '/' : row.cellValue } },
|
||||
{ field: 'lineName', title: '监测点名称', minWidth: "150px", },
|
||||
{ field: 'lineScale', title: '电压等级', minWidth: "120px", },
|
||||
{ field: 'loadType', title: '干扰源类型', minWidth: "150px", },
|
||||
{ field: 'lineObjectName', title: '监测点对象名称', minWidth: "150px", formatter: (row: any) => { return row.cellValue == null ? '/' : row.cellValue } },
|
||||
{ field: 'overDay', title: '超标天数', minWidth: "80px", },
|
||||
{ field: 'freqOverDay', title: '频率偏差超标天数', minWidth: "100px", },
|
||||
{ field: 'volDevOverDay', title: '电压偏差超标天数', minWidth: "100px", },
|
||||
{ field: 'volDisOverDay', title: '电压总畸变率超标天数', minWidth: "100px", },
|
||||
{ field: 'volContainOverDay', title: '谐波电压含有率超标天数', minWidth: "110px", },
|
||||
{ field: 'harmVolOverDay', title: '谐波电压超标天数', minWidth: "100px", },
|
||||
{ field: 'harmCurOverDay', title: '谐波电流超标天数', minWidth: "100px", },
|
||||
{ field: 'freqOverDay', title: '频率偏差', minWidth: "100px", },
|
||||
{ field: 'volDevOverDay', title: '电压偏差', minWidth: "100px", },
|
||||
{ field: 'volDisOverDay', title: '电压总畸变率', minWidth: "100px", },
|
||||
{ field: 'volContainOverDay', title: '谐波电压含有率', minWidth: "100px", },
|
||||
{ field: 'harmVolOverDay', title: '谐波电压', minWidth: "100px", },
|
||||
{ field: 'harmCurOverDay', title: '谐波电流', minWidth: "100px", },
|
||||
{
|
||||
title: '各次谐波电压含有率超标天数',
|
||||
children: [
|
||||
@@ -104,10 +109,11 @@ const tableStore = new TableStore({
|
||||
|
||||
],
|
||||
},
|
||||
{ field: 'threeUnbalance', title: '三相电压不平衡度超标天数', minWidth: "110px", },
|
||||
{ field: 'negativeOverDay', title: '负序电流超标天数', minWidth: "100px", },
|
||||
{ field: 'flickerOverDay', title: '闪变超标天数', minWidth: "100px", },
|
||||
{ field: 'monitorNumber', title: '监测点编号', minWidth: "180px", formatter: (row: any) => { return row.cellValue == null ? '/' : row.cellValue } },
|
||||
{ field: 'intHarmOverDay', title: '间谐波电压含有率', minWidth: "100px", },
|
||||
{ field: 'threeUnbalance', title: '三相电压不平衡度', minWidth: "100px", },
|
||||
{ field: 'negativeOverDay', title: '负序电流', minWidth: "100px", },
|
||||
{ field: 'flickerOverDay', title: '闪变', minWidth: "100px", },
|
||||
{ field: 'monitorNumber', title: '监测点编号', minWidth: "100px", formatter: (row: any) => { return row.cellValue == null ? '/' : row.cellValue } },
|
||||
|
||||
|
||||
|
||||
@@ -125,6 +131,7 @@ tableStore.table.params.monitorFlag = 2
|
||||
tableStore.table.params.scale = []
|
||||
tableStore.table.params.manufacturer = []
|
||||
tableStore.table.params.loadType = []
|
||||
tableStore.table.params.searchValue = ''
|
||||
const wp = ref({})
|
||||
|
||||
provide('tableStore', tableStore)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<TableHeader datePicker area ref="TableHeaderRef" showExport>
|
||||
<TableHeader datePicker area ref="TableHeaderRef" showExport showCustomColumn>
|
||||
<template #select>
|
||||
<el-form-item label="统计类型">
|
||||
<el-select
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader datePicker area showExport>
|
||||
<TableHeader datePicker area showExport showCustomColumn>
|
||||
<template #select>
|
||||
<el-form-item label="统计类型:">
|
||||
<el-form-item label="统计类型">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.statisticalType"
|
||||
placeholder="请选择统计类型"
|
||||
@@ -16,7 +16,7 @@
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="电压等级:">
|
||||
<el-form-item label="电压等级">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.scale"
|
||||
filterable
|
||||
@@ -34,7 +34,7 @@
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="终端厂家:">
|
||||
<el-form-item label="终端厂家">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.manufacturer"
|
||||
filterable
|
||||
@@ -52,7 +52,7 @@
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="干扰源类型:">
|
||||
<el-form-item label="干扰源类型">
|
||||
<el-select
|
||||
v-model="tableStore.table.params.loadType"
|
||||
filterable
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template v-slot:operation>
|
||||
<el-button type="primary" icon="el-icon-Search" @click="Search">查询</el-button>
|
||||
<el-button type="primary" icon="el-icon-Download" @click="exportTemplate">导出</el-button>
|
||||
</template>
|
||||
</TableHeader>
|
||||
@@ -51,6 +52,7 @@
|
||||
:interval="datePickerRef?.interval"
|
||||
:w="item.w"
|
||||
:h="item.h"
|
||||
:searchKey="searchKey"
|
||||
/>
|
||||
<div v-else class="pd10">组件加载失败...</div>
|
||||
</div>
|
||||
@@ -114,6 +116,7 @@ const layout: any = ref([
|
||||
// path: '/src/views/pqs/runManage/assessment/components/uese/index.vue'
|
||||
// },
|
||||
])
|
||||
const searchKey = ref(0)
|
||||
const layoutCopy: any = ref([])
|
||||
const flag = ref(true)
|
||||
// 组件映射
|
||||
@@ -293,6 +296,10 @@ const fetchLayoutData = async () => {
|
||||
// 可以添加错误提示逻辑
|
||||
}
|
||||
}
|
||||
const Search = () => {
|
||||
searchKey.value += 1
|
||||
}
|
||||
|
||||
// 导出
|
||||
const exportTemplate = () => {
|
||||
console.log(123)
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="筛选数据">
|
||||
<el-input v-model="tableStore.table.params.searchValue" clearable placeholder="请输入监测点名称" />
|
||||
<el-input v-model="tableStore.table.params.searchValue" clearable style="width: 240px;" placeholder="请输入变电站、监测点、监测对象" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
@@ -159,17 +159,19 @@
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="cit" title="所在地市" minWidth="110px"></vxe-column>
|
||||
<vxe-column field="company" title="供电公司" minWidth="110px"></vxe-column>
|
||||
<vxe-column v-if="!IS_LN" field="company" title="供电公司" minWidth="110px"></vxe-column>
|
||||
<vxe-column field="subStation" title="变电站" minWidth="110px"></vxe-column>
|
||||
<vxe-column field="manufacturer" title="终端厂家" minWidth="110px"></vxe-column>
|
||||
<vxe-column field="deviceName" title="终端名称" minWidth="110px"></vxe-column>
|
||||
<vxe-column field="deviceName" title="终端名称" minWidth="130px"></vxe-column>
|
||||
<vxe-column field="ip" title="终端IP" :formatter="formatter" width="120px"></vxe-column>
|
||||
<vxe-column v-if="VITE_FLAG" field="objName" title="监测对象" minWidth="130px"></vxe-column>
|
||||
<vxe-column
|
||||
field="lineName"
|
||||
title="监测点名称"
|
||||
:formatter="formatter"
|
||||
minWidth="110px"
|
||||
minWidth="130px"
|
||||
></vxe-column>
|
||||
|
||||
<vxe-column field="runFlag" title="运行状态" width="90px">
|
||||
<template #default="{ row }">
|
||||
<el-tag
|
||||
@@ -210,18 +212,19 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { onMounted, provide, ref, watch } from 'vue'
|
||||
import { defaultAttribute } from '@/components/table/defaultAttribute'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
import { getMonitorVerifyDay } from '@/api/device-boot/dataVerify'
|
||||
const IS_LN = import.meta.env.VITE_NAME == 'LN' || import.meta.env.VITE_NAME == 'LNqr'
|
||||
|
||||
defineOptions({
|
||||
name: 'harmonic-boot/harmonic/getIntegrityData'
|
||||
})
|
||||
import { useRoute } from 'vue-router'
|
||||
const VITE_FLAG = import.meta.env.VITE_NAME != 'jibei'
|
||||
const route = useRoute()
|
||||
const dictData = useDictData()
|
||||
//字典获取监督对象类型
|
||||
@@ -275,7 +278,7 @@ const tableStore = new TableStore({
|
||||
if (tableStore.table.params.statisticalType.name == '终端厂家') {
|
||||
return k.citTotalNum != 0
|
||||
} else {
|
||||
return k.citName != '上送国网' && k.citName != '非上送国网'
|
||||
return !k.citName.includes('上送')
|
||||
}
|
||||
})
|
||||
// 合并子集数据 并去重
|
||||
@@ -336,21 +339,19 @@ const echart = () => {
|
||||
z: 0,
|
||||
zlevel: 0,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: {
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 1,
|
||||
y2: 0,
|
||||
colorStops: [
|
||||
{
|
||||
offset: 1,
|
||||
color: '#FF9100' // 100% 处的颜色
|
||||
}
|
||||
],
|
||||
global: false // 缺省为 false
|
||||
}
|
||||
color: {
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 1,
|
||||
y2: 0,
|
||||
colorStops: [
|
||||
{
|
||||
offset: 1,
|
||||
color: '#FF9100' // 100% 处的颜色
|
||||
}
|
||||
],
|
||||
global: false // 缺省为 false
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -368,34 +369,30 @@ const echart = () => {
|
||||
z: 0,
|
||||
zlevel: 0,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: {
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 1,
|
||||
y2: 0,
|
||||
colorStops: [
|
||||
{
|
||||
offset: 0,
|
||||
color: '#57bc6e' // 0% 处的颜色
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: '#57bc6e' // 100% 处的颜色
|
||||
}
|
||||
],
|
||||
global: false // 缺省为 false
|
||||
}
|
||||
color: {
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 1,
|
||||
y2: 0,
|
||||
colorStops: [
|
||||
{
|
||||
offset: 0,
|
||||
color: '#57bc6e' // 0% 处的颜色
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: '#57bc6e' // 100% 处的颜色
|
||||
}
|
||||
],
|
||||
global: false // 缺省为 false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'pictorialBar',
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: '#fff'
|
||||
}
|
||||
color: '#fff'
|
||||
},
|
||||
symbolRepeat: 50,
|
||||
// symbolMargin: 300,
|
||||
@@ -416,11 +413,9 @@ const echart = () => {
|
||||
barWidth: 18,
|
||||
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: 'transparent',
|
||||
barBorderColor: 'rgb(148,217,249)',
|
||||
barBorderWidth: 1
|
||||
}
|
||||
color: 'transparent',
|
||||
borderColor: 'rgb(148,217,249)',
|
||||
borderWidth: 1
|
||||
},
|
||||
z: 2
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<TableHeader area datePicker ref="TableHeaderRef">
|
||||
<TableHeader area datePicker ref="TableHeaderRef" showCustomColumn>
|
||||
<template #select>
|
||||
<el-form-item label="筛选数据">
|
||||
<el-input v-model="tableStore.table.params.filterName" @keyup="searchEvent" placeholder="输入关键字筛选" />
|
||||
|
||||
@@ -157,11 +157,12 @@
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="cit" title="所在地市" width="110px"></vxe-column>
|
||||
<vxe-column field="company" title="供电公司" minWidth="110px"></vxe-column>
|
||||
<vxe-column field="subStation" title="变电站" minWidth="110px"></vxe-column>
|
||||
<vxe-column field="manufacturer" title="终端厂家" minWidth="110px"></vxe-column>
|
||||
<vxe-column field="deviceName" title="终端名称" minWidth="110px"></vxe-column>
|
||||
<vxe-column v-if="!IS_LN" field="company" title="供电公司" minWidth="100px"></vxe-column>
|
||||
<vxe-column field="subStation" title="变电站" minWidth="100px"></vxe-column>
|
||||
<vxe-column field="manufacturer" title="终端厂家" minWidth="90px"></vxe-column>
|
||||
<vxe-column field="deviceName" title="终端名称" minWidth="100px"></vxe-column>
|
||||
<vxe-column field="ip" title="终端IP" :formatter="formatter" width="120px"></vxe-column>
|
||||
<vxe-column field="timeID" title="最新数据时间" :formatter="formatter" width="160px"></vxe-column>
|
||||
<vxe-column field="runFlag" title="运行状态" width="90px">
|
||||
<template #default="{ row }">
|
||||
<el-tag
|
||||
@@ -181,6 +182,19 @@
|
||||
</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="comFlag" title="通讯状态" width="90px">
|
||||
<template #default="{ row }">
|
||||
<el-tag
|
||||
:type="
|
||||
row.comFlag == '正常'
|
||||
? 'success'
|
||||
: 'danger'
|
||||
"
|
||||
>
|
||||
{{ row.comFlag }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="onlineRate" title="在线率(%)" width="90px"></vxe-column>
|
||||
</vxe-table>
|
||||
</div>
|
||||
@@ -200,20 +214,19 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// import '@/assets/font/iconfont.css'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { onMounted, provide, ref } from 'vue'
|
||||
import { defaultAttribute } from '@/components/table/defaultAttribute'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
import { getMonitorVerifyDay } from '@/api/device-boot/dataVerify'
|
||||
const IS_LN = import.meta.env.VITE_NAME == 'LN' || import.meta.env.VITE_NAME == 'LNqr'
|
||||
defineOptions({
|
||||
name: 'harmonic-boot/harmonic/getIntegrityData'
|
||||
})
|
||||
import { useRoute } from 'vue-router'
|
||||
const VITE_FLAG = import.meta.env.VITE_NAME != 'jibei'
|
||||
const route = useRoute()
|
||||
const dictData = useDictData()
|
||||
//字典获取监督对象类型
|
||||
@@ -268,7 +281,7 @@ const tableStore = new TableStore({
|
||||
if (tableStore.table.params.statisticalType.name == '终端厂家') {
|
||||
return k.citTotalNum != 0
|
||||
} else {
|
||||
return k.citName != '上送国网' && k.citName != '非上送国网'
|
||||
return !k.citName.includes('上送')
|
||||
}
|
||||
})
|
||||
// console.log(123, tableStore.table.params.statisticalType.name)
|
||||
@@ -333,21 +346,19 @@ const echart = () => {
|
||||
z: 0,
|
||||
zlevel: 0,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: {
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 1,
|
||||
y2: 0,
|
||||
colorStops: [
|
||||
{
|
||||
offset: 1,
|
||||
color: '#FF9100' // 100% 处的颜色
|
||||
}
|
||||
],
|
||||
global: false // 缺省为 false
|
||||
}
|
||||
color: {
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 1,
|
||||
y2: 0,
|
||||
colorStops: [
|
||||
{
|
||||
offset: 1,
|
||||
color: '#FF9100' // 100% 处的颜色
|
||||
}
|
||||
],
|
||||
global: false // 缺省为 false
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -359,34 +370,30 @@ const echart = () => {
|
||||
z: 0,
|
||||
zlevel: 0,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: {
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 1,
|
||||
y2: 0,
|
||||
colorStops: [
|
||||
{
|
||||
offset: 0,
|
||||
color: '#57bc6e' // 0% 处的颜色
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: '#57bc6e' // 100% 处的颜色
|
||||
}
|
||||
],
|
||||
global: false // 缺省为 false
|
||||
}
|
||||
color: {
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 1,
|
||||
y2: 0,
|
||||
colorStops: [
|
||||
{
|
||||
offset: 0,
|
||||
color: '#57bc6e' // 0% 处的颜色
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: '#57bc6e' // 100% 处的颜色
|
||||
}
|
||||
],
|
||||
global: false // 缺省为 false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'pictorialBar',
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: '#fff'
|
||||
}
|
||||
color: '#fff'
|
||||
},
|
||||
symbolRepeat: 50,
|
||||
// symbolMargin: 300,
|
||||
@@ -407,11 +414,9 @@ const echart = () => {
|
||||
barWidth: 18,
|
||||
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: 'transparent',
|
||||
barBorderColor: 'rgb(148,217,249)',
|
||||
barBorderWidth: 1
|
||||
}
|
||||
color: 'transparent',
|
||||
borderColor: 'rgb(148,217,249)',
|
||||
borderWidth: 1
|
||||
},
|
||||
z: 2
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<TableHeader datePicker ref="TableHeaderRef">
|
||||
<TableHeader datePicker ref="TableHeaderRef" >
|
||||
<template v-slot:select>
|
||||
<el-form-item label="超标指标">
|
||||
<el-select
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<el-tab-pane label="稳态指标合格率" name="2" lazy v-if="!isReload">
|
||||
<Wentaizhibiaohegelv v-if="activeName == '2'" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="稳态数据分析" name="3" lazy v-if="!isReload">
|
||||
<el-tab-pane label="稳态数据分析" name="3" lazy v-if="!isReload && !IS_LNQR">
|
||||
<Wentaishujufenxi v-if="activeName == '3'" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="谐波频谱" name="4" lazy v-if="!isReload">
|
||||
@@ -38,10 +38,10 @@
|
||||
<el-tab-pane label="告警数据统计" name="5" lazy v-if="!isReload && VITE_FLAG">
|
||||
<Gaojingshujutongji v-if="activeName == '5'" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="监测点运行状态" name="6" lazy v-if="!isReload">
|
||||
<el-tab-pane label="监测点运行状态" name="6" lazy v-if="!isReload && !VITE_FLAG1 && !IS_LNQR">
|
||||
<Yunxingzhuangtai v-if="activeName == '6'" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="实时数据" name="7" lazy v-if="!isReload && !VITE_FLAG && !VITE_FLAG1">
|
||||
<el-tab-pane label="实时数据" name="7" lazy v-if="!isReload && !VITE_FLAG1 && !IS_LNQR">
|
||||
<Shishishuju v-if="activeName == '7'" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="统计报表" name="8" lazy v-if="!isReload && VITE_FLAG">
|
||||
@@ -77,6 +77,8 @@ import { useRoute } from 'vue-router'
|
||||
import StatisticalReport from './statisticalReport/index.vue'
|
||||
const VITE_FLAG = import.meta.env.VITE_NAME == 'jibei'
|
||||
const VITE_FLAG1 = import.meta.env.VITE_NAME == 'hainan'
|
||||
// 环境标识
|
||||
const IS_LNQR = import.meta.env.VITE_NAME === 'LNqr'
|
||||
import router from '@/router'
|
||||
import { useMonitoringPoint } from '@/stores/monitoringPoint'
|
||||
import { id } from 'element-plus/es/locale'
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user