109 Commits

Author SHA1 Message Date
guanj
98e0f9de02 修改关键字 2026-05-28 19:28:12 +08:00
guanj
21756e05d4 修改地图 2026-05-27 10:47:31 +08:00
guanj
abfdf29a38 修改页面样式 调整查询条件 2026-05-22 09:58:07 +08:00
guanj
120892808b 提交代码 2026-04-25 15:21:53 +08:00
guanj
0f5cb1d3c5 提交代码 2026-04-09 11:44:06 +08:00
cdf
dbaa42ff7e 通用台账查询页面调整 2026-04-09 11:42:54 +08:00
guanj
48472bdb85 微调 2026-04-03 14:48:10 +08:00
guanj
fafc5f82c4 修改itic点击波形图 2026-03-26 14:53:34 +08:00
cdf
93ee7e4034 通用台账查询页面调整 2026-03-23 09:19:43 +08:00
guanj
7d2ce51510 修改问题 2026-03-17 08:43:51 +08:00
guanj
9202da17f1 微调 2026-03-05 15:42:15 +08:00
guanj
30eddd0572 修改用户台账管理接口 2026-03-05 11:08:36 +08:00
sjl
15bd1ac6d2 事件报告导出 2026-03-02 15:35:29 +08:00
sjl
f5c76c1b7a 报告模版配置 2026-02-27 14:46:19 +08:00
sjl
b25515b5db 系统相关配置 2026-02-27 08:49:57 +08:00
guanj
bfa061fb03 冀北数据总览添加导出功能 2026-02-06 14:45:15 +08:00
sjl
15e3d4aec8 微调 2026-02-06 10:10:24 +08:00
sjl
59489aaafa 微调 2026-01-30 15:01:19 +08:00
guanj
5d0421dd40 Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx 2026-01-29 14:10:32 +08:00
guanj
6d7ef7cf5d 修改终端型号 2026-01-29 14:10:18 +08:00
sjl
8d9ccf97a7 前置管理分配终端 2026-01-29 13:44:12 +08:00
sjl
7188e3e681 微调 2026-01-28 14:33:42 +08:00
sjl
a9fc77eb8b 区域概览未关联暂降次数和已关联处理事件合并 2026-01-28 10:33:59 +08:00
sjl
87af11288d 微调 2026-01-28 08:45:38 +08:00
sjl
0763187744 前置管理重启,稳态统计报表重置 2026-01-23 13:46:00 +08:00
sjl
ae641604ba 区域概览表格sarfi9总计 2026-01-23 09:20:57 +08:00
sjl
564e6ef4ab Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx
# Conflicts:
#	src/views/pqs/voltageSags/Region/components/echart.vue
2026-01-23 09:07:11 +08:00
sjl
c84c5dae3b 微调 2026-01-23 09:04:08 +08:00
guanj
c902dabb73 微调 2026-01-23 09:03:37 +08:00
guanj
8d1497032f Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx 2026-01-23 08:51:12 +08:00
guanj
6aeac753ef 修改触发类型 2026-01-23 08:51:03 +08:00
sjl
56d65a6c17 9000系统测试用例调整 2026-01-22 16:15:33 +08:00
sjl
8b356c87a3 微调 2026-01-20 14:33:06 +08:00
guanj
c0feeaee7b 删除海南备份技术监督 2026-01-20 14:25:24 +08:00
guanj
6a112c8ae2 修改表格操作列 2026-01-20 14:18:41 +08:00
guanj
a19952b771 调整云南曲靖问题 2026-01-16 14:03:40 +08:00
guanj
0b76347853 Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx 2026-01-12 14:49:30 +08:00
guanj
379951699d 修改日志 2026-01-12 14:49:21 +08:00
sjl
003737cf52 Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx 2026-01-12 14:02:06 +08:00
sjl
20e6d3719a 微调 2026-01-12 14:01:43 +08:00
guanj
77617412dd Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx
# Conflicts:
#	src/views/pqs/voltageSags/monitoringPoint/online/navigation/index.vue
修改冲突
2026-01-12 14:01:09 +08:00
guanj
68ea43c42b 修改在线监测数据问题 2026-01-12 13:56:49 +08:00
sjl
e65df4daad Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx
# Conflicts:
#	src/views/pqs/voltageSags/monitoringPoint/online/navigation/index.vue
2026-01-12 11:24:34 +08:00
sjl
136248eec2 角色用户管理,区域概览 2026-01-12 11:22:42 +08:00
guanj
bfafb6dc5b 修改曲靖问题 2026-01-12 11:19:05 +08:00
sjl
0b91027da4 微调 2026-01-09 11:21:07 +08:00
guanj
22aeb0bf4c Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx 2026-01-09 11:20:10 +08:00
guanj
87bc9d9017 添加绑定监测点筛选 2026-01-09 11:20:02 +08:00
sjl
43d4d37cd0 Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx 2026-01-09 10:45:07 +08:00
sjl
ad1528e53b 导出日志 2026-01-09 10:44:35 +08:00
guanj
c1e36440e7 修改实时数据 2026-01-09 10:40:55 +08:00
guanj
16f5213d7a Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx 2026-01-09 08:47:18 +08:00
guanj
ab891e6125 修改角色管理页面 2026-01-09 08:47:07 +08:00
sjl
36c8ab87a2 微调 2026-01-08 15:17:19 +08:00
guanj
6c3037f19b 修改云南曲靖项目 2026-01-08 14:52:01 +08:00
sjl
54517c0d5f 稳态合格率,畸变率表格调整 2026-01-08 14:50:29 +08:00
guanj
715cdb892f 修改树 2026-01-07 08:38:45 +08:00
sjl
953b96fe05 Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx
# Conflicts:
#	src/components/tree/pqs/bearingTree.vue
#	src/views/pqs/harmonicMonitoring/monitoringPoint/online/wentaizhibiaohegelv/index.vue
2026-01-06 08:38:11 +08:00
sjl
cb19fef4c6 微调 2026-01-06 08:35:36 +08:00
guanj
98c887b79d 添加云南曲靖打包命令修改5层树逻辑 2026-01-05 10:13:53 +08:00
guanj
fd09e24cf0 Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx 2026-01-04 09:01:56 +08:00
guanj
2a11891988 正则替换[] 2026-01-04 09:01:32 +08:00
sjl
e7d90c3a73 微调 2026-01-04 08:39:17 +08:00
sjl
72b1f39814 预告警单 2025-12-31 08:36:14 +08:00
sjl
38028b5cb0 预告警查看报告 2025-12-30 10:16:56 +08:00
sjl
409999b37b Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx
# Conflicts:
#	src/components/PreviewFile/index.vue
2025-12-30 10:05:00 +08:00
sjl
0fc7b528d4 微调 2025-12-30 10:02:01 +08:00
guanj
06764c073a 修改算法库 2025-12-29 20:46:24 +08:00
guanj
26ff8087c6 修改冀北现场问题 2025-12-29 19:44:17 +08:00
sjl
83e57c92b4 区域,海南不调getLastData 2025-12-26 11:16:48 +08:00
sjl
a9245abb5c 稳态数据分析趋势图值显示 2025-12-25 18:56:57 +08:00
sjl
7a7c584217 微调 2025-12-25 18:21:25 +08:00
sjl
bf3d033f39 预览小眼睛放开 2025-12-25 15:11:52 +08:00
guanj
42ce7aec5a Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx 2025-12-25 13:19:37 +08:00
guanj
17589e30da 修改文件预览 2025-12-25 13:19:24 +08:00
sjl
eb38fdd601 稳态数据调整 2025-12-25 13:17:49 +08:00
sjl
454d612a32 完整性图表 2025-12-24 16:06:03 +08:00
sjl
4dde761784 暂态事件列表调整 2025-12-24 13:17:49 +08:00
GGJ
5f4f75d9dd 修改稳态告警统计,异常数据清洗详情 2025-12-24 11:22:57 +08:00
sjl
cf7e5fa991 数据完整性图表显示 2025-12-24 11:19:41 +08:00
sjl
4f0dc512e2 Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx 2025-12-24 10:42:23 +08:00
sjl
a77b153ac8 微调 2025-12-24 10:42:17 +08:00
sjl
dbb6a9f72b 修改部分预览,数据完整性,暂态列表等bug调整 2025-12-24 10:41:04 +08:00
GGJ
9567fe1295 添加海南打包命令 2025-12-24 10:38:27 +08:00
sjl
a52021572a 解决下载路径为空 2025-12-22 15:13:43 +08:00
GGJ
d69a6e1e5d Merge branch 'master' of http://pqmcc.com:3000/Web/admin-sjzx
# Conflicts:
#	src/views/pqs/supervise/technology/feedbackPopup.vue
2025-12-19 14:08:17 +08:00
GGJ
a67535abbf 修改打包报错 2025-12-19 14:05:56 +08:00
sjl
dffc735edb 待办任务提交审核返回刷新 2025-12-19 13:27:18 +08:00
sjl
38806367b4 Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx 2025-12-19 13:12:46 +08:00
sjl
6f770aa91d 修改文件查看只有冀北可行 2025-12-19 13:12:38 +08:00
GGJ
dc32cc3bb7 修改冀北现场反馈问题 2025-12-19 11:58:26 +08:00
sjl
d64d18f330 微调 2025-12-19 10:56:30 +08:00
sjl
909f43e257 电能质量异常管理,谐波测试计划管理bug修改 2025-12-18 16:09:44 +08:00
GGJ
92aa66436e 修改冀北现场问题 2025-12-17 09:22:19 +08:00
GGJ
264f33302f 修改冀北问题 2025-12-16 13:38:12 +08:00
sjl
7b9f5302d0 流程图时间和结果,流程审核表单默认勾选 2025-12-16 11:15:27 +08:00
sjl
72d836020b 编辑打开时,干扰源类型决定类别 2025-12-15 17:41:49 +08:00
sjl
67efef738a 干扰源接入,终端检测,台账管理bug修复 2025-12-15 16:19:33 +08:00
GGJ
6918611d06 添加上传全局提示 2025-12-15 10:35:34 +08:00
GGJ
9f5b2ecc46 修改冀北现场反馈问题 2025-12-15 09:33:34 +08:00
sjl
d30b8247cf 微调 2025-12-15 09:24:25 +08:00
GGJ
0b61c4b7ba 修改冀北现场问题 2025-12-14 12:47:53 +08:00
sjl
ff2b9db7b8 我的任务,干扰源分析,常态化干扰源用户管理,终端检测,bug调整 2025-12-12 15:44:56 +08:00
sjl
289900f9ff Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx 2025-12-12 09:29:16 +08:00
sjl
e87d05c587 微调 2025-12-12 09:29:09 +08:00
GGJ
46c55d48ec 修改冀北现场问题 2025-12-12 09:26:56 +08:00
GGJ
b36f765d07 修改技术监督 2025-12-11 15:03:11 +08:00
guanj
0fe2d2b911 修改冀北问题 2025-12-09 20:04:55 +08:00
guanj
8c41a8fc77 冀北问题修改 2025-12-08 16:28:34 +08:00
536 changed files with 81486 additions and 87859 deletions

5
.env.hainan Normal file
View File

@@ -0,0 +1,5 @@
NODE_ENV = hainan
VITE_NAME="hainan"
# 电网一张图 地图图层
VITE_NARIMAP=null
VITE_NRGISCOMMON=null

6
.env.qujing Normal file
View File

@@ -0,0 +1,6 @@
# 云南曲靖
NODE_ENV = qujing
VITE_NAME="qujing"
# 电网一张图 地图图层
VITE_NARIMAP=null
VITE_NRGISCOMMON=null

156
README.md
View File

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

View File

@@ -15,7 +15,7 @@
<script src="/static/luckysheet/plugin.js"></script> <script src="/static/luckysheet/plugin.js"></script>
<script src="/static/luckysheet/luckysheet.umd.js"></script> <script src="/static/luckysheet/luckysheet.umd.js"></script>
<!-- 冀北地图 --> <!-- jb地图 -->
<!--引入样式文件--> <!--引入样式文件-->
<script src="%VITE_NARIMAP%"></script> <script src="%VITE_NARIMAP%"></script>
<!-- <script src="%VITE_NRGISCOMMON%"></script> --> <!-- <script src="%VITE_NRGISCOMMON%"></script> -->

8813
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -6,9 +6,13 @@
"scripts": { "scripts": {
"dev": "vite --mode dev", "dev": "vite --mode dev",
"dev:jibei": "vite --mode jibei", "dev:jibei": "vite --mode jibei",
"dev:hainan": "vite --mode hainan",
"dev:qujing": "vite --mode qujing",
"dev:removeMode": "vite --mode removeMode", "dev:removeMode": "vite --mode removeMode",
"build": "vite build --mode dev", "build": "vite build --mode dev",
"build:jibei": "vite build --mode jibei", "build:jibei": "vite build --mode jibei",
"build:hainan": "vite build --mode hainan",
"build:qujing": "vite build --mode qujing",
"build:removeMode": "vite build --mode removeMode", "build:removeMode": "vite build --mode removeMode",
"preview": "vite preview" "preview": "vite preview"
}, },
@@ -19,7 +23,7 @@
"@form-create/element-ui": "^3.1.24", "@form-create/element-ui": "^3.1.24",
"@fortawesome/fontawesome-free": "^6.5.1", "@fortawesome/fontawesome-free": "^6.5.1",
"@kjgl77/datav-vue3": "^1.7.4", "@kjgl77/datav-vue3": "^1.7.4",
"@vue-office/docx": "^1.6.2", "@vue-office/docx": "^1.6.3",
"@vue-office/excel": "^1.7.8", "@vue-office/excel": "^1.7.8",
"@vue-office/pdf": "^2.0.2", "@vue-office/pdf": "^2.0.2",
"@vueuse/core": "^10.7.0", "@vueuse/core": "^10.7.0",

BIN
public/favicon4.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -13,9 +13,11 @@ onMounted(async () => {
const response = await fetch('/') const response = await fetch('/')
const WebSocketUrl:any = response.headers.get('X-WebSocket-Url') const WebSocketUrl:any = response.headers.get('X-WebSocket-Url')
const WebSocketUrl2:any = response.headers.get('X-WebSocket-Url2') 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') const MqttUrl:any = response.headers.get('X-MqttUrl-Url')
localStorage.setItem('WebSocketUrl2', WebSocketUrl2)
localStorage.setItem('WebSocketUrl', WebSocketUrl) localStorage.setItem('WebSocketUrl', WebSocketUrl)
localStorage.setItem('WebSocketUrl2', WebSocketUrl2)
localStorage.setItem('WebSocketUrl3', WebSocketUrl3)
localStorage.setItem('MqttUrl', MqttUrl) localStorage.setItem('MqttUrl', MqttUrl)
}) })
</script> </script>

View File

@@ -1,5 +1,6 @@
import createAxios from '@/utils/request' import createAxios from '@/utils/request'
// 密码规则修改 // 密码规则修改
export function ruleUpdate(data) { export function ruleUpdate(data) {
return createAxios({ return createAxios({
@@ -24,3 +25,77 @@ export function unlockRoot(data) {
data data
}) })
} }
//根据客户端名查询信息
export function getClientInfoByPath() {
return createAxios({
url: '/user-boot/authClient/getAuthClientByName/njcn',
method: 'GET',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
}
//客户端会话配置更新
export function updateClientSessionConfig(data) {
return createAxios({
url: '/user-boot/authClient/sessionConfigUpdate',
method: 'post',
data
})
}
//获取用户配置
export function getUserConfig() {
return createAxios({
url: '/user-boot/password/getUserStrategyList',
method: 'post'
})
}
//查询系统列表
export function getSystemList() {
return createAxios({
url: '/system-boot/config/getSysConfigData',
method: 'get'
})
}
//激活系统配置
export function activeSystemConfig(data) {
return createAxios({
url: '/system-boot/config/updateSysConfig',
method: 'post',
data
})
}
//删除系统配置
export function deleteSystemConfig( data) {
return createAxios({
url: '/system-boot/config/removeSysConfigById',
method: 'get',
params: data
})
}
//新增系统配置
export function addSystemConfig(data) {
return createAxios({
url: '/system-boot/config/addSysConfig',
method: 'post',
data
})
}
//修改系统配置
export function updateSystemConfig(data) {
return createAxios({
url: '/system-boot/config/updateSysConfig',
method: 'post',
data
})
}

View File

@@ -129,11 +129,27 @@ export function queryAllByType(params: any) {
//获取用户 //获取用户
export function selectUserList(data: any) { export function selectUserList(data: any) {
return createAxios({ return createAxios({
url: '/supervision-boot/userReport/selectUserList', url: '/device-boot/userReport/selectUserList',
method: 'post', method: 'post',
data data
}) })
} }
//获取用户
export function selectUserAssessMentList(data: any) {
return createAxios({
url: '/supervision-boot/userReport/selectUserAssessMentList',
method: 'post',
data
})
}
//绑定用户
export function bindAssessmentId(data: any) {
return createAxios({
url: '/supervision-boot/userReport/bindAssessmentId',
method: 'get',
params: data
})
}
//查询列表 //查询列表
export function getStatusManageList(data: any) { export function getStatusManageList(data: any) {
return createAxios({ return createAxios({
@@ -190,3 +206,11 @@ export function exportTerminalBase() {
responseType: 'blob' responseType: 'blob'
}) })
} }
//一键分配终端
export function allotTerminal(data: any) {
return createAxios({
url: '/device-boot/nodeDevice/oneKeyDistribution',
method: 'post',
params: data
})
}

View File

@@ -1,32 +1,57 @@
import request from '@/utils/request' import request from '@/utils/request'
import { DEVICE_BOOT } from '@/utils/constantRequest' import { DEVICE_BOOT } from '@/utils/constantRequest'
const MAPPING_PATH = DEVICE_BOOT + '/line' const MAPPING_PATH = DEVICE_BOOT + '/line'
/** /**
* 查询终端详细信息 * 查询终端详细信息
*/ */
export const getDeviceDetailData = (id: string) => { export const getDeviceDetailData = (id: string) => {
return request({ return request({
url: MAPPING_PATH + '/getDeviceDetailData?id=' + id, url: MAPPING_PATH + '/getDeviceDetailData?id=' + id,
method: 'POST' method: 'POST'
}) })
} }
/** /**
* 查询监测点详细信息 * 查询监测点详细信息
*/ */
export const getLineDetailData = (id: string) => { export const getLineDetailData = (id: string) => {
return request({ return request({
url: MAPPING_PATH + '/getLineDetailData?id=' + id, url: MAPPING_PATH + '/getLineDetailData?id=' + id,
method: 'POST' method: 'POST'
}) })
} }
export const getSubstationSelect = () => { export const getSubstationSelect = () => {
return request({ return request({
url: 'device-boot/substation/getSubstationSelect', url: 'device-boot/substation/getSubstationSelect',
method: 'get' method: 'get'
}) })
} }
// 查询变电站详情
export const getSubstationSelectLine = (id: string) => {
return request({
url: '/device-boot/line/getSubstationData',
method: 'post',
data: [id]
})
}
// 查询监测点
export const getLineOverLimitData = (id: string) => {
return request({
url: '/device-boot/line/getLineOverLimitData?id=' + id,
method: 'post'
})
}
//导出数据总览
export function dataVerifyExcel(params: any) {
return request({
url: '/device-boot/dataVerify/dataVerifyExcel',
method: 'get',
params,
responseType: 'blob'
})
}

View File

@@ -31,4 +31,13 @@ export function getDevTypeList() {
method: 'post', method: 'post',
}) })
}
export const getDeviceTypeList = (params: any) => {
return createAxios({
url: '/device-boot/devType/pageDevTypeList',
method: 'POST',
data: params
})
} }

View File

@@ -165,3 +165,20 @@ export function getSupervisionDetailsData(data: any) {
export function getSupervisionCityDetailsData(data: any) { export function getSupervisionCityDetailsData(data: any) {
return request({ url: '/supervision-boot/gridDiagram/getSupervisionCityDetailsData', method: 'post', data }) return request({ url: '/supervision-boot/gridDiagram/getSupervisionCityDetailsData', method: 'post', data })
} }
//区域污染值统计
export function getAreaPollution(data: any) {
return request({ url: '/harmonic-boot/PollutionSubstation/getAreaPollution', method: 'post', data })
}
//场站级评估
export function downPollutionSubCalc(data: any) {
return request({ url: '/harmonic-boot/PollutionSubstation/downPollutionSubCalc', method: 'post', data })
}
//监测点评价
export function limitTableDetail(data: any) {
return request({ url: '/device-boot/dataVerify/limitTableDetail', method: 'post', data })
}
//重要及敏感用户详情
export function downPollutionSensitiveUser(data: any) {
return request({ url: '/harmonic-boot/PollutionSubstation/downPollutionSensitiveUser', method: 'post', data })
}

View File

@@ -0,0 +1,103 @@
import request from '@/utils/request'
// 新增敏感用户
export function saveUser(data: any) {
return request({
url: '/device-boot/pqSensitiveUser/save',
method: 'post',
data: data
})
}
// 修改敏感用户
export function updateUser(data: any) {
return request({
url: '/device-boot/pqSensitiveUser/update',
method: 'post',
data: data
})
}
// 删除敏感用户
export function deleteUser(data: any) {
return request({
url: '/device-boot/pqSensitiveUser/delete',
method: 'post',
data: data
})
}
/**
* 干扰源接入功能删除流程
*/
export const deleteUserReport = (data: any) => {
return request({
url: '/device-boot/userReport/deleteUserReport',
method: 'POST',
data
})
}
/**
* 提交表单数据
*/
export const submitFormData = (data: any) => {
return request({
url: '/device-boot/userReport/add',
method: 'POST',
data: data
})
}
// 根据id获取用户档案录入的详细数据
export const getById = (data: any) => {
return request({
url: '/device-boot/userReport/getById',
method: 'get',
params: data
})
}
/**
* 提交表单数据
*/
export const addEditor = (data: any) => {
return request({
url: '/device-boot/userReportRenewal/addEditor',
method: 'POST',
data: data
})
}
// 根据id获取用户档案录入的详细数据
export const getByDeptDevLine = (params: any) => {
return request({
url: '/device-boot/line/getByDeptDevLine',
method: 'get',
params
})
}
/**
* 根据id获取用户档案录入的详细数据
*/
export const getUserReportUpdateById = (id: any) => {
return request({
url: '/device-boot/userReportRenewal/getUserReportUpdateById?businessId='+id,
method: 'POST',
})
}
// 根据id获取用户档案录入的详细数据
export const getUserReportById = (id: any) => {
return request({
url: '/device-boot/userReport/getUserReportById?id='+id,
method: 'get'
})
}
// 根据id查询文件信息集合
export const getFileById = (params: any) => {
return request({
url: '/device-boot/fileUrl/getFileById',
method: 'get',
params
})
}

View File

@@ -1,72 +1,137 @@
import createAxios from '@/utils/request' import createAxios from '@/utils/request'
import { genFileId, ElMessage, ElNotification } from 'element-plus'
//事件报告
export function getEventReport(data) { //事件报告
return createAxios({ // export function getEventReport(data) {
url: '/event-boot/report/getEventReport', // return createAxios({
method: 'post', // url: '/event-boot/report/getEventReport',
data // method: 'post',
}) // data
} // })
// 生成报告 // }
export function getAreaReport(data) {
return createAxios({ export function getEventReport(data) {
url: '/event-boot/report/getAreaReport', return createAxios({
method: 'post', url: '/event-boot/report/createEventReport',
data, method: 'post',
responseType: 'blob' data,
}) responseType: 'blob'
} }).then(async res => {
//查询所有模板 let load: any = await readJsonBlob(res)
export function getList(data) { if (load.code) {
return createAxios({ if (load.data.code == 'A0011') {
url: '/system-boot/EventTemplate/getList', ElMessage.warning('下载失败!')
method: 'post', } else {
data ElMessage.warning(load.data.message)
}) }
} } else {
export function selectReleation(data) { return res
return createAxios({ }
url: '/system-boot/EventTemplate/selectReleation', })
method: 'post', }
params: data
})
} // 生成报告
export function getLineExport(data) { export function getAreaReport(data) {
return createAxios({ return createAxios({
url: '/event-boot/report/getLineExport', url: '/event-boot/report/getAreaReport',
method: 'post', method: 'post',
data: data, data,
responseType: 'blob' responseType: 'blob'
}) }).then(async res => {
} let load: any = await readJsonBlob(res)
export function getVoltage(data: any) { if (load.code) {
return createAxios({ if (load.data.code == 'A0011') {
url: '/event-boot/report/getVoltage', ElMessage.warning('下载失败!')
method: 'post', } else {
data ElMessage.warning(load.data.message)
}) }
} } else {
export function getGeneralSituation(data: any) { return res
return createAxios({ }
url: '/event-boot/report/getGeneralSituation', })
method: 'post', }
data async function readJsonBlob(blob) {
}) try {
} // 1. Blob.text() 读取二进制 → 直接转为 字符串(自动处理编码)
export function getTransientValue(data: any) { const jsonStr = await blob.text()
return createAxios({ // 2. JSON.parse 解析字符串 → 得到可用的 JS 对象/数组
url: '/event-boot/transient/getTransientValue', const jsonData = JSON.parse(jsonStr)
method: 'post', // 3. 拿到数据,后续随便用
data return {
}) code: true,
} data: jsonData
// 周报导出 }
export function getExport(data: any) { } catch (err) {
return createAxios({ return {
url: '/event-boot/report/getExport', code: false,
method: 'post', data: {}
data, }
responseType: 'blob' // console.error('解析Blob的JSON数据失败', err)
}) }
} }
//查询所有模板
export function getList(data) {
return createAxios({
url: '/system-boot/EventTemplate/getList',
method: 'post',
data
})
}
export function selectReleation(data) {
return createAxios({
url: '/system-boot/EventTemplate/selectReleation',
method: 'post',
params: data
})
}
export function getLineExport(data) {
return createAxios({
url: '/event-boot/report/getLineExport',
method: 'post',
data: data,
responseType: 'blob'
}).then(async res => {
let load: any = await readJsonBlob(res)
if (load.code) {
if (load.data.code == 'A0011') {
ElMessage.warning('下载失败!')
} else {
ElMessage.warning(load.data.message)
}
} else {
return res
}
})
}
export function getVoltage(data: any) {
return createAxios({
url: '/event-boot/report/getVoltage',
method: 'post',
data
})
}
export function getGeneralSituation(data: any) {
return createAxios({
url: '/event-boot/report/getGeneralSituation',
method: 'post',
data
})
}
export function getTransientValue(data: any) {
return createAxios({
url: '/event-boot/transient/getTransientValue',
method: 'post',
data
})
}
// 周报导出
export function getExport(data: any) {
return createAxios({
url: '/event-boot/report/getExport',
method: 'post',
data,
responseType: 'blob'
})
}

View File

@@ -1,106 +1,114 @@
import request from '@/utils/request' import request from '@/utils/request'
export function getTypeIdData(data: any) { export function getTypeIdData(data: any) {
return request({ return request({
url: '/system-boot/dictData/getTypeIdData', url: '/system-boot/dictData/getTypeIdData',
method: 'post', method: 'post',
data: data data: data
}) })
} }
export function getOnlineRateData2(data:any) { export function getOnlineRateData2(data:any) {
return request({ return request({
url: '/harmonic-boot/onlineRateData/getOnlineRateData', url: '/harmonic-boot/onlineRateData/getOnlineRateData',
method: 'post', method: 'post',
data: data data: data
}) })
} }
export function getAreaDept() { export function getAreaDept() {
return request({ return request({
url: '/user-boot/dept/loginDeptTree', url: '/user-boot/dept/loginDeptTree',
method: 'post' method: 'post'
}) })
} }
export function getOnlineRateDataCensus(data:any) { // 承载能力评估去除前缀
return request({ export function getAreaDeptRemoveMode(params) {
url: '/device-boot/terminalOnlineRateData/getOnlineRateDataCensus', return request({
method: 'post', url: '/user-boot/dept/loginDeptTree',
data: data method: 'GET',
}) params: params
} })
export function IntegrityIcon(data:any) { }
return request({ export function getOnlineRateDataCensus(data:any) {
url: '/harmonic-boot/integrity/getIntegrityIcon', return request({
method: 'post', url: '/device-boot/terminalOnlineRateData/getOnlineRateDataCensus',
data: data method: 'post',
}) data: data
} })
export function getDeptIdAreaTree() { }
return request({ export function IntegrityIcon(data:any) {
url: '/system-boot/area/getDeptIdAreaTree', return request({
method: 'post' url: '/harmonic-boot/integrity/getIntegrityIcon',
}) method: 'post',
} data: data
export function getOnlineRateData(data:any) { })
return request({ }
url: '/device-boot/terminalOnlineRateData/getOnlineRateData', export function getDeptIdAreaTree() {
method: 'post', return request({
data: data url: '/system-boot/area/getDeptIdAreaTree',
}) method: 'post'
} })
export function getSubstationInfoById(data:any) { }
return request({ export function getOnlineRateData(data:any) {
url: '/harmonic-boot/PollutionSubstation/getSubstationInfoById', return request({
method: 'post', url: '/device-boot/terminalOnlineRateData/getOnlineRateData',
data: data method: 'post',
}) data: data
} })
export function getLineInfoById(data:any) { }
return request({ export function getSubstationInfoById(data:any) {
url: '/harmonic-boot/PollutionSubstation/getLineInfoById', return request({
method: 'post', url: '/harmonic-boot/PollutionSubstation/getSubstationInfoById',
data: data method: 'post',
}) data: data
} })
export function getLineRank(data:any) { }
return request({ export function getLineInfoById(data:any) {
url: '/harmonic-boot/PollutionSubstation/getLineRank', return request({
method: 'post', url: '/harmonic-boot/PollutionSubstation/getLineInfoById',
data: data method: 'post',
}) data: data
} })
export function deptInfo(data:any) { }
return request({ export function getLineRank(data:any) {
url: '/harmonic-boot/detailAnalysis/deptInfo', return request({
method: 'post', url: '/harmonic-boot/PollutionSubstation/getLineRank',
data: data method: 'post',
}) data: data
} })
export function getXbLineInfoById(data:any) { }
return request({ export function deptInfo(data:any) {
url: '/harmonic-boot/detailAnalysis/getXbLineInfoById', return request({
method: 'post', url: '/harmonic-boot/detailAnalysis/deptInfo',
data: data method: 'post',
}) data: data
} })
export function getSubInfoById(data:any) { }
return request({ export function getXbLineInfoById(data:any) {
url: '/harmonic-boot/detailAnalysis/getSubInfoById', return request({
method: 'post', url: '/harmonic-boot/detailAnalysis/getXbLineInfoById',
data: data method: 'post',
}) data: data
} })
export function getXbLineRank(data:any) { }
return request({ export function getSubInfoById(data:any) {
url: '/harmonic-boot/detailAnalysis/getXbLineRank', return request({
method: 'post', url: '/harmonic-boot/detailAnalysis/getSubInfoById',
data: data method: 'post',
}) data: data
} })
// 数据补招 }
export function FullRecall(data:any) { export function getXbLineRank(data:any) {
return request({ return request({
url: '/data-processing-boot/data/FullRecall', url: '/harmonic-boot/detailAnalysis/getXbLineRank',
method: 'post', method: 'post',
data: data data: data
}) })
} }
// 数据补招
export function FullRecall(data:any) {
return request({
url: '/data-processing-boot/data/FullRecall',
method: 'post',
data: data
})
}

View File

@@ -1,18 +1,48 @@
import request from '@/utils/request' import request from '@/utils/request'
import { genFileId, ElMessage, ElNotification } from 'element-plus'
export function getHistoryResult(data: any) { export function getHistoryResult(data: any) {
return request({ return request({
url: '/harmonic-boot/harmonic/getHistoryResult', url: '/harmonic-boot/harmonic/getHistoryResult',
method: 'post', method: 'post',
data: data data: data
}) })
} }
// word报告 // word报告
export function exportModelJB(data: any) { export function exportModelJB(data: any) {
return request({ return request({
url: '/harmonic-boot/exportmodel/exportModelJB', url: '/harmonic-boot/exportmodel/exportModelJB',
method: 'post', method: 'post',
responseType: 'blob', responseType: 'blob',
data: data data: data
}) }).then(async res => {
} let load: any = await readJsonBlob(res)
if (load.code) {
if (load.data.code == 'A0011') {
ElMessage.warning('下载失败!')
} else {
ElMessage.warning(load.data.message)
}
} else {
return res
}
})
}
async function readJsonBlob(blob) {
try {
// 1. Blob.text() 读取二进制 → 直接转为 字符串(自动处理编码)
const jsonStr = await blob.text()
// 2. JSON.parse 解析字符串 → 得到可用的 JS 对象/数组
const jsonData = JSON.parse(jsonStr)
// 3. 拿到数据,后续随便用
return {
code: true,
data: jsonData
}
} catch (err) {
return {
code: false,
data: {}
}
// console.error('解析Blob的JSON数据失败', err)
}
}

View File

@@ -6,7 +6,7 @@ export function getUndocumentednonlinearData() {
method: 'get' method: 'get'
}) })
} }
//获取入网评估报告审核数据 //获取系统接入方案审核数据
export function getReportreviewData() { export function getReportreviewData() {
return createAxios({ return createAxios({
url: '/Process-supervision/Reportreview/getReportreview', url: '/Process-supervision/Reportreview/getReportreview',

View File

@@ -1,10 +1,60 @@
import createAxios from '@/utils/request' import createAxios from '@/utils/request'
import { genFileId, ElMessage, ElNotification } from 'element-plus'
export function exportModel(data: any) {
return createAxios({ export function exportModel(data: any) {
url: '/harmonic-boot/exportmodel/exportModel', return createAxios({
method: 'post', url: '/harmonic-boot/exportmodel/exportModel',
data: data, method: 'post',
responseType: 'blob' data: data,
}) responseType: 'blob'
} }).then(async res => {
let load: any = await readJsonBlob(res)
if (load.code) {
if (load.data.code == 'A0011') {
ElMessage.warning('下载失败!')
} else {
ElMessage.warning(load.data.message)
}
} else {
return res
}
})
}
export function areaHarmonicReport(data: any) {
return createAxios({
url: '/harmonic-boot/areaHarmonicReport/areaHarmonicReport',
method: 'post',
data: data,
responseType: 'blob'
}).then(async res => {
let load: any = await readJsonBlob(res)
if (load.code) {
if (load.data.code == 'A0011') {
ElMessage.warning('下载失败!')
} else {
ElMessage.warning(load.data.message)
}
} else {
return res
}
})
}
async function readJsonBlob(blob) {
try {
// 1. Blob.text() 读取二进制 → 直接转为 字符串(自动处理编码)
const jsonStr = await blob.text()
// 2. JSON.parse 解析字符串 → 得到可用的 JS 对象/数组
const jsonData = JSON.parse(jsonStr)
// 3. 拿到数据,后续随便用
return {
code: true,
data: jsonData
}
} catch (err) {
return {
code: false,
data: {}
}
// console.error('解析Blob的JSON数据失败', err)
}
}

View File

@@ -0,0 +1,42 @@
import request from "@/utils/request";
//查询所有模板
export function getList(data: any) {
return request({
url: "/system-boot/EventTemplate/getList",
method: "post",
data,
});
}
//字典树
export function getDictTree(data: any) {
return request({
url: "/system-boot/reportDict/DictTree",
method: "post",
params:data
});
}
//新增模板
export function addData(data: any) {
return request({
url: "/system-boot/EventTemplate/add",
method: "post",
data,
});
}
//修改模板
export function updateData(data: any) {
return request({
url: "/system-boot/EventTemplate/update",
method: "post",
data,
});
}
//删除模板
export function deleteData(data: any) {
return request({
url: "/system-boot/EventTemplate/delete",
method: "post",
data,
});
}

View File

@@ -0,0 +1,43 @@
import request from '@/utils/request'
//获取字典树数据
export function getDictTree(data) {
return request({
url: "/system-boot/reportDict/DictTree",
method: "post",
params:data
});
}
//查询字典列表
export function getReportDictList(data: any) {
return request({
url: "/system-boot/reportDict/getReportDictList",
method: "post",
data
});
}
//新增字典表
export function addDict(data: any) {
return request({
url: "/system-boot/reportDict/addDict",
method: "post",
data
});
}
//更新字典表
export function updateDict(data: any) {
return request({
url: "/system-boot/reportDict/updateDict",
method: "put",
data
});
}
//删除字典表
export function deleteDict(data: any) {
return request({
url: "/system-boot/reportDict/deleteDict",
method: "delete",
params:data
});
}

View File

@@ -0,0 +1,37 @@
import request from '@/utils/request'
//区域树形表格接口
export function areaTree(data: any) {
return request({
url: '/system-boot/area/areaTree',
method: 'post',
params: data,
})
}
export function areaAdd(data: any) {
return request({
url: '/system-boot/area/add',
method: 'post',
data: data,
})
}
export function areaDelete(data: any) {
return request({
url: '/system-boot/area/delete',
method: 'post',
data: data,
})
}
export function update(data: any) {
return request({
url: '/system-boot/area/update',
method: 'post',
data: data,
})
}
export function selectPid(data: any) {
return request({
url: '/system-boot/area/selectPid',
method: 'post',
data: data,
})
}

View File

@@ -1,5 +1,5 @@
import createAxios from '@/utils/request' import createAxios from '@/utils/request'
import { ElMessage } from 'element-plus'
const SYSTEM_PREFIX = '/system-boot' const SYSTEM_PREFIX = '/system-boot'
/** /**
@@ -7,8 +7,20 @@ const SYSTEM_PREFIX = '/system-boot'
* @param file * @param file
*/ */
export const uploadFile = (file: any, path: string) => { export const uploadFile = (file: any, path: string) => {
const regex = /\[|\]/g
// 替换规则:[ 换成 (] 换成 )
const newFile = new File(
[file], // 原文件的二进制内容
file.name.replace(regex, match => (match === '[' ? '(' : ')')), // 新的文件名
{
type: file.type, // 复用原文件的MIME类型
lastModified: file.lastModified // 复用最后修改时间
}
)
let form = new FormData() let form = new FormData()
form.append('file', file) form.append('file', newFile)
form.append('path', path) form.append('path', path)
return createAxios({ return createAxios({
url: SYSTEM_PREFIX + '/file/upload', url: SYSTEM_PREFIX + '/file/upload',
@@ -17,6 +29,11 @@ export const uploadFile = (file: any, path: string) => {
'Content-Type': 'multipart/form-data' 'Content-Type': 'multipart/form-data'
}, },
data: form data: form
}).then(res => {
if (res.code == `A0000`) {
ElMessage.success('文件上传成功!')
return res
}
}) })
} }
@@ -50,7 +67,7 @@ export const downloadFile = (filePath: any) => {
/** /**
* 获取文件的短期url展示 * 获取文件的短期url展示
*/ */
export const getFileUrl = (params:any) => { export const getFileUrl = (params: any) => {
let form = new FormData() let form = new FormData()
// form.append('filePath', filePath) // form.append('filePath', filePath)
return createAxios({ return createAxios({

View File

@@ -54,6 +54,54 @@
<div class="content unicode" style="display: block;"> <div class="content unicode" style="display: block;">
<ul class="icon_lists dib-box"> <ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont">&#xe782;</span>
<div class="name">253_ipower</div>
<div class="code-name">&amp;#xe782;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe665;</span>
<div class="name">电压</div>
<div class="code-name">&amp;#xe665;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe758;</span>
<div class="name">三相电压幅值不平衡</div>
<div class="code-name">&amp;#xe758;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe61e;</span>
<div class="name">电压总谐波畸变率</div>
<div class="code-name">&amp;#xe61e;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe612;</span>
<div class="name">闪变</div>
<div class="code-name">&amp;#xe612;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe65d;</span>
<div class="name">停运事件管理</div>
<div class="code-name">&amp;#xe65d;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe604;</span>
<div class="name">在运设备</div>
<div class="code-name">&amp;#xe604;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe666;</span>
<div class="name">异常类_14非智能表在运异常</div>
<div class="code-name">&amp;#xe666;</div>
</li>
<li class="dib"> <li class="dib">
<span class="icon iconfont">&#xe82f;</span> <span class="icon iconfont">&#xe82f;</span>
<div class="name">综合评价</div> <div class="name">综合评价</div>
@@ -234,9 +282,9 @@
<pre><code class="language-css" <pre><code class="language-css"
>@font-face { >@font-face {
font-family: 'iconfont'; font-family: 'iconfont';
src: url('iconfont.woff2?t=1744179175277') format('woff2'), src: url('iconfont.woff2?t=1765612648830') format('woff2'),
url('iconfont.woff?t=1744179175277') format('woff'), url('iconfont.woff?t=1765612648830') format('woff'),
url('iconfont.ttf?t=1744179175277') format('truetype'); url('iconfont.ttf?t=1765612648830') format('truetype');
} }
</code></pre> </code></pre>
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3> <h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
@@ -262,6 +310,78 @@
<div class="content font-class"> <div class="content font-class">
<ul class="icon_lists dib-box"> <ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont icon-a-253_ipower"></span>
<div class="name">
253_ipower
</div>
<div class="code-name">.icon-a-253_ipower
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-dianya"></span>
<div class="name">
电压
</div>
<div class="code-name">.icon-dianya
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-sanxiangdianyafuzhibupingheng"></span>
<div class="name">
三相电压幅值不平衡
</div>
<div class="code-name">.icon-sanxiangdianyafuzhibupingheng
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-dianyazongxiebojibianshuai"></span>
<div class="name">
电压总谐波畸变率
</div>
<div class="code-name">.icon-dianyazongxiebojibianshuai
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-shanbian"></span>
<div class="name">
闪变
</div>
<div class="code-name">.icon-shanbian
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-tingyunshijianguanli"></span>
<div class="name">
停运事件管理
</div>
<div class="code-name">.icon-tingyunshijianguanli
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-zaiyunshebei"></span>
<div class="name">
在运设备
</div>
<div class="code-name">.icon-zaiyunshebei
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-yichanglei_14feizhinengbiaozaiyunyichang"></span>
<div class="name">
异常类_14非智能表在运异常
</div>
<div class="code-name">.icon-yichanglei_14feizhinengbiaozaiyunyichang
</div>
</li>
<li class="dib"> <li class="dib">
<span class="icon iconfont icon-zonghepingjia1"></span> <span class="icon iconfont icon-zonghepingjia1"></span>
<div class="name"> <div class="name">
@@ -532,6 +652,70 @@
<div class="content symbol"> <div class="content symbol">
<ul class="icon_lists dib-box"> <ul class="icon_lists dib-box">
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-a-253_ipower"></use>
</svg>
<div class="name">253_ipower</div>
<div class="code-name">#icon-a-253_ipower</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-dianya"></use>
</svg>
<div class="name">电压</div>
<div class="code-name">#icon-dianya</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-sanxiangdianyafuzhibupingheng"></use>
</svg>
<div class="name">三相电压幅值不平衡</div>
<div class="code-name">#icon-sanxiangdianyafuzhibupingheng</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-dianyazongxiebojibianshuai"></use>
</svg>
<div class="name">电压总谐波畸变率</div>
<div class="code-name">#icon-dianyazongxiebojibianshuai</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-shanbian"></use>
</svg>
<div class="name">闪变</div>
<div class="code-name">#icon-shanbian</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-tingyunshijianguanli"></use>
</svg>
<div class="name">停运事件管理</div>
<div class="code-name">#icon-tingyunshijianguanli</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-zaiyunshebei"></use>
</svg>
<div class="name">在运设备</div>
<div class="code-name">#icon-zaiyunshebei</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-yichanglei_14feizhinengbiaozaiyunyichang"></use>
</svg>
<div class="name">异常类_14非智能表在运异常</div>
<div class="code-name">#icon-yichanglei_14feizhinengbiaozaiyunyichang</div>
</li>
<li class="dib"> <li class="dib">
<svg class="icon svg-icon" aria-hidden="true"> <svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-zonghepingjia1"></use> <use xlink:href="#icon-zonghepingjia1"></use>

View File

@@ -1,8 +1,8 @@
@font-face { @font-face {
font-family: "iconfont"; /* Project id 3482754 */ font-family: "iconfont"; /* Project id 3482754 */
src: url('iconfont.woff2?t=1744179175277') format('woff2'), src: url('iconfont.woff2?t=1765612648830') format('woff2'),
url('iconfont.woff?t=1744179175277') format('woff'), url('iconfont.woff?t=1765612648830') format('woff'),
url('iconfont.ttf?t=1744179175277') format('truetype'); url('iconfont.ttf?t=1765612648830') format('truetype');
} }
.iconfont { .iconfont {
@@ -13,6 +13,38 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.icon-a-253_ipower:before {
content: "\e782";
}
.icon-dianya:before {
content: "\e665";
}
.icon-sanxiangdianyafuzhibupingheng:before {
content: "\e758";
}
.icon-dianyazongxiebojibianshuai:before {
content: "\e61e";
}
.icon-shanbian:before {
content: "\e612";
}
.icon-tingyunshijianguanli:before {
content: "\e65d";
}
.icon-zaiyunshebei:before {
content: "\e604";
}
.icon-yichanglei_14feizhinengbiaozaiyunyichang:before {
content: "\e666";
}
.icon-zonghepingjia1:before { .icon-zonghepingjia1:before {
content: "\e82f"; content: "\e82f";
} }

File diff suppressed because one or more lines are too long

View File

@@ -5,6 +5,62 @@
"css_prefix_text": "icon-", "css_prefix_text": "icon-",
"description": "", "description": "",
"glyphs": [ "glyphs": [
{
"icon_id": "33424624",
"name": "253_ipower",
"font_class": "a-253_ipower",
"unicode": "e782",
"unicode_decimal": 59266
},
{
"icon_id": "12331657",
"name": "电压",
"font_class": "dianya",
"unicode": "e665",
"unicode_decimal": 58981
},
{
"icon_id": "33073330",
"name": "三相电压幅值不平衡",
"font_class": "sanxiangdianyafuzhibupingheng",
"unicode": "e758",
"unicode_decimal": 59224
},
{
"icon_id": "37400988",
"name": "电压总谐波畸变率",
"font_class": "dianyazongxiebojibianshuai",
"unicode": "e61e",
"unicode_decimal": 58910
},
{
"icon_id": "43700638",
"name": "闪变",
"font_class": "shanbian",
"unicode": "e612",
"unicode_decimal": 58898
},
{
"icon_id": "25458995",
"name": "停运事件管理",
"font_class": "tingyunshijianguanli",
"unicode": "e65d",
"unicode_decimal": 58973
},
{
"icon_id": "35341056",
"name": "在运设备",
"font_class": "zaiyunshebei",
"unicode": "e604",
"unicode_decimal": 58884
},
{
"icon_id": "22630860",
"name": "异常类_14非智能表在运异常",
"font_class": "yichanglei_14feizhinengbiaozaiyunyichang",
"unicode": "e666",
"unicode_decimal": 58982
},
{ {
"icon_id": "32402696", "icon_id": "32402696",
"name": "综合评价", "name": "综合评价",

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
src/assets/img/inlogo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
src/assets/img/region.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 KiB

View File

@@ -6,7 +6,7 @@
</div> --> </div> -->
<TableHeader :showSearch="false"> <TableHeader :showSearch="false">
<template v-slot:select> <template v-slot:select>
<el-form-item label="日期"> <el-form-item label="统计时间">
<DatePicker ref="datePickerRef" :nextFlag="false" :theCurrentTime="true"></DatePicker> <DatePicker ref="datePickerRef" :nextFlag="false" :theCurrentTime="true"></DatePicker>
</el-form-item> </el-form-item>
</template> </template>

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
src/assets/imgs/m4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

BIN
src/assets/logo/海南.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

BIN
src/assets/logo/灿能.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
src/assets/logo/电网.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 KiB

BIN
src/assets/logo/电网1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

File diff suppressed because one or more lines are too long

View File

@@ -23,7 +23,7 @@ export function upper(str) {
} }
export function makeOptionsRule(t, to, userOptions) { export function makeOptionsRule(t, to, userOptions) {
console.log(userOptions[0]) //console.log(userOptions[0])
const options = [ const options = [
{ label: t('props.optionsType.struct'), value: 0 }, { label: t('props.optionsType.struct'), value: 0 },
{ label: t('props.optionsType.json'), value: 1 }, { label: t('props.optionsType.json'), value: 1 },

View File

@@ -1,11 +1,19 @@
<template> <template>
<div style="overflow: auto; height: 100vh"> <div style="overflow: auto; height: 100vh">
<vue-office-docx v-if="url.includes('.doc') || url.includes('.docx')" :src="url" /> <vue-office-docx v-if="urlKey.includes('.doc') || urlKey.includes('.docx')" :src="url" />
<vue-office-excel v-if="url.includes('.xls') || url.includes('.xlsx')" :src="url" :options="excelOptions" /> <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" /> --> <!-- <vue-office-pdf v-if="url.includes('.pdf')" :src="url" /> -->
<iframe v-if="url.includes('.pdf')" :src="url" style="width: 100%; height: 99%"></iframe> <iframe v-if="urlKey.includes('.pdf')||urlKey.includes('.txt')" :src="url" style="width: 100%; height: 99%"></iframe>
<img v-if="url.includes('.png') || url.includes('.jpg') || url.includes('.gif') || url.includes('.bmp')" <img
:src="url" /> v-if="
urlKey.includes('.png') || urlKey.includes('.jpg') || urlKey.includes('.gif') || urlKey.includes('.bmp')
"
:src="url"
/>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@@ -18,15 +26,34 @@ import VueOfficeDocx from '@vue-office/docx'
import VueOfficeExcel from '@vue-office/excel' import VueOfficeExcel from '@vue-office/excel'
//引入VueOfficePdf组件 //引入VueOfficePdf组件
import VueOfficePdf from '@vue-office/pdf' import VueOfficePdf from '@vue-office/pdf'
const { push, options, currentRoute } = useRouter() import { downloadFile } from '@/api/system-boot/file'
// const url = 'http://192.168.1.22:9009/excelreport' + currentRoute.value.href?.split('?')[1] import { previewFile } from '@/utils/fileDownLoad'
const { push, options, currentRoute } = useRouter()
const VITE_FLAG = 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({})
const urlKey = currentRoute.value?.href?.split('?')[1]
if (VITE_FLAG) {
url.value = '/api-docx/excelreport' + currentRoute.value?.href?.split('?')[1]
excelOptions.value = ref({
xls: currentRoute.value.href?.split('?')[1].split('.')[1] == 'xls' ? true : false
})
} else {
setTimeout(async () => {
const previewUrl = await previewFile(currentRoute.value?.href?.split('?')[1])
url.value = previewUrl
excelOptions.value = ref({
xls: currentRoute.value.href?.split('?')[1].split('.')[1] == 'xls' ? true : false
})
}, 0)
}
const url = '/api-docx/excelreport' + currentRoute.value?.href?.split('?')[1]
console.log("🚀 ~ url:", url)
const excelOptions = ref({
xls: currentRoute.value.href?.split('?')[1].split('.')[1] == 'xls' ? true : false
})
onMounted(() => { onMounted(() => {
// 从路由参数获取文件路径
console.log() console.log()
}) })
</script> </script>

View File

@@ -707,7 +707,7 @@ const processSave = async () => {
// return result.value || '&nbsp;' // return result.value || '&nbsp;'
// } // }
onBeforeMount(() => { onBeforeMount(() => {
console.log(props, 'propspropspropsprops') //console.log(props, 'propspropspropsprops')
}) })
onMounted(() => { onMounted(() => {
initBpmnModeler() initBpmnModeler()

View File

@@ -279,6 +279,27 @@ const getResultCss = (status) => {
return '' return ''
} }
const getTaskNameItemType = (itemStatus: any) => {
if (itemStatus === 1) {
return '审批中'
}else if (itemStatus === 2) {
return '审批通过'
}else if (itemStatus === 3) {
return '审批不通过'
}else if (itemStatus === 4) {
return '已取消'
}else if (itemStatus === 5) {
return '退回'
} else if (itemStatus === 6) {
return '委派'
} else if (itemStatus === 7) {
return '审批通过中'
} else if (itemStatus === 0) {
return '待审批'
}
return ''
}
const getActivityOutgoing = (activity) => { const getActivityOutgoing = (activity) => {
// 如果有 outgoing则直接使用它 // 如果有 outgoing则直接使用它
if (activity.outgoing && activity.outgoing.length > 0) { if (activity.outgoing && activity.outgoing.length > 0) {
@@ -316,7 +337,9 @@ const elementHover = (element) => {
!overlays.value && (overlays.value = bpmnModeler.get('overlays')) !overlays.value && (overlays.value = bpmnModeler.get('overlays'))
// 展示信息 // 展示信息
// console.log(activityLists.value, 'activityLists.value') // console.log(activityLists.value, 'activityLists.value')
// console.log(element.value, 'element.value') if (element.value.type === 'bpmn:SequenceFlow') {
return
}
const activity = activityLists.value.find((m) => m.key === element.value.id) const activity = activityLists.value.find((m) => m.key === element.value.id)
// console.log(activity, 'activityactivityactivityactivity') // console.log(activity, 'activityactivityactivityactivity')
if (!activity) { if (!activity) {
@@ -330,22 +353,22 @@ const elementHover = (element) => {
if (element.value.type === 'bpmn:StartEvent' && processInstance.value) { if (element.value.type === 'bpmn:StartEvent' && processInstance.value) {
html = `<p>发起人:${processInstance.value.startUser.name}</p> html = `<p>发起人:${processInstance.value.startUser.name}</p>
<p>部门:${processInstance.value.startUser.deptName}</p> <p>部门:${processInstance.value.startUser.deptName}</p>
<p>创建时间:${formatDate(processInstance.value.createTime)}` <p>创建时间:${formatDate(processInstance.value.startTime)}`
} else if (element.value.type === 'bpmn:UserTask') { } else if (element.value.type === 'bpmn:UserTask') {
let task = taskList.value.find((m) => m.id === activity.taskId) // 找到活动对应的 taskId let task = taskList.value.find((m) => m.id === activity.taskId) // 找到活动对应的 taskId
if (!task) { if (!task) {
return return
} }
let optionData = getIntDictOptions(DICT_TYPE.BPM_TASK_STATUS) // let optionData = getIntDictOptions(DICT_TYPE.BPM_TASK_STATUS)
let dataResult = '' // let dataResult = ''
optionData.forEach((element) => { // optionData.forEach((element) => {
if (element.value == task.status) { // if (element.value == task.status) {
dataResult = element.label // dataResult = element.label
} // }
}) // })
html = `<p>审批人:${task.assigneeUser.name}</p> html = `<p>审批人:${task.assigneeUser.name}</p>
<p>部门:${task.assigneeUser.deptName}</p> <p>部门:${task.assigneeUser.deptName}</p>
<p>结果:${dataResult}</p> <p>结果:${getTaskNameItemType(task.status)}</p>
<p>创建时间:${formatDate(task.createTime)}</p>` <p>创建时间:${formatDate(task.createTime)}</p>`
// html = `<p>审批人:${task.assigneeUser.nickname}</p> // html = `<p>审批人:${task.assigneeUser.nickname}</p>
// <p>部门:${task.assigneeUser.deptName}</p> // <p>部门:${task.assigneeUser.deptName}</p>
@@ -368,20 +391,20 @@ const elementHover = (element) => {
html += `<p>结束时间:${formatDate(activity.endTime)}</p>` html += `<p>结束时间:${formatDate(activity.endTime)}</p>`
} }
} else if (element.value.type === 'bpmn:EndEvent' && processInstance.value) { } else if (element.value.type === 'bpmn:EndEvent' && processInstance.value) {
let optionData = getIntDictOptions(DICT_TYPE.BPM_TASK_STATUS) // let optionData = getIntDictOptions(DICT_TYPE.BPM_TASK_STATUS)
let dataResult = '' // let dataResult = ''
optionData.forEach((element) => { // optionData.forEach((element) => {
if (element.value == processInstance.value.status) { // if (element.value == processInstance.value.status) {
dataResult = element.label // dataResult = element.label
} // }
}) // })
html = `<p>结果:${dataResult}</p>` // html = `<p>结果:${dataResult}</p>`
// html = `<p>结果:${getIntDictOptions( // html = `<p>结果:${getIntDictOptions(
// DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT, // DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT,
// processInstance.value.status // processInstance.value.status
// )}</p>` // )}</p>`
if (processInstance.value.endTime) { if (processInstance.value.endTime) {
html += `<p>结束时间:${formatDate(processInstance.value.endTime)}</p>` html = `<p>结束时间:${formatDate(processInstance.value.endTime)}</p>`
} }
} }
elementOverlayIds.value[element.value.id] = toRaw(overlays.value)?.add(element.value, { elementOverlayIds.value[element.value.id] = toRaw(overlays.value)?.add(element.value, {
@@ -660,7 +683,7 @@ watch(
} }
.element-overlays { .element-overlays {
width: 200px; width: 250px;
padding: 8px; padding: 8px;
color: #fafafa; color: #fafafa;
background: rgb(0 0 0 / 60%); background: rgb(0 0 0 / 60%);

View File

@@ -15,7 +15,7 @@ const addTask = (event, options: any = {}) => {
const ElementFactory = bpmnInstances().elementFactory const ElementFactory = bpmnInstances().elementFactory
const create = bpmnInstances().modeler.get('create') const create = bpmnInstances().modeler.get('create')
console.log(ElementFactory, create) //console.log(ElementFactory, create)
const shape = ElementFactory.createShape(assign({ type: 'bpmn:UserTask' }, options)) const shape = ElementFactory.createShape(assign({ type: 'bpmn:UserTask' }, options))
@@ -23,8 +23,8 @@ const addTask = (event, options: any = {}) => {
shape.businessObject.di.isExpanded = options.isExpanded shape.businessObject.di.isExpanded = options.isExpanded
} }
console.log(event, 'event') //console.log(event, 'event')
console.log(shape, 'shape') //console.log(shape, 'shape')
create.start(event, shape) create.start(event, shape)
} }
</script> </script>

View File

@@ -172,7 +172,7 @@ const unwatchBpmn = watch(
return return
} }
console.log('props.bpmnModeler 有值了!!!') //console.log('props.bpmnModeler 有值了!!!')
const w = window as any const w = window as any
w.bpmnInstances = { w.bpmnInstances = {
modeler: props.bpmnModeler, modeler: props.bpmnModeler,

View File

@@ -179,7 +179,7 @@ onBeforeUnmount(() => {
watch( watch(
() => props.businessObject, () => props.businessObject,
(val) => { (val) => {
console.log(val, 'val') //console.log(val, 'val')
nextTick(() => { nextTick(() => {
resetFlowCondition() resetFlowCondition()
}) })

View File

@@ -1,491 +1,491 @@
<template> <template>
<div class="panel-tab__content"> <div class="panel-tab__content">
<el-table :data="elementListenersList" size="small" border> <el-table :data="elementListenersList" size="small" border>
<el-table-column label="序号" width="80px" type="index" /> <el-table-column label="序号" width="80px" type="index" />
<el-table-column <el-table-column
label="事件类型" label="事件类型"
min-width="80px" min-width="80px"
show-overflow-tooltip show-overflow-tooltip
:formatter="(row) => listenerEventTypeObject[row.event]" :formatter="(row) => listenerEventTypeObject[row.event]"
/> />
<el-table-column label="事件id" min-width="80px" prop="id" show-overflow-tooltip /> <el-table-column label="事件id" min-width="80px" prop="id" show-overflow-tooltip />
<el-table-column <el-table-column
label="监听器类型" label="监听器类型"
min-width="80px" min-width="80px"
show-overflow-tooltip show-overflow-tooltip
:formatter="(row) => listenerTypeObject[row.listenerType]" :formatter="(row) => listenerTypeObject[row.listenerType]"
/> />
<el-table-column label="操作" width="90px"> <el-table-column label="操作" width="90px">
<template #default="scope"> <template #default="scope">
<el-button size="small" link @click="openListenerForm(scope.row, scope.$index)" <el-button size="small" link @click="openListenerForm(scope.row, scope.$index)"
>编辑</el-button >编辑</el-button
> >
<el-divider direction="vertical" /> <el-divider direction="vertical" />
<el-button <el-button
size="small" size="small"
link link
style="color: #ff4d4f" style="color: #ff4d4f"
@click="removeListener(scope.row, scope.$index)" @click="removeListener(scope.row, scope.$index)"
>移除</el-button >移除</el-button
> >
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<div class="element-drawer__button"> <div class="element-drawer__button">
<XButton <XButton
size="small" size="small"
type="primary" type="primary"
preIcon="ep:plus" preIcon="ep:plus"
title="添加监听器" title="添加监听器"
@click="openListenerForm(null)" @click="openListenerForm(null)"
/> />
<XButton <XButton
type="success" type="success"
preIcon="ep:select" preIcon="ep:select"
title="选择监听器" title="选择监听器"
size="small" size="small"
@click="openProcessListenerDialog" @click="openProcessListenerDialog"
/> />
</div> </div>
<!-- 监听器 编辑/创建 部分 --> <!-- 监听器 编辑/创建 部分 -->
<el-drawer <el-drawer
v-model="listenerFormModelVisible" v-model="listenerFormModelVisible"
title="任务监听器" title="任务监听器"
:size="`${width}px`" :size="`${width}px`"
append-to-body append-to-body
destroy-on-close destroy-on-close
> >
<el-form size="small" :model="listenerForm" label-width="96px" ref="listenerFormRef"> <el-form size="small" :model="listenerForm" label-width="96px" ref="listenerFormRef">
<el-form-item <el-form-item
label="事件类型" label="事件类型"
prop="event" prop="event"
:rules="{ required: true, trigger: ['blur', 'change'] }" :rules="{ required: true, trigger: ['blur', 'change'] }"
> >
<el-select v-model="listenerForm.event"> <el-select v-model="listenerForm.event">
<el-option <el-option
v-for="i in Object.keys(listenerEventTypeObject)" v-for="i in Object.keys(listenerEventTypeObject)"
:key="i" :key="i"
:label="listenerEventTypeObject[i]" :label="listenerEventTypeObject[i]"
:value="i" :value="i"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item <el-form-item
label="监听器ID" label="监听器ID"
prop="id" prop="id"
:rules="{ required: true, trigger: ['blur', 'change'] }" :rules="{ required: true, trigger: ['blur', 'change'] }"
> >
<el-input v-model="listenerForm.id" clearable /> <el-input v-model="listenerForm.id" clearable />
</el-form-item> </el-form-item>
<el-form-item <el-form-item
label="监听器类型" label="监听器类型"
prop="listenerType" prop="listenerType"
:rules="{ required: true, trigger: ['blur', 'change'] }" :rules="{ required: true, trigger: ['blur', 'change'] }"
> >
<el-select v-model="listenerForm.listenerType"> <el-select v-model="listenerForm.listenerType">
<el-option <el-option
v-for="i in Object.keys(listenerTypeObject)" v-for="i in Object.keys(listenerTypeObject)"
:key="i" :key="i"
:label="listenerTypeObject[i]" :label="listenerTypeObject[i]"
:value="i" :value="i"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item <el-form-item
v-if="listenerForm.listenerType === 'classListener'" v-if="listenerForm.listenerType === 'classListener'"
label="Java类" label="Java类"
prop="class" prop="class"
key="listener-class" key="listener-class"
:rules="{ required: true, trigger: ['blur', 'change'] }" :rules="{ required: true, trigger: ['blur', 'change'] }"
> >
<el-input v-model="listenerForm.class" clearable /> <el-input v-model="listenerForm.class" clearable />
</el-form-item> </el-form-item>
<el-form-item <el-form-item
v-if="listenerForm.listenerType === 'expressionListener'" v-if="listenerForm.listenerType === 'expressionListener'"
label="表达式" label="表达式"
prop="expression" prop="expression"
key="listener-expression" key="listener-expression"
:rules="{ required: true, trigger: ['blur', 'change'] }" :rules="{ required: true, trigger: ['blur', 'change'] }"
> >
<el-input v-model="listenerForm.expression" clearable /> <el-input v-model="listenerForm.expression" clearable />
</el-form-item> </el-form-item>
<el-form-item <el-form-item
v-if="listenerForm.listenerType === 'delegateExpressionListener'" v-if="listenerForm.listenerType === 'delegateExpressionListener'"
label="代理表达式" label="代理表达式"
prop="delegateExpression" prop="delegateExpression"
key="listener-delegate" key="listener-delegate"
:rules="{ required: true, trigger: ['blur', 'change'] }" :rules="{ required: true, trigger: ['blur', 'change'] }"
> >
<el-input v-model="listenerForm.delegateExpression" clearable /> <el-input v-model="listenerForm.delegateExpression" clearable />
</el-form-item> </el-form-item>
<template v-if="listenerForm.listenerType === 'scriptListener'"> <template v-if="listenerForm.listenerType === 'scriptListener'">
<el-form-item <el-form-item
label="脚本格式" label="脚本格式"
prop="scriptFormat" prop="scriptFormat"
key="listener-script-format" key="listener-script-format"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本格式' }" :rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本格式' }"
> >
<el-input v-model="listenerForm.scriptFormat" clearable /> <el-input v-model="listenerForm.scriptFormat" clearable />
</el-form-item> </el-form-item>
<el-form-item <el-form-item
label="脚本类型" label="脚本类型"
prop="scriptType" prop="scriptType"
key="listener-script-type" key="listener-script-type"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请选择脚本类型' }" :rules="{ required: true, trigger: ['blur', 'change'], message: '请选择脚本类型' }"
> >
<el-select v-model="listenerForm.scriptType"> <el-select v-model="listenerForm.scriptType">
<el-option label="内联脚本" value="inlineScript" /> <el-option label="内联脚本" value="inlineScript" />
<el-option label="外部脚本" value="externalScript" /> <el-option label="外部脚本" value="externalScript" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item <el-form-item
v-if="listenerForm.scriptType === 'inlineScript'" v-if="listenerForm.scriptType === 'inlineScript'"
label="脚本内容" label="脚本内容"
prop="value" prop="value"
key="listener-script" key="listener-script"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本内容' }" :rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本内容' }"
> >
<el-input v-model="listenerForm.value" clearable /> <el-input v-model="listenerForm.value" clearable />
</el-form-item> </el-form-item>
<el-form-item <el-form-item
v-if="listenerForm.scriptType === 'externalScript'" v-if="listenerForm.scriptType === 'externalScript'"
label="资源地址" label="资源地址"
prop="resource" prop="resource"
key="listener-resource" key="listener-resource"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写资源地址' }" :rules="{ required: true, trigger: ['blur', 'change'], message: '请填写资源地址' }"
> >
<el-input v-model="listenerForm.resource" clearable /> <el-input v-model="listenerForm.resource" clearable />
</el-form-item> </el-form-item>
</template> </template>
<template v-if="listenerForm.event === 'timeout'"> <template v-if="listenerForm.event === 'timeout'">
<el-form-item label="定时器类型" prop="eventDefinitionType" key="eventDefinitionType"> <el-form-item label="定时器类型" prop="eventDefinitionType" key="eventDefinitionType">
<el-select v-model="listenerForm.eventDefinitionType"> <el-select v-model="listenerForm.eventDefinitionType">
<el-option label="日期" value="date" /> <el-option label="统计时间" value="date" />
<el-option label="持续时长" value="duration" /> <el-option label="持续时长" value="duration" />
<el-option label="循环" value="cycle" /> <el-option label="循环" value="cycle" />
<el-option label="无" value="null" /> <el-option label="无" value="null" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item <el-form-item
v-if="!!listenerForm.eventDefinitionType && listenerForm.eventDefinitionType !== 'null'" v-if="!!listenerForm.eventDefinitionType && listenerForm.eventDefinitionType !== 'null'"
label="定时器" label="定时器"
prop="eventTimeDefinitions" prop="eventTimeDefinitions"
key="eventTimeDefinitions" key="eventTimeDefinitions"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写定时器配置' }" :rules="{ required: true, trigger: ['blur', 'change'], message: '请填写定时器配置' }"
> >
<el-input v-model="listenerForm.eventTimeDefinitions" clearable /> <el-input v-model="listenerForm.eventTimeDefinitions" clearable />
</el-form-item> </el-form-item>
</template> </template>
</el-form> </el-form>
<el-divider /> <el-divider />
<p class="listener-filed__title"> <p class="listener-filed__title">
<span><Icon icon="ep:menu" />注入字段</span> <span><Icon icon="ep:menu" />注入字段</span>
<el-button size="small" type="primary" @click="openListenerFieldForm(null)" <el-button size="small" type="primary" @click="openListenerFieldForm(null)"
>添加字段</el-button >添加字段</el-button
> >
</p> </p>
<el-table <el-table
:data="fieldsListOfListener" :data="fieldsListOfListener"
size="small" size="small"
max-height="240" max-height="240"
fit fit
border border
style="flex: none" style="flex: none"
> >
<el-table-column label="序号" width="80px" type="index" /> <el-table-column label="序号" width="80px" type="index" />
<el-table-column label="字段名称" min-width="100px" prop="name" /> <el-table-column label="字段名称" min-width="100px" prop="name" />
<el-table-column <el-table-column
label="字段类型" label="字段类型"
min-width="80px" min-width="80px"
show-overflow-tooltip show-overflow-tooltip
:formatter="(row) => fieldTypeObject[row.fieldType]" :formatter="(row) => fieldTypeObject[row.fieldType]"
/> />
<el-table-column <el-table-column
label="字段值/表达式" label="字段值/表达式"
min-width="100px" min-width="100px"
show-overflow-tooltip show-overflow-tooltip
:formatter="(row) => row.string || row.expression" :formatter="(row) => row.string || row.expression"
/> />
<el-table-column label="操作" width="100px"> <el-table-column label="操作" width="100px">
<template #default="scope"> <template #default="scope">
<el-button size="small" link @click="openListenerFieldForm(scope.row, scope.$index)" <el-button size="small" link @click="openListenerFieldForm(scope.row, scope.$index)"
>编辑</el-button >编辑</el-button
> >
<el-divider direction="vertical" /> <el-divider direction="vertical" />
<el-button <el-button
size="small" size="small"
link link
style="color: #ff4d4f" style="color: #ff4d4f"
@click="removeListenerField(scope.row, scope.$index)" @click="removeListenerField(scope.row, scope.$index)"
>移除</el-button >移除</el-button
> >
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<div class="element-drawer__button"> <div class="element-drawer__button">
<el-button size="small" @click="listenerFormModelVisible = false"> </el-button> <el-button size="small" @click="listenerFormModelVisible = false"> </el-button>
<el-button size="small" type="primary" @click="saveListenerConfig"> </el-button> <el-button size="small" type="primary" @click="saveListenerConfig"> </el-button>
</div> </div>
</el-drawer> </el-drawer>
<!-- 注入西段 编辑/创建 部分 --> <!-- 注入西段 编辑/创建 部分 -->
<el-dialog <el-dialog
title="字段配置" title="字段配置"
v-model="listenerFieldFormModelVisible" v-model="listenerFieldFormModelVisible"
width="600px" width="600px"
append-to-body append-to-body
destroy-on-close destroy-on-close
> >
<el-form <el-form
:model="listenerFieldForm" :model="listenerFieldForm"
size="small" size="small"
label-width="96px" label-width="96px"
ref="listenerFieldFormRef" ref="listenerFieldFormRef"
style="height: 136px" style="height: 136px"
> >
<el-form-item <el-form-item
label="字段名称:" label="字段名称:"
prop="name" prop="name"
:rules="{ required: true, trigger: ['blur', 'change'] }" :rules="{ required: true, trigger: ['blur', 'change'] }"
> >
<el-input v-model="listenerFieldForm.name" clearable /> <el-input v-model="listenerFieldForm.name" clearable />
</el-form-item> </el-form-item>
<el-form-item <el-form-item
label="字段类型:" label="字段类型:"
prop="fieldType" prop="fieldType"
:rules="{ required: true, trigger: ['blur', 'change'] }" :rules="{ required: true, trigger: ['blur', 'change'] }"
> >
<el-select v-model="listenerFieldForm.fieldType"> <el-select v-model="listenerFieldForm.fieldType">
<el-option <el-option
v-for="i in Object.keys(fieldTypeObject)" v-for="i in Object.keys(fieldTypeObject)"
:key="i" :key="i"
:label="fieldTypeObject[i]" :label="fieldTypeObject[i]"
:value="i" :value="i"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item <el-form-item
v-if="listenerFieldForm.fieldType === 'string'" v-if="listenerFieldForm.fieldType === 'string'"
label="字段值:" label="字段值:"
prop="string" prop="string"
key="field-string" key="field-string"
:rules="{ required: true, trigger: ['blur', 'change'] }" :rules="{ required: true, trigger: ['blur', 'change'] }"
> >
<el-input v-model="listenerFieldForm.string" clearable /> <el-input v-model="listenerFieldForm.string" clearable />
</el-form-item> </el-form-item>
<el-form-item <el-form-item
v-if="listenerFieldForm.fieldType === 'expression'" v-if="listenerFieldForm.fieldType === 'expression'"
label="表达式:" label="表达式:"
prop="expression" prop="expression"
key="field-expression" key="field-expression"
:rules="{ required: true, trigger: ['blur', 'change'] }" :rules="{ required: true, trigger: ['blur', 'change'] }"
> >
<el-input v-model="listenerFieldForm.expression" clearable /> <el-input v-model="listenerFieldForm.expression" clearable />
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
<el-button size="small" @click="listenerFieldFormModelVisible = false"> </el-button> <el-button size="small" @click="listenerFieldFormModelVisible = false"> </el-button>
<el-button size="small" type="primary" @click="saveListenerFiled"> </el-button> <el-button size="small" type="primary" @click="saveListenerFiled"> </el-button>
</template> </template>
</el-dialog> </el-dialog>
</div> </div>
<!-- 选择弹窗 --> <!-- 选择弹窗 -->
<ProcessListenerDialog ref="processListenerDialogRef" @select="selectProcessListener" /> <ProcessListenerDialog ref="processListenerDialogRef" @select="selectProcessListener" />
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ElMessageBox } from 'element-plus' import { ElMessageBox } from 'element-plus'
import { createListenerObject, updateElementExtensions } from '../../utils' import { createListenerObject, updateElementExtensions } from '../../utils'
import { import {
initListenerForm, initListenerForm,
initListenerType, initListenerType,
eventType, eventType,
listenerType, listenerType,
fieldType, fieldType,
initListenerForm2 initListenerForm2
} from './utilSelf' } from './utilSelf'
import ProcessListenerDialog from '@/components/bpmnProcessDesigner/package/penal/listeners/ProcessListenerDialog.vue' import ProcessListenerDialog from '@/components/bpmnProcessDesigner/package/penal/listeners/ProcessListenerDialog.vue'
defineOptions({ name: 'UserTaskListeners' }) defineOptions({ name: 'UserTaskListeners' })
const props = defineProps({ const props = defineProps({
id: String, id: String,
type: String type: String
}) })
const prefix = inject('prefix') const prefix = inject('prefix')
const width = inject('width') const width = inject('width')
const elementListenersList = ref<any[]>([]) const elementListenersList = ref<any[]>([])
const listenerEventTypeObject = ref(eventType) const listenerEventTypeObject = ref(eventType)
const listenerTypeObject = ref(listenerType) const listenerTypeObject = ref(listenerType)
const listenerFormModelVisible = ref(false) const listenerFormModelVisible = ref(false)
const listenerForm = ref<any>({}) const listenerForm = ref<any>({})
const fieldTypeObject = ref(fieldType) const fieldTypeObject = ref(fieldType)
const fieldsListOfListener = ref<any[]>([]) const fieldsListOfListener = ref<any[]>([])
const listenerFieldFormModelVisible = ref(false) // 监听器 注入字段表单弹窗 显示状态 const listenerFieldFormModelVisible = ref(false) // 监听器 注入字段表单弹窗 显示状态
const editingListenerIndex = ref(-1) // 监听器所在下标,-1 为新增 const editingListenerIndex = ref(-1) // 监听器所在下标,-1 为新增
const editingListenerFieldIndex = ref(-1) // 字段所在下标,-1 为新增 const editingListenerFieldIndex = ref(-1) // 字段所在下标,-1 为新增
const listenerFieldForm = ref<any>({}) // 监听器 注入字段 详情表单 const listenerFieldForm = ref<any>({}) // 监听器 注入字段 详情表单
const bpmnElement = ref() const bpmnElement = ref()
const bpmnElementListeners = ref() const bpmnElementListeners = ref()
const otherExtensionList = ref() const otherExtensionList = ref()
const listenerFormRef = ref() const listenerFormRef = ref()
const listenerFieldFormRef = ref() const listenerFieldFormRef = ref()
const bpmnInstances = () => (window as any)?.bpmnInstances const bpmnInstances = () => (window as any)?.bpmnInstances
const resetListenersList = () => { const resetListenersList = () => {
// console.log( // console.log(
// bpmnInstances().bpmnElement, // bpmnInstances().bpmnElement,
// 'window.bpmnInstances.bpmnElementwindow.bpmnInstances.bpmnElementwindow.bpmnInstances.bpmnElementwindow.bpmnInstances.bpmnElementwindow.bpmnInstances.bpmnElementwindow.bpmnInstances.bpmnElement' // 'window.bpmnInstances.bpmnElementwindow.bpmnInstances.bpmnElementwindow.bpmnInstances.bpmnElementwindow.bpmnInstances.bpmnElementwindow.bpmnInstances.bpmnElementwindow.bpmnInstances.bpmnElement'
// ) // )
bpmnElement.value = bpmnInstances().bpmnElement bpmnElement.value = bpmnInstances().bpmnElement
otherExtensionList.value = [] otherExtensionList.value = []
bpmnElementListeners.value = bpmnElementListeners.value =
bpmnElement.value.businessObject?.extensionElements?.values.filter( bpmnElement.value.businessObject?.extensionElements?.values.filter(
(ex) => ex.$type === `${prefix}:TaskListener` (ex) => ex.$type === `${prefix}:TaskListener`
) ?? [] ) ?? []
elementListenersList.value = bpmnElementListeners.value.map((listener) => elementListenersList.value = bpmnElementListeners.value.map((listener) =>
initListenerType(listener) initListenerType(listener)
) )
} }
const openListenerForm = (listener, index?) => { const openListenerForm = (listener, index?) => {
if (listener) { if (listener) {
listenerForm.value = initListenerForm(listener) listenerForm.value = initListenerForm(listener)
editingListenerIndex.value = index editingListenerIndex.value = index
} else { } else {
listenerForm.value = {} listenerForm.value = {}
editingListenerIndex.value = -1 // 标记为新增 editingListenerIndex.value = -1 // 标记为新增
} }
if (listener && listener.fields) { if (listener && listener.fields) {
fieldsListOfListener.value = listener.fields.map((field) => ({ fieldsListOfListener.value = listener.fields.map((field) => ({
...field, ...field,
fieldType: field.string ? 'string' : 'expression' fieldType: field.string ? 'string' : 'expression'
})) }))
} else { } else {
fieldsListOfListener.value = [] fieldsListOfListener.value = []
listenerForm.value['fields'] = [] listenerForm.value['fields'] = []
} }
// 打开侧边栏并清楚验证状态 // 打开侧边栏并清楚验证状态
listenerFormModelVisible.value = true listenerFormModelVisible.value = true
nextTick(() => { nextTick(() => {
if (listenerFormRef.value) listenerFormRef.value.clearValidate() if (listenerFormRef.value) listenerFormRef.value.clearValidate()
}) })
} }
// 移除监听器 // 移除监听器
const removeListener = (listener, index?) => { const removeListener = (listener, index?) => {
console.log(listener, 'listener') //console.log(listener, 'listener')
ElMessageBox.confirm('确认移除该监听器吗?', '提示', { ElMessageBox.confirm('确认移除该监听器吗?', '提示', {
confirmButtonText: '确 认', confirmButtonText: '确 认',
cancelButtonText: '取 消' cancelButtonText: '取 消'
}) })
.then(() => { .then(() => {
bpmnElementListeners.value.splice(index, 1) bpmnElementListeners.value.splice(index, 1)
elementListenersList.value.splice(index, 1) elementListenersList.value.splice(index, 1)
updateElementExtensions( updateElementExtensions(
bpmnElement.value, bpmnElement.value,
otherExtensionList.value.concat(bpmnElementListeners.value) otherExtensionList.value.concat(bpmnElementListeners.value)
) )
}) })
.catch(() => console.info('操作取消')) .catch(() => console.info('操作取消'))
} }
// 保存监听器 // 保存监听器
const saveListenerConfig = async () => { const saveListenerConfig = async () => {
let validateStatus = await listenerFormRef.value.validate() let validateStatus = await listenerFormRef.value.validate()
if (!validateStatus) return // 验证不通过直接返回 if (!validateStatus) return // 验证不通过直接返回
const listenerObject = createListenerObject(listenerForm.value, true, prefix) const listenerObject = createListenerObject(listenerForm.value, true, prefix)
if (editingListenerIndex.value === -1) { if (editingListenerIndex.value === -1) {
bpmnElementListeners.value.push(listenerObject) bpmnElementListeners.value.push(listenerObject)
elementListenersList.value.push(listenerForm.value) elementListenersList.value.push(listenerForm.value)
} else { } else {
bpmnElementListeners.value.splice(editingListenerIndex.value, 1, listenerObject) bpmnElementListeners.value.splice(editingListenerIndex.value, 1, listenerObject)
elementListenersList.value.splice(editingListenerIndex.value, 1, listenerForm.value) elementListenersList.value.splice(editingListenerIndex.value, 1, listenerForm.value)
} }
// 保存其他配置 // 保存其他配置
otherExtensionList.value = otherExtensionList.value =
bpmnElement.value.businessObject?.extensionElements?.values?.filter( bpmnElement.value.businessObject?.extensionElements?.values?.filter(
(ex) => ex.$type !== `${prefix}:TaskListener` (ex) => ex.$type !== `${prefix}:TaskListener`
) ?? [] ) ?? []
updateElementExtensions( updateElementExtensions(
bpmnElement.value, bpmnElement.value,
otherExtensionList.value.concat(bpmnElementListeners.value) otherExtensionList.value.concat(bpmnElementListeners.value)
) )
// 4. 隐藏侧边栏 // 4. 隐藏侧边栏
listenerFormModelVisible.value = false listenerFormModelVisible.value = false
listenerForm.value = {} listenerForm.value = {}
} }
// 打开监听器字段编辑弹窗 // 打开监听器字段编辑弹窗
const openListenerFieldForm = (field, index?) => { const openListenerFieldForm = (field, index?) => {
listenerFieldForm.value = field ? JSON.parse(JSON.stringify(field)) : {} listenerFieldForm.value = field ? JSON.parse(JSON.stringify(field)) : {}
editingListenerFieldIndex.value = field ? index : -1 editingListenerFieldIndex.value = field ? index : -1
listenerFieldFormModelVisible.value = true listenerFieldFormModelVisible.value = true
nextTick(() => { nextTick(() => {
if (listenerFieldFormRef.value) listenerFieldFormRef.value.clearValidate() if (listenerFieldFormRef.value) listenerFieldFormRef.value.clearValidate()
}) })
} }
// 保存监听器注入字段 // 保存监听器注入字段
const saveListenerFiled = async () => { const saveListenerFiled = async () => {
let validateStatus = await listenerFieldFormRef.value.validate() let validateStatus = await listenerFieldFormRef.value.validate()
if (!validateStatus) return // 验证不通过直接返回 if (!validateStatus) return // 验证不通过直接返回
if (editingListenerFieldIndex.value === -1) { if (editingListenerFieldIndex.value === -1) {
fieldsListOfListener.value.push(listenerFieldForm.value) fieldsListOfListener.value.push(listenerFieldForm.value)
listenerForm.value.fields.push(listenerFieldForm.value) listenerForm.value.fields.push(listenerFieldForm.value)
} else { } else {
fieldsListOfListener.value.splice(editingListenerFieldIndex.value, 1, listenerFieldForm.value) fieldsListOfListener.value.splice(editingListenerFieldIndex.value, 1, listenerFieldForm.value)
listenerForm.value.fields.splice(editingListenerFieldIndex.value, 1, listenerFieldForm.value) listenerForm.value.fields.splice(editingListenerFieldIndex.value, 1, listenerFieldForm.value)
} }
listenerFieldFormModelVisible.value = false listenerFieldFormModelVisible.value = false
nextTick(() => { nextTick(() => {
listenerFieldForm.value = {} listenerFieldForm.value = {}
}) })
} }
// 移除监听器字段 // 移除监听器字段
const removeListenerField = (field, index) => { const removeListenerField = (field, index) => {
console.log(field, 'field') console.log(field, 'field')
ElMessageBox.confirm('确认移除该字段吗?', '提示', { ElMessageBox.confirm('确认移除该字段吗?', '提示', {
confirmButtonText: '确 认', confirmButtonText: '确 认',
cancelButtonText: '取 消' cancelButtonText: '取 消'
}) })
.then(() => { .then(() => {
fieldsListOfListener.value.splice(index, 1) fieldsListOfListener.value.splice(index, 1)
listenerForm.value.fields.splice(index, 1) listenerForm.value.fields.splice(index, 1)
}) })
.catch(() => console.info('操作取消')) .catch(() => console.info('操作取消'))
} }
// 打开监听器弹窗 // 打开监听器弹窗
const processListenerDialogRef = ref() const processListenerDialogRef = ref()
const openProcessListenerDialog = async () => { const openProcessListenerDialog = async () => {
processListenerDialogRef.value.open('task') processListenerDialogRef.value.open('task')
} }
const selectProcessListener = (listener) => { const selectProcessListener = (listener) => {
const listenerForm = initListenerForm2(listener) const listenerForm = initListenerForm2(listener)
const listenerObject = createListenerObject(listenerForm, true, prefix) const listenerObject = createListenerObject(listenerForm, true, prefix)
bpmnElementListeners.value.push(listenerObject) bpmnElementListeners.value.push(listenerObject)
elementListenersList.value.push(listenerForm) elementListenersList.value.push(listenerForm)
// 保存其他配置 // 保存其他配置
otherExtensionList.value = otherExtensionList.value =
bpmnElement.value.businessObject?.extensionElements?.values?.filter( bpmnElement.value.businessObject?.extensionElements?.values?.filter(
(ex) => ex.$type !== `${prefix}:TaskListener` (ex) => ex.$type !== `${prefix}:TaskListener`
) ?? [] ) ?? []
updateElementExtensions( updateElementExtensions(
bpmnElement.value, bpmnElement.value,
otherExtensionList.value.concat(bpmnElementListeners.value) otherExtensionList.value.concat(bpmnElementListeners.value)
) )
} }
watch( watch(
() => props.id, () => props.id,
(val) => { (val) => {
val && val &&
val.length && val.length &&
nextTick(() => { nextTick(() => {
resetListenersList() resetListenersList()
}) })
}, },
{ immediate: true } { immediate: true }
) )
</script> </script>

View File

@@ -20,7 +20,7 @@ export function initListenerForm(listener) {
self.eventDefinitionType = key.replace('time', '').toLowerCase() self.eventDefinitionType = key.replace('time', '').toLowerCase()
} }
} }
console.log(k) //console.log(k)
self.eventTimeDefinitions = listener.eventDefinitions[0][k].body self.eventTimeDefinitions = listener.eventDefinitions[0][k].body
} }
} }

View File

@@ -68,7 +68,7 @@ const modelConfig = computed(() => {
const bpmnInstances = () => (window as any)?.bpmnInstances const bpmnInstances = () => (window as any)?.bpmnInstances
const initDataList = () => { const initDataList = () => {
console.log(window, 'window') //console.log(window, 'window')
rootElements.value = bpmnInstances().modeler.getDefinitions().rootElements rootElements.value = bpmnInstances().modeler.getDefinitions().rootElements
messageIdMap.value = {} messageIdMap.value = {}
signalIdMap.value = {} signalIdMap.value = {}

View File

@@ -39,7 +39,7 @@ function xml2json(xml) {
function xmlObj2json(xml) { function xmlObj2json(xml) {
const xmlObj = xmlStr2XmlObj(xml) const xmlObj = xmlStr2XmlObj(xml)
console.log(xmlObj) // console.log(xmlObj)
let jsonObj = {} let jsonObj = {}
if (xmlObj.childNodes.length > 0) { if (xmlObj.childNodes.length > 0) {
jsonObj = xml2json(xmlObj) jsonObj = xml2json(xmlObj)

View File

@@ -204,6 +204,7 @@ const tableStore: any = new TableStore({
tableStore.table.params.deptId = dictData.state.area[0].id tableStore.table.params.deptId = dictData.state.area[0].id
tableStore.table.params.alarmDayLimit = 5 tableStore.table.params.alarmDayLimit = 5
tableStore.table.params.warnDayLimit = 1 tableStore.table.params.warnDayLimit = 1
tableStore.table.params.lineRunFlag = 0
const echart = () => { const echart = () => {
percentage.value = { percentage.value = {
color: ['#FF9100'], color: ['#FF9100'],
@@ -364,6 +365,7 @@ watch(
) )
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import '@/assets/font/iconfont.css';
.monitoringPoints { .monitoringPoints {
display: flex; display: flex;
.statistics { .statistics {

View File

@@ -31,7 +31,7 @@
<div class="divBox mt10"> <div class="divBox mt10">
<span class="iconfont icon-igw-f-warning-data" style="color: #ff6600"></span> <span class="iconfont icon-igw-f-warning-data" style="color: #ff6600"></span>
<span class="divBox_title">低于90%监测点数</span> <span class="divBox_title">低于90%监测点数</span>
<span class="divBox_num" style="color: #ff6600"> <span class="divBox_num" style="color: #57bc6e">
{{ monitoringPoints.abnormalNum }} {{ monitoringPoints.abnormalNum }}
</span> </span>
</div> </div>
@@ -90,7 +90,7 @@
{{ o.citTotalNum }} {{ o.citTotalNum }}
</span> </span>
<!-- 低于90%监测点数 --> <!-- 低于90%监测点数 -->
<span style="flex: 1; color: #ff9100" class="text"> <span style="flex: 1; color: #388e3c" class="text">
{{ o.citBelowNum }} {{ o.citBelowNum }}
</span> </span>
<span <span
@@ -179,10 +179,17 @@ const tableStore: any = new TableStore({
monitoringPoints.value.runNum = tableStore.table.data.totalNum monitoringPoints.value.runNum = tableStore.table.data.totalNum
monitoringPoints.value.abnormalNum = tableStore.table.data.belowNum monitoringPoints.value.abnormalNum = tableStore.table.data.belowNum
monitoringPoints.value.totalOnlineRate = tableStore.table.data.totalOnlineRate - 0 monitoringPoints.value.totalOnlineRate = tableStore.table.data.totalOnlineRate - 0
abnormal.value = tableStore.table.data.citDetailList abnormal.value = tableStore.table.data.citDetailList.filter((k: any) => {
if (tableStore.table.params.statisticalType.name == '终端厂家') {
return k.citTotalNum != 0
} else {
return !k.citName.includes('上送')
}
})
} }
}) })
tableStore.table.params.deptIndex = dictData.state.area[0].id tableStore.table.params.deptIndex = dictData.state.area[0].id
tableStore.table.params.lineRunFlag = 0
const echart = () => { const echart = () => {
percentage.value = { percentage.value = {
color: ['#FF9100'], color: ['#FF9100'],
@@ -216,7 +223,7 @@ const echart = () => {
series: [ series: [
{ {
name: '异常总数', name: '',
type: 'bar', type: 'bar',
barWidth: 12, barWidth: 12,
data: [100], data: [100],
@@ -233,7 +240,7 @@ const echart = () => {
colorStops: [ colorStops: [
{ {
offset: 1, offset: 1,
color: '#57bc6e' // 100% 处的颜色 color: '#FF9100' // 100% 处的颜色
} }
], ],
global: false // 缺省为 false global: false // 缺省为 false
@@ -242,7 +249,7 @@ const echart = () => {
} }
}, },
{ {
name: '异常占比', name: '',
type: 'bar', type: 'bar',
barWidth: 13, barWidth: 13,
data: [ data: [
@@ -263,11 +270,11 @@ const echart = () => {
colorStops: [ colorStops: [
{ {
offset: 0, offset: 0,
color: '#FF9100' // 0% 处的颜色 color: '#57bc6e ' // 0% 处的颜色
}, },
{ {
offset: 1, offset: 1,
color: '#FF9100' // 100% 处的颜色 color: '#57bc6e' // 100% 处的颜色
} }
], ],
global: false // 缺省为 false global: false // 缺省为 false
@@ -340,6 +347,7 @@ watch(
) )
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import '@/assets/font/iconfont.css';
.monitoringPoints { .monitoringPoints {
display: flex; display: flex;
.statistics { .statistics {

View File

@@ -31,7 +31,7 @@
<div class="divBox mt10"> <div class="divBox mt10">
<span class="iconfont icon-igw-f-warning-data" style="color: #ff6600"></span> <span class="iconfont icon-igw-f-warning-data" style="color: #ff6600"></span>
<span class="divBox_title">低于90%终端数</span> <span class="divBox_title">低于90%终端数</span>
<span class="divBox_num" style="color: #ff6600"> <span class="divBox_num" style="color: #57bc6e">
{{ monitoringPoints.abnormalNum }} {{ monitoringPoints.abnormalNum }}
</span> </span>
</div> </div>
@@ -88,7 +88,7 @@
{{ o.citTotalNum }} {{ o.citTotalNum }}
</span> </span>
<!-- 低于90%终端数 --> <!-- 低于90%终端数 -->
<span style="flex: 1; color: #ff9100" class="text"> <span style="flex: 1; color: #388e3c" class="text">
{{ o.citBelowNum }} {{ o.citBelowNum }}
</span> </span>
<span <span
@@ -177,10 +177,18 @@ const tableStore: any = new TableStore({
monitoringPoints.value.runNum = tableStore.table.data.totalNum monitoringPoints.value.runNum = tableStore.table.data.totalNum
monitoringPoints.value.abnormalNum = tableStore.table.data.belowNum monitoringPoints.value.abnormalNum = tableStore.table.data.belowNum
monitoringPoints.value.totalOnlineRate = tableStore.table.data.totalOnlineRate - 0 monitoringPoints.value.totalOnlineRate = tableStore.table.data.totalOnlineRate - 0
abnormal.value = tableStore.table.data.citDetailList abnormal.value = tableStore.table.data.citDetailList.filter((k: any) => {
if (tableStore.table.params.statisticalType.name == '终端厂家') {
return k.citTotalNum != 0
} else {
return !k.citName.includes('上送')
}
})
} }
}) })
tableStore.table.params.deptIndex = dictData.state.area[0].id tableStore.table.params.deptIndex = dictData.state.area[0].id
tableStore.table.params.lineRunFlag = 0
const echart = () => { const echart = () => {
percentage.value = { percentage.value = {
color: ['#FF9100'], color: ['#FF9100'],
@@ -214,7 +222,7 @@ const echart = () => {
series: [ series: [
{ {
name: '异常总数', name: '',
type: 'bar', type: 'bar',
barWidth: 12, barWidth: 12,
data: [100], data: [100],
@@ -231,7 +239,7 @@ const echart = () => {
colorStops: [ colorStops: [
{ {
offset: 1, offset: 1,
color: '#57bc6e' // 100% 处的颜色 color: '#FF9100' // 100% 处的颜色
} }
], ],
global: false // 缺省为 false global: false // 缺省为 false
@@ -240,7 +248,7 @@ const echart = () => {
} }
}, },
{ {
name: '异常占比', name: '',
type: 'bar', type: 'bar',
barWidth: 13, barWidth: 13,
data: [ data: [
@@ -261,11 +269,11 @@ const echart = () => {
colorStops: [ colorStops: [
{ {
offset: 0, offset: 0,
color: '#FF9100' // 0% 处的颜色 color: '#57bc6e' // 0% 处的颜色
}, },
{ {
offset: 1, offset: 1,
color: '#FF9100' // 100% 处的颜色 color: '#57bc6e' // 100% 处的颜色
} }
], ],
global: false // 缺省为 false global: false // 缺省为 false
@@ -338,6 +346,7 @@ watch(
) )
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import '@/assets/font/iconfont.css';
.monitoringPoints { .monitoringPoints {
display: flex; display: flex;
.statistics { .statistics {

View File

@@ -18,29 +18,53 @@
> >
<div style="flex: 1"> <div style="flex: 1">
<div class="title">终端统计</div> <div class="title">终端统计</div>
<div style="height: 135px" class="box1"> <div
<div class="boxDiv hexagon"> class="box1"
<div style="color: #fff">{{ statisticsList.allNum }}</div> :style="{
<div class="mt10 divBot">总数</div> height: `calc(${prop.height} - ${headerHeight}px + ${fullscreen ? 0 : 56}px - 30px )`,
overflow: 'auto'
}"
>
<div class="statistics">
<div class="divBox div1">
<span class="iconfont icon-qiyezongshu" style="color: #57bc6e"></span>
<span class="divBox_title">终端总数</span>
<span class="divBox_num text-style" style="color: #57bc6e">
{{ statisticsList.allNum }}
</span>
</div>
<div class="divBox div2">
<span class="iconfont icon-zaiyunshebei" style="color: #67c23a"></span>
<span class="divBox_title">在运终端数</span>
<span class="divBox_num text-style" style="color: #67c23a">
{{ statisticsList.runNum }}
</span>
</div>
</div> </div>
<div class="boxDiv hexagon hexagon1">
<div style="color: #fff">{{ statisticsList.runNum }}</div> <div class="statistics">
<div class="mt10 divBot">在运</div> <div class="divBox div3">
</div> <span
</div> class="iconfont icon-yichanglei_14feizhinengbiaozaiyunyichang"
<div style="height: 135px" class="box1"> style="color: #ffbf00"
<div class="boxDiv hexagon hexagon2"> ></span>
<div style="color: #fff">{{ statisticsList.checkNum }}</div> <span class="divBox_title">调试终端数</span>
<div class="mt10 divBot">调试</div> <span class="divBox_num text-style" style="color: #ffbf00">
</div> {{ statisticsList.checkNum }}
<div class="boxDiv hexagon hexagon3"> </span>
<div style="color: #fff">{{ statisticsList.stopRunNum }}</div> </div>
<div class="mt10 divBot">停运</div> <div class="divBox div4">
<span class="iconfont icon-tingyunshijianguanli" style="color: #f56c6c"></span>
<span class="divBox_title">停运终端数</span>
<span class="divBox_num text-style" style="color: #f56c6c">
{{ statisticsList.stopRunNum }}
</span>
</div>
</div> </div>
</div> </div>
</div> </div>
<div style="flex: 2" class="ml15"> <div style="flex: 2" class="ml15">
<div class="title">完整性统计</div> <div class="title">终端运行统计</div>
<div class="mb5" style="height: 40px"> <div class="mb5" style="height: 40px">
<el-segmented <el-segmented
@@ -65,7 +89,7 @@
<span style="width: 90px">终端总数</span> <span style="width: 90px">终端总数</span>
<span style="flex: 1">完整性(%)</span> <span style="flex: 1">完整性(%)</span>
<span style="flex: 1">在线率(%)</span> <span style="flex: 1">在线率(%)</span>
<span style="flex: 1">合格(%)</span> <span style="flex: 1">异常(%)</span>
</div> </div>
<div <div
:style="{ :style="{
@@ -84,7 +108,7 @@
</span> </span>
<!-- --> <!-- -->
<sp <sp
style="flex: 1; color: #ff9100" style="flex: 1; color: #388e3c"
class="text" class="text"
:class="` ${o.integrity < 90 ? 'text-red' : ''}`" :class="` ${o.integrity < 90 ? 'text-red' : ''}`"
> >
@@ -99,7 +123,7 @@
</span> </span>
<span <span
style="flex: 1; color: #388e3c" style="flex: 1; color: #388e3c"
:class="` ${o.qualified < 90 ? 'text-red' : ''}`" :class="` ${o.qualified > 10 ? 'text-red' : ''}`"
class="text" class="text"
> >
{{ o.qualified }} {{ o.qualified }}
@@ -205,11 +229,17 @@ const tableStore: any = new TableStore({
statisticsList.value.checkNum = totalData.value.filter(item => item.runFlag === '调试').length statisticsList.value.checkNum = totalData.value.filter(item => item.runFlag === '调试').length
statisticsList.value.stopRunNum = totalData.value.filter(item => item.runFlag === '停运').length statisticsList.value.stopRunNum = totalData.value.filter(item => item.runFlag === '停运').length
abnormal.value = tableStore.table.data abnormal.value = tableStore.table.data.filter((k: any) => {
if (tableStore.table.params.statisticalType.name == '终端厂家') {
return k.count != 0
} else {
return !k.citName.includes('上送')
}
})
} }
}) })
tableStore.table.params.deptIndex = dictData.state.area[0].id tableStore.table.params.deptIndex = dictData.state.area[0].id
tableStore.table.params.lineRunFlag = 0
provide('tableStore', tableStore) provide('tableStore', tableStore)
onMounted(() => { onMounted(() => {
@@ -234,6 +264,7 @@ watch(
) )
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import '@/assets/font/iconfont.css';
.monitoringPoints { .monitoringPoints {
display: flex; display: flex;
} }
@@ -344,32 +375,7 @@ watch(
color: #fff; color: #fff;
border-radius: 8px; border-radius: 8px;
} }
.box1 {
display: flex;
align-items: center;
justify-content: space-around;
.boxDiv {
// flex: 1;
display: flex;
flex-direction: column;
align-items: center;
position: relative;
margin: 0 5px;
div:nth-child(1) {
position: absolute;
font-size: 30px;
top: -10px;
font-weight: 700;
}
.divBot {
font-size: 16px;
position: absolute;
top: 20px;
}
color: #fff;
}
}
.hexagon { .hexagon {
position: relative; position: relative;
width: 100px; width: 100px;
@@ -427,4 +433,44 @@ watch(
border-top: 27.5px solid #a52a2a; border-top: 27.5px solid #a52a2a;
} }
} }
.statistics {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.divBox {
width: 100%;
height: 70px;
padding: 10px;
display: flex;
margin-bottom: 10px;
.iconfont {
font-size: 40px;
margin-right: 5px;
}
.divBox_title {
font-weight: 550;
}
.divBox_num {
font-size: 20px;
font-weight: 550;
margin-left: auto;
font-family: AlimamaDongFangDaKai;
}
align-items: center;
// text-align: center;
border-radius: 5px;
}
.div1 {
background-color: #eef8f0;
}
.div2 {
background-color: #67c23a24;
}
.div3 {
background-color: #ffbf0024;
}
.div4 {
background-color: #f56c6c24;
}
}
</style> </style>

View File

@@ -15,8 +15,9 @@ import { color, gradeColor3 } from './color'
import { useConfig } from '@/stores/config' import { useConfig } from '@/stores/config'
const config = useConfig() const config = useConfig()
// import { nextTick } from 'process' // import { nextTick } from 'process'
const emit = defineEmits(['triggerPoint', 'group']) const emit = defineEmits(['triggerPoint', 'group', 'echartClick'])
color[0] = config.layout.elementUiPrimary[0] color[0] = config.layout.elementUiPrimary[0]
const chartRef = ref<HTMLDivElement>() const chartRef = ref<HTMLDivElement>()
const props = defineProps(['options', 'isInterVal', 'pieInterVal']) const props = defineProps(['options', 'isInterVal', 'pieInterVal'])
@@ -70,6 +71,8 @@ const initChart = () => {
const value = const value =
item.value === 3.14159 || item.value === 0.14159 item.value === 3.14159 || item.value === 0.14159
? '暂无数据' ? '暂无数据'
: item.value === 0.14158
? 0
: Math.round(item.value * 100) / 100 // 处理特殊值 : Math.round(item.value * 100) / 100 // 处理特殊值
tips += `<div style=" display: flex;justify-content: space-between;"> tips += `<div style=" display: flex;justify-content: space-between;">
<span>${item.marker} <span>${item.marker}
@@ -153,6 +156,8 @@ const initChart = () => {
chart.on('click', function (params) { chart.on('click', function (params) {
if (params.seriesName == '暂态触发点') { if (params.seriesName == '暂态触发点') {
emit('triggerPoint', params.data) emit('triggerPoint', params.data)
} else {
emit('echartClick', params)
} }
}) })

View File

@@ -7,7 +7,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onBeforeUnmount, ref, watch, onMounted, defineEmits } from 'vue' import { onBeforeUnmount, ref, watch, onMounted, } from 'vue'
import * as echarts from 'echarts' import * as echarts from 'echarts'
import 'echarts-gl' import 'echarts-gl'
import 'echarts-liquidfill' import 'echarts-liquidfill'
@@ -19,14 +19,21 @@ const myCharts = ref()
const showCircle = ref(false) const showCircle = ref(false)
const fetchConfig = async (name: string) => { const fetchConfig = async (name: string) => {
const res = await import(`../../assets/map/${name.replace(/市$/, "")}.json`) try {
return res.default // 处理城市名称(去掉末尾的"市")并尝试导入对应文件
const res = await import(`../../assets/map/${name.replace(/市$/, '')}.json`)
return res.default
} catch (error) {
const chinaRes = await import(`../../assets/map/中国.json`) // 请确认中国文件的实际命名
return chinaRes.default
}
// const res = await import(`../../assets/map/${name.replace(/市$/, "")}.json`)
// return res.default
// GetEchar(res.default) // GetEchar(res.default)
} }
// fetchConfig() // fetchConfig()
const emit = defineEmits(['getRegionByRegion', 'eliminate', 'clickMap']) const emit = defineEmits(['getRegionByRegion', 'eliminate', 'clickMap'])
onMounted(() => { })
const GetEchar = async (name: string) => { const GetEchar = async (name: string) => {
let chartDom = document.getElementById('chartMap') let chartDom = document.getElementById('chartMap')
@@ -36,6 +43,7 @@ const GetEchar = async (name: string) => {
name == dictData.state.area?.[0].name ? (showCircle.value = false) : (showCircle.value = true) name == dictData.state.area?.[0].name ? (showCircle.value = false) : (showCircle.value = true)
echarts.registerMap(name, await fetchConfig(name)) //注册可用的地图 echarts.registerMap(name, await fetchConfig(name)) //注册可用的地图
let option = { let option = {
title: { title: {
left: 'center', left: 'center',
@@ -91,6 +99,7 @@ const GetEchar = async (name: string) => {
// top: 10, // top: 10,
// bottom: 0, // bottom: 0,
roam: true, roam: true,
label: { label: {
normal: { normal: {
show: true, show: true,
@@ -170,6 +179,7 @@ const GetEchar = async (name: string) => {
}, 0) }, 0)
window.addEventListener('resize', resizeHandler) window.addEventListener('resize', resizeHandler)
const flag1 = ref(true) const flag1 = ref(true)
// 点击事件 // 点击事件
myCharts.value.off('click') myCharts.value.off('click')
myCharts.value.on('click', (e: any) => { myCharts.value.on('click', (e: any) => {

View File

@@ -1,441 +1,499 @@
<template> <template>
<div v-loading="loading"> <div v-loading="loading">
<div> <div>
<div id="boxi" :style="`height:${vh};overflow: hidden;`"> <div id="boxi" :style="`height:${vh};overflow: hidden;`">
<div class="bx" id="wave"></div> <div class="bx" id="wave"></div>
</div> </div>
<el-tabs type="border-card"> <el-tabs type="border-card">
<el-tab-pane label="暂态波形上送" :style="'height:' + vhh"> <el-tab-pane label="暂态波形上送" :style="'height:' + vhh">
<el-table stripe :data="Data" :height="height" border style="width: 100%" <vxe-table
header-cell-class-name="table_header"> stripe
<el-table-column align="center" prop="number" label="事件段"></el-table-column> :data="Data"
<el-table-column align="center" prop="number" label="波形起始点相位(°)"> :height="height"
<el-table-column align="center" prop="number" label="A相"></el-table-column> border
<el-table-column align="center" prop="number" label="B相"></el-table-column> style="width: 100%"
<el-table-column align="center" prop="number" label="C相"></el-table-column> header-cell-class-name="table_header"
</el-table-column> >
<el-table-column align="center" prop="number" label="跳变段电压变化率(V/ms)"> <vxe-column align="center" field="number" title="事件段"></vxe-column>
<el-table-column align="center" prop="number" label="A相"></el-table-column> <vxe-colgroup align="center" field="number1" title="波形起始点相位(°)">
<el-table-column align="center" prop="number" label="B相"></el-table-column> <vxe-column align="center" field="number2" title="A相"></vxe-column>
<el-table-column align="center" prop="number" label="C相"></el-table-column> <vxe-column align="center" field="number3" title="B相"></vxe-column>
</el-table-column> <vxe-column align="center" field="number4" title="C相"></vxe-column>
<el-table-column align="center" prop="number" label="相位跳变(°)"> </vxe-colgroup>
<el-table-column align="center" prop="number" label="A相"></el-table-column> <vxe-colgroup align="center" field="number" title="跳变段电压变化率(V/ms)">
<el-table-column align="center" prop="number" label="B相"></el-table-column> <vxe-column align="center" field="number5" title="A相"></vxe-column>
<el-table-column align="center" prop="number" label="C相"></el-table-column> <vxe-column align="center" field="number6" title="B相"></vxe-column>
</el-table-column> <vxe-column align="center" field="number7" title="C相"></vxe-column>
<el-table-column align="center" prop="number" label="总分段数目"></el-table-column> </vxe-colgroup>
<el-table-column align="center" prop="number" label="三相电压不平衡度(%)" width="180"></el-table-column> <vxe-colgroup align="center" field="number" title="相位跳变(°)">
<el-table-column align="center" prop="number" label="暂降类型"></el-table-column> <vxe-column align="center" field="number8" title="A相"></vxe-column>
<el-table-column align="center" prop="number" label="暂降原因"></el-table-column> <vxe-column align="center" field="number9" title="B相"></vxe-column>
</el-table> <vxe-column align="center" field="number10" title="C相"></vxe-column>
</el-tab-pane> </vxe-colgroup>
</el-tabs> <vxe-column align="center" field="number11" title="总分段数目"></vxe-column>
</div> <vxe-column
</div> align="center"
</template> field="number12"
<script> title="三相电压不平衡度(%)"
import { downloadWaveFile, getMonitorEventAnalyseWave } from '@/api/event-boot/transient' width="180"
import { mainHeight } from '@/utils/layout' ></vxe-column>
import * as echarts from 'echarts' <vxe-column align="center" field="number13" title="触发类型"></vxe-column>
import url from '@/assets/img/point.png' <vxe-column align="center" field="number14" title="暂降原因"></vxe-column>
import $ from 'jquery' </vxe-table>
export default { </el-tab-pane>
props: { </el-tabs>
flag: { </div>
type: Boolean, </div>
default: false </template>
}, <script>
DColor: { import { downloadWaveFile, getMonitorEventAnalyseWave } from '@/api/event-boot/transient'
type: Boolean, import { mainHeight } from '@/utils/layout'
default: false import * as echarts from 'echarts'
}, import url from '@/assets/img/point.png'
boxoList: { import $ from 'jquery'
type: [Object, Array] export default {
}, props: {
GJList: { flag: {
type: [Object, Array] type: Boolean,
} default: false
}, },
data() { DColor: {
return { type: Boolean,
loading: true, default: false
},
valA: 0, boxoList: {
isOpen: false, type: [Object, Array]
time: '', },
type: '', GJList: {
severity: '', type: [Object, Array]
iphasic: '', }
eventValue: '', },
persistTime: '', data() {
lineName: '', return {
subName: '', loading: true,
waveDatas: [],
valA: 0,
Data: [], isOpen: false,
height: null, time: '',
vhh: null, type: '',
ptpass: '', severity: '',
waveHeight: undefined, iphasic: '',
$wave: undefined, eventValue: '',
color: '#006565', persistTime: '',
charts: {}, lineName: '',
arrpoints: [], subName: '',
titles: '', waveDatas: [],
vh: null,
vw: null, Data: [
zoom: '' {
} number: 1,
}, number1: 0,
created() { }, number2: 0,
watch: { number3: 0,
value: function (a, b) { number4: 0,
if (a == 2) { number5: 0,
// $("#wave1").remove(); number6: 0,
this.initWaves() number7: 0,
} else { number8: 0,
$('#wave1').remove() number9: 0,
this.initWaves() number10: 0,
} number11: 1,
} number12: 0,
}, number13: '其他',
mounted() { number14: '其他'
this.setHeight() }
window.addEventListener('resize', this.setHeight) ],
this.$wave = $('#wave').eq(0) height: null,
this.$nextTick(() => { vhh: null,
this.query() ptpass: '',
}) waveHeight: undefined,
}, $wave: undefined,
beforeDestroy() { color: '#006565',
window.removeEventListener('resize', this.setHeight) charts: {},
}, arrpoints: [],
methods: { titles: '',
setHeight() { vh: null,
this.zoom = 1 / document.body.style.zoom vw: null,
if (this.flag) { zoom: ''
// console.log(123); }
this.vh = mainHeight(250).height },
} else { created() {},
// console.log(3333); watch: {
this.vh = mainHeight(270).height value: function (a, b) {
} if (a == 2) {
}, // $("#wave1").remove();
query() { this.initWaves()
this.loading = true } else {
this.initWave() $('#wave1').remove()
}, this.initWaves()
}
//开始画图 }
initWave() { },
//清除之前增加的div mounted() {
// $("#wave ~ .bx1").remove(); this.setHeight()
$('div.bx1').remove() window.addEventListener('resize', this.setHeight)
//设置暂降触发点的位置 一次值与二次值Y轴不同不是计算出来的 this.$wave = $('#wave').eq(0)
// var height = $(window).height() - 90; this.$nextTick(() => {
var picHeight this.query()
var show = true })
},
//var v = $("#interval").val(); beforeDestroy() {
var isvisible = false window.removeEventListener('resize', this.setHeight)
},
picHeight = this.vh methods: {
// this.$wave.css('height', picHeight) setHeight() {
// this.$wave.css('width', '100%') this.zoom = 1 / document.body.style.zoom
$('#wave').css('height', picHeight) if (this.flag) {
$('#wave').css('width', this.vw) // console.log(123);
this.vh = mainHeight(280).height
var adata = [] } else {
var bdata = [] // console.log(3333);
var cdata = [] this.vh = mainHeight(305).height
var max = 0 }
var min = 0 },
//绘制横向第一个波形图 query() {
this.GJList.smp_x.forEach((item, ind) => { this.loading = true
if (this.GJList.smp_a[ind] > max) { this.initWave()
max = this.GJList.smp_a[ind] },
} else if (this.GJList.smp_a[ind] < min) {
min = this.GJList.smp_a[ind] //开始画图
} initWave() {
if (this.GJList.smp_b[ind] > max) { //清除之前增加的div
max = this.GJList.smp_b[ind] // $("#wave ~ .bx1").remove();
} else if (this.GJList.smp_b[ind] < min) { $('div.bx1').remove()
min = this.GJList.smp_b[ind] //设置暂降触发点的位置 一次值与二次值Y轴不同不是计算出来的
} // var height = $(window).height() - 90;
if (this.GJList.smp_c[ind] > max) { var picHeight
max = this.GJList.smp_c[ind] var show = true
} else if (this.GJList.smp_c[ind] < min) {
min = this.GJList.smp_c[ind] //var v = $("#interval").val();
} var isvisible = false
adata.push([item, this.GJList.smp_a[ind]]) picHeight = this.vh
bdata.push([item, this.GJList.smp_b[ind]]) // this.$wave.css('height', picHeight)
cdata.push([item, this.GJList.smp_c[ind]]) // this.$wave.css('width', '100%')
}) $('#wave').css('height', picHeight)
//绘制瞬时波形图 $('#wave').css('width', this.vw)
// const echarts = require('echarts')
let wave = document.getElementById('wave') var adata = []
let _this = this var bdata = []
var myChartes = echarts.init(wave) var cdata = []
let echartsColor = { var max = 0
WordColor: '#000', var min = 0
thread: '#000000', //绘制横向第一个波形图
FigureColor: [ this.GJList.smp_x.forEach((item, ind) => {
'#07CCCA ', if (this.GJList.smp_a[ind] > max) {
'#00BFF5', max = this.GJList.smp_a[ind]
'#FFBF00', } else if (this.GJList.smp_a[ind] < min) {
'#77DA63', min = this.GJList.smp_a[ind]
'#D5FF6B', }
'#Ff6600', if (this.GJList.smp_b[ind] > max) {
'#FF9100', max = this.GJList.smp_b[ind]
'#5B6E96', } else if (this.GJList.smp_b[ind] < min) {
'#66FFCC', min = this.GJList.smp_b[ind]
'#B3B3B3', }
'#FF00FF', if (this.GJList.smp_c[ind] > max) {
'#CC00FF', max = this.GJList.smp_c[ind]
'#FF9999' } else if (this.GJList.smp_c[ind] < min) {
] min = this.GJList.smp_c[ind]
} }
var option = {
tooltip: { adata.push([item, this.GJList.smp_a[ind]])
top: '10px', bdata.push([item, this.GJList.smp_b[ind]])
trigger: 'axis', cdata.push([item, this.GJList.smp_c[ind]])
borderColor: 'grey', })
backgroundColor: '#fff', //绘制瞬时波形图
style: { // const echarts = require('echarts')
color: '#000', let wave = document.getElementById('wave')
fontSize: '15px', let _this = this
padding: 10 var myChartes = echarts.init(wave)
}, let echartsColor = {
formatter: function (params) { WordColor: '#000',
// console.log(params) thread: '#000000',
var tips = '' FigureColor: [
tips += '时刻:' + params[0].data[0] + '</br/>' '#07CCCA ',
'#00BFF5',
for (var i = 0; i < params.length; i++) { '#FFBF00',
if (params[i].seriesName != '暂降触发点') { '#77DA63',
tips += params[i].seriesName + ':' + params[i].value[1] + '<br/>' '#D5FF6B',
} '#Ff6600',
} '#FF9100',
return tips '#5B6E96',
}, '#66FFCC',
// axisPointer: { '#B3B3B3',
// type: "cross", '#FF00FF',
// label: { '#CC00FF',
// color: "#fff", '#FF9999'
// fontSize: 16, ]
// }, }
// }, console.log('🚀 ~ this.boxoList:', this.boxoList)
textStyle: {
color: '#fff', var option = {
fontStyle: 'normal', tooltip: {
opacity: 0.35, top: '10px',
fontSize: 14 trigger: 'axis',
}, borderColor: 'grey',
backgroundColor: 'rgba(0,0,0,0.55)', backgroundColor: '#fff',
borderWidth: 0 style: {
}, color: '#000',
fontSize: '15px',
title: { padding: 10
left: 'center', },
text: '发生时刻:' + this.boxoList.startTime + ' PT变化:' + this.boxoList.measurementPointName, formatter: function (params) {
textStyle: { // console.log(params)
fontSize: 16, var tips = ''
color: _this.DColor ? '#fff' : echartsColor.WordColor tips += '时刻:' + params[0].data[0] + '</br/>'
}
}, for (var i = 0; i < params.length; i++) {
legend: { if (params[i].seriesName != '暂降触发点') {
left: '5%', tips += params[i].seriesName + ':' + params[i].value[1] + '<br/>'
top: '20', }
verticalAlign: 'top', }
enabled: true, return tips
itemDistance: 5, },
textStyle: { // axisPointer: {
color: _this.DColor ? '#fff' : echartsColor.WordColor, // type: "cross",
rich: { // label: {
a: { // color: "#fff",
verticalAlign: 'middle' // fontSize: 16,
} // },
}, // },
textStyle: {
padding: [2, 0, 0, 0] //[上、右、下、左] color: '#fff',
} fontStyle: 'normal',
}, opacity: 0.35,
toolbox: { fontSize: 14
show: false, },
feature: { backgroundColor: 'rgba(0,0,0,0.55)',
//restore: {}, borderWidth: 0
saveAsImage: { },
iconStyle: {
borderColor: _this.DColor ? '#fff' : echartsColor.WordColor title: {
} left: 'center',
} text: '发生时刻:' + this.boxoList.startTime + ' PT变化:' + this.boxoList.pt,
} textStyle: {
}, fontSize: 16,
xAxis: { color: _this.DColor ? '#fff' : echartsColor.WordColor
type: 'value', }
name: '时刻', },
boundaryGap: false, legend: {
min: this.GJList.smp_x[0], left: '5%',
max: this.GJList.smp_x[this.GJList.smp_x.length - 1] + 1, top: '20',
title: { verticalAlign: 'top',
text: 'ms', enabled: true,
textStyle: { itemDistance: 5,
fontSize: 12, textStyle: {
color: _this.DColor ? '#fff' : echartsColor.WordColor color: _this.DColor ? '#fff' : echartsColor.WordColor,
}, rich: {
enabled: true, a: {
align: 'high' verticalAlign: 'middle'
}, }
splitLine: { },
show: false
}, padding: [2, 0, 0, 0] //[上、右、下、左]
axisTick: { }
alignWithLabel: true },
}, toolbox: {
axisLine: { show: false,
lineStyle: { feature: {
color: _this.DColor ? '#fff' : echartsColor.thread //restore: {},
}, saveAsImage: {
onZero: false //-----------重点 iconStyle: {
}, borderColor: _this.DColor ? '#fff' : echartsColor.WordColor
axisLabel: { }
color: _this.DColor ? '#fff' : echartsColor.WordColor, }
formatter: function (value, index) { }
if (_this.valA != (value - 0).toFixed(0)) { },
_this.valA = (value - 0).toFixed(0) xAxis: {
return (value - 0).toFixed(0) type: 'value',
} name: '时刻',
} boundaryGap: false,
//rotate:39 min: this.GJList.smp_x[0],
} max: this.GJList.smp_x[this.GJList.smp_x.length - 1] + 1,
// data: this.syncExtremes, title: {
}, text: 'ms',
yAxis: { textStyle: {
type: 'value', fontSize: 12,
name: 'kV', color: _this.DColor ? '#fff' : echartsColor.WordColor
title: { },
align: 'high', enabled: true,
offset: 0, align: 'high'
text: 'kV', },
rotation: 0, splitLine: {
y: -10 show: false
}, },
axisTick: {
boundaryGap: [0, '100%'], alignWithLabel: true
showLastLabel: true, },
max: (max + 10).toFixed(2), axisLine: {
min: (min - 10).toFixed(2), lineStyle: {
opposite: false, color: _this.DColor ? '#fff' : echartsColor.thread
nameTextStyle: { },
color: _this.DColor ? '#fff' : echartsColor.WordColor onZero: false //-----------重点
}, },
//minInterval: 1, axisLabel: {
type: 'value', color: _this.DColor ? '#fff' : echartsColor.WordColor,
axisLine: { formatter: function (value, index) {
show: true, if (_this.valA != (value - 0).toFixed(0)) {
lineStyle: { _this.valA = (value - 0).toFixed(0)
color: _this.DColor ? '#fff' : echartsColor.thread return (value - 0).toFixed(0)
}, }
onZero: false //-----------重点 }
}, //rotate:39
axisLabel: { }
color: _this.DColor ? '#fff' : echartsColor.WordColor, // data: this.syncExtremes,
formatter: function (value, index) { },
return (value - 0).toFixed(2) yAxis: {
} type: 'value',
}, name: 'kV',
splitLine: { title: {
lineStyle: { align: 'high',
// 使用深浅的间隔色 offset: 0,
color: [_this.DColor ? '#fff' : echartsColor.thread], text: 'kV',
type: 'dashed', rotation: 0,
opacity: 0.5 y: -10
} },
}
}, boundaryGap: [0, '100%'],
grid: { showLastLabel: true,
left: '1%', max: (max + 10).toFixed(2),
right: '40px', min: (min - 10).toFixed(2),
bottom: '40px', opposite: false,
top: '55px', nameTextStyle: {
containLabel: true color: _this.DColor ? '#fff' : echartsColor.WordColor
}, },
dataZoom: [ //minInterval: 1,
{ type: 'value',
type: 'inside', axisLine: {
height: 13, show: true,
start: 0, lineStyle: {
bottom: '20px', color: _this.DColor ? '#fff' : echartsColor.thread
end: 100 },
}, onZero: false //-----------重点
{ },
start: 0, axisLabel: {
height: 13, color: _this.DColor ? '#fff' : echartsColor.WordColor,
bottom: '20px', formatter: function (value, index) {
end: 100 return (value - 0).toFixed(2)
} }
], },
series: [ splitLine: {
{ lineStyle: {
name: 'A相', // 使用深浅的间隔色
type: 'line', color: [_this.DColor ? '#fff' : echartsColor.thread],
smooth: true, type: 'dashed',
symbol: 'none', opacity: 0.5
sampling: 'lttb', }
itemStyle: { }
color: '#DAA520' },
}, grid: {
data: adata left: '1%',
}, right: '40px',
{ bottom: '40px',
name: 'B相', top: '55px',
type: 'line', containLabel: true
smooth: true, },
symbol: 'none', dataZoom: [
sampling: 'lttb', {
itemStyle: { type: 'inside',
color: '#2E8B57' height: 13,
}, start: 0,
data: bdata bottom: '20px',
}, end: 100
{ },
name: 'C相', {
type: 'line', start: 0,
smooth: true, height: 13,
symbol: 'none', bottom: '20px',
sampling: 'lttb', end: 100
itemStyle: { }
color: '#A52a2a' ],
}, series: [
data: cdata {
}, name: '跳变期',
{ type: 'line',
name: '暂降触发点', data: [],
type: 'scatter', showSymbol: true, // 强制显示标记
symbol: 'image://' + url, symbol: 'rect', // 标记形状为方块
itemStyle: { symbolSize: 10, // 方块大小
width: 16, itemStyle: {
height: 16 color: '#888888', // 方块颜色为灰色
}, borderWidth: 0
data: [[0, min]] },
}
] markArea: {
} silent: true, // 不响应交互
itemStyle: { color: '#ccc' },
myChartes.setOption(option) data: [
// window.echartsArr.push(myChartes) [
setTimeout(() => { { xAxis: '0' }, // 第一个跳变期起始
myChartes.resize() { xAxis: '5' } // 第一个跳变期结束
this.loading = false ],
}, 400) [
{ xAxis: '210' }, // 第二个跳变期起始
//第一个波形图数据绘制完毕后,绘制后续的波形图 { xAxis: '220' } // 第二个跳变期结束
]
// let waveDatasTemp = waveDatas.slice(1); ]
// waveDatasTemp.reverse(); }
} },
} {
} name: 'A相',
</script> type: 'line',
smooth: true,
symbol: 'none',
sampling: 'lttb',
itemStyle: {
color: '#DAA520'
},
data: adata
},
{
name: 'B相',
type: 'line',
smooth: true,
symbol: 'none',
sampling: 'lttb',
itemStyle: {
color: '#2E8B57'
},
data: bdata
},
{
name: 'C相',
type: 'line',
smooth: true,
symbol: 'none',
sampling: 'lttb',
itemStyle: {
color: '#A52a2a'
},
data: cdata
},
{
name: '暂降触发点',
type: 'scatter',
symbol: 'image://' + url,
itemStyle: {
width: 16,
height: 16
},
data: [[0, min]]
}
]
}
myChartes.setOption(option)
// window.echartsArr.push(myChartes)
setTimeout(() => {
myChartes.resize()
this.loading = false
}, 400)
//第一个波形图数据绘制完毕后,绘制后续的波形图
// let waveDatasTemp = waveDatas.slice(1);
// waveDatasTemp.reverse();
}
}
}
</script>

View File

@@ -1,14 +1,17 @@
export let color = [ export const color = [
'#07CCCA', '#07CCCA',
'#00BFF5', '#00BFF5',
'#FFBF00', '#FFBF00',
'#77DA63', '#77DA63',
'#D5FF6B', '#D5FF6B',
'#Ff6600', '#Ff6600',
'#FF9100', '#FF9100',
'#5B6E96', '#5B6E96',
'#66FFCC', '#66FFCC',
'#B3B' '#B266FF',
] '#FF6680',
export const gradeColor3 = ['#339966', '#FFCC33', '#A52a2a'] '#40A0FF',
export const gradeColor5 = ['#00CC00', '#99CC99', '#FF9900', '#996600', '#A52a2a'] '#33CC99'
]
export const gradeColor3 = ['#339966', '#FFCC33', '#A52a2a']
export const gradeColor5 = ['#00CC00', '#99CC99', '#FF9900', '#996600', '#A52a2a']

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -16,18 +16,12 @@
:value="item.value" :value="item.value"
></el-option> ></el-option>
</el-select> </el-select>
<!-- <el-button v-if="view2 && senior" class="ml10" type="primary" <!-- <el-button v-if="view2 && senior" class="ml10" type="primary" @click="AdvancedAnalytics">
@click="AdvancedAnalytics">高级分析</el-button> --> 高级分析
</el-button> -->
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-button <el-button @click="backbxlb" icon="el-icon-Back" style="float: right">返回</el-button>
@click="backbxlb"
class="el-icon-refresh-right"
icon="el-icon-Back"
style="float: right"
>
返回
</el-button>
</el-col> </el-col>
</el-row> </el-row>
<div v-loading="loading" style="height: calc(100vh - 190px)"> <div v-loading="loading" style="height: calc(100vh - 190px)">
@@ -108,12 +102,12 @@ const options = ref([
const shushiboxiRef = ref() const shushiboxiRef = ref()
const bxecharts = ref(mainHeight(95).height as any) const bxecharts = ref(mainHeight(95).height as any)
const view2 = ref(true) const view2 = ref(true)
const boxoList = ref(null) const boxoList: any = ref(null)
const wp = ref(null) const wp = ref(null)
const showBoxi = ref(true) const showBoxi = ref(true)
const view3 = ref(false) const view3 = ref(false)
const view4 = ref(false) const view4 = ref(false)
const GJList = ref([]) const GJList = ref({})
const open = async (row: any) => { const open = async (row: any) => {
loading.value = true loading.value = true
@@ -122,6 +116,7 @@ const open = async (row: any) => {
row.loading = false row.loading = false
if (res != undefined) { if (res != undefined) {
boxoList.value = row boxoList.value = row
boxoList.value.pt = res.data.pt
wp.value = res.data wp.value = res.data
loading.value = false loading.value = false
view4.value = true view4.value = true
@@ -129,6 +124,7 @@ const open = async (row: any) => {
}) })
.catch(() => { .catch(() => {
loading.value = false loading.value = false
backbxlb()
}) })
} }
const bxhandleClick = (tab: any) => { const bxhandleClick = (tab: any) => {
@@ -168,10 +164,13 @@ const AdvancedAnalytics = () => {
analysis({ analysis({
eventIndex: boxoList.value.eventId eventIndex: boxoList.value.eventId
}).then(res => { }).then(res => {
GJList.value = res.data // GJList.value = res.data
view3.value = true // view3.value = true
view2.value = false // view2.value = false
}) })
GJList.value = {}
view3.value = true
view2.value = false
} }
const changeView = () => { const changeView = () => {
if (shushiboxiRef.value) shushiboxiRef.value.backbxlb() if (shushiboxiRef.value) shushiboxiRef.value.backbxlb()

View File

@@ -127,7 +127,7 @@ const timeChange = (e: number) => {
// 当前 // 当前
const nowTime = () => { const nowTime = () => {
console.log(interval.value, '000000000') //console.log(interval.value, '000000000')
timeChange(interval.value) timeChange(interval.value)
} }
// 上一个 // 上一个
@@ -312,7 +312,7 @@ const next = () => {
} }
} else { } else {
month = month + 3 month = month + 3
console.log('🚀 ~ next ~ presentM:', presentM, month) // console.log('🚀 ~ next ~ presentM:', presentM, month)
// 季度进位后,超过当前月份是不科学的 // 季度进位后,超过当前月份是不科学的
if (year == presentY && !props.nextFlag) { if (year == presentY && !props.nextFlag) {
@@ -327,7 +327,7 @@ const next = () => {
endTime = year + '-0' + presentM + '-' + presentD endTime = year + '-0' + presentM + '-' + presentD
} }
} else if (presentM > 3 && presentM < 7) { } else if (presentM > 3 && presentM < 7) {
console.log(123123) // console.log(123123)
// 第二季度 // 第二季度
startTime = year + '-04-01' startTime = year + '-04-01'
if (presentD < 10) { if (presentD < 10) {
@@ -380,7 +380,7 @@ const next = () => {
} }
} }
} }
console.log(startTime, endTime) // console.log(startTime, endTime)
} else if (interval.value == 5) { } else if (interval.value == 5) {
} else if (interval.value == 4) { } else if (interval.value == 4) {
//根据开始时间推 //根据开始时间推

View File

@@ -4,7 +4,7 @@ export const defaultAttribute: VxeTableProps = {
align: 'center', align: 'center',
headerCellClassName: 'table-header-cell', headerCellClassName: 'table-header-cell',
border: true, border: true,
stripe: true,
size: 'small', size: 'small',
columnConfig: { resizable: true }, columnConfig: { resizable: true },
rowConfig: { isCurrent: true, isHover: true }, rowConfig: { isCurrent: true, isHover: true },
@@ -13,6 +13,7 @@ export const defaultAttribute: VxeTableProps = {
treeConfig: { treeConfig: {
reserve: true reserve: true
}, },
showOverflow: true,
showOverflow: true showFooter:true
} }

View File

@@ -1,29 +1,20 @@
<template> <template>
<div ref="tableHeader" class="cn-table-header"> <div ref="tableHeader" class="cn-table-header">
<div class="table-header ba-scroll-style"> <div class="table-header ba-scroll-style">
<el-form <el-form style="flex: 1; height: 32px; display: flex; flex-wrap: wrap" ref="headerForm" @submit.prevent=""
style="flex: 1; height: 32px; display: flex; flex-wrap: wrap" @keyup.enter="onComSearch" label-position="left" :inline="true">
ref="headerForm"
@submit.prevent=""
@keyup.enter="onComSearch"
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; max-width: 630px">
<template #label> <template #label>
<el-checkbox v-if="showTimeAll" v-model="timeAll" label="时间" /> <el-checkbox v-if="showTimeAll" v-model="timeAll" label="统计时间" />
<span v-else>{{ dateLabel }}</span> <span v-else>{{ dateLabel }}</span>
</template> </template>
<DatePicker <DatePicker ref="datePickerRef" v-if="timeAll" :nextFlag="nextFlag"
ref="datePickerRef" :theCurrentTime="theCurrentTime"></DatePicker>
v-if="timeAll"
:nextFlag="nextFlag"
:theCurrentTime="theCurrentTime"
></DatePicker>
</el-form-item> </el-form-item>
<el-form-item label="区域" v-if="area"> <el-form-item label="区域" v-if="area">
<Area ref="areaRef" v-model="tableStore.table.params.deptIndex" /> <Area ref="areaRef" v-model="tableStore.table.params.deptIndex" @change-value="onAreaChange"
style="width: 200px;" />
</el-form-item> </el-form-item>
<slot name="select"></slot> <slot name="select"></slot>
</el-form> </el-form>
@@ -32,43 +23,24 @@
<Icon size="14" name="el-icon-ArrowUp" style="color: #fff" v-if="showSelect" /> <Icon size="14" name="el-icon-ArrowUp" style="color: #fff" v-if="showSelect" />
<Icon size="14" name="el-icon-ArrowDown" style="color: #fff" v-else /> <Icon size="14" name="el-icon-ArrowDown" style="color: #fff" v-else />
</el-button> </el-button>
<el-button <el-button @click="onComSearch" v-if="showSearch" :loading="tableStore.table.loading" type="primary"
@click="onComSearch" :icon="Search">
v-if="showSearch"
:loading="tableStore.table.loading"
type="primary"
:icon="Search"
>
查询 查询
</el-button> </el-button>
<el-button <el-button @click="onResetForm" v-if="showSearch && showReset" :loading="tableStore.table.loading"
@click="onResetForm" :icon="RefreshLeft">
v-if="showSearch && showReset"
:loading="tableStore.table.loading"
:icon="RefreshLeft"
>
重置 重置
</el-button> </el-button>
<el-button <el-button @click="onExport" v-if="showExport" :loading="tableStore.table.exportLoading" type="primary"
@click="onExport" icon="el-icon-Download">
v-if="showExport"
:loading="tableStore.table.loading"
type="primary"
icon="el-icon-Download"
>
导出 导出
</el-button> </el-button>
</template> </template>
<slot name="operation"></slot> <slot name="operation"></slot>
</div> </div>
<el-form <el-form :style="showSelect && showUnfoldButton ? headerFormSecondStyleOpen : headerFormSecondStyleClose"
:style="showSelect && showUnfoldButton ? headerFormSecondStyleOpen : headerFormSecondStyleClose" ref="headerFormSecond" @submit.prevent="" @keyup.enter="onComSearch" label-position="left"
ref="headerFormSecond" :inline="true"></el-form>
@submit.prevent=""
@keyup.enter="onComSearch"
label-position="left"
:inline="true"
></el-form>
</div> </div>
</template> </template>
@@ -81,7 +53,7 @@ import { mainHeight } from '@/utils/layout'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
import { Search, RefreshLeft } from '@element-plus/icons-vue' import { Search, RefreshLeft } from '@element-plus/icons-vue'
import { defineProps } from 'vue' import { defineProps } from 'vue'
const emit = defineEmits(['selectChange']) const emit = defineEmits(['selectChange', 'areaChange'])
const tableStore = inject('tableStore') as TableStore const tableStore = inject('tableStore') as TableStore
const tableHeader = ref() const tableHeader = ref()
const datePickerRef = ref() const datePickerRef = ref()
@@ -111,7 +83,7 @@ const props = withDefaults(defineProps<Props>(), {
showReset: true, showReset: true,
showExport: false, showExport: false,
showTimeAll: false, showTimeAll: false,
dateLabel: '时间' dateLabel: '统计日期'
}) })
// 动态计算table高度 // 动态计算table高度
const resizeObserver = new ResizeObserver(entries => { const resizeObserver = new ResizeObserver(entries => {
@@ -132,6 +104,10 @@ const headerFormSecondStyleClose = {
padding: '0' padding: '0'
} }
const onAreaChange = data => {
emit('areaChange', { label: data.label })
}
watch( watch(
() => tableStore?.table.params.deptIndex, () => tableStore?.table.params.deptIndex,
newVal => { newVal => {
@@ -182,7 +158,7 @@ const handlerHeight = () => {
} }
} }
const computedSearchRow = () => { const computedSearchRow = () => {
if (!headerForm.value.$el) return if (!headerForm.value?.$el) return
// 清空headerFormSecond.value.$el下的元素 // 清空headerFormSecond.value.$el下的元素
while (headerFormSecond.value.$el.firstChild) { while (headerFormSecond.value.$el.firstChild) {
headerForm.value.$el.appendChild(headerFormSecond.value.$el.firstChild) headerForm.value.$el.appendChild(headerFormSecond.value.$el.firstChild)
@@ -231,6 +207,26 @@ const setDatePicker = (list: any) => {
const onResetForm = () => { const onResetForm = () => {
//时间重置成默认值 //时间重置成默认值
datePickerRef.value?.setTheDate(3) 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.datePicker && timeAll.value) {
tableStore.table.params.searchBeginTime = datePickerRef.value.timeValue[0]
tableStore.table.params.searchEndTime = datePickerRef.value.timeValue[1]
tableStore.table.params.startTime = datePickerRef.value.timeValue[0]
tableStore.table.params.endTime = datePickerRef.value.timeValue[1]
tableStore.table.params.timeFlag = datePickerRef.value.timeFlag
tableStore.table.params.interval = datePickerRef.value.interval
}
tableStore.onTableAction('reset', {}) tableStore.onTableAction('reset', {})
} }
const setTheDate = (val: any) => { const setTheDate = (val: any) => {
@@ -238,7 +234,6 @@ const setTheDate = (val: any) => {
} }
// 导出 // 导出
const onExport = () => { const onExport = () => {
console.log('导出')
tableStore.onTableAction('export', { showAllFlag: true }) tableStore.onTableAction('export', { showAllFlag: true })
} }
@@ -274,6 +269,7 @@ defineExpose({
padding: 13px 15px; padding: 13px 15px;
font-size: 14px; font-size: 14px;
overflow: hidden; overflow: hidden;
.table-header-operate-text { .table-header-operate-text {
margin-left: 6px; margin-left: 6px;
} }
@@ -301,7 +297,7 @@ defineExpose({
margin-left: 12px; margin-left: 12px;
} }
.mlr-12 + .el-button { .mlr-12+.el-button {
margin-left: 12px; margin-left: 12px;
} }
@@ -336,7 +332,7 @@ defineExpose({
border-radius: 0; border-radius: 0;
} }
.el-button + .el-button { .el-button+.el-button {
margin: 0; margin: 0;
} }
@@ -347,6 +343,7 @@ defineExpose({
html.dark { html.dark {
.table-search-button-group { .table-search-button-group {
button:focus, button:focus,
button:active { button:active {
background-color: var(--el-color-info-dark-2); background-color: var(--el-color-info-dark-2);

View File

@@ -0,0 +1,187 @@
<template>
<div :style="{ width: menuCollapse ? '40px' : props.width }" style="transition: all 0.3s; overflow: hidden">
<div class="mt15 mr10" style="display: flex; justify-content: end">
<el-button type="primary" icon="el-icon-Select" @click="save" :loading="loading">保存</el-button>
</div>
<Icon
v-show="menuCollapse"
@click="onMenuCollapse"
:name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'"
:class="menuCollapse ? 'unfold' : ''"
size="18"
class="fold ml10 mt20 menu-collapse"
style="cursor: pointer"
/>
<div class="cn-tree" :style="{ opacity: menuCollapse ? 0 : 1 }">
<div style="display: flex; align-items: center" class="mb10">
<el-input maxlength="32" show-word-limit v-model.trim="filterText" placeholder="请输入内容" clearable>
<template #prefix>
<Icon name="el-icon-Search" style="font-size: 16px" />
</template>
</el-input>
<el-tooltip placement="bottom" :hide-after="0" v-if="props.showPush">
<template #content>
<span>台账推送</span>
</template>
<Icon
name="el-icon-Promotion"
size="20"
class="fold ml10 menu-collapse"
style="cursor: pointer"
:style="{ color: config.getColorVal('elementUiPrimary') }"
@click="onAdd"
/>
</el-tooltip>
<!-- <Icon @click='onMenuCollapse' :name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'" v-else
:class="menuCollapse ? 'unfold' : ''" size='18' class='fold ml10 menu-collapse'
style='cursor: pointer' v-if='props.canExpand' /> -->
</div>
<el-tree
:style="{ height: 'calc(100vh - 235px)' }"
style="overflow: auto"
ref="treeRef"
:props="defaultProps"
highlight-current
:default-expand-all="false"
@check-change="checkTreeNodeChange"
:filter-node-method="filterNode"
node-key="id"
v-bind="$attrs"
>
<template #default="{ node, data }">
<span class="custom-tree-node">
<Icon
:name="data.icon"
style="font-size: 16px"
:style="{ color: data.color }"
v-if="data.icon"
/>
<span style="margin-left: 4px">{{ node.label }}</span>
</span>
</template>
</el-tree>
</div>
</div>
</template>
<script lang="ts" setup>
import useCurrentInstance from '@/utils/useCurrentInstance'
import { ElTree } from 'element-plus'
import { emit } from 'process'
import { ref, watch } from 'vue'
import { t } from 'vxe-table'
import { useConfig } from '@/stores/config'
defineOptions({
name: 'govern/tree'
})
interface Props {
width?: string
canExpand?: boolean
showPush?: boolean
}
const loading = ref(false)
const props = withDefaults(defineProps<Props>(), {
width: '280px',
canExpand: true,
showPush: false
})
const config = useConfig()
const { proxy } = useCurrentInstance()
const menuCollapse = ref(false)
const filterText = ref('')
const defaultProps = {
label: 'name',
value: 'id'
}
const emit = defineEmits(['checkTreeNodeChange', 'onAdd', 'checkChange'])
watch(filterText, val => {
treeRef.value!.filter(val)
})
const onMenuCollapse = () => {
menuCollapse.value = !menuCollapse.value
proxy.eventBus.emit('cnTreeCollapse', menuCollapse)
}
const save = () => {
loading.value = true
emit('checkChange')
}
const filterNode = (value: string, data: any, node: any) => {
console.log(value, data, node, 'filterNode')
if (!value) return true
// return data.name.includes(value)
if (data.name) {
return chooseNode(value, data, node)
}
}
// 过滤父节点 / 子节点 (如果输入的参数是父节点且能匹配则返回该节点以及其下的所有子节点如果参数是子节点则返回该节点的父节点。name是中文字符enName是英文字符.
const chooseNode = (value: string, data: any, node: any) => {
if (data.name.indexOf(value) !== -1) {
return true
}
const level = node.level
// 如果传入的节点本身就是一级节点就不用校验了
if (level === 1) {
return false
}
// 先取当前节点的父节点
let parentData = node.parent
// 遍历当前节点的父节点
let index = 0
while (index < level - 1) {
// 如果匹配到直接返回此处name值是中文字符enName是英文字符。判断匹配中英文过滤
if (parentData.data.name.indexOf(value) !== -1) {
return true
}
// 否则的话再往上一层做匹配
parentData = parentData.parent
index++
}
// 没匹配到返回false
return false
}
const checkTreeNodeChange = () => {
// console.log(treeRef.value?.getCheckedNodes(), "ikkkkkiisiiisis");
emit('checkTreeNodeChange', treeRef.value?.getCheckedNodes())
}
const onAdd = () => {
emit('onAdd')
}
const treeRef = ref<InstanceType<typeof ElTree>>()
defineExpose({ treeRef, loading })
</script>
<style lang="scss" scoped>
.cn-tree {
flex-shrink: 0;
display: flex;
flex-direction: column;
box-sizing: border-box;
padding: 10px;
height: 100%;
width: 100%;
:deep(.el-tree) {
border: 1px solid var(--el-border-color);
}
:deep(.el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content) {
background-color: var(--el-color-primary-light-7);
}
.menu-collapse {
color: var(--el-color-primary);
}
}
.custom-tree-node {
display: flex;
align-items: center;
}
</style>

View File

@@ -0,0 +1,205 @@
<template>
<el-dialog draggable v-model="dialogVisible" :title="title" width="1200px">
<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="项目工程">
{{ details.areaName }}
</el-descriptions-item>
<el-descriptions-item label="项目单位">
{{ details.gdName }}
</el-descriptions-item>
<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="监测点名称">
{{ 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="监测点对象名称">
{{ details.objName }}
</el-descriptions-item>
<el-descriptions-item label="接线方式">
{{ details.ptType }}
</el-descriptions-item>
<el-descriptions-item label="PT变比">
{{ details.pt }}
</el-descriptions-item>
<el-descriptions-item label="CT变比">
{{ details.ct }}
</el-descriptions-item>
<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)">
{{ details.devCapacity }}
</el-descriptions-item>
<el-descriptions-item label="用户协议容量(MVA)">
{{ 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="电压偏差上限值(%)">
{{ limitValue.voltageDev }}
</el-descriptions-item>
<el-descriptions-item label="电压偏差下限值(%)">
{{ limitValue.uvoltageDev }}
</el-descriptions-item>
<el-descriptions-item label="频率偏差限值(Hz)">
{{ limitValue.freqDev }}
</el-descriptions-item>
<el-descriptions-item label="三相电压不平衡度限值(%)">
{{ limitValue.ubalance }}
</el-descriptions-item>
<el-descriptions-item label="负序电流限值(A)">
{{ limitValue.ineg }}
</el-descriptions-item>
<el-descriptions-item label="长时闪变限值(%)">
{{ limitValue.flicker }}
</el-descriptions-item>
<el-descriptions-item label="电压总畸变率限值(%)">
{{ limitValue.uaberrance }}
</el-descriptions-item>
<el-descriptions-item label="奇次谐波电压含有率限值(%)">
{{ limitValue.oddHarm }}
</el-descriptions-item>
<el-descriptions-item label="偶次谐波电压含有率限值(%)">
{{ limitValue.evenHarm }}
</el-descriptions-item>
<el-descriptions-item label="3次谐波电流幅值限值(A)">
{{ limitValue.iharm3 }}
</el-descriptions-item>
<el-descriptions-item label="4次谐波电流幅值限值(A)">
{{ limitValue.iharm4 }}
</el-descriptions-item>
<el-descriptions-item label="5次谐波电流幅值限值(A)">
{{ limitValue.iharm5 }}
</el-descriptions-item>
<el-descriptions-item label="6次谐波电流幅值限值(A)">
{{ limitValue.iharm6 }}
</el-descriptions-item>
<el-descriptions-item label="7次谐波电流幅值限值(A)">
{{ limitValue.iharm7 }}
</el-descriptions-item>
<el-descriptions-item label="8次谐波电流幅值限值(A)">
{{ limitValue.iharm8 }}
</el-descriptions-item>
<el-descriptions-item label="9次谐波电流幅值限值(A)">
{{ limitValue.iharm9 }}
</el-descriptions-item>
<el-descriptions-item label="10次谐波电流幅值限值(A)">
{{ limitValue.iharm10 }}
</el-descriptions-item>
<el-descriptions-item label="11次谐波电流幅值限值(A)">
{{ limitValue.iharm11 }}
</el-descriptions-item>
<el-descriptions-item label="12次谐波电流幅值限值(A)">
{{ limitValue.iharm12 }}
</el-descriptions-item>
<el-descriptions-item label="13次谐波电流幅值限值(A)">
{{ limitValue.iharm13 }}
</el-descriptions-item>
<el-descriptions-item label="14次谐波电流幅值限值(A)">
{{ limitValue.iharm14 }}
</el-descriptions-item>
<el-descriptions-item label="15次谐波电流幅值限值(A)">
{{ limitValue.iharm15 }}
</el-descriptions-item>
<el-descriptions-item label="16次谐波电流幅值限值(A)">
{{ limitValue.iharm16 }}
</el-descriptions-item>
<el-descriptions-item label="17次谐波电流幅值限值(A)">
{{ limitValue.iharm17 }}
</el-descriptions-item>
<el-descriptions-item label="18次谐波电流幅值限值(A)">
{{ limitValue.iharm18 }}
</el-descriptions-item>
<el-descriptions-item label="19次谐波电流幅值限值(A)">
{{ limitValue.iharm19 }}
</el-descriptions-item>
<el-descriptions-item label="20次谐波电流幅值限值(A)">
{{ limitValue.iharm20 }}
</el-descriptions-item>
<el-descriptions-item label="21次谐波电流幅值限值(A)">
{{ limitValue.iharm21 }}
</el-descriptions-item>
<el-descriptions-item label="22次谐波电流幅值限值(A)">
{{ limitValue.iharm22 }}
</el-descriptions-item>
<el-descriptions-item label="23次谐波电流幅值限值(A)">
{{ limitValue.iharm23 }}
</el-descriptions-item>
<el-descriptions-item label="24次谐波电流幅值限值(A)">
{{ limitValue.iharm24 }}
</el-descriptions-item>
<el-descriptions-item label="25次谐波电流幅值限值(A)">
{{ limitValue.iharm25 }}
</el-descriptions-item>
<el-descriptions-item label="0.5-1.5次间谐波电压含有率限值(%)">
{{ limitValue.inUharm }}
</el-descriptions-item>
<el-descriptions-item label="2.5-15.5次谐波电压含有率限值(%)">
{{ limitValue.inUharm16 }}
</el-descriptions-item>
</el-descriptions>
</el-tab-pane>
</el-tabs>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, inject } from 'vue'
import { getLineOverLimitData, getLineDetailData } from '@/api/device-boot/line'
const dialogVisible = ref(false)
const title = ref('')
const activeName = ref('tab1')
const details: any = ref([])
const limitValue: any = ref([])
const open = (data: any) => {
details.value = []
limitValue.value = []
activeName.value = 'tab1'
title.value = data.name.replace(/[^]*/g, '') + '_详情'
getLineDetailData(data.id).then(res => {
details.value = res.data
})
getLineOverLimitData(data.id).then(res => {
limitValue.value = res.data
})
dialogVisible.value = true
}
const handleClick = (tab: any, event: Event) => {}
defineExpose({ open })
</script>
<style lang="scss" scoped>
:deep(.el-upload-list__item) {
width: 400px;
}
</style>

View File

@@ -0,0 +1,34 @@
<template>
<el-dialog draggable v-model="dialogVisible" :title="title" width="500px">
<el-descriptions class="margin-top" :column="1" border label-width="150px">
<el-descriptions-item label="变电站名称">{{ list[0]?.srbName }}</el-descriptions-item>
<el-descriptions-item label="电压等级">{{ list[0]?.scale }}</el-descriptions-item>
<el-descriptions-item label="经度">{{ list[0]?.coordY }}</el-descriptions-item>
<el-descriptions-item label="纬度">{{ list[0]?.coordX }}</el-descriptions-item>
</el-descriptions>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, inject } from 'vue'
import { getSubstationSelectLine } from '@/api/device-boot/line'
const dialogVisible = ref(false)
const title = ref('')
const list: any = ref([])
const open = (data: any) => {
list.value = []
title.value = data.name.replace(/[^]*/g, '') + '_详情'
getSubstationSelectLine(data.id).then(res => {
list.value = res.data
})
dialogVisible.value = true
}
defineExpose({ open })
</script>
<style lang="scss" scoped>
:deep(.el-upload-list__item) {
width: 400px;
}
</style>

View File

@@ -1,162 +1,272 @@
<template> <template>
<div :style="{ width: menuCollapse ? '40px' : props.width }" style="transition: all 0.3s; overflow: hidden"> <div :style="{ width: menuCollapse ? '40px' : props.width }" style="transition: all 0.3s; overflow: hidden">
<Icon v-show="menuCollapse" @click="onMenuCollapse" :name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'" <Icon
:class="menuCollapse ? 'unfold' : ''" size="18" class="fold ml10 mt20 menu-collapse" v-show="menuCollapse"
style="cursor: pointer" /> @click="onMenuCollapse"
<div class="cn-tree" :style="{ opacity: menuCollapse ? 0 : 1 }"> :name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'"
<div style="display: flex; align-items: center" class="mb10"> :class="menuCollapse ? 'unfold' : ''"
<el-input v-model="filterText" placeholder="请输入内容" clearable maxlength="10" show-word-limit @input="change"> size="18"
<template #prefix> class="fold ml10 mt20 menu-collapse"
<Icon name="el-icon-Search" style="font-size: 16px" /> style="cursor: pointer"
</template> />
</el-input> <div class="cn-tree" :style="{ opacity: menuCollapse ? 0 : 1 }">
<Icon @click="onMenuCollapse" :name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'" <div style="display: flex; align-items: center" class="mb10">
:class="menuCollapse ? 'unfold' : ''" size="18" class="fold ml10 menu-collapse" <el-input
style="cursor: pointer" v-if="props.canExpand" /> v-model="filterText"
<el-button icon="el-icon-Plus" v-if="props.addTree" type="primary" class="ml10" placeholder="请输入内容"
@click="onAddTree">新增</el-button> clearable
</div> maxlength="10"
<el-tree style="flex: 1; overflow: auto" ref="treeRef" :props="defaultProps" highlight-current show-word-limit
:filter-node-method="filterNode" node-key="id" v-bind="$attrs"> @input="change"
<template #default="{ node, data }"> >
<span class="custom-tree-node"> <template #prefix>
<Icon :name="data.icon" style="font-size: 16px" :style="{ color: data.color }" <Icon name="el-icon-Search" style="font-size: 16px" />
v-if="data.icon" /> </template>
<span style="margin-left: 4px">{{ node.label }}</span> </el-input>
</span> <Icon
</template> @click="onMenuCollapse"
</el-tree> :name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'"
</div> :class="menuCollapse ? 'unfold' : ''"
</div> size="18"
</template> class="fold ml10 menu-collapse"
style="cursor: pointer"
<script lang="ts" setup> v-if="props.canExpand"
import useCurrentInstance from '@/utils/useCurrentInstance' />
import { ElTree } from 'element-plus' <el-button icon="el-icon-Plus" v-if="props.addTree" type="primary" class="ml10" @click="onAddTree">
import { ref, watch } from 'vue' 新增
import { ElMessage } from 'element-plus' </el-button>
defineOptions({ </div>
name: 'govern/tree' <el-tree
}) style="flex: 1; overflow: auto"
const emit = defineEmits(['onAddTree']) ref="treeRef"
interface Props { :props="defaultProps"
width?: string highlight-current
canExpand?: boolean :filter-node-method="filterNode"
addTree?: boolean node-key="id"
} v-bind="$attrs"
>
const props = withDefaults(defineProps<Props>(), { <template #default="{ node, data }">
width: '280px', <span class="custom-tree-node">
canExpand: true, <Icon
addTree: false :name="data.icon"
}) style="font-size: 16px"
const { proxy } = useCurrentInstance() :style="{ color: data.color }"
const menuCollapse = ref(false) v-if="data.icon"
const filterText = ref('') />
const defaultProps = {
label: 'name', <el-tooltip
value: 'id' class="box-item"
} effect="customized"
const specialCharsPattern = /[`~!@$%^&*\-+=<>?:"{}|,.\/;'\\[\]·~@¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、~]/g; placement="bottom-start"
const change=(val) => { :offset="0"
v-if="data.level == 6"
>
if (specialCharsPattern.test(val)) { <template #content>
ElMessage.warning('禁止输入特殊字符!') <el-button type="primary" plain @click="viewDetails(data)">
filterText.value = val.replace(/[`~!@$%^&*\-+=<>?:"{}|,.\/;'\\[\]·~@¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、~]/g, "") {{ data.level == 3 ? '变电站详情' : '监测点详情' }}
console.log("🚀 ~ change ~ filterText.value:", filterText.value) </el-button>
</template>
treeRef.value!.filter(filterText.value) <span style="margin-left: 4px">{{ node.label }}</span>
}else{ </el-tooltip>
treeRef.value!.filter(filterText.value) <span v-else style="margin-left: 4px">{{ node.label }}</span>
} </span>
} </template>
// watch(filterText, val => { </el-tree>
</div>
// console.log("🚀 ~ val:", specialCharsPattern.test(val)) <!-- 变电站详情 -->
// if (specialCharsPattern.test(val)) { <SubstationDetails ref="SubstationRef" />
// ElMessage.warning('禁止输入特殊字符!') <!-- 监测点详情 -->
// filterText.value = val.replace(/[`~!@$%^&*\-+=<>?:"{}|,.\/;'\\[\]·~@¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、~]/g, "") <MonitoringPointDetails ref="MonitoringPointRef" />
// console.log("🚀 ~ filterText.value:", filterText.value) </div>
// treeRef.value!.filter(filterText.value) </template>
// }else{
// treeRef.value!.filter(filterText.value) <script lang="ts" setup>
// } import useCurrentInstance from '@/utils/useCurrentInstance'
import { ElTree } from 'element-plus'
// }) import { ref, watch, onMounted, nextTick } from 'vue'
const onMenuCollapse = () => { import { ElMessage } from 'element-plus'
menuCollapse.value = !menuCollapse.value import MonitoringPointDetails from './details/monitoringPointDetails.vue'
proxy.eventBus.emit('cnTreeCollapse', menuCollapse) import SubstationDetails from './details/substationDetails.vue'
}
const filterNode = (value: string, data: any, node: any) => { defineOptions({
if (!value) return true name: 'govern/tree'
// return data.name.includes(value) })
if (data.name) { const emit = defineEmits(['onAddTree'])
interface Props {
return chooseNode(value, data, node) width?: string
} canExpand?: boolean
} addTree?: boolean
}
// 过滤父节点 / 子节点 (如果输入的参数是父节点且能匹配则返回该节点以及其下的所有子节点如果参数是子节点则返回该节点的父节点。name是中文字符enName是英文字符.
const chooseNode = (value: string, data: any, node: any) => { const props = withDefaults(defineProps<Props>(), {
width: '280px',
if (data.name.indexOf(value) !== -1) { canExpand: true,
return true addTree: false
} })
const level = node.level const { proxy } = useCurrentInstance()
// 如果传入的节点本身就是一级节点就不用校验了 const menuCollapse = ref(false)
if (level === 1) { const MonitoringPointRef = ref()
return false const SubstationRef = ref()
} const filterText = ref('')
// 先取当前节点的父节点 const treeRef = ref()
let parentData = node.parent const defaultProps = {
// 遍历当前节点的父节点 label: 'name',
let index = 0 value: 'id'
while (index < level - 1) { }
// 如果匹配到直接返回此处name值是中文字符enName是英文字符。判断匹配中英文过滤 const specialCharsPattern = /[`~!@$%^&*\-+=<>?:"{}|,.\/;'\\[\]·~@¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、~]/g
if (parentData.data.name.indexOf(value) !== -1) { const change = val => {
return true if (specialCharsPattern.test(val)) {
} ElMessage.warning('禁止输入特殊字符!')
// 否则的话再往上一层做匹配 filterText.value = val.replace(
parentData = parentData.parent /[`~!@$%^&*\-+=<>?:"{}|,.\/;'\\[\]·~@¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、~]/g,
index++ ''
} )
// 没匹配到返回false console.log('🚀 ~ change ~ filterText.value:', filterText.value)
return false
} treeRef.value!.filter(filterText.value)
// 添加树 } else {
const onAddTree = () => { treeRef.value!.filter(filterText.value)
emit('onAddTree') }
} }
const treeRef = ref<InstanceType<typeof ElTree>>() // watch(filterText, val => {
defineExpose({ treeRef })
</script> // console.log("🚀 ~ val:", specialCharsPattern.test(val))
// if (specialCharsPattern.test(val)) {
<style lang="scss" scoped> // ElMessage.warning('禁止输入特殊字符!')
.cn-tree { // filterText.value = val.replace(/[`~!@$%^&*\-+=<>?:"{}|,.\/;'\\[\]·~@¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、~]/g, "")
flex-shrink: 0; // console.log("🚀 ~ filterText.value:", filterText.value)
display: flex; // treeRef.value!.filter(filterText.value)
flex-direction: column; // }else{
box-sizing: border-box; // treeRef.value!.filter(filterText.value)
padding: 10px; // }
height: 100%;
width: 100%; // })
const onMenuCollapse = () => {
:deep(.el-tree) { menuCollapse.value = !menuCollapse.value
border: 1px solid var(--el-border-color); proxy.eventBus.emit('cnTreeCollapse', menuCollapse)
} }
// 查看详情
:deep(.el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content) { const viewDetails = (data: any) => {
background-color: var(--el-color-primary-light-7); // console.log('🚀 ~ viewDetails ~ data:', data)
} if (data.level == 3) {
// 变电站详情
.menu-collapse { // substationDetails
color: var(--el-color-primary); SubstationRef.value.open(data)
} } else {
} // 监测点详情
MonitoringPointRef.value.open(data)
.custom-tree-node { }
display: flex;
align-items: center; // proxy.eventBus.emit('viewDetails', data)
} }
</style> const filterNode = (value: string, data: any, node: any) => {
if (!value) return true
// return data.name.includes(value)
if (data.name) {
return chooseNode(value, data, node)
}
}
// 过滤父节点 / 子节点 (如果输入的参数是父节点且能匹配则返回该节点以及其下的所有子节点如果参数是子节点则返回该节点的父节点。name是中文字符enName是英文字符.
const chooseNode = (value: string, data: any, node: any) => {
if (data.name.indexOf(value) !== -1) {
return true
}
const level = node.level
// 如果传入的节点本身就是一级节点就不用校验了
if (level === 1) {
return false
}
// 先取当前节点的父节点
let parentData = node.parent
// 遍历当前节点的父节点
let index = 0
while (index < level - 1) {
// 如果匹配到直接返回此处name值是中文字符enName是英文字符。判断匹配中英文过滤
if (parentData.data.name.indexOf(value) !== -1) {
return true
}
// 否则的话再往上一层做匹配
parentData = parentData.parent
index++
}
// 没匹配到返回false
return false
}
onMounted(async () => {
// 等待树渲染完成
await nextTick()
// 可以等待更长时间确保树完全展开
})
const scrollToNode = (id: string) => {
// console.log("🚀 ~ scrollToNode ~ id:", id)
if (!treeRef.value) return
// 获取目标节点的元素
const targetNode = treeRef.value.getNode(id)
if (!targetNode) return
// 获取节点的DOM元素
const nodeElement = document.querySelector(`[data-key="${id}"]`)
if (nodeElement) {
// 滚动到节点位置
nodeElement.scrollIntoView({
behavior: 'smooth', // 平滑滚动
block: 'center', // 垂直方向居中
inline: 'nearest' // 水平方向最近
})
// 如果需要高亮当前节点
treeRef.value.setCurrentKey(id)
}
}
// 添加树
const onAddTree = () => {
emit('onAddTree')
}
defineExpose({ treeRef, scrollToNode })
</script>
<style lang="scss" scoped>
.cn-tree {
flex-shrink: 0;
display: flex;
flex-direction: column;
box-sizing: border-box;
padding: 10px;
height: 100%;
width: 100%;
:deep(.el-tree) {
border: 1px solid var(--el-border-color);
}
:deep(.el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content) {
background-color: var(--el-color-primary-light-7);
}
.menu-collapse {
color: var(--el-color-primary);
}
}
.custom-tree-node {
display: flex;
align-items: center;
}
</style>
<style>
.el-popper.is-customized {
/* Set padding to ensure the height is 32px */
padding: 0;
background: var(--el-color-primary-light-3);
}
.el-popper.is-customized .el-popper__arrow::before {
background: var(--el-color-primary-light-3);
right: 0;
display: none;
}
</style>

View File

@@ -28,66 +28,66 @@ const info = (id: any) => {
expanded.value = [id] expanded.value = [id]
getTerminalTree().then(res => { getTerminalTree().then(res => {
// let arr: any[] = [] // let arr: any[] = []
if (VITE_FLAG) { // if (VITE_FLAG) {
res.data.forEach((item: any) => { // res.data.forEach((item: any) => {
item.icon = 'el-icon-Menu' // item.icon = 'el-icon-Menu'
item.plevel = item.level // item.plevel = item.level
item.level = 0 // item.level = 0
item.children.forEach((item2: any) => { // item.children.forEach((item2: any) => {
item2.icon = 'el-icon-HomeFilled' // item2.icon = 'el-icon-HomeFilled'
item2.plevel = item2.level // item2.plevel = item2.level
item2.level = 100 // item2.level = 100
expanded.value.push(item2.id) // expanded.value.push(item2.id)
item2.children.forEach((item3: any) => { // item2.children.forEach((item3: any) => {
item3.icon = 'el-icon-CollectionTag' // item3.icon = 'el-icon-CollectionTag'
item3.plevel = item3.level // item3.plevel = item3.level
item3.level = 200 // item3.level = 200
item3.children.forEach((item4: any) => { // item3.children.forEach((item4: any) => {
item4.icon = 'el-icon-Flag' // item4.icon = 'el-icon-Flag'
item4.plevel = item4.level // item4.plevel = item4.level
item4.level = 300 // item4.level = 300
// arr.push(item4) // // arr.push(item4)
item4.children.forEach((item5: any) => { // item4.children.forEach((item5: any) => {
item5.icon = 'el-icon-OfficeBuilding' // item5.icon = 'el-icon-OfficeBuilding'
item5.plevel = item5.level // item5.plevel = item5.level
item5.level = 300 // item5.level = 300
// item5.id = item4.id // // item5.id = item4.id
item5.children.forEach((item6: any) => { // item5.children.forEach((item6: any) => {
item6.icon = 'el-icon-HelpFilled' // item6.icon = 'el-icon-HelpFilled'
item6.plevel = 4 // item6.plevel = 4
if (item6.name == '电网侧' && item6.children.length == 0) { // if (item6.name == '电网侧' && item6.children.length == 0) {
item6.level = 400 // item6.level = 400
} else { // } else {
item6.level = 400 // item6.level = 400
} // }
item6.children.forEach((item7: any) => { // item6.children.forEach((item7: any) => {
item7.icon = 'el-icon-Film' // item7.icon = 'el-icon-Film'
item7.plevel = item7.level // item7.plevel = item7.level
item7.level = 400 // item7.level = 400
item7.children.forEach((item8: any) => { // item7.children.forEach((item8: any) => {
item8.icon = 'el-icon-Collection' // item8.icon = 'el-icon-Collection'
item8.plevel = item8.level // item8.plevel = item8.level
item8.level = 500 // item8.level = 500
item8.children.forEach((item9: any) => { // item8.children.forEach((item9: any) => {
item9.icon = 'el-icon-Share' // item9.icon = 'el-icon-Share'
item9.plevel = item9.level // item9.plevel = item9.level
item9.level = 600 // item9.level = 600
item9.children.forEach((item10: any) => { // item9.children.forEach((item10: any) => {
item10.icon = 'el-icon-Location' // item10.icon = 'el-icon-Location'
item10.plevel = item10.level // item10.plevel = item10.level
item10.level = 700 // item10.level = 700
}) // })
}) // })
}) // })
}) // })
}) // })
}) // })
}) // })
}) // })
}) // })
}) // })
} else { // } else {
res.data.forEach((item: any) => { res.data.forEach((item: any) => {
item.icon = 'el-icon-Menu' item.icon = 'el-icon-Menu'
item.plevel = item.level item.plevel = item.level
@@ -129,7 +129,7 @@ const info = (id: any) => {
}) })
}) })
}) })
} // }
tree.value = res.data tree.value = res.data

View File

@@ -1,88 +1,105 @@
<template> <template>
<div class="point-tree"> <div class="point-tree">
<div style="flex: 1; overflow: hidden"> <div style="flex: 1; overflow: hidden">
<Tree <Tree
ref="treeRef" ref="treeRef"
:data="tree" :data="tree"
:canExpand="false" :canExpand="false"
style="width: 100%; height: 100%" style="width: 100%; height: 100%"
v-bind="$attrs" v-bind="$attrs"
default-expand-all default-expand-all
@onAddTree="onAddTree"
@onAddTree="onAddTree" />
/> </div>
</div> </div>
</div> </template>
</template>
<script lang="ts" setup>
<script lang="ts" setup> import { nextTick, onMounted, ref, useAttrs } from 'vue'
import { nextTick, onMounted, ref, useAttrs } from 'vue' import Tree from '../index.vue'
import Tree from '../index.vue' import { useAdminInfo } from '@/stores/adminInfo'
import { useAdminInfo } from '@/stores/adminInfo' import { useDictData } from '@/stores/dictData'
import { useDictData } from '@/stores/dictData' import { useConfig } from '@/stores/config'
import { getTerminalTreeForFive } from '@/api/device-boot/terminalTree' import { queryAllAlgorithmLibrary } from '@/api/supervision-boot/database/index'
import { useConfig } from '@/stores/config' defineOptions({
import { queryAllAlgorithmLibrary } from '@/api/supervision-boot/database/index' name: 'pms/pointTree'
defineOptions({ })
name: 'pms/pointTree' const emit = defineEmits(['init', 'onAddTree'])
}) const attrs = useAttrs()
const emit = defineEmits(['init', 'onAddTree']) const adminInfo = useAdminInfo()
const attrs = useAttrs() const dictData = useDictData()
const adminInfo = useAdminInfo() const config = useConfig()
const dictData = useDictData() const classificationData = dictData.getBasicData('Statistical_Type', ['Report_Type'])
const config = useConfig() const tree = ref()
const classificationData = dictData.getBasicData('Statistical_Type', ['Report_Type']) const treeRef = ref()
const tree = ref()
const treeRef = ref() const loadData = (id?: any) => {
// console.log('🚀 ~ loadData ~ id:', id)
const loadData = (id?: any) => { let nodeKey = ''
console.log('🚀 ~ loadData ~ id:', id) queryAllAlgorithmLibrary().then(res => {
let nodeKey = '' res.data.forEach((item: any) => {
queryAllAlgorithmLibrary().then(res => { item.icon = 'el-icon-FolderOpened'
res.data.forEach((item: any) => { item.color = config.getColorVal('elementUiPrimary')
item.icon = 'el-icon-FolderOpened' item.children.forEach((item2: any) => {
item.color = config.getColorVal('elementUiPrimary') item2.icon = 'el-icon-Document'
item.children.forEach((item2: any) => { item2.color = config.getColorVal('elementUiPrimary')
item2.icon = 'el-icon-Document' item2.childrens = item2.children
item2.color = config.getColorVal('elementUiPrimary') item2.children = []
item2.childrens = item2.children if (item2.id == id) {
item2.children = [] emit('init', item2)
if (item2.id == id) { }
emit('init', item2) })
} })
})
}) nodeKey = res.data[0].children[0].id
nodeKey = res.data[0].children[0].id tree.value = res.data
if (id) {
tree.value = res.data setTimeout(() => {
if (id) { treeRef.value.treeRef.setCurrentKey(id)
setTimeout(() => { }, 10)
treeRef.value.treeRef.setCurrentKey(id) } else {
}, 10) setTimeout(() => {
} else { treeRef.value.treeRef.setCurrentKey(nodeKey)
setTimeout(() => { emit('init', res.data[0].children[0])
treeRef.value.treeRef.setCurrentKey(nodeKey) }, 10)
emit('init', res.data[0].children[0]) }
}, 10) })
} }
})
} const onAddTree = () => {
emit('onAddTree')
const onAddTree = () => { }
emit('onAddTree') const setKey = (id: string) => {
} treeRef.value.treeRef.setCurrentKey(id)
loadData() return findNodeById(tree.value, id)
defineExpose({ loadData }) }
</script> const findNodeById = (tree1: any, targetId: any) => {
<style lang="scss"> for (const node of tree1) {
.point-tree { // 1. 当前节点匹配ID直接返回该节点
height: 100%; if (node.id === targetId) {
width: 100%; return node
display: flex; }
flex-direction: column; // 2. 当前节点有子节点,递归查找子节点
background: #fff; if (node.children && node.children.length > 0) {
border: 1px solid var(--el-border-color); const result: any = findNodeById(node.children, targetId)
} // 子节点中找到结果,立即返回(终止递归)
</style> if (result) return result
}
}
// 3. 遍历完未找到返回null
return null
}
loadData()
defineExpose({ loadData, setKey })
</script>
<style lang="scss">
.point-tree {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
background: #fff;
border: 1px solid var(--el-border-color);
}
</style>

View File

@@ -0,0 +1,150 @@
<template>
<div class="point-tree">
<div style="flex: 1; overflow: hidden">
<Tree ref="treeRef" :data="tree" style="width: 100%; height: 100%" :canExpand="false" v-bind="$attrs" />
</div>
</div>
</template>
<script lang="ts" setup>
import { nextTick, onMounted, ref, useAttrs } from 'vue'
import Tree from '../index.vue'
import { useAdminInfo } from '@/stores/adminInfo'
import { useDictData } from '@/stores/dictData'
import { getTerminalTreeForFive } from '@/api/device-boot/terminalTree'
import { useConfig } from '@/stores/config'
import { getAreaList } from '@/api/common'
const VITE_FLAG = import.meta.env.VITE_NAME == 'qujing'
defineOptions({
name: 'pms/pointTree'
})
interface Props {
showSelect?: boolean
}
const props = withDefaults(defineProps<Props>(), {
showSelect: true
})
const emit = defineEmits(['init'])
const attrs = useAttrs()
const adminInfo = useAdminInfo()
const dictData = useDictData()
const config = useConfig()
const tree = ref()
const treeRef = ref()
const loadData = () => {
let nodeKey = ''
getAreaList().then(res => {
processTreeData(res.data, res.data[0].level)
let firstLevel6Node = getDeepestFirstChildData(res.data)
nodeKey = firstLevel6Node.id
emit('init', firstLevel6Node)
tree.value = res.data
if (nodeKey) {
nextTick(() => {
treeRef.value.treeRef.setCurrentKey(nodeKey)
// treeRef.value.treeRef.setExpandedKeys(nodeKey)
})
}
})
}
const scrollToNode = (id: string) => {
// 树滚动
treeRef.value.scrollToNode(id)
}
// 定义不同层级对应的图标配置(可根据实际需求调整)
const levelIconMap = {
'-1': 'el-icon-HomeFilled',
0: 'el-icon-CollectionTag',
1: 'el-icon-CollectionTag',
2: 'el-icon-Flag',
3: 'el-icon-OfficeBuilding',
4: 'el-icon-DataAnalysis',
5: 'el-icon-DataAnalysis',
7: 'el-icon-DataAnalysis',
6: 'fa-solid fa-location-dot'
}
/**
* 递归处理树形数据,为不同层级节点设置图标和颜色
* @param data 树形数据数组
* @param level 当前层级默认从1开始
*/
function processTreeData(data: any[], level: number = -1, alias: string = '') {
// 空值判断避免数组为空或undefined时报错
if (!Array.isArray(data) || data.length === 0) return
data.forEach(item => {
// 1. 设置基础图标(根据层级匹配)
item.icon = levelIconMap[level] || ''
item.alias = alias + `${item.name}`
// 2. 设置基础颜色
item.color = config.getColorVal('elementUiPrimary')
// 3. 第6层特殊处理根据comFlag调整颜色
if (level === 6 && item.hasOwnProperty('comFlag')) {
switch (item.comFlag) {
case 0:
item.color = 'red !important'
break
case 1:
item.color = '#00f93b !important'
break
case 2:
item.color = '#8c8c8c !important'
break
// 默认值:保持原有基础颜色
default:
item.color = config.getColorVal('elementUiPrimary')
}
}
// 4. 递归处理子节点,层级+1
if (item.children && item.children.length > 0) {
processTreeData(item.children, item.children[0].level, level == '-1' ? '' : item.alias + '>')
}
})
}
/**
* 递归获取树形结构中一直向下的第一个children的最后一组有效数据
* @param {Array} treeData - 原始递归树形数据
* @returns {Object|null} 路径最后一组有效数据无有效数据时返回null
*/
function getDeepestFirstChildData(treeData) {
// 递归辅助函数逐层查找第一个children
function findDeepestNode(currentNode) {
// 检查当前节点是否有有效的children数组
if (currentNode && Array.isArray(currentNode.children) && currentNode.children.length > 0) {
// 有下一级children继续递归查找下一级第一个元素
return findDeepestNode(currentNode.children[0])
}
// 没有下一级children返回当前节点递归终止
return currentNode
}
// 边界处理:原始数据非数组/空数组时返回null
if (!Array.isArray(treeData) || treeData.length === 0) {
return null
}
// 从根节点第一个元素开始递归查找
return findDeepestNode(treeData[0])
}
defineExpose({ treeRef, scrollToNode, tree })
loadData()
</script>
<style lang="scss">
.point-tree {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
background: #fff;
border: 1px solid var(--el-border-color);
}
</style>

View File

@@ -11,12 +11,9 @@ import { nextTick, onMounted, ref, useAttrs } from 'vue'
import Tree from '../index.vue' import Tree from '../index.vue'
import { useAdminInfo } from '@/stores/adminInfo' import { useAdminInfo } from '@/stores/adminInfo'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
import { getTerminalTreeForFive } from '@/api/device-boot/terminalTree'
import { useConfig } from '@/stores/config' import { useConfig } from '@/stores/config'
import { defineProps } from 'vue' import { defineProps } from 'vue'
import { import { getTree } from '@/api/advance-boot/assess'
getTree
} from '@/api/advance-boot/assess'
defineOptions({ defineOptions({
name: 'pms/pointTree' name: 'pms/pointTree'
@@ -46,25 +43,24 @@ const formData = ref({
scale: null scale: null
}) })
// 添加数据转换函数 // 添加数据转换函数
const transformTreeData = (data: any[]) => { const transformTreeData = (data: any[]) => {
if (!data || !Array.isArray(data)) return []; if (!data || !Array.isArray(data)) return []
return data.map(item => { return data.map(item => {
// 创建新对象,确保不修改原始数据 // 创建新对象,确保不修改原始数据
const newItem: any = { const newItem: any = {
name: item.treeName , name: item.treeName,
id: item.treeId , id: item.treeId,
children: [] children: []
}; }
// 递归处理子节点 // 递归处理子节点
if (item.children && Array.isArray(item.children)) { if (item.children && Array.isArray(item.children)) {
newItem.children = transformTreeData(item.children); newItem.children = transformTreeData(item.children)
} }
return newItem; return newItem
}); })
}; }
const loadData = () => { const loadData = () => {
let obj = classificationData.find(function (i) { let obj = classificationData.find(function (i) {
@@ -73,19 +69,22 @@ const loadData = () => {
let form = JSON.parse(JSON.stringify(formData.value)) let form = JSON.parse(JSON.stringify(formData.value))
form.statisticalType = classificationData.find((item: any) => item.id == form.statisticalType) form.statisticalType = classificationData.find((item: any) => item.id == form.statisticalType)
let nodeKey = '' let nodeKey = ''
getTree({}).then(res => { getTree({}).then(res => {
// 转换数据结构为指定格式 // 转换数据结构为指定格式
const transformedData = transformTreeData(res.data); const transformedData = transformTreeData(res.data)
// 确保有数据再进行处理 // 确保有数据再进行处理
if (transformedData && transformedData.length > 0 && if (
transformedData[0].children && transformedData[0].children.length > 0) { transformedData &&
transformedData.length > 0 &&
transformedData[0].children &&
transformedData[0].children.length > 0
) {
nodeKey = transformedData[0].children[0].id nodeKey = transformedData[0].children[0].id
emit('init', transformedData[0].children[0]) emit('init', transformedData[0].children[0])
tree.value = transformedData tree.value = transformedData
if (nodeKey) { if (nodeKey) {
nextTick(() => { nextTick(() => {
treeRef.value.treeRef.setCurrentKey(nodeKey) treeRef.value.treeRef.setCurrentKey(nodeKey)
@@ -94,7 +93,15 @@ const loadData = () => {
} }
}) })
} }
const scrollToNode = (id: string) => {
// 树滚动
treeRef.value.scrollToNode(id)
}
loadData() loadData()
defineExpose({
tree,
scrollToNode
})
</script> </script>
<style lang="scss"> <style lang="scss">
.point-tree { .point-tree {

View File

@@ -36,6 +36,7 @@ const adminInfo = useAdminInfo()
const dictData = useDictData() const dictData = useDictData()
const config = useConfig() const config = useConfig()
const classificationData = dictData.getBasicData('Statistical_Type', ['Report_Type']) const classificationData = dictData.getBasicData('Statistical_Type', ['Report_Type'])
const VITE_FLAG = import.meta.env.VITE_NAME == 'qujing'
const tree = ref() const tree = ref()
const treeRef = ref() const treeRef = ref()
const formData = ref({ const formData = ref({
@@ -54,6 +55,9 @@ const loadData = () => {
}) || { code: '' } }) || { code: '' }
let form = JSON.parse(JSON.stringify(formData.value)) let form = JSON.parse(JSON.stringify(formData.value))
form.statisticalType = classificationData.find((item: any) => item.id == form.statisticalType) form.statisticalType = classificationData.find((item: any) => item.id == form.statisticalType)
if (VITE_FLAG && form.statisticalType.code == 'Power_Network') {
form.statisticalType.deptName = 'qujing'
}
let nodeKey = '' let nodeKey = ''
getTerminalTreeForFive(form).then(res => { getTerminalTreeForFive(form).then(res => {
console.log(res) console.log(res)
@@ -67,56 +71,62 @@ const loadData = () => {
} }
] ]
} }
res.data.forEach((item: any) => { // if (VITE_FLAG) {
item.icon = 'el-icon-HomeFilled' processTreeData(res.data)
item.color = config.getColorVal('elementUiPrimary') let firstLevel6Node = findFirstLevel6Node(res.data)
item.children.forEach((item2: any) => {
item2.icon = 'el-icon-CollectionTag'
item2.color = config.getColorVal('elementUiPrimary')
item2.children.forEach((item3: any) => {
item3.icon = 'el-icon-Flag'
item3.color = config.getColorVal('elementUiPrimary')
item3.children.forEach((item4: any) => {
item4.icon = 'el-icon-OfficeBuilding'
item4.color = config.getColorVal('elementUiPrimary')
item4.children.forEach((item5: anyObj) => {
if (item5.level == 7) {
item5.icon = 'el-icon-DataAnalysis'
item5.color = config.getColorVal('elementUiPrimary')
item5.children.forEach((item6: anyObj) => {
item6.alias = `${item.name}>${item2.name}>${item3.name}>${item4.name}>${item5.name}>${item6.name}`
item6.pid = item4.id
item6.icon = 'fa-solid fa-location-dot'
item6.color = config.getColorVal('elementUiPrimary')
if (item6.comFlag == 0) {
item6.color = 'red !important'
} else if (item6.comFlag == 1) {
item6.color = '#00f93b !important'
} else if (item6.comFlag == 2) {
item6.color = '#8c8c8c !important'
}
})
} else {
item5.alias = `${item.name}>${item2.name}>${item3.name}>${item4.name}>${item5.name}`
item5.pid = item4.id
item5.icon = 'fa-solid fa-location-dot'
item5.color = config.getColorVal('elementUiPrimary')
if (item5.comFlag == 0) {
item5.color = 'red !important'
} else if (item5.comFlag == 1) {
item5.color = '#00f93b !important'
} else if (item5.comFlag == 2) {
item5.color = '#8c8c8c !important'
}
}
})
})
})
})
})
nodeKey = res.data[0].children[0].children[0].children[0].children[0].id nodeKey = firstLevel6Node.id
emit('init', res.data[0].children[0].children[0].children[0].children[0]) emit('init', firstLevel6Node)
// res.data.forEach((item: any) => {
// item.icon = 'el-icon-HomeFilled'
// item.color = config.getColorVal('elementUiPrimary')
// item.children.forEach((item2: any) => {
// item2.icon = 'el-icon-CollectionTag'
// item2.color = config.getColorVal('elementUiPrimary')
// item2.children.forEach((item3: any) => {
// item3.icon = 'el-icon-Flag'
// item3.color = config.getColorVal('elementUiPrimary')
// item3.children.forEach((item4: any) => {
// item4.icon = 'el-icon-OfficeBuilding'
// item4.color = config.getColorVal('elementUiPrimary')
// item4.children.forEach((item5: anyObj) => {
// if (item5.level == 7) {
// item5.icon = 'el-icon-DataAnalysis'
// item5.color = config.getColorVal('elementUiPrimary')
// item5.children.forEach((item6: anyObj) => {
// item6.alias = `${item.name}>${item2.name}>${item3.name}>${item4.name}>${item5.name}>${item6.name}`
// item6.pid = item4.id
// item6.icon = 'fa-solid fa-location-dot'
// item6.color = config.getColorVal('elementUiPrimary')
// if (item6.comFlag == 0) {
// item6.color = 'red !important'
// } else if (item6.comFlag == 1) {
// item6.color = '#00f93b !important'
// } else if (item6.comFlag == 2) {
// item6.color = '#8c8c8c !important'
// }
// })
// } else {
// item5.alias = `${item.name}>${item2.name}>${item3.name}>${item4.name}>${item5.name}`
// item5.pid = item4.id
// item5.icon = 'fa-solid fa-location-dot'
// item5.color = config.getColorVal('elementUiPrimary')
// if (item5.comFlag == 0) {
// item5.color = 'red !important'
// } else if (item5.comFlag == 1) {
// item5.color = '#00f93b !important'
// } else if (item5.comFlag == 2) {
// item5.color = '#8c8c8c !important'
// }
// }
// })
// })
// })
// })
// })
// nodeKey = res.data[0].children[0].children[0].children[0].children[0].id
// emit('init', res.data[0].children[0].children[0].children[0].children[0])
tree.value = res.data tree.value = res.data
if (nodeKey) { if (nodeKey) {
@@ -127,9 +137,113 @@ const loadData = () => {
} }
}) })
} }
const setKey = (key: string) => { const setKey = (key: string) => {
treeRef.value.treeRef.setCurrentKey(key) treeRef.value.treeRef.setCurrentKey(key)
} }
// 定义不同层级对应的图标配置(可根据实际需求调整)
const levelIconMap = {
'-1': 'el-icon-HomeFilled',
0: 'el-icon-CollectionTag',
1: 'el-icon-CollectionTag',
2: 'el-icon-Flag',
3: 'el-icon-OfficeBuilding',
4: 'el-icon-DataAnalysis',
5: 'el-icon-DataAnalysis',
7: 'el-icon-DataAnalysis',
6: 'fa-solid fa-location-dot'
}
/**
* 递归处理树形数据,为不同层级节点设置图标和颜色
* @param data 树形数据数组
* @param level 当前层级默认从1开始
*/
function processTreeData(data: any[], level: number = -1) {
// 空值判断避免数组为空或undefined时报错
if (!Array.isArray(data) || data.length === 0) return
data.forEach(item => {
// 1. 设置基础图标(根据层级匹配)
item.icon = levelIconMap[level] || ''
// 2. 设置基础颜色
item.color = config.getColorVal('elementUiPrimary')
// 3. 第6层特殊处理根据comFlag调整颜色
if (level === 6 && item.hasOwnProperty('comFlag')) {
switch (item.comFlag) {
case 0:
item.color = 'red !important'
break
case 1:
item.color = '#00f93b !important'
break
case 2:
item.color = '#8c8c8c !important'
break
// 默认值:保持原有基础颜色
default:
item.color = config.getColorVal('elementUiPrimary')
}
}
// 4. 递归处理子节点,层级+1
if (item.children && item.children.length > 0) {
processTreeData(item.children, item.children[0].level)
}
})
}
/**
* 递归查找树形结构中第一个level===6的节点找到即终止递归
* @param {Object|Array} tree - 树形数据(根节点数组 或 单个根节点)
* @returns {Object|null} 第一个level为6的节点无则返回null
*/
function findFirstLevel6Node(tree: any) {
// 统一处理入参:如果是数组,遍历根节点数组(按顺序找第一个符合条件的)
if (Array.isArray(tree)) {
for (const rootNode of tree) {
const result = traverse(rootNode)
// 找到第一个匹配节点,立即返回(终止根节点遍历)
if (result) return result
}
// 所有根节点遍历完未找到
return null
} else {
// 入参是单个节点,直接递归遍历
return traverse(tree)
}
// 核心递归遍历函数
function traverse(node) {
// 终止条件1节点不存在返回null
if (!node) return null
// 终止条件2找到level===6的节点立即返回终止递归
if (node.level === 6) {
return node
}
// 终止条件3节点无children返回null
if (!node.children || node.children.length === 0) {
return null
}
// 按顺序遍历当前节点的子节点
for (const child of node.children) {
const foundNode = traverse(child)
// 子节点中找到目标节点,立即返回(终止后续子节点遍历)
if (foundNode) {
return foundNode
}
}
// 当前节点及所有子节点都无匹配返回null
return null
}
}
defineExpose({ setKey }) defineExpose({ setKey })
loadData() loadData()
</script> </script>

View File

@@ -11,7 +11,7 @@
/> />
<div class="cn-tree" :style="{ opacity: menuCollapse ? 0 : 1 }"> <div class="cn-tree" :style="{ opacity: menuCollapse ? 0 : 1 }">
<div style="display: flex; align-items: center" class="mb10"> <div style="display: flex; align-items: center" class="mb10">
<el-input v-model="filterText" placeholder="请输入内容" clearable> <el-input v-model="filterText" placeholder="请输入内容" maxlength="10" show-word-limit clearable>
<template #prefix> <template #prefix>
<Icon name="el-icon-Search" style="font-size: 16px" /> <Icon name="el-icon-Search" style="font-size: 16px" />
</template> </template>

View File

@@ -28,6 +28,7 @@ import { useDictData } from '@/stores/dictData'
import { getTerminalTreeForFive } from '@/api/device-boot/terminalTree' import { getTerminalTreeForFive } from '@/api/device-boot/terminalTree'
import { useConfig } from '@/stores/config' import { useConfig } from '@/stores/config'
import { defineProps } from 'vue' import { defineProps } from 'vue'
const VITE_FLAG = import.meta.env.VITE_NAME == 'qujing'
defineOptions({ defineOptions({
name: 'pms/pointTree' name: 'pms/pointTree'
}) })
@@ -61,6 +62,9 @@ const loadData = () => {
}) || { code: '' } }) || { code: '' }
let form = JSON.parse(JSON.stringify(formData.value)) let form = JSON.parse(JSON.stringify(formData.value))
form.statisticalType = classificationData.find((item: any) => item.id == form.statisticalType) form.statisticalType = classificationData.find((item: any) => item.id == form.statisticalType)
if (VITE_FLAG && form.statisticalType.code == 'Power_Network') {
form.statisticalType.deptName = 'qujing'
}
let nodeKey = '' let nodeKey = ''
getTerminalTreeForFive(form).then(res => { getTerminalTreeForFive(form).then(res => {
//console.log('---',res) //console.log('---',res)
@@ -74,72 +78,190 @@ const loadData = () => {
} }
] ]
} }
res.data.forEach((item: any) => { // if (VITE_FLAG) {
item.icon = 'el-icon-HomeFilled' processTreeData(res.data)
item.color = config.getColorVal('elementUiPrimary') let firstLevel6Node = findFirstLevel6Node(res.data)
item.children.forEach((item2: any) => {
item2.icon = 'el-icon-CollectionTag'
item2.color = config.getColorVal('elementUiPrimary')
item2.children.forEach((item3: any) => {
item3.icon = 'el-icon-Flag'
item3.color = config.getColorVal('elementUiPrimary')
item3.children.forEach((item4: any) => {
item4.icon = 'el-icon-OfficeBuilding'
item4.color = config.getColorVal('elementUiPrimary')
item4.children.forEach((item5: anyObj) => {
if (item5.level == 7) {
item5.icon = 'el-icon-DataAnalysis'
item5.color = config.getColorVal('elementUiPrimary')
item5.children.forEach((item6: anyObj) => {
item6.alias = `${item.name}>${item2.name}>${item3.name}>${item4.name}>${item5.name}>${item6.name}`
item6.pid = item4.id
item6.icon = 'fa-solid fa-location-dot'
item6.color = config.getColorVal('elementUiPrimary')
if (item6.comFlag == 0) {
item6.color = 'red !important'
} else if (item6.comFlag == 1) {
item6.color = '#00f93b !important'
} else if (item6.comFlag == 2) {
item6.color = '#8c8c8c !important'
}
})
} else {
item5.alias = `${item.name}>${item2.name}>${item3.name}>${item4.name}>${item5.name}`
item5.pid = item4.id
item5.icon = 'fa-solid fa-location-dot'
item5.color = config.getColorVal('elementUiPrimary')
if (item5.comFlag == 0) {
item5.color = 'red !important'
} else if (item5.comFlag == 1) {
item5.color = '#00f93b !important'
} else if (item5.comFlag == 2) {
item5.color = '#8c8c8c !important'
}
}
})
})
})
})
})
nodeKey = nodeKey = firstLevel6Node.id
res.data[0].children[0].children[0].children[0].children[0].children[0]?.id || emit('init', firstLevel6Node)
res.data[0].children[0].children[0].children[0].children[0]?.id // } else {
emit( // // 正常树处理
'init', // res.data.forEach((item: any) => {
res.data[0].children[0].children[0].children[0].children[0]?.children[0] || // item.icon = 'el-icon-HomeFilled'
res.data[0].children[0].children[0].children[0].children[0] // item.color = config.getColorVal('elementUiPrimary')
) // item.children.forEach((item2: any) => {
// item2.icon = 'el-icon-CollectionTag'
// item2.color = config.getColorVal('elementUiPrimary')
// item2.children.forEach((item3: any) => {
// item3.icon = 'el-icon-Flag'
// item3.color = config.getColorVal('elementUiPrimary')
// item3.children.forEach((item4: any) => {
// item4.icon = 'el-icon-OfficeBuilding'
// item4.color = config.getColorVal('elementUiPrimary')
// item4.children.forEach((item5: anyObj) => {
// if (item5.level == 7) {
// item5.icon = 'el-icon-DataAnalysis'
// item5.color = config.getColorVal('elementUiPrimary')
// item5.children.forEach((item6: anyObj) => {
// item6.alias = `${item.name}>${item2.name}>${item3.name}>${item4.name}>${item5.name}>${item6.name}`
// item6.pid = item4.id
// item6.icon = 'fa-solid fa-location-dot'
// item6.color = config.getColorVal('elementUiPrimary')
// if (item6.comFlag == 0) {
// item6.color = 'red !important'
// } else if (item6.comFlag == 1) {
// item6.color = '#00f93b !important'
// } else if (item6.comFlag == 2) {
// item6.color = '#8c8c8c !important'
// }
// })
// } else {
// item5.alias = `${item.name}>${item2.name}>${item3.name}>${item4.name}>${item5.name}`
// item5.pid = item4.id
// item5.icon = 'fa-solid fa-location-dot'
// item5.color = config.getColorVal('elementUiPrimary')
// if (item5.comFlag == 0) {
// item5.color = 'red !important'
// } else if (item5.comFlag == 1) {
// item5.color = '#00f93b !important'
// } else if (item5.comFlag == 2) {
// item5.color = '#8c8c8c !important'
// }
// }
// })
// })
// })
// })
// })
// nodeKey =
// res.data[0].children[0].children[0].children[0].children[0].children[0]?.id ||
// res.data[0].children[0].children[0].children[0].children[0]?.id
// emit(
// 'init',
// res.data[0].children[0].children[0].children[0].children[0]?.children[0] ||
// res.data[0].children[0].children[0].children[0].children[0]
// )
// }
tree.value = res.data tree.value = res.data
if (nodeKey) { if (nodeKey) {
nextTick(() => { nextTick(() => {
treeRef.value.treeRef.setCurrentKey(nodeKey) treeRef.value.treeRef.setCurrentKey(nodeKey)
// treeRef.value.treeRef.setExpandedKeys(nodeKey) // treeRef.value.treeRef.setExpandedKeys(nodeKey)
}) })
} }
}) })
} }
const scrollToNode = (id: string) => {
// 树滚动
treeRef.value.scrollToNode(id)
}
// 定义不同层级对应的图标配置(可根据实际需求调整)
const levelIconMap = {
'-1': 'el-icon-HomeFilled',
0: 'el-icon-CollectionTag',
1: 'el-icon-CollectionTag',
2: 'el-icon-Flag',
3: 'el-icon-OfficeBuilding',
4: 'el-icon-DataAnalysis',
5: 'el-icon-DataAnalysis',
7: 'el-icon-DataAnalysis',
6: 'fa-solid fa-location-dot'
}
/**
* 递归处理树形数据,为不同层级节点设置图标和颜色
* @param data 树形数据数组
* @param level 当前层级默认从1开始
*/
function processTreeData(data: any[], level: number = -1, alias: string = '') {
// 空值判断避免数组为空或undefined时报错
if (!Array.isArray(data) || data.length === 0) return
data.forEach(item => {
// 1. 设置基础图标(根据层级匹配)
item.icon = levelIconMap[level] || ''
item.alias = alias + `${item.name}`
// 2. 设置基础颜色
item.color = config.getColorVal('elementUiPrimary')
// 3. 第6层特殊处理根据comFlag调整颜色
if (level === 6 && item.hasOwnProperty('comFlag')) {
switch (item.comFlag) {
case 0:
item.color = 'red !important'
break
case 1:
item.color = '#00f93b !important'
break
case 2:
item.color = '#8c8c8c !important'
break
// 默认值:保持原有基础颜色
default:
item.color = config.getColorVal('elementUiPrimary')
}
}
// 4. 递归处理子节点,层级+1
if (item.children && item.children.length > 0) {
processTreeData(item.children, item.children[0].level, level == '-1' ? '' : item.alias + '>')
}
})
}
/**
* 递归查找树形结构中第一个level===6的节点找到即终止递归
* @param {Object|Array} tree - 树形数据(根节点数组 或 单个根节点)
* @returns {Object|null} 第一个level为6的节点无则返回null
*/
function findFirstLevel6Node(tree: any) {
// 统一处理入参:如果是数组,遍历根节点数组(按顺序找第一个符合条件的)
if (Array.isArray(tree)) {
for (const rootNode of tree) {
const result = traverse(rootNode)
// 找到第一个匹配节点,立即返回(终止根节点遍历)
if (result) return result
}
// 所有根节点遍历完未找到
return null
} else {
// 入参是单个节点,直接递归遍历
return traverse(tree)
}
// 核心递归遍历函数
function traverse(node) {
// 终止条件1节点不存在返回null
if (!node) return null
// 终止条件2找到level===6的节点立即返回终止递归
if (node.level === 6) {
return node
}
// 终止条件3节点无children返回null
if (!node.children || node.children.length === 0) {
return null
}
// 按顺序遍历当前节点的子节点
for (const child of node.children) {
const foundNode = traverse(child)
// 子节点中找到目标节点,立即返回(终止后续子节点遍历)
if (foundNode) {
return foundNode
}
}
// 当前节点及所有子节点都无匹配返回null
return null
}
}
defineExpose({ treeRef, scrollToNode, tree })
loadData() loadData()
</script> </script>
<style lang="scss"> <style lang="scss">

View File

@@ -28,7 +28,7 @@ const tree = ref()
const treeRef = ref() const treeRef = ref()
const loadData = (id?: any) => { const loadData = (id?: any) => {
console.log('🚀 ~ loadData ~ id:', id)
let nodeKey = '' let nodeKey = ''
queryAll().then(res => { queryAll().then(res => {
res.data.forEach((item: any) => { res.data.forEach((item: any) => {

View File

@@ -25,7 +25,7 @@
{{ Math.floor(row.eventValue * 10000) / 100 }} {{ Math.floor(row.eventValue * 10000) / 100 }}
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="eventType" width="100px" title="暂降类型"> <vxe-column field="eventType" width="100px" title="触发类型">
<template #default="{ row }"> <template #default="{ row }">
{{ event.filter(item => item.id == row.eventType)[0]?.name || '/' }} {{ event.filter(item => item.id == row.eventType)[0]?.name || '/' }}
</template> </template>
@@ -50,7 +50,8 @@ import { ref, reactive, onMounted } from 'vue'
import { defaultAttribute } from '@/components/table/defaultAttribute' import { defaultAttribute } from '@/components/table/defaultAttribute'
import { mainHeight } from '@/utils/layout' import { mainHeight } from '@/utils/layout'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
import MQTT from '@/utils/mqtt' // import MQTT from '@/utils/mqtt'
import socketClient from '@/utils/webSocketClient'
const dictData = useDictData() const dictData = useDictData()
const event = dictData.getBasicData('Event_Statis') const event = dictData.getBasicData('Event_Statis')
import { useAdminInfo } from '@/stores/adminInfo' import { useAdminInfo } from '@/stores/adminInfo'
@@ -68,37 +69,72 @@ const handleClose = (done: any) => {
drawer.value = false drawer.value = false
done() done()
} }
const init = async () => { const dataSocket = reactive({
const mqttClient = new MQTT('/sendEvent') socketServe: socketClient.Instance
// 设置消息接收回调 })
try { // const init = async () => {
await mqttClient.init() // const mqttClient = new MQTT('/sendEvent')
// // 设置消息接收回调
// try {
// await mqttClient.init()
// 订阅主题 // // 订阅主题
await mqttClient.subscribe() // await mqttClient.subscribe()
// 设置消息接收回调 // // 设置消息接收回调
mqttClient.onMessage((topic, message) => { // mqttClient.onMessage((topic, message) => {
const msg = JSON.parse(message.toString()) // const msg = JSON.parse(message.toString())
console.log('🚀 ~ init ~ msg:', msg) // // console.log('🚀 ~ init ~ msg:', msg)
if (msg.deptList.includes(adminInfo.$state.deptId)) { // if (msg.deptList.includes(adminInfo.$state.deptId)) {
drawer.value = true // drawer.value = true
isLoading.value = true // isLoading.value = true
eventList.value.unshift(msg) // eventList.value.unshift(msg)
setTimeout(() => { // setTimeout(() => {
isLoading.value = false // isLoading.value = false
}, 500) // }, 500)
} // }
}) // })
} catch (error) { // } catch (error) {
console.error('MQTT 初始化失败:', 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(() => { onMounted(() => {
// startMqtt('/sendEvent', (topic, message) => { // startMqtt('/sendEvent', (topic, message) => {
// const msg = JSON.parse(message.toString()) // const msg = JSON.parse(message.toString())
// console.log(msg) // console.log(msg)
// }) // })
init()
setTimeout(() => {
socket()
}, 3000)
}) })
defineExpose({ defineExpose({
open, open,

View File

@@ -1,6 +1,6 @@
<template> <template>
<div class="layout-logo"> <div class="layout-logo">
<img v-if="!config.layout.menuCollapse" class="logo-img" :src="getTheme.logoUrl" /> <img v-if="!config.layout.menuCollapse && getTheme && getTheme.logoUrl" class="logo-img" :src="getTheme.logoUrl" />
<!-- <div--> <!-- <div-->
<!-- v-if="!config.layout.menuCollapse"--> <!-- v-if="!config.layout.menuCollapse"-->
<!-- :style="{ color: config.getColorVal('menuActiveColor') }"--> <!-- :style="{ color: config.getColorVal('menuActiveColor') }"-->
@@ -28,7 +28,9 @@ import { Session } from '@/utils/storage'
import { setNavTabsWidth } from '@/utils/layout' import { setNavTabsWidth } from '@/utils/layout'
const config = useConfig() const config = useConfig()
const getTheme = JSON.parse(window.localStorage.getItem('getTheme') as string) const getTheme = window.localStorage.getItem('getTheme')
? JSON.parse(window.localStorage.getItem('getTheme') as string)
: null
const onMenuCollapse = function () { const onMenuCollapse = function () {
if (config.layout.shrink && !config.layout.menuCollapse) { if (config.layout.shrink && !config.layout.menuCollapse) {
closeShade() closeShade()

View File

@@ -9,7 +9,7 @@
/> />
</div> </div>
<span class="nav-bar-title"> <span class="nav-bar-title">
{{ getTheme.name }} {{ getTheme?.name || '' }}
<span style="font-size: 14px">({{ Version || 'v1.0.0' }})</span> <span style="font-size: 14px">({{ Version || 'v1.0.0' }})</span>
<!-- <span style="font-size: 14px;" v-if="Version?.versionName"> <!-- <span style="font-size: 14px;" v-if="Version?.versionName">
({{ Version?.versionName }}) ({{ Version?.versionName }})
@@ -28,8 +28,10 @@ import { getLastData } from '@/api/systerm'
const Version: any = ref(null) const Version: any = ref(null)
const config = useConfig() const config = useConfig()
const getTheme = JSON.parse(window.localStorage.getItem('getTheme') as string) const getTheme = window.localStorage.getItem('getTheme')
? JSON.parse(window.localStorage.getItem('getTheme') as string)
: { name: '' }
const VITE_FLAG = import.meta.env.VITE_NAME == 'hainan'
const onMenuCollapse = () => { const onMenuCollapse = () => {
showShade('ba-aside-menu-shade', () => { showShade('ba-aside-menu-shade', () => {
config.setLayout('menuCollapse', true) config.setLayout('menuCollapse', true)
@@ -37,10 +39,13 @@ const onMenuCollapse = () => {
config.setLayout('menuCollapse', false) config.setLayout('menuCollapse', false)
} }
onMounted(() => { onMounted(() => {
getLastData({ versionType: 'WEB' }).then(res => { if(!VITE_FLAG){
Version.value = res.data.versionName getLastData({ versionType: 'WEB' }).then(res => {
}) Version.value = res.data.versionName
document.title = getTheme.name })
}
document.title = getTheme?.name || ''
}) })
</script> </script>

View File

@@ -122,7 +122,7 @@ const onFullScreen = () => {
}) })
} }
const handleCommand = (key: string) => { const handleCommand = async(key: string) => {
console.log(key) console.log(key)
switch (key) { switch (key) {
case 'adminInfo': case 'adminInfo':
@@ -132,10 +132,17 @@ const handleCommand = (key: string) => {
popupPwd.value.open() popupPwd.value.open()
break break
case 'layout': case 'layout':
navTabs.closeTabs() await window.location.reload()
window.localStorage.clear() setTimeout(() => {
adminInfo.reset() navTabs.closeTabs()
router.push({ name: 'login' }) window.localStorage.clear()
adminInfo.reset()
router.push({ name: 'login' })
}, 0)
// navTabs.closeTabs()
// window.localStorage.clear()
// adminInfo.reset()
// router.push({ name: 'login' })
break break
default: default:
break break

View File

@@ -1,109 +1,117 @@
<template> <template>
<el-dialog draggable width="500px" v-model="dialogVisible" :title="title"> <el-dialog draggable width="500px" v-model="dialogVisible" :title="title">
<el-scrollbar> <el-scrollbar>
<el-form :inline="false" :model="form" label-width="120px" :rules="rules" ref="formRef"> <el-form :inline="false" :model="form" label-width="120px" :rules="rules" ref="formRef">
<el-form-item label="校验密码:" prop="password"> <el-form-item label="校验密码:" prop="password">
<el-input v-model="form.password" type="password" placeholder="请输入校验密码" show-password /> <el-input v-model="form.password" type="password" placeholder="请输入校验密码" show-password />
</el-form-item> </el-form-item>
<el-form-item label="新密码:" prop="newPwd" style="margin-top: 20px"> <el-form-item label="新密码:" prop="newPwd" style="margin-top: 20px">
<el-input v-model="form.newPwd" type="password" placeholder="请输入新密码" show-password /> <el-input v-model="form.newPwd" type="password" placeholder="请输入新密码" show-password />
</el-form-item> </el-form-item>
<el-form-item label="确认密码:" prop="confirmPwd" style="margin-top: 20px"> <el-form-item label="确认密码:" prop="confirmPwd" style="margin-top: 20px">
<el-input v-model="form.confirmPwd" type="password" placeholder="请输入确认密码" show-password /> <el-input v-model="form.confirmPwd" type="password" placeholder="请输入确认密码" show-password />
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-scrollbar> </el-scrollbar>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button> <el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submit">确认</el-button> <el-button type="primary" @click="submit">确认</el-button>
</span> </span>
</template> </template>
</el-dialog> </el-dialog>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, inject } from 'vue' import { ref, inject } from 'vue'
import { reactive } from 'vue' import { reactive } from 'vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { passwordConfirm, updatePassword } from '@/api/user-boot/user' import { passwordConfirm, updatePassword } from '@/api/user-boot/user'
import { validatePwd } from '@/utils/common' import { validatePwd } from '@/utils/common'
import { useAdminInfo } from '@/stores/adminInfo' import { useAdminInfo } from '@/stores/adminInfo'
import router from '@/router'
const adminInfo = useAdminInfo() import { useNavTabs } from '@/stores/navTabs'
const dialogVisible = ref(false) const navTabs = useNavTabs()
const title = ref('修改密码') const adminInfo = useAdminInfo()
const formRef = ref() const dialogVisible = ref(false)
// 注意不要和表单ref的命名冲突 const title = ref('修改密码')
const form = reactive({ const formRef = ref()
password: '', // 注意不要和表单ref的命名冲突
newPwd: '', const form = reactive({
confirmPwd: '' password: '',
}) newPwd: '',
const rules = { confirmPwd: ''
password: [ })
{ required: true, message: '请输入校验密码', trigger: 'blur' }, const rules = {
{ password: [
min: 6, { required: true, message: '请输入校验密码', trigger: 'blur' },
max: 12, {
message: '长度在 6 到 12 个字符', min: 6,
trigger: 'blur' max: 12,
} message: '长度在 6 到 12 个字符',
], trigger: 'blur'
newPwd: [ }
{ required: true, message: '请输入密码', trigger: 'blur' }, ],
{ newPwd: [
min: 6, { required: true, message: '请输入密码', trigger: 'blur' },
max: 12, {
message: '长度在 6 到 12 个字符', min: 6,
trigger: 'blur' max: 12,
}, message: '长度在 6 到 12 个字符',
{ validator: validatePwd, trigger: 'blur' } trigger: 'blur'
], },
confirmPwd: [ { validator: validatePwd, trigger: 'blur' }
{ required: true, message: '请确认密码', trigger: 'blur' }, ],
{ confirmPwd: [
min: 6, { required: true, message: '请确认密码', trigger: 'blur' },
max: 12, {
message: '长度在 6 到 12 个字符', min: 6,
trigger: 'blur' max: 12,
}, message: '长度在 6 到 12 个字符',
{ trigger: 'blur'
validator: (rule: any, value: string, callback: any) => { },
if (value === '') { {
callback(new Error('请再次输入密码')) validator: (rule: any, value: string, callback: any) => {
} else if (value !== form.newPwd) { if (value === '') {
callback(new Error('次输入密码不一致!')) callback(new Error('请再次输入密码'))
} else { } else if (value !== form.newPwd) {
callback() callback(new Error('两次输入密码不一致!'))
} } else {
}, callback()
trigger: 'blur', }
required: true },
} trigger: 'blur',
] required: true
} }
]
const open = () => { }
dialogVisible.value = true
form.password = '' const open = () => {
form.newPwd = '' dialogVisible.value = true
form.confirmPwd = '' form.password = ''
} form.newPwd = ''
const submit = () => { form.confirmPwd = ''
formRef.value.validate(async (valid: boolean) => { }
if (valid) { const submit = () => {
passwordConfirm(form.password).then(res => { formRef.value.validate(async (valid: boolean) => {
updatePassword({ if (valid) {
id: adminInfo.$state.userIndex, passwordConfirm(form.password).then(res => {
newPassword: form.newPwd updatePassword({
}).then((res: any) => { id: adminInfo.$state.userIndex,
ElMessage.success('密码修改成功') newPassword: form.newPwd
dialogVisible.value = false }).then((res: any) => {
}) ElMessage.success('密码修改成功,请重新登录!')
}) dialogVisible.value = false
} setTimeout(() => {
}) navTabs.closeTabs()
} window.localStorage.clear()
adminInfo.reset()
defineExpose({ open }) router.push({ name: 'login' })
</script> }, 0)
})
})
}
})
}
defineExpose({ open })
</script>

View File

@@ -29,7 +29,7 @@ const emit = defineEmits(['update:modelValue'])
const dialogVisible = computed({ const dialogVisible = computed({
get: () => props.modelValue, get: () => props.modelValue,
set: (val) => { set: (val) => {
console.log('set: ', val)
emit('update:modelValue', val) emit('update:modelValue', val)
} }
}) })

View File

@@ -16,12 +16,14 @@ import '@/assets/font/iconfont.css'
import { ElDialog } from 'element-plus' import { ElDialog } from 'element-plus'
import BaiduMap from 'vue-baidu-map-3x' import BaiduMap from 'vue-baidu-map-3x'
import BaiduMapOffline from 'vue-baidu-map-offline' import BaiduMapOffline from 'vue-baidu-map-offline'
import ExcelJS from 'exceljs' import ExcelJS from 'exceljs'
import VXETablePluginExportXLSX from 'vxe-table-plugin-export-xlsx' import VXETablePluginExportXLSX from 'vxe-table-plugin-export-xlsx'
// 方式1NPM 安装,注入 ExcelJS 对象 // 方式1NPM 安装,注入 ExcelJS 对象
VXETable.use(VXETablePluginExportXLSX, { VXETable.use(VXETablePluginExportXLSX, {
ExcelJS ExcelJS
}) })
// 全局注册 tooltip 组件
window.XEUtils = XEUtils window.XEUtils = XEUtils
// 初始化多语言 // 初始化多语言
@@ -35,21 +37,21 @@ const setupAll = async () => {
const app = createApp(App) const app = createApp(App)
//开启离线地图 //开启离线地图
// app.use(BaiduMapOffline, { app.use(BaiduMapOffline, {
// offline: true, offline: true,
// offlineConfig: { offlineConfig: {
// imgext: '.png', imgext: '.png',
// customstyle: '', customstyle: '',
// tiles_dir: '', tiles_dir: '',
// tiles_hybrid: '', tiles_hybrid: '',
// tiles_self: '', tiles_self: '',
// tiles_v_dir: '', tiles_v_dir: '',
// tiles_satellite_dir: '', tiles_satellite_dir: '',
// tiles_road_dir: '', tiles_road_dir: '',
// tiles_v_road_dir: '', tiles_v_road_dir: '',
// home: './plugin/offline/' home: './plugin/offline/'
// } }
// }) })
app.use(BaiduMap, { app.use(BaiduMap, {
// ak: 'Yp57V71dkOPiXjiN8VdcFRsVELzlVNKK', // ak: 'Yp57V71dkOPiXjiN8VdcFRsVELzlVNKK',
ak: 'RpQi6WNFZ9tseKzhdwOQsXwFsoVntnsN', ak: 'RpQi6WNFZ9tseKzhdwOQsXwFsoVntnsN',
@@ -61,6 +63,7 @@ const setupAll = async () => {
app.use(pinia) app.use(pinia)
app.use(ElementPlus) app.use(ElementPlus)
app.use(VXETable) app.use(VXETable)
;(app._context.components.ElDialog as typeof ElDialog).props.closeOnClickModal.default = false ;(app._context.components.ElDialog as typeof ElDialog).props.closeOnClickModal.default = false
registerIcons(app) // icons registerIcons(app) // icons

View File

@@ -1,49 +1,49 @@
import { createRouter, createWebHashHistory } from 'vue-router' import { createRouter, createWebHashHistory } from 'vue-router'
import staticRoutes from '@/router/static' import staticRoutes from '@/router/static'
import { useAdminInfo } from '@/stores/adminInfo' import { useAdminInfo } from '@/stores/adminInfo'
import NProgress from 'nprogress' import NProgress from 'nprogress'
import { loading } from '@/utils/loading' import { loading } from '@/utils/loading'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
const router = createRouter({ const router = createRouter({
history: createWebHashHistory(), history: createWebHashHistory(),
routes: staticRoutes routes: staticRoutes
}) })
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
NProgress.configure({ showSpinner: false }) NProgress.configure({ showSpinner: false })
NProgress.start() NProgress.start()
if (!window.existLoading) { if (!window.existLoading) {
loading.show() loading.show()
window.existLoading = true window.existLoading = true
} }
if (to.path == '/login' || to.path == '/404') { if (to.path == '/login' || to.path == '/404') {
// 登录或者注册才可以往下进行 // 登录或者注册才可以往下进行
next() next()
} else if (to.path == '/admin/center/homePage') { } else if (to.path == '/admin/center/homePage') {
window.open(window.location.origin + '/homePage/#/') window.open(window.location.origin + '/homePage/#/')
} else { } else {
// 获取 token // 获取 token
const adminInfo = useAdminInfo() const adminInfo = useAdminInfo()
const token = adminInfo.getToken() const token = adminInfo.getToken()
// token 不存在 // token 不存在
if (token === null || token === '') { if (token === null || token === '') {
ElMessage.error('您还没有登录,请先登录') // ElMessage.error('您还没有登录,请先登录')
next('/login') next('/login')
} else { } else {
next() next()
} }
} }
// next() // next()
}) })
// 路由加载后 // 路由加载后
router.afterEach(() => { router.afterEach(() => {
if (window.existLoading) { if (window.existLoading) {
loading.hide() loading.hide()
} }
NProgress.done() NProgress.done()
}) })
export default router export default router

View File

@@ -1,246 +1,246 @@
import { reactive } from 'vue' import { reactive } from 'vue'
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { STORE_CONFIG } from '@/stores/constant/cacheKey' import { STORE_CONFIG } from '@/stores/constant/cacheKey'
import type { Layout } from '@/stores/interface' import type { Layout } from '@/stores/interface'
export const useConfig = defineStore( export const useConfig = defineStore(
'config', 'config',
() => { () => {
const layout: Layout = reactive({ const layout: Layout = reactive({
/* 全局 */ /* 全局 */
showDrawer: false, showDrawer: false,
// 是否收缩布局(小屏终端) // 是否收缩布局(小屏终端)
shrink: false, shrink: false,
// 后台布局方式,可选值<Default|Classic|Streamline|Double> // 后台布局方式,可选值<Default|Classic|Streamline|Double>
layoutMode: 'Classic', layoutMode: 'Classic',
// 后台主页面切换动画,可选值<slide-right|slide-left|el-fade-in-linear|el-fade-in|el-zoom-in-center|el-zoom-in-top|el-zoom-in-bottom> // 后台主页面切换动画,可选值<slide-right|slide-left|el-fade-in-linear|el-fade-in|el-zoom-in-center|el-zoom-in-top|el-zoom-in-bottom>
mainAnimation: 'slide-right', mainAnimation: 'slide-right',
// 是否暗黑模式 // 是否暗黑模式
isDark: false, isDark: false,
elementUiPrimary: ['#002B6A', '#002B6A'], elementUiPrimary: ['#002B6A', '#002B6A'],
tableHeaderBackground: ['#F3F6F9', '#F3F6F9'], tableHeaderBackground: ['#F3F6F9', '#F3F6F9'],
tableHeaderColor: ['#111', '#fff'], tableHeaderColor: ['#111', '#fff'],
tableCurrent: ['#F3F6F9', '#F3F6F9'], tableCurrent: ['#F3F6F9', '#F3F6F9'],
/* 侧边菜单 */ /* 侧边菜单 */
// 侧边菜单背景色 // 侧边菜单背景色
menuBackground: ['#002B6A', '#1d1e1f'], menuBackground: ['#002B6A', '#1d1e1f'],
// 侧边菜单文字颜色 // 侧边菜单文字颜色
menuColor: ['#FFFFFF', '#CFD3DC'], menuColor: ['#FFFFFF', '#CFD3DC'],
// 侧边菜单激活项背景色 // 侧边菜单激活项背景色
menuActiveBackground: ['#002255', '#1d1e1f'], menuActiveBackground: ['#002255', '#1d1e1f'],
// 侧边菜单激活项文字色 // 侧边菜单激活项文字色
menuActiveColor: ['#409eff', '#3375b9'], menuActiveColor: ['#409eff', '#3375b9'],
// 侧边菜单顶栏背景色 // 侧边菜单顶栏背景色
menuTopBarBackground: ['#002B6A', '#1d1e1f'], menuTopBarBackground: ['#002B6A', '#1d1e1f'],
// 侧边菜单宽度(展开时)单位px // 侧边菜单宽度(展开时)单位px
menuWidth: 260, menuWidth: 260,
// 侧边菜单项默认图标 // 侧边菜单项默认图标
menuDefaultIcon: 'fa fa-circle-o', menuDefaultIcon: 'fa fa-circle-o',
// 是否水平折叠收起菜单 // 是否水平折叠收起菜单
menuCollapse: false, menuCollapse: false,
// 是否只保持一个子菜单的展开(手风琴) // 是否只保持一个子菜单的展开(手风琴)
menuUniqueOpened: false, menuUniqueOpened: false,
// 显示菜单栏顶栏(LOGO) // 显示菜单栏顶栏(LOGO)
menuShowTopBar: true, menuShowTopBar: true,
/* 顶栏 */ /* 顶栏 */
// 顶栏文字色 // 顶栏文字色
headerBarTabColor: ['#FFFFFF', '#CFD3DC'], headerBarTabColor: ['#FFFFFF', '#CFD3DC'],
// // 顶栏激活项背景色 // // 顶栏激活项背景色
headerBarTabActiveBackground: ['#ffffff', '#1d1e1f'], headerBarTabActiveBackground: ['#ffffff', '#1d1e1f'],
// 顶栏激活项文字色 // 顶栏激活项文字色
headerBarTabActiveColor: ['#000000', '#409EFF'], headerBarTabActiveColor: ['#000000', '#409EFF'],
// 顶栏背景色 // 顶栏背景色
headerBarBackground: ['#002B6A', '#1d1e1f'], headerBarBackground: ['#002B6A', '#1d1e1f'],
// 顶栏悬停时背景色 // 顶栏悬停时背景色
headerBarHoverBackground: ['#f5f5f5', '#18222c'] headerBarHoverBackground: ['#f5f5f5', '#18222c']
}) })
const lang = reactive({ const lang = reactive({
// 默认语言,可选值<zh-cn|en> // 默认语言,可选值<zh-cn|en>
defaultLang: 'zh-cn', defaultLang: 'zh-cn',
// 当在默认语言包找不到翻译时,继续在 fallbackLang 语言包内查找翻译 // 当在默认语言包找不到翻译时,继续在 fallbackLang 语言包内查找翻译
fallbackLang: 'zh-cn', fallbackLang: 'zh-cn',
// 支持的语言列表 // 支持的语言列表
langArray: [ langArray: [
{ name: 'zh-cn', value: '中文简体' }, { name: 'zh-cn', value: '中文简体' },
{ name: 'en', value: 'English' } { name: 'en', value: 'English' }
] ]
}) })
function menuWidth() { function menuWidth() {
if (layout.shrink) { if (layout.shrink) {
return layout.menuCollapse ? '0px' : layout.menuWidth + 'px' return layout.menuCollapse ? '0px' : layout.menuWidth + 'px'
} }
// 菜单是否折叠 // 菜单是否折叠
return layout.menuCollapse ? '64px' : layout.menuWidth + 'px' return layout.menuCollapse ? '64px' : layout.menuWidth + 'px'
} }
function setLang(val: string) { function setLang(val: string) {
lang.defaultLang = val lang.defaultLang = val
} }
function onSetLayoutColor(data = layout.layoutMode) { function onSetLayoutColor(data = layout.layoutMode) {
// 切换布局时,如果是为默认配色方案,对菜单激活背景色重新赋值 // 切换布局时,如果是为默认配色方案,对菜单激活背景色重新赋值
const tempValue = layout.isDark const tempValue = layout.isDark
? { idx: 1, color: '#1d1e1f', newColor: '#141414' } ? { idx: 1, color: '#1d1e1f', newColor: '#141414' }
: { idx: 0, color: '#ffffff', newColor: '#f5f5f5' } : { idx: 0, color: '#ffffff', newColor: '#f5f5f5' }
if ( if (
data == 'Classic' && data == 'Classic' &&
layout.headerBarBackground[tempValue.idx] == tempValue.color && layout.headerBarBackground[tempValue.idx] == tempValue.color &&
layout.headerBarTabActiveBackground[tempValue.idx] == tempValue.color layout.headerBarTabActiveBackground[tempValue.idx] == tempValue.color
) { ) {
layout.headerBarTabActiveBackground[tempValue.idx] = tempValue.newColor layout.headerBarTabActiveBackground[tempValue.idx] = tempValue.newColor
} else if ( } else if (
data == 'Default' && data == 'Default' &&
layout.headerBarBackground[tempValue.idx] == tempValue.color && layout.headerBarBackground[tempValue.idx] == tempValue.color &&
layout.headerBarTabActiveBackground[tempValue.idx] == tempValue.newColor layout.headerBarTabActiveBackground[tempValue.idx] == tempValue.newColor
) { ) {
layout.headerBarTabActiveBackground[tempValue.idx] = tempValue.color layout.headerBarTabActiveBackground[tempValue.idx] = tempValue.color
} }
} }
function setLayoutMode(data: string) { function setLayoutMode(data: string) {
layout.layoutMode = data layout.layoutMode = data
onSetLayoutColor(data) onSetLayoutColor(data)
} }
const setLayout = (name: keyof Layout, value: any) => { const setLayout = (name: keyof Layout, value: any) => {
layout[name] = value as never layout[name] = value as never
} }
const getColorVal = function (name: keyof Layout): string { const getColorVal = function (name: keyof Layout): string {
const colors = layout[name] as string[] const colors = layout[name] as string[] || ['#082E6C', '#0e8780']
if (layout.isDark) { if (layout.isDark) {
return colors[1] return colors[1]
} else { } else {
return colors[0] return colors[0]
} }
} }
return { layout, lang, menuWidth, setLang, setLayoutMode, setLayout, getColorVal, onSetLayoutColor } return { layout, lang, menuWidth, setLang, setLayoutMode, setLayout, getColorVal, onSetLayoutColor }
}, },
// () => { // () => {
// //
// console.log('🚀 ~ subject:', subject) // console.log('🚀 ~ subject:', subject)
// const layout: Layout = reactive({ // const layout: Layout = reactive({
// /* 全局 */ // /* 全局 */
// showDrawer: false, // showDrawer: false,
// // 是否收缩布局(小屏终端) // // 是否收缩布局(小屏终端)
// shrink: false, // shrink: false,
// // 后台布局方式,可选值<Default|Classic|Streamline|Double> // // 后台布局方式,可选值<Default|Classic|Streamline|Double>
// layoutMode: 'Classic', // layoutMode: 'Classic',
// // 后台主页面切换动画,可选值<slide-right|slide-left|el-fade-in-linear|el-fade-in|el-zoom-in-center|el-zoom-in-top|el-zoom-in-bottom> // // 后台主页面切换动画,可选值<slide-right|slide-left|el-fade-in-linear|el-fade-in|el-zoom-in-center|el-zoom-in-top|el-zoom-in-bottom>
// mainAnimation: subject.mainAnimation, // mainAnimation: subject.mainAnimation,
// // 是否暗黑模式 // // 是否暗黑模式
// isDark: false, // isDark: false,
// elementUiPrimary: JSON.parse(subject.elementUiPrimary), // elementUiPrimary: JSON.parse(subject.elementUiPrimary),
// tableHeaderBackground: JSON.parse(subject.tableHeaderBackground), // tableHeaderBackground: JSON.parse(subject.tableHeaderBackground),
// tableHeaderColor:JSON.parse(subject.tableHeaderColor), // tableHeaderColor:JSON.parse(subject.tableHeaderColor),
// tableCurrent: JSON.parse(subject.tableCurrent), // tableCurrent: JSON.parse(subject.tableCurrent),
// /* 侧边菜单 */ // /* 侧边菜单 */
// // 侧边菜单背景色 // // 侧边菜单背景色
// menuBackground: JSON.parse(subject.menuBackground), // menuBackground: JSON.parse(subject.menuBackground),
// // 侧边菜单文字颜色 // // 侧边菜单文字颜色
// menuColor:JSON.parse(subject.menuColor), // menuColor:JSON.parse(subject.menuColor),
// // 侧边菜单激活项背景色 // // 侧边菜单激活项背景色
// menuActiveBackground:JSON.parse(subject.menuActiveBackground), // menuActiveBackground:JSON.parse(subject.menuActiveBackground),
// // 侧边菜单激活项文字色 // // 侧边菜单激活项文字色
// menuActiveColor:JSON.parse(subject.menuActiveColor), // menuActiveColor:JSON.parse(subject.menuActiveColor),
// // 侧边菜单顶栏背景色 // // 侧边菜单顶栏背景色
// menuTopBarBackground: JSON.parse(subject.menuTopBarBackground), // menuTopBarBackground: JSON.parse(subject.menuTopBarBackground),
// // 侧边菜单宽度(展开时)单位px // // 侧边菜单宽度(展开时)单位px
// menuWidth: 260, // menuWidth: 260,
// // 侧边菜单项默认图标 // // 侧边菜单项默认图标
// menuDefaultIcon: 'fa fa-circle-o', // menuDefaultIcon: 'fa fa-circle-o',
// // 是否水平折叠收起菜单 // // 是否水平折叠收起菜单
// menuCollapse: false, // menuCollapse: false,
// // 是否只保持一个子菜单的展开(手风琴) // // 是否只保持一个子菜单的展开(手风琴)
// menuUniqueOpened: false, // menuUniqueOpened: false,
// // 显示菜单栏顶栏(LOGO) // // 显示菜单栏顶栏(LOGO)
// menuShowTopBar: true, // menuShowTopBar: true,
// /* 顶栏 */ // /* 顶栏 */
// // 顶栏文字色 // // 顶栏文字色
// headerBarTabColor:JSON.parse(subject.headerBarTabColor), // headerBarTabColor:JSON.parse(subject.headerBarTabColor),
// // // 顶栏激活项背景色 // // // 顶栏激活项背景色
// headerBarTabActiveBackground: ['#ffffff', '#1d1e1f'], // headerBarTabActiveBackground: ['#ffffff', '#1d1e1f'],
// // 顶栏激活项文字色 // // 顶栏激活项文字色
// headerBarTabActiveColor: ['#000000', '#409EFF'], // headerBarTabActiveColor: ['#000000', '#409EFF'],
// // 顶栏背景色 // // 顶栏背景色
// headerBarBackground: JSON.parse(subject.headerBarBackground), // headerBarBackground: JSON.parse(subject.headerBarBackground),
// // 顶栏悬停时背景色 // // 顶栏悬停时背景色
// headerBarHoverBackground: ['#f5f5f5', '#18222c'] // headerBarHoverBackground: ['#f5f5f5', '#18222c']
// }) // })
// // console.log(123, window.localStorage.getItem('getTheme')) // // console.log(123, window.localStorage.getItem('getTheme'))
// const lang = reactive({ // const lang = reactive({
// // 默认语言,可选值<zh-cn|en> // // 默认语言,可选值<zh-cn|en>
// defaultLang: 'zh-cn', // defaultLang: 'zh-cn',
// // 当在默认语言包找不到翻译时,继续在 fallbackLang 语言包内查找翻译 // // 当在默认语言包找不到翻译时,继续在 fallbackLang 语言包内查找翻译
// fallbackLang: 'zh-cn', // fallbackLang: 'zh-cn',
// // 支持的语言列表 // // 支持的语言列表
// langArray: [ // langArray: [
// { name: 'zh-cn', value: '中文简体' }, // { name: 'zh-cn', value: '中文简体' },
// { name: 'en', value: 'English' } // { name: 'en', value: 'English' }
// ] // ]
// }) // })
// function menuWidth() { // function menuWidth() {
// if (layout.shrink) { // if (layout.shrink) {
// return layout.menuCollapse ? '0px' : layout.menuWidth + 'px' // return layout.menuCollapse ? '0px' : layout.menuWidth + 'px'
// } // }
// // 菜单是否折叠 // // 菜单是否折叠
// return layout.menuCollapse ? '64px' : layout.menuWidth + 'px' // return layout.menuCollapse ? '64px' : layout.menuWidth + 'px'
// } // }
// function setLang(val: string) { // function setLang(val: string) {
// lang.defaultLang = val // lang.defaultLang = val
// } // }
// function onSetLayoutColor(data = layout.layoutMode) { // function onSetLayoutColor(data = layout.layoutMode) {
// // 切换布局时,如果是为默认配色方案,对菜单激活背景色重新赋值 // // 切换布局时,如果是为默认配色方案,对菜单激活背景色重新赋值
// const tempValue = layout.isDark // const tempValue = layout.isDark
// ? { idx: 1, color: '#1d1e1f', newColor: '#141414' } // ? { idx: 1, color: '#1d1e1f', newColor: '#141414' }
// : { idx: 0, color: '#ffffff', newColor: '#f5f5f5' } // : { idx: 0, color: '#ffffff', newColor: '#f5f5f5' }
// if ( // if (
// data == 'Classic' && // data == 'Classic' &&
// layout.headerBarBackground[tempValue.idx] == tempValue.color && // layout.headerBarBackground[tempValue.idx] == tempValue.color &&
// layout.headerBarTabActiveBackground[tempValue.idx] == tempValue.color // layout.headerBarTabActiveBackground[tempValue.idx] == tempValue.color
// ) { // ) {
// layout.headerBarTabActiveBackground[tempValue.idx] = tempValue.newColor // layout.headerBarTabActiveBackground[tempValue.idx] = tempValue.newColor
// } else if ( // } else if (
// data == 'Default' && // data == 'Default' &&
// layout.headerBarBackground[tempValue.idx] == tempValue.color && // layout.headerBarBackground[tempValue.idx] == tempValue.color &&
// layout.headerBarTabActiveBackground[tempValue.idx] == tempValue.newColor // layout.headerBarTabActiveBackground[tempValue.idx] == tempValue.newColor
// ) { // ) {
// layout.headerBarTabActiveBackground[tempValue.idx] = tempValue.color // layout.headerBarTabActiveBackground[tempValue.idx] = tempValue.color
// } // }
// } // }
// function setLayoutMode(data: string) { // function setLayoutMode(data: string) {
// layout.layoutMode = data // layout.layoutMode = data
// onSetLayoutColor(data) // onSetLayoutColor(data)
// } // }
// const setLayout = (name: keyof Layout, value: any) => { // const setLayout = (name: keyof Layout, value: any) => {
// layout[name] = value as never // layout[name] = value as never
// } // }
// const getColorVal = function (name: keyof Layout): string { // const getColorVal = function (name: keyof Layout): string {
// const colors = layout[name] as string[] // const colors = layout[name] as string[]
// if (layout.isDark) { // if (layout.isDark) {
// return colors[1] // return colors[1]
// } else { // } else {
// return colors[0] // return colors[0]
// } // }
// } // }
// return { layout, lang, menuWidth, setLang, setLayoutMode, setLayout, getColorVal, onSetLayoutColor } // return { layout, lang, menuWidth, setLang, setLayoutMode, setLayout, getColorVal, onSetLayoutColor }
// }, // },
{ {
persist: { persist: {
key: STORE_CONFIG key: STORE_CONFIG
} }
} }
) )

View File

@@ -68,6 +68,7 @@ export const useDictStore = defineStore('dict', {
} }
}, },
getDictByType(type: string) { getDictByType(type: string) {
console.log("🚀 ~ type:", type)
if (!this.isSetDict) { if (!this.isSetDict) {
this.setDictMap() this.setDictMap()
} }

View File

@@ -29,12 +29,10 @@ export const useMonitoringPoint = defineStore(
const setShowCheckBox = (val: boolean) => { const setShowCheckBox = (val: boolean) => {
if (val && state.lineIds.length === 0) { if (val && state.lineIds.length === 0) {
state.lineIds = [state.lineId] state.lineIds = [state.lineId]
console.log('====================================')
console.log(state.lineIds)
console.log('====================================')
} }
state.showCheckBox = val state.showCheckBox = val
} }
return { state, setValue, setShowCheckBox } return { state, setValue, setShowCheckBox }
}, },
{ {

View File

@@ -373,3 +373,4 @@ body,
.w-e-scroll { .w-e-scroll {
min-height: 200px !important; min-height: 200px !important;
} }

View File

@@ -404,6 +404,11 @@ body,
.el-select__wrapper { .el-select__wrapper {
height: 32px !important; height: 32px !important;
} }
.BMap_center,
.BMap_top,
.BMap_bottom {
background-color: #fff;
}
@font-face { @font-face {
font-family: 'AlimamaFangYuanTiVF'; font-family: 'AlimamaFangYuanTiVF';
src: url('../assets/font/ali/AlimamaFangYuanTiVF-Thin.woff') format('woff'), src: url('../assets/font/ali/AlimamaFangYuanTiVF-Thin.woff') format('woff'),

View File

@@ -268,3 +268,8 @@
.el-drawer__body { .el-drawer__body {
padding: 10px; padding: 10px;
} }
.aLoad{
color: var(--el-color-primary);
cursor: pointer;
}

View File

@@ -8,29 +8,31 @@ $primary-light: #3f6ad8;
// --ba-background // --ba-background
$bg-color: () !default; $bg-color: () !default;
$bg-color: map.merge( $bg-color: map.merge(
( (
'': #edf0f3, '': #edf0f3,
'overlay': #ffffff, 'overlay': #ffffff
), ),
$bg-color $bg-color
); );
// --ba-border-color // --ba-border-color
$border-color: () !default; $border-color: () !default;
$border-color: map.merge( $border-color: map.merge(
( (
'': #f6f6f6, '': #f6f6f6
), ),
$border-color $border-color
); );
:root { :root {
@include set-css-var-value('main-space', $main-space); @include set-css-var-value('main-space', $main-space);
@include set-css-var-value('color-primary-light', $primary-light); @include set-css-var-value('color-primary-light', $primary-light);
@include set-component-css-var('bg-color', $bg-color); @include set-component-css-var('bg-color', $bg-color);
@include set-component-css-var('border-color', $border-color); @include set-component-css-var('border-color', $border-color);
// --vxe-table-row-current-background-color: var(--el-color-primary-light-7); --vxe-ui-table-row-current-background-color: var(--el-color-primary-light-8);
// --vxe-table-row-hover-background-color: var(--el-color-primary-light-9); --vxe-ui-table-row-hover-current-background-color: var(--el-color-primary-light-8);
// --vxe-table-row-hover-current-background-color: var(--el-color-primary-light-7); // --vxe-table-row-current-background-color: var(--el-color-primary-light-7);
// --vxe-table-row-hover-striped-background-color: var(--el-color-primary-light-9); // --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);
// --vxe-table-row-hover-striped-background-color: var(--el-color-primary-light-9);
} }

View File

@@ -1,7 +1,7 @@
.vxe-header--row { .vxe-header--row {
background: var(--vxe-table-header-background-color); background: var(--vxe-table-header-background-color);
color: var(--vxe-table-header-font-color); color: var(--vxe-table-header-font-color);
font-size: 14px; font-size: 14px;
} }
.is--checked.vxe-checkbox, .is--checked.vxe-checkbox,
@@ -25,7 +25,7 @@
.vxe-table--render-default .is--indeterminate.vxe-cell--checkbox, .vxe-table--render-default .is--indeterminate.vxe-cell--checkbox,
.vxe-table--render-default .is--indeterminate.vxe-cell--checkbox .vxe-checkbox--icon, .vxe-table--render-default .is--indeterminate.vxe-cell--checkbox .vxe-checkbox--icon,
.vxe-table--render-default .is--checked.vxe-cell--radio .vxe-radio--icon { .vxe-table--render-default .is--checked.vxe-cell--radio .vxe-radio--icon {
color: var(--el-color-primary-light-3); color: var(--el-color-primary-light-3);
} }
.vxe-checkbox:not(.is--disabled):hover .vxe-checkbox--icon, .vxe-checkbox:not(.is--disabled):hover .vxe-checkbox--icon,
@@ -38,40 +38,41 @@
.vxe-export--panel-column-option:not(.is--disabled):hover .vxe-radio--icon, .vxe-export--panel-column-option:not(.is--disabled):hover .vxe-radio--icon,
.vxe-table--filter-option:not(.is--disabled):hover .vxe-radio--icon, .vxe-table--filter-option:not(.is--disabled):hover .vxe-radio--icon,
.vxe-table--render-default .vxe-cell--radio:not(.is--disabled):hover .vxe-radio--icon { .vxe-table--render-default .vxe-cell--radio:not(.is--disabled):hover .vxe-radio--icon {
color: var(--el-color-primary-light-5); color: var(--el-color-primary-light-5);
} }
.vxe-table--tooltip-wrapper { .vxe-table--tooltip-wrapper {
z-index: 10000 !important; z-index: 10000 !important;
} }
.is--disabled { .is--disabled {
background-color: var(--vxe-input-disabled-color); background-color: var(--vxe-input-disabled-color);
} }
.vxe-modal--wrapper { .vxe-modal--wrapper {
z-index: 5000 !important; z-index: 5000 !important;
} }
.vxe-table--body .vxe-body--row:nth-child(even) { .vxe-table--body .vxe-body--row:nth-child(even) {
background-color: #f9f9f9; background-color: #f9f9f9;
} }
.vxe-table--body .vxe-body--row:nth-child(odd) { .vxe-table--body .vxe-body--row:nth-child(odd) {
background-color: #ffffff; background-color: #ffffff;
} }
.default-theme.splitpanes--vertical > .splitpanes__splitter, .default-theme.splitpanes--vertical > .splitpanes__splitter,
.default-theme .splitpanes--vertical > .splitpanes__splitter { .default-theme .splitpanes--vertical > .splitpanes__splitter {
width: 10px !important; width: 10px !important;
} }
.default-theme.splitpanes--vertical > .splitpanes__splitter:after, .default-theme.splitpanes--vertical > .splitpanes__splitter:after,
.default-theme .splitpanes--vertical > .splitpanes__splitter:after { .default-theme .splitpanes--vertical > .splitpanes__splitter:after {
background-color: #000 !important; background-color: #000 !important;
} }
.default-theme.splitpanes--vertical > .splitpanes__splitter:before, .default-theme.splitpanes--vertical > .splitpanes__splitter:before,
.default-theme .splitpanes--vertical > .splitpanes__splitter:before { .default-theme .splitpanes--vertical > .splitpanes__splitter:before {
background-color: #000 !important; background-color: #000 !important;
} }

Some files were not shown because too many files have changed in this diff Show More