17 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
128 changed files with 31928 additions and 27602 deletions

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> -->

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,7 +129,7 @@ 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
}) })

View File

@@ -45,3 +45,13 @@ export const getLineOverLimitData = (id: string) => {
method: 'post' 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

@@ -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

@@ -2,13 +2,35 @@ import createAxios from '@/utils/request'
import { genFileId, ElMessage, ElNotification } from 'element-plus' import { genFileId, ElMessage, ElNotification } from 'element-plus'
//事件报告 //事件报告
// export function getEventReport(data) {
// return createAxios({
// url: '/event-boot/report/getEventReport',
// method: 'post',
// data
// })
// }
export function getEventReport(data) { export function getEventReport(data) {
return createAxios({ return createAxios({
url: '/event-boot/report/getEventReport', url: '/event-boot/report/createEventReport',
method: 'post', 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 getAreaReport(data) { export function getAreaReport(data) {
return createAxios({ return createAxios({

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

@@ -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,
})
}

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

File diff suppressed because one or more lines are too long

View File

@@ -183,7 +183,7 @@ const tableStore: any = new TableStore({
if (tableStore.table.params.statisticalType.name == '终端厂家') { if (tableStore.table.params.statisticalType.name == '终端厂家') {
return k.citTotalNum != 0 return k.citTotalNum != 0
} else { } else {
return k.citName != '上送国网' && k.citName != '上送国网' return !k.citName.includes('上送')
} }
}) })
} }

View File

@@ -181,7 +181,7 @@ const tableStore: any = new TableStore({
if (tableStore.table.params.statisticalType.name == '终端厂家') { if (tableStore.table.params.statisticalType.name == '终端厂家') {
return k.citTotalNum != 0 return k.citTotalNum != 0
} else { } else {
return k.citName != '上送国网' && k.citName != '上送国网' return !k.citName.includes('上送')
} }
}) })

View File

@@ -233,7 +233,7 @@ const tableStore: any = new TableStore({
if (tableStore.table.params.statisticalType.name == '终端厂家') { if (tableStore.table.params.statisticalType.name == '终端厂家') {
return k.count != 0 return k.count != 0
} else { } else {
return k.name != '上送国网' && k.name != '上送国网' return !k.citName.includes('上送')
} }
}) })
} }

View File

@@ -6,29 +6,40 @@
</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>
</vxe-colgroup>
<vxe-column align="center" field="number11" title="总分段数目"></vxe-column>
<vxe-column
align="center"
field="number12"
title="三相电压不平衡度(%)"
width="180"
></vxe-column>
<vxe-column align="center" field="number13" title="触发类型"></vxe-column>
<vxe-column align="center" field="number14" title="暂降原因"></vxe-column>
</vxe-table>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</div> </div>
@@ -73,7 +84,25 @@ export default {
subName: '', subName: '',
waveDatas: [], waveDatas: [],
Data: [], Data: [
{
number: 1,
number1: 0,
number2: 0,
number3: 0,
number4: 0,
number5: 0,
number6: 0,
number7: 0,
number8: 0,
number9: 0,
number10: 0,
number11: 1,
number12: 0,
number13: '其他',
number14: '其他'
}
],
height: null, height: null,
vhh: null, vhh: null,
ptpass: '', ptpass: '',
@@ -88,7 +117,7 @@ export default {
zoom: '' zoom: ''
} }
}, },
created() { }, created() {},
watch: { watch: {
value: function (a, b) { value: function (a, b) {
if (a == 2) { if (a == 2) {
@@ -116,10 +145,10 @@ export default {
this.zoom = 1 / document.body.style.zoom this.zoom = 1 / document.body.style.zoom
if (this.flag) { if (this.flag) {
// console.log(123); // console.log(123);
this.vh = mainHeight(250).height this.vh = mainHeight(280).height
} else { } else {
// console.log(3333); // console.log(3333);
this.vh = mainHeight(270).height this.vh = mainHeight(305).height
} }
}, },
query() { query() {
@@ -197,6 +226,8 @@ export default {
'#FF9999' '#FF9999'
] ]
} }
console.log('🚀 ~ this.boxoList:', this.boxoList)
var option = { var option = {
tooltip: { tooltip: {
top: '10px', top: '10px',
@@ -239,7 +270,7 @@ export default {
title: { title: {
left: 'center', left: 'center',
text: '发生时刻:' + this.boxoList.startTime + ' PT变化:' + this.boxoList.measurementPointName, text: '发生时刻:' + this.boxoList.startTime + ' PT变化:' + this.boxoList.pt,
textStyle: { textStyle: {
fontSize: 16, fontSize: 16,
color: _this.DColor ? '#fff' : echartsColor.WordColor color: _this.DColor ? '#fff' : echartsColor.WordColor
@@ -378,6 +409,33 @@ export default {
} }
], ],
series: [ series: [
{
name: '跳变期',
type: 'line',
data: [],
showSymbol: true, // 强制显示标记
symbol: 'rect', // 标记形状为方块
symbolSize: 10, // 方块大小
itemStyle: {
color: '#888888', // 方块颜色为灰色
borderWidth: 0
},
markArea: {
silent: true, // 不响应交互
itemStyle: { color: '#ccc' },
data: [
[
{ xAxis: '0' }, // 第一个跳变期起始
{ xAxis: '5' } // 第一个跳变期结束
],
[
{ xAxis: '210' }, // 第二个跳变期起始
{ xAxis: '220' } // 第二个跳变期结束
]
]
}
},
{ {
name: 'A相', name: 'A相',
type: 'line', type: 'line',

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

@@ -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" @change-value="onAreaChange" /> <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.exportLoading"
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','areaChange']) 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()
@@ -132,9 +104,8 @@ const headerFormSecondStyleClose = {
padding: '0' padding: '0'
} }
const onAreaChange = (data) => { const onAreaChange = data => {
emit('areaChange', { label: data.label })
emit('areaChange', {label: data.label})
} }
watch( watch(
@@ -142,7 +113,6 @@ watch(
newVal => { newVal => {
setTimeout(() => { setTimeout(() => {
areaRef.value && areaRef.value.change() areaRef.value && areaRef.value.change()
}, 0) }, 0)
} }
) )
@@ -238,14 +208,14 @@ const onResetForm = () => {
//时间重置成默认值 //时间重置成默认值
datePickerRef.value?.setTheDate(3) datePickerRef.value?.setTheDate(3)
if(props.showTimeAll){ if (props.showTimeAll) {
timeAll.value = false timeAll.value = false
delete tableStore.table.params.searchBeginTime delete tableStore.table.params.searchBeginTime
delete tableStore.table.params.searchEndTime delete tableStore.table.params.searchEndTime
delete tableStore.table.params.startTime delete tableStore.table.params.startTime
delete tableStore.table.params.endTime delete tableStore.table.params.endTime
delete tableStore.table.params.timeFlag delete tableStore.table.params.timeFlag
delete tableStore.table.params.interval delete tableStore.table.params.interval
} }
if (props.datePicker && timeAll.value) { if (props.datePicker && timeAll.value) {
@@ -264,7 +234,6 @@ const setTheDate = (val: any) => {
} }
// 导出 // 导出
const onExport = () => { const onExport = () => {
tableStore.onTableAction('export', { showAllFlag: true }) tableStore.onTableAction('export', { showAllFlag: true })
} }
@@ -300,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;
} }
@@ -327,7 +297,7 @@ defineExpose({
margin-left: 12px; margin-left: 12px;
} }
.mlr-12 + .el-button { .mlr-12+.el-button {
margin-left: 12px; margin-left: 12px;
} }
@@ -362,7 +332,7 @@ defineExpose({
border-radius: 0; border-radius: 0;
} }
.el-button + .el-button { .el-button+.el-button {
margin: 0; margin: 0;
} }
@@ -373,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

@@ -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

@@ -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

@@ -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

@@ -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

@@ -1,14 +1,14 @@
// 高级算法 // 高级算法
export const ADVANCE_BOOT = '/advance-boot' export const ADVANCE_BOOT = '/advance-boot'
//技术监督 //技术监督
export const PROCESS_BOOT = '/process-boot' export const PROCESS_BOOT = '/process-boot'
//工作流模块 //工作流模块
export const BPM_BOOT = '/bpm-boot' export const BPM_BOOT = '/bpm-boot'
//冀北技术监督 //网公司技术监督
export const SUPERVISION_BOOT = '/supervision-boot' export const SUPERVISION_BOOT = '/supervision-boot'
//终端模块 //终端模块
export const DEVICE_BOOT = '/device-boot' export const DEVICE_BOOT = '/device-boot'

View File

@@ -1,286 +1,337 @@
//指标类型 //指标类型
export const indexOptions = [ export const indexOptions = [
{ {
label: '电压趋势', label: '电压趋势',
options: [ options: [
{ {
value: '10', value: '10',
label: '相电压有效值' label: '相电压有效值'
}, },
{ {
value: '11', value: '11',
label: '线电压有效值' label: '线电压有效值'
}, },
{ {
value: '12', value: '12',
label: '电压偏差' label: '电压偏差'
}, },
{ {
value: '13', value: '13',
label: '三相电压不平衡' label: '三相电压不平衡'
}, },
{ {
value: '14', value: '14',
label: '电压不平衡' label: '电压不平衡'
}, },
{ {
value: '15', value: '15',
label: '电压总谐波畸变率' label: '电压总谐波畸变率'
} }
] ]
}, },
{ {
label: '电流趋势', label: '电流趋势',
options: [ options: [
{ {
value: '20', value: '20',
label: '电流有效值' label: '电流有效值'
}, },
{ {
value: '21', value: '21',
label: '电流总谐波畸变率' label: '电流总谐波畸变率'
}, },
{ {
value: '22', value: '22',
label: '负序电流' label: '负序电流'
} }
] ]
}, },
{ {
label: '频率趋势', label: '频率趋势',
options: [ options: [
{ {
value: '30', value: '30',
label: '频率' label: '频率'
} }
] ]
}, },
{ {
label: '谐波趋势', label: '谐波趋势',
options: [ options: [
{ {
value: '40', value: '40',
label: '谐波电压含有率' label: '谐波电压含有率'
}, },
{ {
value: '43', value: '43',
label: '谐波电流幅值' label: '谐波电流幅值'
}, },
{ {
value: '44', value: '44',
label: '谐波电压相角' label: '谐波电压相角'
}, },
{ {
value: '45', value: '45',
label: '谐波电流相角' label: '谐波电流相角'
}, },
{ {
value: '46', value: '46',
label: '间谐波电压含有率' label: '间谐波电压含有率'
}, },
// { // {
// value: '47', // value: '47',
// label: '间谐波电流含有率' // label: '间谐波电流含有率'
// }, // },
// { // {
// value: '48', // value: '48',
// label: '间谐波电压幅值' // label: '间谐波电压幅值'
// }, // },
{ {
value: '49', value: '49',
label: '间谐波电流幅值' label: '间谐波电流幅值'
} }
] ]
}, },
{ {
label: '功率趋势', label: '功率趋势',
options: [ options: [
{ {
value: '50', value: '50',
label: '谐波有功功率' label: '谐波有功功率'
}, },
{ {
value: '51', value: '51',
label: '谐波无功功率' label: '谐波无功功率'
}, },
{ {
value: '52', value: '52',
label: '谐波视在功率' label: '谐波视在功率'
}, },
{ {
value: '53', value: '53',
label: '三相有功功率' label: '三相有功功率'
}, },
{ {
value: '54', value: '54',
label: '三相无功功率' label: '三相无功功率'
}, },
{ {
value: '55', value: '55',
label: '三相视在功率' label: '三相视在功率'
}, },
{ {
value: '56', value: '56',
label: '三相总有功功率' label: '三相总有功功率'
}, },
{ {
value: '57', value: '57',
label: '三相总无功功率' label: '三相总无功功率'
}, },
{ {
value: '58', value: '58',
label: '三相总视在功率' label: '三相总视在功率'
}, },
{ {
value: '59', value: '59',
label: '视在功率因数' label: '视在功率因数'
}, },
{ {
value: '591', value: '591',
label: '位移功率因数' label: '位移功率因数'
}, },
{ {
value: '592', value: '592',
label: '总视在功率因数' label: '总视在功率因数'
}, },
{ {
value: '593', value: '593',
label: '总位移功率因数' label: '总位移功率因数'
} }
] ]
}, },
{ {
label: '闪变趋势', label: '闪变趋势',
options: [ options: [
{ {
value: '60', value: '60',
label: '短时电压闪变' label: '短时电压闪变'
}, },
{ {
value: '61', value: '61',
label: '长时电压闪变' label: '长时电压闪变'
}, },
{ {
value: '62', value: '62',
label: '电压波动' label: '电压波动'
} }
] ]
} }
] ]
//谐波次数 //谐波次数
export const harmonicOptions = [ export const harmonicOptions = [
{ label: '基波', value: 1 }, { label: '基波', value: 1 },
{ label: '2次', value: 2 }, { label: '2次', value: 2 },
{ label: '3次', value: 3 }, { label: '3次', value: 3 },
{ label: '4次', value: 4 }, { label: '4次', value: 4 },
{ label: '5次', value: 5 }, { label: '5次', value: 5 },
{ label: '6次', value: 6 }, { label: '6次', value: 6 },
{ label: '7次', value: 7 }, { label: '7次', value: 7 },
{ label: '8次', value: 8 }, { label: '8次', value: 8 },
{ label: '9次', value: 9 }, { label: '9次', value: 9 },
{ label: '10次', value: 10 }, { label: '10次', value: 10 },
{ label: '11次', value: 11 }, { label: '11次', value: 11 },
{ label: '12次', value: 12 }, { label: '12次', value: 12 },
{ label: '13次', value: 13 }, { label: '13次', value: 13 },
{ label: '14次', value: 14 }, { label: '14次', value: 14 },
{ label: '15次', value: 15 }, { label: '15次', value: 15 },
{ label: '16次', value: 16 }, { label: '16次', value: 16 },
{ label: '17次', value: 17 }, { label: '17次', value: 17 },
{ label: '18次', value: 18 }, { label: '18次', value: 18 },
{ label: '19次', value: 19 }, { label: '19次', value: 19 },
{ label: '20次', value: 20 }, { label: '20次', value: 20 },
{ label: '21次', value: 21 }, { label: '21次', value: 21 },
{ label: '22次', value: 22 }, { label: '22次', value: 22 },
{ label: '23次', value: 23 }, { label: '23次', value: 23 },
{ label: '24次', value: 24 }, { label: '24次', value: 24 },
{ label: '25次', value: 25 }, { label: '25次', value: 25 },
{ label: '26次', value: 26 }, { label: '26次', value: 26 },
{ label: '27次', value: 27 }, { label: '27次', value: 27 },
{ label: '28次', value: 28 }, { label: '28次', value: 28 },
{ label: '29次', value: 29 }, { label: '29次', value: 29 },
{ label: '30次', value: 30 }, { label: '30次', value: 30 },
{ label: '31次', value: 31 }, { label: '31次', value: 31 },
{ label: '32次', value: 32 }, { label: '32次', value: 32 },
{ label: '33次', value: 33 }, { label: '33次', value: 33 },
{ label: '34次', value: 34 }, { label: '34次', value: 34 },
{ label: '35次', value: 35 }, { label: '35次', value: 35 },
{ label: '36次', value: 36 }, { label: '36次', value: 36 },
{ label: '37次', value: 37 }, { label: '37次', value: 37 },
{ label: '38次', value: 38 }, { label: '38次', value: 38 },
{ label: '39次', value: 39 }, { label: '39次', value: 39 },
{ label: '40次', value: 40 }, { label: '40次', value: 40 },
{ label: '41次', value: 41 }, { label: '41次', value: 41 },
{ label: '42次', value: 42 }, { label: '42次', value: 42 },
{ label: '43次', value: 43 }, { label: '43次', value: 43 },
{ label: '44次', value: 44 }, { label: '44次', value: 44 },
{ label: '45次', value: 45 }, { label: '45次', value: 45 },
{ label: '46次', value: 46 }, { label: '46次', value: 46 },
{ label: '47次', value: 47 }, { label: '47次', value: 47 },
{ label: '48次', value: 48 }, { label: '48次', value: 48 },
{ label: '49次', value: 49 }, { label: '49次', value: 49 },
{ label: '50次', value: 50 } { label: '50次', value: 50 }
] ]
//简谐波次数 export const harmonicOptions1 = [
export const inharmonicOptions = [ { label: '2次', value: 2 },
{ label: '0.5次', value: 1 }, { label: '3次', value: 3 },
{ label: '1.5次', value: 2 }, { label: '4次', value: 4 },
{ label: '2.5次', value: 3 }, { label: '5次', value: 5 },
{ label: '3.5次', value: 4 }, { label: '6次', value: 6 },
{ label: '4.5次', value: 5 }, { label: '7次', value: 7 },
{ label: '5.5次', value: 6 }, { label: '8次', value: 8 },
{ label: '6.5次', value: 7 }, { label: '9次', value: 9 },
{ label: '7.5次', value: 8 }, { label: '10次', value: 10 },
{ label: '8.5次', value: 9 }, { label: '11次', value: 11 },
{ label: '9.5次', value: 10 }, { label: '12次', value: 12 },
{ label: '10.5次', value: 11 }, { label: '13次', value: 13 },
{ label: '11.5次', value: 12 }, { label: '14次', value: 14 },
{ label: '12.5次', value: 13 }, { label: '15次', value: 15 },
{ label: '13.5次', value: 14 }, { label: '16次', value: 16 },
{ label: '14.5次', value: 15 }, { label: '17次', value: 17 },
{ label: '15.5次', value: 16 }, { label: '18次', value: 18 },
{ label: '16.5次', value: 17 }, { label: '19次', value: 19 },
{ label: '17.5次', value: 18 }, { label: '20次', value: 20 },
{ label: '18.5次', value: 19 }, { label: '21次', value: 21 },
{ label: '19.5次', value: 20 }, { label: '22次', value: 22 },
{ label: '20.5次', value: 21 }, { label: '23次', value: 23 },
{ label: '21.5次', value: 22 }, { label: '24次', value: 24 },
{ label: '22.5次', value: 23 }, { label: '25次', value: 25 },
{ label: '23.5次', value: 24 }, { label: '26次', value: 26 },
{ label: '24.5次', value: 25 }, { label: '27次', value: 27 },
{ label: '25.5次', value: 26 }, { label: '28次', value: 28 },
{ label: '26.5次', value: 27 }, { label: '29次', value: 29 },
{ label: '27.5次', value: 28 }, { label: '30次', value: 30 },
{ label: '28.5次', value: 29 }, { label: '31次', value: 31 },
{ label: '29.5次', value: 30 }, { label: '32次', value: 32 },
{ label: '30.5次', value: 31 }, { label: '33次', value: 33 },
{ label: '31.5次', value: 32 }, { label: '34次', value: 34 },
{ label: '32.5次', value: 33 }, { label: '35次', value: 35 },
{ label: '33.5次', value: 34 }, { label: '36次', value: 36 },
{ label: '34.5次', value: 35 }, { label: '37次', value: 37 },
{ label: '35.5次', value: 36 }, { label: '38次', value: 38 },
{ label: '36.5次', value: 37 }, { label: '39次', value: 39 },
{ label: '37.5次', value: 38 }, { label: '40次', value: 40 },
{ label: '38.5次', value: 39 }, { label: '41次', value: 41 },
{ label: '39.5次', value: 40 }, { label: '42次', value: 42 },
{ label: '40.5次', value: 41 }, { label: '43次', value: 43 },
{ label: '41.5次', value: 42 }, { label: '44次', value: 44 },
{ label: '42.5次', value: 43 }, { label: '45次', value: 45 },
{ label: '43.5次', value: 44 }, { label: '46次', value: 46 },
{ label: '44.5次', value: 45 }, { label: '47次', value: 47 },
{ label: '45.5次', value: 46 }, { label: '48次', value: 48 },
{ label: '46.5次', value: 47 }, { label: '49次', value: 49 },
{ label: '47.5次', value: 48 }, { label: '50次', value: 50 }
{ label: '48.5次', value: 49 }, ]
{ label: '49.5次', value: 50 }, //简谐波次数
export const inharmonicOptions = [
{ label: '0.5次', value: 1 },
{ label: '1.5次', value: 2 },
] { label: '2.5次', value: 3 },
{ label: '3.5次', value: 4 },
//值类型 { label: '4.5次', value: 5 },
export const typeOptions = [ { label: '5.5次', value: 6 },
{ label: '平均值', value: 1 }, { label: '6.5次', value: 7 },
{ label: '最小值', value: 2 }, { label: '7.5次', value: 8 },
{ label: '最大值', value: 3 }, { label: '8.5次', value: 9 },
{ label: 'cp95值', value: 4 } { label: '9.5次', value: 10 },
] { label: '10.5次', value: 11 },
{ label: '11.5次', value: 12 },
{ label: '12.5次', value: 13 },
{ label: '13.5次', value: 14 },
{ label: '14.5次', value: 15 },
{ label: '15.5次', value: 16 },
{ label: '16.5次', value: 17 },
{ label: '17.5次', value: 18 },
{ label: '18.5次', value: 19 },
{ label: '19.5次', value: 20 },
{ label: '20.5次', value: 21 },
{ label: '21.5次', value: 22 },
{ label: '22.5次', value: 23 },
{ label: '23.5次', value: 24 },
{ label: '24.5次', value: 25 },
{ label: '25.5次', value: 26 },
{ label: '26.5次', value: 27 },
{ label: '27.5次', value: 28 },
{ label: '28.5次', value: 29 },
{ label: '29.5次', value: 30 },
{ label: '30.5次', value: 31 },
{ label: '31.5次', value: 32 },
{ label: '32.5次', value: 33 },
{ label: '33.5次', value: 34 },
{ label: '34.5次', value: 35 },
{ label: '35.5次', value: 36 },
{ label: '36.5次', value: 37 },
{ label: '37.5次', value: 38 },
{ label: '38.5次', value: 39 },
{ label: '39.5次', value: 40 },
{ label: '40.5次', value: 41 },
{ label: '41.5次', value: 42 },
{ label: '42.5次', value: 43 },
{ label: '43.5次', value: 44 },
{ label: '44.5次', value: 45 },
{ label: '45.5次', value: 46 },
{ label: '46.5次', value: 47 },
{ label: '47.5次', value: 48 },
{ label: '48.5次', value: 49 },
{ label: '49.5次', value: 50 },
]
//值类型
export const typeOptions = [
{ label: '平均值', value: 1 },
{ label: '最小值', value: 2 },
{ label: '最大值', value: 3 },
{ label: 'cp95值', value: 4 }
]

View File

@@ -11,6 +11,7 @@ const calculateValue = (o: number, value: number, num: number, isMin: boolean) =
} else if (value > -1 && value < 0 && isMin == false) { } else if (value > -1 && value < 0 && isMin == false) {
return 0 return 0
} }
let base let base
if (Math.abs(o) >= 100) { if (Math.abs(o) >= 100) {
base = 100 base = 100
@@ -19,8 +20,11 @@ const calculateValue = (o: number, value: number, num: number, isMin: boolean) =
} else if (Math.abs(o) >= 1) { } else if (Math.abs(o) >= 1) {
base = 1 base = 1
} else { } else {
base = 0.1 const multiple = 1 / 0.1
base = Math.ceil(Math.abs(o) * multiple) / multiple
} }
let calculatedValue let calculatedValue
if (isMin) { if (isMin) {
if (value < 0) { if (value < 0) {
@@ -35,18 +39,19 @@ const calculateValue = (o: number, value: number, num: number, isMin: boolean) =
calculatedValue = value + num * value calculatedValue = value + num * value
} }
} }
if (base === 0.1) { if (base === 0.1) {
return parseFloat(calculatedValue.toFixed(1)) // return parseFloat(calculatedValue.toFixed(1))
return Math.ceil(calculatedValue * 10) / 10
} else if (isMin) { } else if (isMin) {
return Math.floor(calculatedValue / base) * base return Math.floor(calculatedValue / base) * base
} else { } else {
return Math.ceil(calculatedValue / base) * base return Math.ceil(calculatedValue / base) * base
} }
} }
// 处理y轴最大最小值 // 处理y轴最大最小值
export const yMethod = (arr: any) => { export const yMethod = (arr: any) => {
let num = 0.1 let num = 0.2
let numList = dataProcessing(arr) let numList = dataProcessing(arr)
let maxValue = 0 let maxValue = 0
let minValue = 0 let minValue = 0
@@ -54,12 +59,9 @@ export const yMethod = (arr: any) => {
let min = 0 let min = 0
maxValue = Math.max(...numList) maxValue = Math.max(...numList)
minValue = Math.min(...numList) minValue = Math.min(...numList)
const o = maxValue - minValue const o = maxValue - minValue == 0 ? maxValue : maxValue - minValue
if (Math.abs(o) >= 300) {
num = 0.02
}
min = calculateValue(o, minValue, num, true) min = calculateValue(o, minValue, num, true)
max = calculateValue(o, maxValue, num, false) max = calculateValue(o, maxValue, num, false)
// if (-100 >= minValue) { // if (-100 >= minValue) {
// min = Math.floor((minValue + num * minValue) / 100) * 100 // min = Math.floor((minValue + num * minValue) / 100) * 100
@@ -158,8 +160,6 @@ export const exportCSV = (title: object, data: any, filename: string) => {
URL.revokeObjectURL(link.href) URL.revokeObjectURL(link.href)
} }
/** /**
* 补全时间序列数据中缺失的条目 * 补全时间序列数据中缺失的条目
* @param rawData 原始数据,格式为 [["时间字符串", "数值", "单位", "类型"], ...] * @param rawData 原始数据,格式为 [["时间字符串", "数值", "单位", "类型"], ...]

View File

@@ -27,8 +27,8 @@ class MQTT {
clean: true, clean: true,
connectTimeout: 30 * 1000, connectTimeout: 30 * 1000,
clientId: `mqttjs_${Math.random().toString(16).substr(2, 8)}`, clientId: `mqttjs_${Math.random().toString(16).substr(2, 8)}`,
username: 't_user', username: '',
password: 'njcnpqs', password: '',
reconnectPeriod: 1000, // 默认1秒重试一次 reconnectPeriod: 1000, // 默认1秒重试一次
maxReconnectTimes: 3 // 默认最大重连5次 maxReconnectTimes: 3 // 默认最大重连5次
} }
@@ -50,14 +50,17 @@ class MQTT {
if (this.client) { if (this.client) {
throw new Error('MQTT 客户端已初始化') throw new Error('MQTT 客户端已初始化')
} }
const mqttUrl = localStorage.getItem('MqttUrl')
console.log('MQTT URL:', mqttUrl)
if (!mqttUrl || mqttUrl === 'null') {
return Promise.resolve()
}
try { try {
// const mqttUrl = // const mqttUrl =
// localStorage.getItem('MqttUrl') == 'null' // localStorage.getItem('MqttUrl') == 'null'
// ? 'ws://192.168.1.68:8083/mqtt' // ? 'ws://192.168.1.68:8083/mqtt'
// : localStorage.getItem('MqttUrl') // : localStorage.getItem('MqttUrl')
const mqttUrl = localStorage.getItem('MqttUrl')
if (mqttUrl == 'null' || mqttUrl == null) return
this.client = mqtt.connect(mqttUrl, this.defaultOptions as IClientOptions) this.client = mqtt.connect(mqttUrl, this.defaultOptions as IClientOptions)
this.setupEventListeners() this.setupEventListeners()
@@ -78,12 +81,12 @@ class MQTT {
this.client?.on('error', error => { this.client?.on('error', error => {
clearTimeout(timeout) clearTimeout(timeout)
console.error('MQTT 连接错误:', error) console.log('MQTT 连接错误:', error)
reject(error) reject(error)
}) })
}) })
} catch (error) { } catch (error) {
console.error('初始化 MQTT 失败:', error) // console.log('初始化 MQTT 失败:', error)
throw error throw error
} }
} }
@@ -132,7 +135,7 @@ class MQTT {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.client?.subscribe(this.topic, { qos: this.defaultOptions.qos, ...subscribeOptions }, error => { this.client?.subscribe(this.topic, { qos: this.defaultOptions.qos, ...subscribeOptions }, error => {
if (error) { if (error) {
console.error('订阅失败:', error) console.log('订阅失败:', error)
reject(error) reject(error)
} else { } else {
console.log('订阅成功') console.log('订阅成功')
@@ -154,7 +157,7 @@ class MQTT {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.client?.unsubscribe(this.topic, error => { this.client?.unsubscribe(this.topic, error => {
if (error) { if (error) {
console.error('取消订阅失败:', error) console.log('取消订阅失败:', error)
reject(error) reject(error)
} else { } else {
console.log('取消订阅成功') console.log('取消订阅成功')
@@ -189,7 +192,7 @@ class MQTT {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.client?.publish(this.topic, message, { qos: this.defaultOptions.qos, ...options }, error => { this.client?.publish(this.topic, message, { qos: this.defaultOptions.qos, ...options }, error => {
if (error) { if (error) {
console.error('消息发布失败:', error) console.log('消息发布失败:', error)
reject(error) reject(error)
} else { } else {
console.log('消息发布成功') console.log('消息发布成功')

View File

@@ -104,11 +104,11 @@ function createAxios<Data = any, T = ApiPromise<Data>>(
if (token) { if (token) {
;(config.headers as anyObj).Authorization = token ;(config.headers as anyObj).Authorization = token
} else { } else {
config.headers.Authorization = 'Basic bmpjbnRlc3Q6bmpjbnBxcw==' config.headers.Authorization = 'Basic bmpjbjpuamNucHFz'
} }
} }
if (config.url == '/user-boot/user/generateSm2Key' || config.url == '/pqs-auth/oauth/token') { if (config.url == '/user-boot/user/generateSm2Key' || config.url == '/pqs-auth/oauth/token') {
config.headers.Authorization = 'Basic bmpjbnRlc3Q6bmpjbnBxcw==' config.headers.Authorization = 'Basic bmpjbjpuamNucHFz'
} }
return config return config
@@ -145,12 +145,14 @@ function createAxios<Data = any, T = ApiPromise<Data>>(
return refreshToken() return refreshToken()
.then(res => { .then(res => {
adminInfo.setToken(res.data.access_token, 'auth') adminInfo.setToken(res.data.access_token, 'auth')
adminInfo.setToken(res.data.refresh_token, 'refresh')
window.requests.forEach(cb => cb(res.data.access_token)) window.requests.forEach(cb => cb(res.data.access_token))
window.requests = [] window.requests = []
return Axios(response.config) return Axios(response.config)
}) })
.catch(err => { .catch(err => {
window.location.reload()
adminInfo.removeToken() adminInfo.removeToken()
router.push({ name: 'login' }) router.push({ name: 'login' })
return Promise.reject(err) return Promise.reject(err)

View File

@@ -77,6 +77,7 @@ export default class TableStore {
} }
index() { index() {
this.table.beforeSearchFun && this.table.beforeSearchFun() this.table.beforeSearchFun && this.table.beforeSearchFun()
this.table.data = [] this.table.data = []
this.table.loading = true this.table.loading = true
@@ -97,10 +98,12 @@ export default class TableStore {
url: this.url, url: this.url,
method: this.method method: this.method
}, },
requestPayload(this.method, this.table.params, this.paramsPOST) requestPayload(this.method, this.table.params, this.paramsPOST)
) )
) )
.then((res: any) => { .then((res: any) => {
if (res.data) { if (res.data) {
this.table.data = res.data.records || res.data this.table.data = res.data.records || res.data
this.table.total = res.data?.total || res.data.length || 0 this.table.total = res.data?.total || res.data.length || 0
@@ -129,13 +132,15 @@ export default class TableStore {
* @param data 携带数据 * @param data 携带数据
*/ */
onTableAction = (event: string, data: anyObj) => { onTableAction = (event: string, data: anyObj) => {
const actionFun = new Map([ const actionFun = new Map([
[ [
'search', 'search',
() => { () => {
this.table.params.pageNum = 1 this.table.params.pageNum = 1
this.index() this.index()
} }
], ],
[ [
@@ -201,9 +206,10 @@ export default class TableStore {
[ [
'export', 'export',
() => { () => {
this.table.exportLoading = true this.table.exportLoading = true
// this.index() // this.index()
//console.log('export')
let params = { ...this.table.params, pageNum: 1, pageSize: this.table.total } let params = { ...this.table.params, pageNum: 1, pageSize: this.table.total }
createAxios( createAxios(
Object.assign( Object.assign(
@@ -219,7 +225,7 @@ export default class TableStore {
this.table.exportProcessingData && this.table.exportProcessingData() this.table.exportProcessingData && this.table.exportProcessingData()
this.table.allFlag = data.showAllFlag || true this.table.allFlag = data.showAllFlag || true
this.table.exportLoading = false this.table.exportLoading = false
}) })
.catch(() => { .catch(() => {
this.table.exportLoading = false this.table.exportLoading = false

View File

@@ -1,400 +1,432 @@
interface TreeHelperConfig { interface TreeHelperConfig {
id: string id: string
children: string children: string
pid: string pid: string
} }
const DEFAULT_CONFIG: TreeHelperConfig = { const DEFAULT_CONFIG: TreeHelperConfig = {
id: 'id', id: 'id',
children: 'children', children: 'children',
pid: 'pid' pid: 'pid'
} }
export const defaultProps = { export const defaultProps = {
children: 'children', children: 'children',
label: 'name', label: 'name',
value: 'id', value: 'id',
isLeaf: 'leaf', isLeaf: 'leaf',
emitPath: false // 用于 cascader 组件:在选中节点改变时,是否返回由该节点所在的各级菜单的值所组成的数组,若设置 false则只返回该节点的值 emitPath: false // 用于 cascader 组件:在选中节点改变时,是否返回由该节点所在的各级菜单的值所组成的数组,若设置 false则只返回该节点的值
} }
const getConfig = (config: Partial<TreeHelperConfig>) => Object.assign({}, DEFAULT_CONFIG, config) const getConfig = (config: Partial<TreeHelperConfig>) => Object.assign({}, DEFAULT_CONFIG, config)
// tree from list // tree from list
export const listToTree = <T = any>(list: any[], config: Partial<TreeHelperConfig> = {}): T[] => { export const listToTree = <T = any>(list: any[], config: Partial<TreeHelperConfig> = {}): T[] => {
const conf = getConfig(config) as TreeHelperConfig const conf = getConfig(config) as TreeHelperConfig
const nodeMap = new Map() const nodeMap = new Map()
const result: T[] = [] const result: T[] = []
const { id, children, pid } = conf const { id, children, pid } = conf
for (const node of list) { for (const node of list) {
node[children] = node[children] || [] node[children] = node[children] || []
nodeMap.set(node[id], node) nodeMap.set(node[id], node)
} }
for (const node of list) { for (const node of list) {
const parent = nodeMap.get(node[pid]) const parent = nodeMap.get(node[pid])
;(parent ? parent.children : result).push(node) ;(parent ? parent.children : result).push(node)
} }
return result return result
} }
export const treeToList = <T = any>(tree: any, config: Partial<TreeHelperConfig> = {}): T => { export const treeToList = <T = any>(tree: any, config: Partial<TreeHelperConfig> = {}): T => {
config = getConfig(config) config = getConfig(config)
const { children } = config const { children } = config
const result: any = [...tree] const result: any = [...tree]
for (let i = 0; i < result.length; i++) { for (let i = 0; i < result.length; i++) {
if (!result[i][children!]) continue if (!result[i][children!]) continue
result.splice(i + 1, 0, ...result[i][children!]) result.splice(i + 1, 0, ...result[i][children!])
} }
return result return result
} }
export const findNode = <T = any>( export const findNode = <T = any>(
tree: any, tree: any,
func: Fn, func: Fn,
config: Partial<TreeHelperConfig> = {} config: Partial<TreeHelperConfig> = {}
): T | null => { ): T | null => {
config = getConfig(config) config = getConfig(config)
const { children } = config const { children } = config
const list = [...tree] const list = [...tree]
for (const node of list) { for (const node of list) {
if (func(node)) return node if (func(node)) return node
node[children!] && list.push(...node[children!]) node[children!] && list.push(...node[children!])
} }
return null return null
} }
export const findNodeAll = <T = any>( export const findNodeAll = <T = any>(
tree: any, tree: any,
func: Fn, func: Fn,
config: Partial<TreeHelperConfig> = {} config: Partial<TreeHelperConfig> = {}
): T[] => { ): T[] => {
config = getConfig(config) config = getConfig(config)
const { children } = config const { children } = config
const list = [...tree] const list = [...tree]
const result: T[] = [] const result: T[] = []
for (const node of list) { for (const node of list) {
func(node) && result.push(node) func(node) && result.push(node)
node[children!] && list.push(...node[children!]) node[children!] && list.push(...node[children!])
} }
return result return result
} }
export const findPath = <T = any>( export const findPath = <T = any>(
tree: any, tree: any,
func: Fn, func: Fn,
config: Partial<TreeHelperConfig> = {} config: Partial<TreeHelperConfig> = {}
): T | T[] | null => { ): T | T[] | null => {
config = getConfig(config) config = getConfig(config)
const path: T[] = [] const path: T[] = []
const list = [...tree] const list = [...tree]
const visitedSet = new Set() const visitedSet = new Set()
const { children } = config const { children } = config
while (list.length) { while (list.length) {
const node = list[0] const node = list[0]
if (visitedSet.has(node)) { if (visitedSet.has(node)) {
path.pop() path.pop()
list.shift() list.shift()
} else { } else {
visitedSet.add(node) visitedSet.add(node)
node[children!] && list.unshift(...node[children!]) node[children!] && list.unshift(...node[children!])
path.push(node) path.push(node)
if (func(node)) { if (func(node)) {
return path return path
} }
} }
} }
return null return null
} }
export const findPathAll = (tree: any, func: Fn, config: Partial<TreeHelperConfig> = {}) => { export const findPathAll = (tree: any, func: Fn, config: Partial<TreeHelperConfig> = {}) => {
config = getConfig(config) config = getConfig(config)
const path: any[] = [] const path: any[] = []
const list = [...tree] const list = [...tree]
const result: any[] = [] const result: any[] = []
const visitedSet = new Set(), const visitedSet = new Set(),
{ children } = config { children } = config
while (list.length) { while (list.length) {
const node = list[0] const node = list[0]
if (visitedSet.has(node)) { if (visitedSet.has(node)) {
path.pop() path.pop()
list.shift() list.shift()
} else { } else {
visitedSet.add(node) visitedSet.add(node)
node[children!] && list.unshift(...node[children!]) node[children!] && list.unshift(...node[children!])
path.push(node) path.push(node)
func(node) && result.push([...path]) func(node) && result.push([...path])
} }
} }
return result return result
} }
export const filter = <T = any>( export const filter = <T = any>(
tree: T[], tree: T[],
func: (n: T) => boolean, func: (n: T) => boolean,
config: Partial<TreeHelperConfig> = {} config: Partial<TreeHelperConfig> = {}
): T[] => { ): T[] => {
config = getConfig(config) config = getConfig(config)
const children = config.children as string const children = config.children as string
function listFilter(list: T[]) { function listFilter(list: T[]) {
return list return list
.map((node: any) => ({ ...node })) .map((node: any) => ({ ...node }))
.filter((node) => { .filter((node) => {
node[children] = node[children] && listFilter(node[children]) node[children] = node[children] && listFilter(node[children])
return func(node) || (node[children] && node[children].length) return func(node) || (node[children] && node[children].length)
}) })
} }
return listFilter(tree) return listFilter(tree)
} }
export const filterTree = <T = any>(
export const forEach = <T = any>( tree: T[],
tree: T[], func: (n: T) => boolean,
func: (n: T) => any, config: Partial<TreeHelperConfig> = {}
config: Partial<TreeHelperConfig> = {} ): T[] => {
): void => { config = getConfig(config)
config = getConfig(config) const children = config.children as string
const list: any[] = [...tree]
const { children } = config function listFilter(list: T[]) {
for (let i = 0; i < list.length; i++) { return list
// func 返回true就终止遍历避免大量节点场景下无意义循环引起浏览器卡顿 .map((node: any) => ({ ...node }))
if (func(list[i])) { .filter((node) => {
return // 1. 如果当前节点匹配 → 直接保留【所有子节点】,不再过滤下级
} if (func(node)) {
children && list[i][children] && list.splice(i + 1, 0, ...list[i][children]) return true;
} }
}
// 2. 如果当前节点不匹配,递归过滤子节点
/** if (node[children]) {
* @description: Extract tree specified structure const filteredChildren = listFilter(node[children]);
*/ if (filteredChildren.length > 0) {
export const treeMap = <T = any>( node[children] = filteredChildren;
treeData: T[], return true;
opt: { children?: string; conversion: Fn } }
): T[] => { }
return treeData.map((item) => treeMapEach(item, opt))
} // 3. 都不匹配,过滤掉
return false;
/** })
* @description: Extract tree specified structure }
*/
export const treeMapEach = ( return listFilter(tree)
data: any, }
{ children = 'children', conversion }: { children?: string; conversion: Fn } export const forEach = <T = any>(
) => { tree: T[],
const haveChildren = Array.isArray(data[children]) && data[children].length > 0 func: (n: T) => any,
const conversionData = conversion(data) || {} config: Partial<TreeHelperConfig> = {}
if (haveChildren) { ): void => {
return { config = getConfig(config)
...conversionData, const list: any[] = [...tree]
[children]: data[children].map((i: number) => const { children } = config
treeMapEach(i, { for (let i = 0; i < list.length; i++) {
children, // func 返回true就终止遍历避免大量节点场景下无意义循环引起浏览器卡顿
conversion if (func(list[i])) {
}) return
) }
} children && list[i][children] && list.splice(i + 1, 0, ...list[i][children])
} else { }
return { }
...conversionData
} /**
} * @description: Extract tree specified structure
} */
export const treeMap = <T = any>(
/** treeData: T[],
* 递归遍历树结构 opt: { children?: string; conversion: Fn }
* @param treeDatas 树 ): T[] => {
* @param callBack 回调 return treeData.map((item) => treeMapEach(item, opt))
* @param parentNode 父节点 }
*/
export const eachTree = (treeDatas: any[], callBack: Fn, parentNode = {}) => { /**
treeDatas.forEach((element) => { * @description: Extract tree specified structure
const newNode = callBack(element, parentNode) || element */
if (element.children) { export const treeMapEach = (
eachTree(element.children, callBack, newNode) data: any,
} { children = 'children', conversion }: { children?: string; conversion: Fn }
}) ) => {
} const haveChildren = Array.isArray(data[children]) && data[children].length > 0
const conversionData = conversion(data) || {}
/** if (haveChildren) {
* 构造树型结构数据 return {
* @param {*} data 数据源 ...conversionData,
* @param {*} id id字段 默认 'id' [children]: data[children].map((i: number) =>
* @param {*} parentId 父节点字段 默认 'parentId' treeMapEach(i, {
* @param {*} children 孩子节点字段 默认 'children' children,
*/ conversion
export const handleTree = (data: any[], id?: string, parentId?: string, children?: string) => { })
if (!Array.isArray(data)) { )
console.warn('data must be an array') }
return [] } else {
} return {
const config = { ...conversionData
id: id || 'id', }
parentId: parentId || 'parentId', }
childrenList: children || 'children' }
}
/**
const childrenListMap = {} * 递归遍历树结构
const nodeIds = {} * @param treeDatas 树
const tree: any[] = [] * @param callBack 回调
* @param parentNode 父节点
for (const d of data) { */
const parentId = d[config.parentId] export const eachTree = (treeDatas: any[], callBack: Fn, parentNode = {}) => {
if (childrenListMap[parentId] == null) { treeDatas.forEach((element) => {
childrenListMap[parentId] = [] const newNode = callBack(element, parentNode) || element
} if (element.children) {
nodeIds[d[config.id]] = d eachTree(element.children, callBack, newNode)
childrenListMap[parentId].push(d) }
} })
}
for (const d of data) {
const parentId = d[config.parentId] /**
if (nodeIds[parentId] == null) { * 构造树型结构数据
tree.push(d) * @param {*} data 数据源
} * @param {*} id id字段 默认 'id'
} * @param {*} parentId 父节点字段 默认 'parentId'
* @param {*} children 孩子节点字段 默认 'children'
for (const t of tree) { */
adaptToChildrenList(t) export const handleTree = (data: any[], id?: string, parentId?: string, children?: string) => {
} if (!Array.isArray(data)) {
console.warn('data must be an array')
function adaptToChildrenList(o) { return []
if (childrenListMap[o[config.id]] !== null) { }
o[config.childrenList] = childrenListMap[o[config.id]] const config = {
} id: id || 'id',
if (o[config.childrenList]) { parentId: parentId || 'parentId',
for (const c of o[config.childrenList]) { childrenList: children || 'children'
adaptToChildrenList(c) }
}
} const childrenListMap = {}
} const nodeIds = {}
const tree: any[] = []
return tree
} for (const d of data) {
const parentId = d[config.parentId]
/** if (childrenListMap[parentId] == null) {
* 构造树型结构数据 childrenListMap[parentId] = []
* @param {*} data 数据源 }
* @param {*} id id字段 默认 'id' nodeIds[d[config.id]] = d
* @param {*} parentId 父节点字段 默认 'parentId' childrenListMap[parentId].push(d)
* @param {*} children 孩子节点字段 默认 'children' }
* @param {*} rootId 根Id 默认 0
*/ for (const d of data) {
// @ts-ignore const parentId = d[config.parentId]
export const handleTree2 = (data, id, parentId, children, rootId) => { if (nodeIds[parentId] == null) {
id = id || 'id' tree.push(d)
parentId = parentId || 'parentId' }
// children = children || 'children' }
rootId =
rootId || for (const t of tree) {
Math.min( adaptToChildrenList(t)
...data.map((item) => { }
return item[parentId]
}) function adaptToChildrenList(o) {
) || if (childrenListMap[o[config.id]] !== null) {
0 o[config.childrenList] = childrenListMap[o[config.id]]
// 对源数据深度克隆 }
const cloneData = JSON.parse(JSON.stringify(data)) if (o[config.childrenList]) {
// 循环所有项 for (const c of o[config.childrenList]) {
const treeData = cloneData.filter((father) => { adaptToChildrenList(c)
const branchArr = cloneData.filter((child) => { }
// 返回每一项的子级数组 }
return father[id] === child[parentId] }
})
branchArr.length > 0 ? (father.children = branchArr) : '' return tree
// 返回第一层 }
return father[parentId] === rootId
}) /**
return treeData !== '' ? treeData : data * 构造树型结构数据
} * @param {*} data 数据源
* @param {*} id id字段 默认 'id'
/** * @param {*} parentId 父节点字段 默认 'parentId'
* 校验选中的节点,是否为指定 level * @param {*} children 孩子节点字段 默认 'children'
* * @param {*} rootId 根Id 默认 0
* @param tree 要操作的树结构数据 */
* @param nodeId 需要判断在什么层级的数据 // @ts-ignore
* @param level 检查的级别, 默认检查到二级 export const handleTree2 = (data, id, parentId, children, rootId) => {
* @return true 是false 否 id = id || 'id'
*/ parentId = parentId || 'parentId'
export const checkSelectedNode = (tree: any[], nodeId: any, level = 2): boolean => { // children = children || 'children'
if (typeof tree === 'undefined' || !Array.isArray(tree) || tree.length === 0) { rootId =
console.warn('tree must be an array') rootId ||
return false Math.min(
} ...data.map((item) => {
return item[parentId]
// 校验是否是一级节点 })
if (tree.some((item) => item.id === nodeId)) { ) ||
return false 0
} // 对源数据深度克隆
const cloneData = JSON.parse(JSON.stringify(data))
// 递归计数 // 循环所有项
let count = 1 const treeData = cloneData.filter((father) => {
const branchArr = cloneData.filter((child) => {
// 深层次校验 // 返回每一项的子级数组
function performAThoroughValidation(arr: any[]): boolean { return father[id] === child[parentId]
count += 1 })
for (const item of arr) { branchArr.length > 0 ? (father.children = branchArr) : ''
if (item.id === nodeId) { // 返回第一层
return true return father[parentId] === rootId
} else if (typeof item.children !== 'undefined' && item.children.length !== 0) { })
if (performAThoroughValidation(item.children)) { return treeData !== '' ? treeData : data
return true }
}
} /**
} * 校验选中的节点,是否为指定 level
return false *
} * @param tree 要操作的树结构数据
* @param nodeId 需要判断在什么层级的数据
for (const item of tree) { * @param level 检查的级别, 默认检查到二级
count = 1 * @return true 是false 否
if (performAThoroughValidation(item.children)) { */
// 找到后对比是否是期望的层级 export const checkSelectedNode = (tree: any[], nodeId: any, level = 2): boolean => {
if (count >= level) { if (typeof tree === 'undefined' || !Array.isArray(tree) || tree.length === 0) {
return true console.warn('tree must be an array')
} return false
} }
}
// 校验是否是一级节点
return false if (tree.some((item) => item.id === nodeId)) {
} return false
}
/**
* 获取节点的完整结构 // 递归计数
* @param tree 树数据 let count = 1
* @param nodeId 节点 id
*/ // 深层次校验
export const treeToString = (tree: any[], nodeId) => { function performAThoroughValidation(arr: any[]): boolean {
if (typeof tree === 'undefined' || !Array.isArray(tree) || tree.length === 0) { count += 1
console.warn('tree must be an array') for (const item of arr) {
return '' if (item.id === nodeId) {
} return true
// 校验是否是一级节点 } else if (typeof item.children !== 'undefined' && item.children.length !== 0) {
const node = tree.find((item) => item.id === nodeId) if (performAThoroughValidation(item.children)) {
if (typeof node !== 'undefined') { return true
return node.name }
} }
let str = '' }
return false
function performAThoroughValidation(arr) { }
for (const item of arr) {
if (item.id === nodeId) { for (const item of tree) {
str += ` / ${item.name}` count = 1
return true if (performAThoroughValidation(item.children)) {
} else if (typeof item.children !== 'undefined' && item.children.length !== 0) { // 找到后对比是否是期望的层级
str += ` / ${item.name}` if (count >= level) {
if (performAThoroughValidation(item.children)) { return true
return true }
} }
} }
}
return false return false
} }
for (const item of tree) { /**
str = `${item.name}` * 获取节点的完整结构
if (performAThoroughValidation(item.children)) { * @param tree 树数据
break * @param nodeId 节点 id
} */
} export const treeToString = (tree: any[], nodeId) => {
return str if (typeof tree === 'undefined' || !Array.isArray(tree) || tree.length === 0) {
} console.warn('tree must be an array')
return ''
}
// 校验是否是一级节点
const node = tree.find((item) => item.id === nodeId)
if (typeof node !== 'undefined') {
return node.name
}
let str = ''
function performAThoroughValidation(arr) {
for (const item of arr) {
if (item.id === nodeId) {
str += ` / ${item.name}`
return true
} else if (typeof item.children !== 'undefined' && item.children.length !== 0) {
str += ` / ${item.name}`
if (performAThoroughValidation(item.children)) {
return true
}
}
}
return false
}
for (const item of tree) {
str = `${item.name}`
if (performAThoroughValidation(item.children)) {
break
}
}
return str
}

View File

@@ -43,13 +43,11 @@ export default class SocketService {
console.log('您的浏览器不支持WebSocket') console.log('您的浏览器不支持WebSocket')
return return
} }
console.log("🚀 ~ SocketService ~ connect ~ url:", url)
if (url === null || (typeof url === 'string' && url.includes('null'))) return;
setTimeout(() => { setTimeout(() => {
// ws://192.168.1.69:10407/mgtt
// const url =
// (localStorage.getItem('WebSocketUrl') == 'null'
// ? 'ws://192.168.1.130:10405'
// : localStorage.getItem('WebSocketUrl')) + id
this.ws = new WebSocket(url) this.ws = new WebSocket(url)
this.ws.onopen = () => this.handleOpen() this.ws.onopen = () => this.handleOpen()
@@ -58,7 +56,6 @@ export default class SocketService {
this.ws.onmessage = event => this.handleMessage(event) this.ws.onmessage = event => this.handleMessage(event)
}, 0) }, 0)
} }
// 处理连接成功事件 // 处理连接成功事件
private handleOpen(): void { private handleOpen(): void {
ElMessage.success('webSocket连接服务端成功了') ElMessage.success('webSocket连接服务端成功了')
@@ -90,7 +87,7 @@ export default class SocketService {
if (event.data == '连接成功') { if (event.data == '连接成功') {
this.sendHeartbeat() this.sendHeartbeat()
} else if (event.data == 'connect') { } else if (event.data == 'over') {
} else if (event.data.length > 10) { } else if (event.data.length > 10) {
let message: MessageType let message: MessageType
try { try {
@@ -104,7 +101,7 @@ export default class SocketService {
// 通过接受服务端发送的type字段来回调函数 // 通过接受服务端发送的type字段来回调函数
if ((message.key || message.code) && this.callBackMapping['message']) { if ((message.key || message.code || message.time) && this.callBackMapping['message']) {
this.callBackMapping['message']!(message) this.callBackMapping['message']!(message)
} else { } else {
console.log('抛弃====>') console.log('抛弃====>')
@@ -112,6 +109,7 @@ export default class SocketService {
// 丢弃或继续写你的逻辑 // 丢弃或继续写你的逻辑
} }
} else { } else {
this.callBackMapping['message']!({ Flag: false })
ElMessage.error(event.data) ElMessage.error(event.data)
} }
} }

View File

@@ -90,7 +90,6 @@ const loading = ref(false)
const statistics = ref() const statistics = ref()
const flg = ref(true) const flg = ref(true)
const showMqtt = ref(false)
const zoom = ref('') //图表焦点校验 const zoom = ref('') //图表焦点校验
const resultList = ref([ const resultList = ref([

View File

@@ -183,7 +183,7 @@ import TableHeader from '@/components/table/header/index.vue'
import MyEChart from '@/components/echarts/MyEchart.vue' import MyEChart from '@/components/echarts/MyEchart.vue'
import { useMonitoringPoint } from '@/stores/monitoringPoint' import { useMonitoringPoint } from '@/stores/monitoringPoint'
import { defaultAttribute } from '@/components/table/defaultAttribute' import { defaultAttribute } from '@/components/table/defaultAttribute'
import { harmonicOptions } from '@/utils/dictionary' import { harmonicOptions1 } from '@/utils/dictionary'
import { Select } from '@element-plus/icons-vue' import { Select } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { import {
@@ -202,7 +202,7 @@ import html2canvas from 'html2canvas'
import { yMethod } from '@/utils/echartMethod' import { yMethod } from '@/utils/echartMethod'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
const props = defineProps(['rowList']) const props = defineProps(['rowList'])
const harmonic = harmonicOptions.filter(item => item.value < 26) const harmonic = harmonicOptions1.filter(item => item.value < 26)
const currentLod = ref(false) const currentLod = ref(false)
const monitoringPoint = useMonitoringPoint() const monitoringPoint = useMonitoringPoint()
const size = ref(19) const size = ref(19)
@@ -844,7 +844,7 @@ onMounted(() => {
} }
.btnBox { .btnBox {
display: flex; display: flex;
justify-content: end; justify-content: flex-end;
} }
:deep(.vxe-table--header thead tr:first-of-type th:first-of-type) { :deep(.vxe-table--header thead tr:first-of-type th:first-of-type) {

View File

@@ -157,7 +157,7 @@ const tableStore: any = new TableStore({
}, },
{ {
name: 'del', name: 'del',
text: '禁止接入', text: '删除',
type: 'danger', type: 'danger',
icon: 'el-icon-Delete', icon: 'el-icon-Delete',
render: 'confirmButton', render: 'confirmButton',
@@ -165,11 +165,11 @@ const tableStore: any = new TableStore({
confirmButtonText: '确认', confirmButtonText: '确认',
cancelButtonText: '取消', cancelButtonText: '取消',
confirmButtonType: 'danger', confirmButtonType: 'danger',
title: '确定禁止接入' title: '确定删除'
}, },
click: row => { click: row => {
remove({ ids: row.id }).then(() => { remove({ ids: row.id }).then(() => {
ElMessage.success('禁止接入成功') ElMessage.success('删除成功')
tableStore.index() tableStore.index()
}) })
} }

View File

@@ -1,163 +1,163 @@
<template> <template>
<el-dialog draggable class="cn-operate-dialog" v-model="dialogVisible" title="设备"> <el-dialog draggable class="cn-operate-dialog" v-model="dialogVisible" title="设备">
<div class="formBox mb10"><el-button icon="el-icon-Plus" type="primary" @click="add">新增</el-button></div> <div class="formBox mb10"><el-button icon="el-icon-Plus" type="primary" @click="add">新增</el-button></div>
<vxe-table v-bind="defaultAttribute" v-loading="loading" height="500px" ref="xTable" :data="userData"> <vxe-table v-bind="defaultAttribute" v-loading="loading" height="500px" ref="xTable" :data="userData">
<vxe-column field="devName" title="设备名称"></vxe-column> <vxe-column field="devName" title="设备名称"></vxe-column>
<vxe-column field="devScale" title="电压等级" :formatter="formatter"></vxe-column> <vxe-column field="devScale" title="电压等级" :formatter="formatter"></vxe-column>
<vxe-column field="protocolCapacity" title="设备容量(MVA)"></vxe-column> <vxe-column field="protocolCapacity" title="设备容量(MVA)"></vxe-column>
<vxe-column title="操作" width="120px"> <vxe-column title="操作" width="120px">
<template #default="{ row }"> <template #default="{ row }">
<el-button type="primary" size="small" link @click="revise(row)">修改</el-button> <el-button type="primary" size="small" link @click="revise(row)">修改</el-button>
<el-popconfirm @confirm="deleteD(row)" title="确认删除设备?"> <el-popconfirm @confirm="deleteD(row)" title="确认删除设备?">
<template #reference> <template #reference>
<el-button type="danger" size="small" link>删除</el-button> <el-button type="danger" size="small" link>删除</el-button>
</template> </template>
</el-popconfirm> </el-popconfirm>
</template> </template>
</vxe-column> </vxe-column>
</vxe-table> </vxe-table>
</el-dialog> </el-dialog>
<el-dialog draggable v-model="addShow" width="400px" :title="title" :before-close="handleClose"> <el-dialog draggable v-model="addShow" width="400px" :title="title" :before-close="handleClose">
<el-form :model="form" ref="formRef" :rules="rules" label-width="auto"> <el-form :model="form" ref="formRef" :rules="rules" label-width="auto">
<el-form-item label="设备名称" prop="devName"> <el-form-item label="设备名称" prop="devName">
<el-input <el-input
v-model.trim="form.devName" v-model.trim="form.devName"
placeholder="请输入设备名称" placeholder="请输入设备名称"
maxlength="32" maxlength="32"
show-word-limit show-word-limit
clearable clearable
/> />
</el-form-item> </el-form-item>
<el-form-item label="电压等级" prop="devScale"> <el-form-item label="电压等级" prop="devScale">
<el-select v-model="form.devScale" clearable placeholder="请选择电压等级"> <el-select v-model="form.devScale" clearable placeholder="请选择电压等级">
<el-option v-for="item in levelList" :key="item.id" :label="item.name" :value="item.id" /> <el-option v-for="item in levelList" :key="item.id" :label="item.name" :value="item.id" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="设备容量(MVA)" prop="protocolCapacity"> <el-form-item label="设备容量(MVA)" prop="protocolCapacity">
<el-input-number <el-input-number
v-model="form.protocolCapacity" v-model="form.protocolCapacity"
style="width: 100%" style="width: 100%"
:min="0" :min="0"
:max="10000000" :max="10000000"
placeholder="请选择设备容量" placeholder="请选择设备容量"
/> />
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
<el-button @click="handleClose">取消</el-button> <el-button @click="handleClose">取消</el-button>
<el-button type="primary" @click="submitForm">确定</el-button> <el-button type="primary" @click="submitForm">确定</el-button>
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref } from 'vue' import { ref } from 'vue'
import { queyDeviceList, addDev, updateDev, removeDev } from '@/api/advance-boot/bearingCapacity' import { queyDeviceList, addDev, updateDev, removeDev } from '@/api/advance-boot/bearingCapacity'
import { defaultAttribute } from '@/components/table/defaultAttribute' import { defaultAttribute } from '@/components/table/defaultAttribute'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
const dictData = useDictData() const dictData = useDictData()
const levelList = dictData.getBasicData('Dev_Voltage_Stand') const levelList = dictData.getBasicData('Dev_Voltage_Stand')
const dialogVisible = ref(false) const dialogVisible = ref(false)
const addShow = ref(false) const addShow = ref(false)
const loading = ref(false) const loading = ref(false)
const userData = ref([]) const userData = ref([])
const rowList = ref([]) const rowList = ref([])
const title = ref('') const title = ref('')
const formRef = ref() const formRef = ref()
const form: any = ref({ const form: any = ref({
devName: '', devName: '',
devScale: '', devScale: '',
protocolCapacity: 0, protocolCapacity: 0,
userId: '' userId: ''
}) })
const rules = { const rules = {
devName: [{ required: true, message: '请输入设备名称', trigger: 'blur' }], devName: [{ required: true, message: '请输入设备名称', trigger: 'blur' }],
devScale: [{ required: true, message: '请输入设备名称', trigger: 'change' }], devScale: [{ required: true, message: '请输入设备名称', trigger: 'change' }],
protocolCapacity: [{ required: true, message: '请输入设备名称', trigger: 'blur' }] protocolCapacity: [{ required: true, message: '请输入设备名称', trigger: 'blur' }]
} }
const open = (row: any) => { const open = (row: any) => {
dialogVisible.value = true dialogVisible.value = true
loading.value = true loading.value = true
rowList.value = row rowList.value = row
queyDeviceList({ queyDeviceList({
userId: row.userId userId: row.userId
}).then(res => { }).then(res => {
loading.value = false loading.value = false
userData.value = res.data userData.value = res.data
}) })
} }
// 新增 // 新增
const add = () => { const add = () => {
addShow.value = true addShow.value = true
title.value = '新增设备' title.value = '新增设备'
} }
// 过滤数据 // 过滤数据
const formatter = (row: any) => { const formatter = (row: any) => {
if (row.column.field == 'devScale') { if (row.column.field == 'devScale') {
return levelList.filter(item => item.id == row.cellValue)[0].name return levelList.filter(item => item.id == row.cellValue)[0].name
} else { } else {
return row.cellValue return row.cellValue
} }
} }
// 修改 // 修改
const revise = (row: any) => { const revise = (row: any) => {
form.value = JSON.parse(JSON.stringify(row)) form.value = JSON.parse(JSON.stringify(row))
title.value = '修改设备' title.value = '修改设备'
addShow.value = true addShow.value = true
} }
// 关闭弹框 // 关闭弹框
const handleClose = () => { const handleClose = () => {
addShow.value = false addShow.value = false
form.value = { form.value = {
devName: '', devName: '',
devScale: '', devScale: '',
protocolCapacity: 0, protocolCapacity: 0,
userId: '' userId: ''
} }
formRef.value.resetFields() formRef.value.resetFields()
} }
// 新增设备 // 新增设备
const submitForm = async () => { const submitForm = async () => {
await formRef.value.validate(valid => { await formRef.value.validate(valid => {
if (valid) { if (valid) {
if (title.value == '新增设备') { if (title.value == '新增设备') {
form.value.userId = rowList.value.userId form.value.userId = rowList.value.userId
addDev(form.value).then(res => { addDev(form.value).then(res => {
ElMessage.success('新增成功!') ElMessage.success('新增成功!')
open(rowList.value) open(rowList.value)
handleClose() handleClose()
}) })
} else { } else {
updateDev(form.value).then(res => { updateDev(form.value).then(res => {
ElMessage.success('修改成功!') ElMessage.success('修改成功!')
open(rowList.value) open(rowList.value)
handleClose() handleClose()
}) })
} }
} }
}) })
} }
// 删除设备 // 删除设备
const deleteD = row => { const deleteD = row => {
removeDev({ devIds: row.devId }).then(res => { removeDev({ devIds: row.devId }).then(res => {
ElMessage.success('删除设备成功!') ElMessage.success('删除设备成功!')
open(rowList.value) open(rowList.value)
}) })
} }
defineExpose({ open }) defineExpose({ open })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.formBox{ .formBox{
display: flex; display: flex;
justify-content: end; justify-content: flex-end;
} }
</style> </style>

View File

@@ -57,9 +57,15 @@
<el-form-item label="区域" prop="regionList"> <el-form-item label="区域" prop="regionList">
<!-- <el-cascader v-model="form.regionList" style="width: 100%" :props="props" :options="areaList" /> --> <!-- <el-cascader v-model="form.regionList" style="width: 100%" :props="props" :options="areaList" /> -->
<el-cascader v-model="form.regionList" :props="props" :options="areaList" style="width: 100%" placeholder="请选择区域" /> <el-cascader
v-model="form.regionList"
:props="props"
:options="areaList"
style="width: 100%"
placeholder="请选择区域"
/>
</el-form-item> </el-form-item>
<el-form-item label="详细地址:" prop="area"> <el-form-item label="详细地址:" prop="area">
<el-input <el-input
clearable clearable
@@ -95,7 +101,7 @@ import { mainHeight } from '@/utils/layout'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
import equipment from './equipment.vue' import equipment from './equipment.vue'
import { addUse, updateUse, removeUse } from '@/api/advance-boot/bearingCapacity' import { addUse, updateUse, removeUse } from '@/api/advance-boot/bearingCapacity'
import { getAreaDept } from '@/api/harmonic-boot/area' import { getAreaDept, getAreaDeptRemoveMode } from '@/api/harmonic-boot/area'
defineOptions({ defineOptions({
name: 'estimate/photovoltaic' name: 'estimate/photovoltaic'
@@ -108,8 +114,9 @@ const disabled = ref(false)
const TableHeaderRef = ref() const TableHeaderRef = ref()
const equipmentRef = ref() const equipmentRef = ref()
const title = ref('') const title = ref('')
const VITE_FLAG = import.meta.env.VITE_NAME == 'removeMode'
//const areaList: any = dictData.areaSelect() //const areaList: any = dictData.areaSelect()
const areaList = ref([]) const areaList: any = ref([])
const userShow: any = ref('Power_Station_Users') const userShow: any = ref('Power_Station_Users')
const form = ref({ const form = ref({
@@ -187,7 +194,8 @@ const tableStore: any = new TableStore({
{ field: 'createBy', title: '创建者' }, { field: 'createBy', title: '创建者' },
{ field: 'createTime', title: '创建日期' }, { field: 'createTime', title: '创建日期' },
{ {
title: '操作',fixed: 'right', title: '操作',
fixed: 'right',
width: '180', width: '180',
render: 'buttons', render: 'buttons',
buttons: [ buttons: [
@@ -258,9 +266,7 @@ const tableStore: any = new TableStore({
} }
], ],
loadCallback: () => { loadCallback: () => {}
}
}) })
tableStore.table.params.userType = '' tableStore.table.params.userType = ''
@@ -268,8 +274,6 @@ tableStore.table.params.userType = ''
provide('tableStore', tableStore) provide('tableStore', tableStore)
onMounted(() => { onMounted(() => {
tableStore.index() tableStore.index()
}) })
const useChange = (e: string) => { const useChange = (e: string) => {
userShow.value = uesrList.filter(item => item.id == e)[0].code userShow.value = uesrList.filter(item => item.id == e)[0].code
@@ -278,10 +282,14 @@ const useChange = (e: string) => {
const add = async () => { const add = async () => {
disabled.value = false disabled.value = false
title.value = '新增承载能力待评估用户' title.value = '新增承载能力待评估用户'
if (VITE_FLAG) {
areaList.value = dictData.state.areaTree
} else {
await getAreaDept().then(res => {
areaList.value = JSON.parse(JSON.stringify(res.data))
})
}
await getAreaDept().then(res => {
areaList.value = JSON.parse(JSON.stringify(res.data))
})
dialogVisible.value = true dialogVisible.value = true
} }
// 保存 // 保存

View File

@@ -40,7 +40,14 @@
></Table> ></Table>
</div> </div>
<div class="pd10" style="width: 400px" v-loading="loading"> <div class="pd10" style="width: 400px" v-loading="loading">
<el-input v-model="filterText" placeholder="请输入内容" clearable maxlength="32" show-word-limit @input="change"> <el-input
v-model="filterText"
placeholder="请输入内容"
clearable
maxlength="32"
show-word-limit
@input="change"
>
<template #prefix> <template #prefix>
<Icon name="el-icon-Search" style="font-size: 16px" /> <Icon name="el-icon-Search" style="font-size: 16px" />
</template> </template>
@@ -139,7 +146,7 @@
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="最大终端数:" prop="nodeDevNum" class="top" > <el-form-item label="最大终端数:" prop="nodeDevNum" class="top">
<el-input <el-input
v-model.trim.number="formData.nodeDevNum" v-model.trim.number="formData.nodeDevNum"
onkeyup="value = value.replace(/[^0-9]/g,'')" onkeyup="value = value.replace(/[^0-9]/g,'')"
@@ -273,7 +280,7 @@ const tableStore = new TableStore({
method: 'POST', method: 'POST',
column: [ column: [
{ title: '名称', field: 'name' }, { title: '名称', field: 'name' },
{ title: 'IP', field: 'ip' ,width:'120px' }, { title: 'IP', field: 'ip', width: '120px' },
{ {
title: '等级', title: '等级',
field: 'nodeGrade', field: 'nodeGrade',
@@ -317,7 +324,8 @@ const tableStore = new TableStore({
{ title: '描述', field: 'remark' }, { title: '描述', field: 'remark' },
{ {
title: '操作',fixed: 'right', title: '操作',
fixed: 'right',
align: 'center', align: 'center',
width: '180', width: '180',
render: 'buttons', render: 'buttons',
@@ -376,8 +384,8 @@ const tableStore = new TableStore({
}, },
click: row => { click: row => {
if (hasDevices.value) { if (hasDevices.value) {
ElMessage.warning('此前置机绑定了设备,无法删除!'); ElMessage.warning('此前置机绑定了设备,无法删除!')
return; return
} }
delNode(row.id).then(res => { delNode(row.id).then(res => {
@@ -386,7 +394,7 @@ const tableStore = new TableStore({
}) })
} }
}, },
{ {
name: 'edit', name: 'edit',
title: '分配终端', title: '分配终端',
type: 'primary', type: 'primary',
@@ -399,10 +407,10 @@ const tableStore = new TableStore({
title: '确定分配终端吗?' title: '确定分配终端吗?'
}, },
click: row => { click: row => {
if (!hasDevices.value) { // if (!hasDevices.value) {
ElMessage.warning('此前置机下无设备,无法分配终端!'); // ElMessage.warning('此前置机下无设备,无法分配终端!')
return; // return
} // }
allotTerminal({ allotTerminal({
nodeId: row.id nodeId: row.id
}).then(res => { }).then(res => {
@@ -410,7 +418,7 @@ const tableStore = new TableStore({
tableStore.index() tableStore.index()
}) })
} }
}, }
] ]
} }
], ],
@@ -448,26 +456,25 @@ const currentChangeEvent = () => {
// 检查返回的数据是否存在且不为空 // 检查返回的数据是否存在且不为空
if (res.data && res.data.processDeviceList) { if (res.data && res.data.processDeviceList) {
// 检查是否有设备绑定 // 检查是否有设备绑定
const hasAnyDevices = res.data.processDeviceList.some(item => const hasAnyDevices = res.data.processDeviceList.some(
item.deviceInfoList && item.deviceInfoList.length > 0 item => item.deviceInfoList && item.deviceInfoList.length > 0
); )
hasDevices.value = hasAnyDevices; hasDevices.value = hasAnyDevices
dataSource.value = res.data.processDeviceList.filter(item => { dataSource.value = res.data.processDeviceList.filter(item => {
item.name = item.processNo + ''; item.name = item.processNo + ''
return true; // 保持原有的过滤逻辑 return true // 保持原有的过滤逻辑
}); })
} else { } else {
dataSource.value = [] dataSource.value = []
hasDevices.value = false; hasDevices.value = false
} }
loading.value = false loading.value = false
}) })
.catch(() => { .catch(() => {
// 添加错误处理,确保 loading 状态也能关闭 // 添加错误处理,确保 loading 状态也能关闭
dataSource.value = [] dataSource.value = []
hasDevices.value = false; hasDevices.value = false
loading.value = false loading.value = false
}) })
@@ -476,7 +483,7 @@ const currentChangeEvent = () => {
// 重启进程 // 重启进程
const restart = (data: any) => { const restart = (data: any) => {
// console.log('🚀 ~ restart ~ data:', data) // console.log('🚀 ~ restart ~ data:', data)
askRestartProcess({ askRestartProcess({
deviceRebootType: null, deviceRebootType: null,
nodeId: nodeId.value, nodeId: nodeId.value,
@@ -518,7 +525,7 @@ const filterNode = (value: string, data: any, node: any) => {
// 过滤父节点 / 子节点 (如果输入的参数是父节点且能匹配则返回该节点以及其下的所有子节点如果参数是子节点则返回该节点的父节点。name是中文字符enName是英文字符. // 过滤父节点 / 子节点 (如果输入的参数是父节点且能匹配则返回该节点以及其下的所有子节点如果参数是子节点则返回该节点的父节点。name是中文字符enName是英文字符.
const chooseNode = (value: string, data: any, node: any) => { const chooseNode = (value: string, data: any, node: any) => {
if (data.name.indexOf(value) !== -1) { if ((data.subName + data.name).indexOf(value) !== -1) {
return true return true
} }
const level = node.level const level = node.level
@@ -629,7 +636,7 @@ const addMenu = () => {}
:deep(.default) { :deep(.default) {
display: flex; display: flex;
.row--current { .row--current {
// background-color: var(--el-color-primary-light-8) !important; // background-color: var(--el-color-primary-light-8) !important;
} }
} }
.custom-tree-node { .custom-tree-node {

View File

@@ -3,7 +3,7 @@
<TableHeader> <TableHeader>
<template #select> <template #select>
<el-form-item label="终端型号"> <el-form-item label="终端型号">
<el-select v-model="tableStore.table.params.teriminal" clearable placeholder="请选择终端型号"> <el-select v-model="tableStore.table.params.devType" clearable placeholder="请选择终端型号">
<el-option <el-option
v-for="item in teriminaloption" v-for="item in teriminaloption"
:key="item.id" :key="item.id"
@@ -13,7 +13,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="终端状态"> <el-form-item label="终端状态">
<el-select v-model="tableStore.table.params.teriminalstatus" clearable placeholder="请选择终端状态"> <el-select v-model="tableStore.table.params.runFlag" clearable placeholder="请选择终端状态">
<el-option <el-option
v-for="item in teriminalstatusoption" v-for="item in teriminalstatusoption"
:key="item.id" :key="item.id"
@@ -23,7 +23,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="通讯状态"> <el-form-item label="通讯状态">
<el-select v-model="tableStore.table.params.state" clearable placeholder="请选择通讯状态"> <el-select v-model="tableStore.table.params.comFlag" clearable placeholder="请选择通讯状态">
<el-option <el-option
v-for="item in stateoption" v-for="item in stateoption"
:key="item.id" :key="item.id"
@@ -42,7 +42,7 @@
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> --> </el-form-item> -->
<el-form-item label="筛选数据"> <!-- <el-form-item label="筛选数据">
<el-input <el-input
v-model="tableStore.table.params.filterName" v-model="tableStore.table.params.filterName"
@keyup="searchEvent" @keyup="searchEvent"
@@ -50,7 +50,7 @@
show-word-limit show-word-limit
placeholder="输入关键字筛选" placeholder="输入关键字筛选"
/> />
</el-form-item> </el-form-item> -->
</template> </template>
<!-- <template #operation> <!-- <template #operation>
<el-button icon="el-icon-Download" @click="add">导出</el-button> <el-button icon="el-icon-Download" @click="add">导出</el-button>
@@ -252,9 +252,9 @@ const tableStore = new TableStore({
}, 0) }, 0)
} }
}) })
tableStore.table.params.teriminal = '' tableStore.table.params.devType = ''
tableStore.table.params.teriminalstatus = '' tableStore.table.params.runFlag = ''
tableStore.table.params.state = '' tableStore.table.params.comFlag = ''
tableStore.table.params.program = '' tableStore.table.params.program = ''
tableStore.table.params.searchEvent = '' tableStore.table.params.searchEvent = ''
tableStore.table.params.filterName = '' tableStore.table.params.filterName = ''

View File

@@ -1740,8 +1740,8 @@ const optionarr = ref([
]) ])
/**母线类型 */ /**母线类型 */
const busBarType = ref([ const busBarType = ref([
{ name: '母线', value: 0 }, { name: '实母线', value: 1 },
{ name: '虚拟母线', value: 1 } { name: '虚拟母线', value: 0 }
]) ])
const bigList: any = ref([]) const bigList: any = ref([])
const smallList: any = ref([]) const smallList: any = ref([])
@@ -1811,7 +1811,7 @@ const busBarDetail = ref({
/**电压等级 */ /**电压等级 */
scale: '', scale: '',
/**母线类型 */ /**母线类型 */
model: 0, model: 1,
/**母线id */ /**母线id */
subvIndex: '', subvIndex: '',
/**监测点 */ /**监测点 */
@@ -2911,7 +2911,7 @@ const selectChanged = async (value: any) => {
capacity = 750 capacity = 750
break break
case '35': case '35':
capacity = 259 capacity = 250
break break
case '10': case '10':
capacity = 100 capacity = 100
@@ -2931,9 +2931,9 @@ const selectChanged = async (value: any) => {
case '750': case '750':
capacity = 7000 capacity = 7000
break break
case '800': // case '800':
capacity = 7000 // capacity = 7000
break // break
case '1000': case '1000':
capacity = 9000 capacity = 9000
break break

View File

@@ -0,0 +1,107 @@
<template>
<el-dialog class="cn-operate-dialog" width="600px" v-model.trim="dialogVisible" :title="title">
<el-form :model="form" class="form-one" label-width="auto" ref="formRef" :rules="rules">
<el-form-item label="所属厂站名称" prop="substationName">
<el-input v-model.trim="form.substationName" placeholder="请输入所属厂站名称"></el-input>
</el-form-item>
<el-form-item label="敏感用户名称" prop="name">
<el-input v-model.trim="form.name" placeholder="请输入敏感用户名称"></el-input>
</el-form-item>
<el-form-item label="敏感负荷类型" prop="loadType">
<el-select v-model.trim="form.loadType" filterable clearable placeholder="请选择数据分类">
<el-option
v-for="item in DataTypeSelect"
:key="item.id"
:label="item.name"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="用户协议容量(MVA)" prop="userAgreementCapacity">
<el-input-number style="width: 100%;" :min="0" maxlength="32" show-word-limit v-model.number="form.userAgreementCapacity" placeholder="请输入用户协议容量"></el-input-number>
</el-form-item>
<el-form-item label="装机容量(MW)" prop="installedCapacity">
<el-input-number style="width: 100%;" :min="0" maxlength="32" show-word-limit v-model.number="form.installedCapacity" placeholder="请输入装机容量"></el-input-number>
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input-number style="width: 100%;" :min="0" maxlength="32" show-word-limit v-model.number="form.sort" placeholder="请输入排序"></el-input-number>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submit">确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref,inject } from 'vue'
import { reactive } from 'vue'
import { ElMessage } from 'element-plus'
import TableStore from '@/utils/tableStore'
import { queryByCode, queryCsDictTree } from '@/api/system-boot/dictTree'
import { saveUser, updateUser } from '@/api/device-boot/sensitiveLoadMange'
import { useDictData } from '@/stores/dictData'
const TypeOptions = ref()
const dictData = useDictData()
const DataTypeSelect = dictData.getBasicData('Interference_Source')
const tableStore = inject('tableStore') as TableStore
const formRef = ref()
const form = reactive<any>({
loadType: [],
substationName: null,
installedCapacity: null,
name: null,
userAgreementCapacity:null,
id: null,
sort:100
})
const rules = {
substationName: [{ required: true, message: '请输入所属厂站名称', trigger: 'blur' }],
name: [{ required: true, message: '请输入敏感用户名称', trigger: 'blur' }],
loadType: [{ required: true, message: '请输入请选择敏感负荷类型', trigger: 'blur' }],
installedCapacity: [{ required: true, message: '请输入用户协议容量', trigger: 'blur' }],
userAgreementCapacity: [{ required: true, message: '请输入装机容量', trigger: 'blur' }],
sort: [{ required: true, message: '请输入排序', trigger: 'blur' }]
}
const dialogVisible = ref(false)
const title = ref('新增')
const open = (text: string, data?: anyObj) => {
formRef.value?.resetFields()
title.value = text
dialogVisible.value = true
if (data) {
for (let key in form) {
form[key] = data[key]
}
} else {
for (let key in form) {
form[key] = null
form.sort = 100
}
}
}
const submit = () => {
formRef.value.validate(async (valid: boolean) => {
if (valid) {
if (form.id) {
await updateUser(form)
} else {
await saveUser(form)
}
ElMessage.success('操作成功')
tableStore.index()
dialogVisible.value = false
}
})
}
defineExpose({ open })
</script>

View File

@@ -0,0 +1,117 @@
<template>
<div class="default-main">
<TableHeader :showReset="false" showExport>
<template #select>
<el-form-item label="筛选数据">
<el-input
maxlength="32"
show-word-limit
style="width: 240px"
v-model.trim="tableStore.table.params.searchValue"
clearable
placeholder="请输入敏感负荷名称"
/>
</el-form-item>
</template>
<template #operation>
<el-button :icon="Plus" type="primary" @click="addMenu" class="ml10">新增</el-button>
</template>
</TableHeader>
<Table ref="tableRef" />
<detail ref="detail"></detail>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, provide } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import Detail from './detail.vue'
import { ElMessage } from 'element-plus'
import { deleteUser } from '@/api/device-boot/sensitiveLoadMange'
import { Plus } from '@element-plus/icons-vue'
import { useDictData } from '@/stores/dictData'
defineOptions({
name: 'govern/sensitiveLoadMange/index'
})
const detail = ref()
const dictData = useDictData()
const interferenceType = dictData.getBasicData('Interference_Source')
const tableStore: any = new TableStore({
url: '/device-boot/pqSensitiveUser/getList',
method: 'POST',
column: [
{
title: '序号',
width: 80,
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '所属厂站名称', field: 'substationName', minWidth: 180 },
{ title: '敏感用户名称', field: 'name', minWidth: 180 },
{
title: '敏感负荷类型',
field: 'loadType',
minWidth: 120,
formatter: row => {
return interferenceType.filter(item => item.id == row.cellValue)[0]?.name
}
},
{ title: '用户协议容量(MVA)', field: 'userAgreementCapacity', minWidth: 100 },
{ title: '装机容量(MW)', field: 'installedCapacity', minWidth: 100 },
{
title: '操作', fixed: 'right',
align: 'center',
width: '180',
render: 'buttons',
buttons: [
{
name: 'edit',
title: '编辑',
type: 'primary',
icon: 'el-icon-EditPen',
render: 'basicButton',
click: row => {
detail.value.open('编辑', row)
}
},
{
name: 'del',
title: '删除',
type: 'danger',
icon: 'el-icon-Delete',
render: 'confirmButton',
popconfirm: {
confirmButtonText: '确认',
cancelButtonText: '取消',
confirmButtonType: 'danger',
title: '确定删除吗?'
},
click: row => {
deleteUser([row.id]).then(res => {
ElMessage.success('删除成功')
tableStore.index()
})
}
}
]
}
],
loadCallback: () => {}
})
tableStore.table.params.searchValue = ''
provide('tableStore', tableStore)
onMounted(() => {
tableStore.index()
})
const addMenu = () => {
detail.value.open('新增')
}
</script>

View File

@@ -400,13 +400,12 @@ import { uploadFile } from '@/api/system-boot/file'
import { import {
submitFormData, submitFormData,
getById, getById,
updateFormData,
addEditor, addEditor,
resend, getByDeptDevLine,
getByDeptDevLine getUserReportUpdateById
} from '@/api/supervision-boot/interfere/index' } from '@/api/device-boot/sensitiveLoadMange'
import { getSubstationSelect } from '@/api/device-boot/line' import { getSubstationSelect } from '@/api/device-boot/line'
import { getUserReportUpdateById } from '@/api/supervision-boot/userReport/form' // import { getUserReportUpdateById } from '@/api/supervision-boot/userReport/form'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
const route = useRoute() const route = useRoute()

View File

@@ -1,217 +1,225 @@
<template> <template>
<div class="default-main"> <div class="default-main">
<div v-if="detailLoading" class="loading"> <div v-if="detailLoading" class="loading">
<el-spin description="加载中..." /> <el-spin description="加载中..." />
</div> </div>
<div v-else> <div v-else>
<el-descriptions :column="2" border> <el-descriptions :column="2" border label-width="200px">
<el-descriptions-item label="所在地市"> <el-descriptions-item label="所在地市">
{{ detailData.city }} {{ detailData.city }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="项目名称"> <el-descriptions-item label="项目名称">
{{ detailData.projectName }} {{ detailData.projectName }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="工程预期投产日期"> <el-descriptions-item label="工程预期投产日期">
{{ formatDate(detailData.expectedProductionDate, 'YYYY-MM-DD') }} {{ formatDate(detailData.expectedProductionDate, 'YYYY-MM-DD') }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="经纬度"> <el-descriptions-item label="经纬度">
{{ detailData.longitude }}  {{ detailData.latitude }} {{ detailData.longitude }}  {{ detailData.latitude }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="用户性质"> <el-descriptions-item label="用户性质">
{{ {{
userTypeList.find(item => { userTypeList.find(item => {
return item.value == detailData.userType return item.value == detailData.userType
})?.label })?.label
}} }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="归口管理部门"> <el-descriptions-item label="归口管理部门">
{{ detailData.responsibleDepartment }} {{ detailData.responsibleDepartment }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="用户状态"> <el-descriptions-item label="用户状态">
{{ {{
userStateList.find(item => { userStateList.find(item => {
return item.value == detailData.userStatus return item.value == detailData.userStatus
})?.label })?.label
}} }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="厂站名称"> <el-descriptions-item label="厂站名称">
{{ detailData.substation }} {{ detailData.substation }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="电压等级"> <el-descriptions-item label="电压等级">
{{ {{
voltageLevelList.find(item => { voltageLevelList.find(item => {
return item.id == detailData.voltageLevel return item.id == detailData.voltageLevel
})?.name })?.name
}} }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="非线性终端类型" v-if="detailData.userType == 0 || detailData.userType == 1"> <el-descriptions-item
{{ proviteData.nonlinearDeviceType ? proviteData.nonlinearDeviceType : '-' }} label="非线性终端类型"
</el-descriptions-item> v-if="detailData.userType == 0 || detailData.userType == 1"
<el-descriptions-item label="预测评估单位"> >
{{ detailData.evaluationDept }} {{ proviteData.nonlinearDeviceType ? proviteData.nonlinearDeviceType : '-' }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="预测评估结论" :span="2"> <el-descriptions-item label="预测评估单位">
{{ detailData.evaluationConclusion }} {{ detailData.evaluationDept }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item <el-descriptions-item label="预测评估结论" :span="2">
:label=" {{ detailData.evaluationConclusion }}
detailData.userType == '4' || detailData.userType == '5' ? '非线性设备类型: ' : '非线性负荷类型:' </el-descriptions-item>
" <el-descriptions-item
v-if=" :label="
detailData.userType == '2' || detailData.userType == '4' || detailData.userType == '5'
detailData.userType == '3' || ? '非线性设备类型: '
detailData.userType == '4' || : '非线性负荷类型:'
detailData.userType == '5' "
"
>
{{ proviteData.nonlinearLoadType }}
</el-descriptions-item>
<el-descriptions-item label="是否需要治理">
<span v-if="detailData.userType == 0 || detailData.userType == 1">
{{ proviteData.needGovernance == 0 ? '否' : '是' }}
</span>
<span
v-if=" v-if="
detailData.userType == 2 || detailData.userType == '2' ||
detailData.userType == 3 || detailData.userType == '3' ||
detailData.userType == 4 || detailData.userType == '4' ||
detailData.userType == 5 detailData.userType == '5'
" "
> >
{{ proviteData.needGovernance == 0 ? '否' : '是' }} {{ proviteData.nonlinearLoadType }}
</span> </el-descriptions-item>
<span v-if="detailData.userType == 6">{{ proviteData.needGovernance == 0 ? '否' : '是' }}</span> <el-descriptions-item label="是否需要治理">
</el-descriptions-item> <span v-if="detailData.userType == 0 || detailData.userType == 1">
<el-descriptions-item label="是否开展背景测试"> {{ proviteData.needGovernance == 0 ? '否' : '是' }}
<span v-if="detailData.userType == 0 || detailData.userType == 1"> </span>
{{ proviteData.backgroundTestPerformed == 0 ? '否' : '是' }} <span
</span> v-if="
<span detailData.userType == 2 ||
detailData.userType == 3 ||
detailData.userType == 4 ||
detailData.userType == 5
"
>
{{ proviteData.needGovernance == 0 ? '否' : '是' }}
</span>
<span v-if="detailData.userType == 6">{{ proviteData.needGovernance == 0 ? '否' : '是' }}</span>
</el-descriptions-item>
<el-descriptions-item label="是否开展背景测试">
<span v-if="detailData.userType == 0 || detailData.userType == 1">
{{ proviteData.backgroundTestPerformed == 0 ? '否' : '是' }}
</span>
<span
v-if="
detailData.userType == 2 ||
detailData.userType == 3 ||
detailData.userType == 4 ||
detailData.userType == 5
"
>
{{ proviteData.backgroundTestPerformed == 0 ? '否' : '是' }}
</span>
<span v-if="detailData.userType == 6">
{{ proviteData.backgroundTestPerformed == 0 ? '否' : '是' }}
</span>
</el-descriptions-item>
<el-descriptions-item label="是否开展抗扰度测试" v-if="detailData.userType == 6">
<span>
{{ proviteData.antiInterferenceTest == 0 ? '否' : '是' }}
</span>
</el-descriptions-item>
<el-descriptions-item
label="用户协议容量MVA"
v-if="detailData.userType == 0 || detailData.userType == 1"
>
{{ proviteData.agreementCapacity }}
</el-descriptions-item>
<el-descriptions-item label="装机容量MW">
{{ detailData?.ratePower }}
</el-descriptions-item>
<el-descriptions-item
label="PCC供电设备容量MVA"
v-if=" v-if="
detailData.userType == 2 || detailData.userType == '2' ||
detailData.userType == 3 || detailData.userType == '3' ||
detailData.userType == 4 || detailData.userType == '4' ||
detailData.userType == 5 detailData.userType == '5'
" "
> >
{{ proviteData.backgroundTestPerformed == 0 ? '否' : '是' }} {{ proviteData.pccEquipmentCapacity }}
</span> </el-descriptions-item>
<span v-if="detailData.userType == 6"> <el-descriptions-item
{{ proviteData.backgroundTestPerformed == 0 ? '否' : '是' }} label="基准短路容量MVA"
</span> v-if="
</el-descriptions-item> detailData.userType == '2' ||
detailData.userType == '3' ||
<el-descriptions-item label="是否开展抗扰度测试" v-if="detailData.userType == 6"> detailData.userType == '4' ||
<span> detailData.userType == '5'
{{ proviteData.antiInterferenceTest == 0 ? '否' : '是' }} "
</span> >
</el-descriptions-item> {{ proviteData.baseShortCircuitCapacity }}
<el-descriptions-item </el-descriptions-item>
label="用户协议容量MVA" <el-descriptions-item
v-if="detailData.userType == 0 || detailData.userType == 1" label="系统最小短路容量MVA"
> v-if="
{{ proviteData.agreementCapacity }} detailData.userType == '2' ||
</el-descriptions-item> detailData.userType == '3' ||
<el-descriptions-item label="装机容量MW"> detailData.userType == '4' ||
{{ detailData?.ratePower }} detailData.userType == '5'
</el-descriptions-item> "
<el-descriptions-item >
label="PCC供电设备容量MVA" {{ proviteData?.minShortCircuitCapacity }}
v-if=" </el-descriptions-item>
detailData.userType == '2' || <el-descriptions-item
detailData.userType == '3' || label="用户用电协议容量MVA"
detailData.userType == '4' || v-if="
detailData.userType == '5' detailData.userType == '2' ||
" detailData.userType == '3' ||
> detailData.userType == '4' ||
{{ proviteData.pccEquipmentCapacity }} detailData.userType == '5'
</el-descriptions-item> "
<el-descriptions-item >
label="基准短路容量MVA" {{ proviteData?.userAgreementCapacity }}
v-if=" </el-descriptions-item>
detailData.userType == '2' || <el-descriptions-item label="PCC点" v-if="detailData.userType != 0 && detailData.userType != 1">
detailData.userType == '3' || {{ proviteData?.pccPoint }}
detailData.userType == '4' || </el-descriptions-item>
detailData.userType == '5' <el-descriptions-item label="评估类型" v-if="detailData.userType != 0 && detailData.userType != 1">
" {{
> evaluationTypeList.find(item => {
{{ proviteData.baseShortCircuitCapacity }} return item.id == proviteData?.evaluationType
</el-descriptions-item> })?.name
<el-descriptions-item }}
label="系统最小短路容量MVA" </el-descriptions-item>
v-if=" <el-descriptions-item
detailData.userType == '2' || label="预测评估评审单位"
detailData.userType == '3' || v-if="detailData.userType != 0 && detailData.userType != 1"
detailData.userType == '4' || >
detailData.userType == '5' {{ proviteData?.evaluationChekDept }}
" </el-descriptions-item>
> <el-descriptions-item label="行业" v-if="detailData.userType == 6">
{{ proviteData?.minShortCircuitCapacity }} {{
</el-descriptions-item> industryList.find(item => {
<el-descriptions-item return item.id == proviteData.industry
label="用户用电协议容量MVA" })?.name
v-if=" }}
detailData.userType == '2' || </el-descriptions-item>
detailData.userType == '3' || <el-descriptions-item label="敏感终端名称" v-if="detailData.userType == 6">
detailData.userType == '4' || {{ proviteData.deviceName }}
detailData.userType == '5' </el-descriptions-item>
" <!-- <el-descriptions-item label="供电电源数量" v-if="detailData.userType == 6">-->
> <!-- {{ proviteData.powerSupplyCount }}-->
{{ proviteData?.userAgreementCapacity }} <!-- </el-descriptions-item>-->
</el-descriptions-item> <el-descriptions-item label="供电电源情况" v-if="detailData.userType == 6">
<el-descriptions-item label="PCC点" v-if="detailData.userType != 0 && detailData.userType != 1"> {{
{{ proviteData?.pccPoint }} powerSupplyInfoOptionList.find(item => {
</el-descriptions-item> return item.id == proviteData.powerSupplyInfo
<el-descriptions-item label="评估类型" v-if="detailData.userType != 0 && detailData.userType != 1"> })?.name
{{ }}
evaluationTypeList.find(item => { </el-descriptions-item>
return item.id == proviteData?.evaluationType <el-descriptions-item label="供电电源" :span="2" v-if="detailData.userType == 6">
})?.name {{ proviteData.powerSupply }}
}} </el-descriptions-item>
</el-descriptions-item> <el-descriptions-item label="负荷级别" v-if="detailData.userType == 6">
<el-descriptions-item label="预测评估评审单位" v-if="detailData.userType != 0 && detailData.userType != 1"> {{
{{ proviteData?.evaluationChekDept }} loadLevelOptionList.find(item => {
</el-descriptions-item> return item.id == proviteData.loadLevel
<el-descriptions-item label="行业" v-if="detailData.userType == 6"> })?.name
{{ }}
industryList.find(item => { </el-descriptions-item>
return item.id == proviteData.industry <el-descriptions-item label="敏感电能质量指标" v-if="detailData.userType == 6">
})?.name {{
}} energyQualityIndexList.find(item => {
</el-descriptions-item> return item.id == proviteData.energyQualityIndex
<el-descriptions-item label="敏感终端名称" v-if="detailData.userType == 6"> })?.name
{{ proviteData.deviceName }} }}
</el-descriptions-item> </el-descriptions-item>
<!-- <el-descriptions-item label="供电电源数量" v-if="detailData.userType == 6">--> </el-descriptions>
<!-- {{ proviteData.powerSupplyCount }}-->
<!-- </el-descriptions-item>-->
<el-descriptions-item label="供电电源情况" v-if="detailData.userType == 6">
{{
powerSupplyInfoOptionList.find(item => {
return item.id == proviteData.powerSupplyInfo
})?.name
}}
</el-descriptions-item>
<el-descriptions-item label="供电电源" :span="2" v-if="detailData.userType == 6">
{{ proviteData.powerSupply }}
</el-descriptions-item>
<el-descriptions-item label="负荷级别" v-if="detailData.userType == 6">
{{
loadLevelOptionList.find(item => {
return item.id == proviteData.loadLevel
})?.name
}}
</el-descriptions-item>
<el-descriptions-item label="敏感电能质量指标" v-if="detailData.userType == 6">
{{
energyQualityIndexList.find(item => {
return item.id == proviteData.energyQualityIndex
})?.name
}}
</el-descriptions-item>
</el-descriptions>
</div> </div>
</div> </div>
</template> </template>
@@ -220,14 +228,13 @@ import { onMounted, ref, reactive, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { formatDate } from '@/utils/formatTime' import { formatDate } from '@/utils/formatTime'
import { propTypes } from '@/utils/propTypes' import { propTypes } from '@/utils/propTypes'
import { getUserReportById, getUserReportUpdateById } from '@/api/supervision-boot/userReport/form' import { getById, getUserReportUpdateById, getByDeptDevLine, getFileById } from '@/api/device-boot/sensitiveLoadMange'
import { getDictTreeById } from '@/api/system-boot/dictTree' import { getDictTreeById } from '@/api/system-boot/dictTree'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
import { getFileNameAndFilePath } from '@/api/system-boot/file' import { getFileNameAndFilePath } from '@/api/system-boot/file'
import { Link, View } from '@element-plus/icons-vue' import { Link, View } from '@element-plus/icons-vue'
import PreviewFile from '@/components/PreviewFile/index.vue' import PreviewFile from '@/components/PreviewFile/index.vue'
import { getByDeptDevLine } from '@/api/supervision-boot/interfere/index' // import { addOrUpdateFile, getFileById } from '@/api/supervision-boot/interfere/index'
import { addOrUpdateFile, getFileById } from '@/api/supervision-boot/interfere/index'
defineOptions({ name: 'BpmUserReportDetail' }) defineOptions({ name: 'BpmUserReportDetail' })
const { query } = useRoute() // 查询参数 const { query } = useRoute() // 查询参数
@@ -340,9 +347,9 @@ const getInfo = async () => {
getProviteData() getProviteData()
}) })
} else { } else {
await getUserReportById(props.id || queryId).then(res => { await getById({ id: props.id || queryId }).then(res => {
detailData.value = res.data detailData.value = res.data
getProviteData() getProviteData()
}) })
} }
@@ -385,7 +392,6 @@ const preview = (val: any, url: any) => {
} }
//预测评估报告 //预测评估报告
if (val == 'predictionEvaluationReport') { if (val == 'predictionEvaluationReport') {
predictionEvaluationReportRef?.value.open(url) predictionEvaluationReportRef?.value.open(url)
} }
//预测评估评审意见报告 //预测评估评审意见报告
@@ -416,11 +422,11 @@ const preview = (val: any, url: any) => {
} }
const queryFiles = () => { const queryFiles = () => {
getFileById({ id: props.id }).then(res => { // getFileById({ id: props.id }).then(res => {
res.data.forEach((item: any) => { // res.data.forEach((item: any) => {
if (item.url.length > 0) getFileNamePaths(item.url, item.name) // if (item.url.length > 0) getFileNamePaths(item.url, item.name)
}) // })
}) // })
} }
//判断userType选择取用的对象 //判断userType选择取用的对象
const getProviteData = async () => { const getProviteData = async () => {

View File

@@ -34,11 +34,11 @@
</TableHeader> </TableHeader>
<Table ref="tableRef" /> <Table ref="tableRef" />
<el-dialog title="详情" width="60%" v-model="dialogShow" v-if="dialogShow"> <el-dialog title="详情" width="1000px" v-model="dialogShow" v-if="dialogShow">
<DetailInfo :id="userId" :openType="'sourcesOfInterference'"></DetailInfo> <DetailInfo :id="userId" :openType="'sourcesOfInterference'"></DetailInfo>
</el-dialog> </el-dialog>
<!-- 批量导入 --> <!-- 批量导入
<sensitive-user-popup ref="sensitiveUserPopup" /> <sensitive-user-popup ref="sensitiveUserPopup" /> -->
<!-- 查看详情 detail 新增/修改 create--> <!-- 查看详情 detail 新增/修改 create-->
<addForm ref="addForms" @onSubmit="tableStore.index()" :openType="'sourcesOfInterference'"></addForm> <addForm ref="addForms" @onSubmit="tableStore.index()" :openType="'sourcesOfInterference'"></addForm>
@@ -57,7 +57,7 @@ import { useRouter } from 'vue-router'
import { downloadSensitiveReportTemplate } from '@/api/supervision-boot/userReport/form' import { downloadSensitiveReportTemplate } from '@/api/supervision-boot/userReport/form'
import DetailInfo from './components/detail.vue' import DetailInfo from './components/detail.vue'
import { cancelFormData, getUserReportById } from '@/api/supervision-boot/interfere/index' import { cancelFormData, getUserReportById } from '@/api/supervision-boot/interfere/index'
import { deleteUserReport } from '@/api/supervision-boot/delete/index' import { deleteUserReport } from '@/api/device-boot/sensitiveLoadMange'
const addForms = ref() const addForms = ref()
const dictData = useDictData() const dictData = useDictData()
const sensitiveUserPopup = ref() const sensitiveUserPopup = ref()
@@ -73,7 +73,7 @@ defineOptions({
//获取登陆用户姓名和部门 //获取登陆用户姓名和部门
const adminInfo = useAdminInfo() const adminInfo = useAdminInfo()
const tableStore = new TableStore({ const tableStore = new TableStore({
url: '/supervision-boot/userReport/getUserLedgerPage', url: '/device-boot/userReport/getUserLedgerPage',
// publicHeight: 65, // publicHeight: 65,
method: 'POST', method: 'POST',
column: [ column: [

View File

@@ -12,7 +12,7 @@
</div> </div>
<el-collapse v-model="activeName" accordion> <el-collapse v-model="activeName" accordion>
<!-- <el-collapse-item title="典型电能质量干扰源" name="1"></el-collapse-item> --> <!-- <el-collapse-item title="典型电能质量干扰源" name="1"></el-collapse-item> -->
<el-collapse-item title="国家电网有限公司企业标准" name="2"> <el-collapse-item title="电网有限公司企业标准" name="2">
<!-- <el-empty description="暂无数据" class="custom-empty iframe" /> --> <!-- <el-empty description="暂无数据" class="custom-empty iframe" /> -->
<div :style="`overflow: auto;`" class="iframe"> <div :style="`overflow: auto;`" class="iframe">
<vue-office-docx v-if="urlKey.includes('.doc') || urlKey.includes('.docx')" :src="url" /> <vue-office-docx v-if="urlKey.includes('.doc') || urlKey.includes('.docx')" :src="url" />

View File

@@ -3,7 +3,7 @@
<!-- 案例库 --> <!-- 案例库 -->
<TableHeader ref="TableHeaderRef"> <TableHeader ref="TableHeaderRef">
<template #select> <template #select>
<el-form-item label="名称"> <el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.searchValue" clearable placeholder="请输入搜索名称" maxlength="32" show-word-limit/> <el-input v-model="tableStore.table.params.searchValue" clearable placeholder="请输入搜索名称" maxlength="32" show-word-limit/>
</el-form-item> </el-form-item>

View File

@@ -3,7 +3,7 @@
<!-- 模版 --> <!-- 模版 -->
<TableHeader ref="TableHeaderRef" > <TableHeader ref="TableHeaderRef" >
<template #select> <template #select>
<el-form-item label="名称"> <el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.searchValue" clearable <el-input v-model="tableStore.table.params.searchValue" clearable
placeholder="请输入搜索名称" maxlength="32" show-word-limit/> placeholder="请输入搜索名称" maxlength="32" show-word-limit/>
</el-form-item> </el-form-item>

View File

@@ -1,274 +1,289 @@
<template> <template>
<div class="default-main online"> <div class="default-main online">
<div class="online_header"> <div class="online_header">
<TableHeader date-picker area ref="tableHeaderRef"> <TableHeader date-picker area ref="tableHeaderRef">
<template #select> <template #select>
<el-form-item label="统计类型:"> <el-form-item label="统计类型">
<el-select <el-select
v-model="tableStore.table.params.statisticalType" v-model="tableStore.table.params.statisticalType"
placeholder="请选择统计类型" placeholder="请选择统计类型"
value-key="id" value-key="id"
style="width: 100%" style="width: 100%"
> >
<el-option <el-option
v-for="item in classificationData" v-for="item in classificationData"
:key="item.id" :key="item.id"
:label="item.name" :label="item.name"
:value="item" :value="item"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="电压等级:"> <el-form-item label="电压等级">
<el-select <el-select
v-model="tableStore.table.params.scale" v-model="tableStore.table.params.scale"
multiple multiple
collapse-tags collapse-tags
clearable clearable
placeholder="请选择电压等级" placeholder="请选择电压等级"
style="width: 100%" style="width: 100%"
value-key="id" value-key="id"
> >
<el-option <el-option
v-for="item in voltageleveloption" v-for="item in voltageleveloption"
:key="item.id" :key="item.id"
:label="item.name" :label="item.name"
:value="item" :value="item"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="电网标识"> <el-form-item label="电网标识">
<el-select <el-select
v-model="tableStore.table.params.powerFlag" v-model="tableStore.table.params.powerFlag"
clearable clearable
style="width: 100%" style="width: 100%"
placeholder="请选择电网标识" placeholder="请选择电网标识"
> >
<el-option <el-option
v-for="item in powerFlagList" v-for="item in powerFlagList"
:key="item.id" :key="item.id"
:label="item.name" :label="item.name"
:value="item.algoDescribe" :value="item.algoDescribe"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="终端厂家:"> <el-form-item label="终端厂家">
<el-select <el-select
v-model="tableStore.table.params.manufacturer" v-model="tableStore.table.params.manufacturer"
multiple multiple
collapse-tags collapse-tags
clearable clearable
placeholder="请选择终端厂家" placeholder="请选择终端厂家"
style="width: 100%" style="width: 100%"
value-key="id" value-key="id"
> >
<el-option <el-option
v-for="(item, index) in terminaloption" v-for="(item, index) in terminaloption"
:key="index" :key="index"
:label="item.name" :label="item.name"
:value="item" :value="item"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="干扰源类型:"> <el-form-item label="干扰源类型:">
<el-select <el-select
v-model="tableStore.table.params.loadType" v-model="tableStore.table.params.loadType"
multiple multiple
collapse-tags collapse-tags
clearable clearable
placeholder="请选择干扰源类型" placeholder="请选择干扰源类型"
style="width: 100%" style="width: 100%"
value-key="id" value-key="id"
> >
<el-option <el-option
v-for="(item, index) in interfereoption" v-for="(item, index) in interfereoption"
:key="index" :key="index"
:label="item.name" :label="item.name"
:value="item" :value="item"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
</template> <el-form-item label="筛选数据">
</TableHeader> <el-input
</div> v-model.trim="tableStore.table.params.searchValue"
<div class="online_main"> clearable
<el-tabs v-model="activeName" type="border-card" @tab-click="handleClick"> style="width: 200px"
<el-tab-pane :name="0" :lazy="true" label="稳态指标符合性占比表格"> placeholder="请输入关键字筛选"
<Table />
ref="tableRef" </el-form-item>
:tree-config="{ transform: true, parentField: 'uPid', rowField: 'uId' }" </template>
:scroll-y="{ enabled: true }" </TableHeader>
v-if="activeName == 0" </div>
/> <div class="online_main">
</el-tab-pane> <el-tabs v-model="activeName" type="border-card" @tab-click="handleClick">
<el-tab-pane :name="1" :lazy="true" label="稳态指标符合性占比"> <el-tab-pane :name="0" :lazy="true" label="稳态指标符合性占比表格">
<charts v-if="activeName == 1" ref="chartsRef" /> <Table
</el-tab-pane> ref="tableRef"
</el-tabs> :tree-config="{ transform: true, parentField: 'uPid', rowField: 'uId' }"
</div> :scroll-y="{ enabled: true }"
</div> v-if="activeName == 0"
</template> />
<script lang="ts" setup> </el-tab-pane>
import { ref, onMounted, watch } from 'vue' <el-tab-pane :name="1" :lazy="true" label="稳态指标符合性占比图">
import { useDictData } from '@/stores/dictData' <charts v-if="activeName == 1" ref="chartsRef" />
import DatePicker from '@/components/form/datePicker/index.vue' </el-tab-pane>
import { getAreaDept } from '@/api/harmonic-boot/area' </el-tabs>
import TableHeader from '@/components/table/header/index.vue' </div>
import TableStore from '@/utils/tableStore' </div>
import Table from '@/components/table/index.vue' </template>
import charts from './components/charts.vue' <script lang="ts" setup>
defineOptions({ import { ref, onMounted, watch } from 'vue'
name: 'harmonic-boot/area/SteadyState' import { useDictData } from '@/stores/dictData'
}) import DatePicker from '@/components/form/datePicker/index.vue'
const tableRef = ref() import { getAreaDept } from '@/api/harmonic-boot/area'
const onlineChartsRef = ref() import TableHeader from '@/components/table/header/index.vue'
const dictData = useDictData() import TableStore from '@/utils/tableStore'
//字典获取电压等级 import Table from '@/components/table/index.vue'
const voltageleveloption = dictData.getBasicData('Dev_Voltage_Stand') import charts from './components/charts.vue'
//字典获取终端厂家 import { filterTree } from '@/utils/tree'
const terminaloption = dictData.getBasicData('Dev_Manufacturers') defineOptions({
//字典获取干扰源类型 name: 'harmonic-boot/area/SteadyState'
const interfereoption = dictData.getBasicData('Interference_Source') })
//字典获取统计类型 const tableRef = ref()
const classificationData = dictData.getBasicData('Statistical_Type', ['Report_Type']) const onlineChartsRef = ref()
//字典获取监督对象类型 const dictData = useDictData()
const powerFlagList = dictData.getBasicData('power_flag') //字典获取电压等级
//调用区域接口获取区域 const voltageleveloption = dictData.getBasicData('Dev_Voltage_Stand')
const treeData = ref([]) //字典获取终端厂家
const idArr = ref([]) const terminaloption = dictData.getBasicData('Dev_Manufacturers')
const activeName = ref(0) //字典获取干扰源类型
const getTreeData = async () => { const interfereoption = dictData.getBasicData('Interference_Source')
await getAreaDept().then(res => { //字典获取统计类型
var data = res.data const classificationData = dictData.getBasicData('Statistical_Type', ['Report_Type'])
data.forEach(element => { //字典获取监督对象类型
idArr.value.push(element.id) const powerFlagList = dictData.getBasicData('power_flag')
}) //调用区域接口获取区域
treeData.value = JSON.parse(JSON.stringify(res.data)) const treeData = ref([])
}) const idArr = ref([])
} const activeName = ref(0)
getTreeData() const getTreeData = async () => {
await getAreaDept().then(res => {
const chartsRef = ref() var data = res.data
const handleClick = (tab: any, e: any) => { data.forEach(element => {
// console.log(tab,e,"??????????"); idArr.value.push(element.id)
// if(activeName.value===1){ })
tableStore.index() treeData.value = JSON.parse(JSON.stringify(res.data))
// } })
} }
getTreeData()
// const datePickerRef = ref()
const tableHeaderRef = ref() const chartsRef = ref()
const tableStore = new TableStore({ const handleClick = (tab: any, e: any) => {
publicHeight: 60, // console.log(tab,e,"??????????");
showPage: false, // if(activeName.value===1){
url: '/harmonic-boot/steadyExceedRate/getSteadyExceedRateData', tableStore.index()
method: 'POST', // }
column: [ }
{
title: '', // const datePickerRef = ref()
field: 'name', const tableHeaderRef = ref()
align: 'left', const tableStore = new TableStore({
treeNode: true, publicHeight: 60,
width: 350 showPage: false,
}, url: '/harmonic-boot/steadyExceedRate/getSteadyExceedRateData',
{ method: 'POST',
title: '电压等级', column: [
field: 'voltageLevel', {
title: '',
formatter: function (row) { field: 'name',
return row.cellValue ? row.cellValue : '/' align: 'left',
} treeNode: true,
}, width: 350
{ },
title: '厂家', {
field: 'factoryName', title: '电压等级',
field: 'voltageLevel',
formatter: function (row) {
return row.cellValue ? row.cellValue : '/' formatter: function (row) {
} return row.cellValue ? row.cellValue : '/'
}, }
{ },
title: '网络参数', {
field: 'networkParam', title: '厂家',
field: 'factoryName',
formatter: function (row) {
return row.cellValue ? row.cellValue : '/' formatter: function (row) {
} return row.cellValue ? row.cellValue : '/'
}, }
{ },
title: '监测点名称', {
field: 'lineName', title: '网络参数',
field: 'networkParam',
formatter: function (row) {
return row.cellValue ? row.cellValue : '/' formatter: function (row) {
} return row.cellValue ? row.cellValue : '/'
}, }
{ },
title: '符合性占比(%)', {
field: 'steadyExceedRate', title: '监测点名称',
field: 'lineName',
formatter: function (row) {
return row.cellValue == 3.14159 ? '暂无数据' : row.cellValue formatter: function (row) {
} return row.cellValue ? row.cellValue : '/'
} }
], },
{
loadCallback: () => { title: '符合性占比(%)',
tableStore.table.data = tree2List(tableStore.table.data, Math.random() * 1000) field: 'steadyExceedRate',
tableStore.table.column[0].title = tableStore.table.params.statisticalType.name
formatter: function (row) {
chartsRef.value && chartsRef.value.getTableStoreParams(tableStore.table.params) return row.cellValue == 3.14159 ? '暂无数据' : row.cellValue
setTimeout(() => { }
activeName.value == 0 && tableRef.value && tableRef.value.getRef().setAllTreeExpand(true) }
}, 0) ],
}
}) loadCallback: () => {
tableStore.table.data = tree2List(
tableStore.table.params.statisticalType = classificationData[0] filterTree(tableStore.table.data, node => {
tableStore.table.params.scale = [] return node.name.includes(tableStore.table.params.searchValue)
tableStore.table.params.manufacturer = [] }),
tableStore.table.params.loadType = [] Math.random() * 1000
tableStore.table.params.powerFlag = 2 )
tableStore.table.params.serverName = 'harmonicBoot' tableStore.table.column[0].title = tableStore.table.params.statisticalType.name
provide('tableStore', tableStore)
const tree2List = (list: any, id?: string) => { chartsRef.value && chartsRef.value.getTableStoreParams(tableStore.table.params)
//存储结果的数组 setTimeout(() => {
let arr: any = [] activeName.value == 0 && tableRef.value && tableRef.value.getRef().setAllTreeExpand(true)
// 遍历 tree 数组 }, 0)
list.forEach((item: any) => { }
item.uPid = id })
item.uId = Math.random() * 1000
item.valueOver == 3.14159 ? 0 : item.valueOver >= 90 ? 1 : item.valueOver && item.valueOver < 90 ? 2 : 3 tableStore.table.params.statisticalType = classificationData[0]
// 判断item是否存在children tableStore.table.params.scale = []
if (!item.children) return arr.push(item) tableStore.table.params.manufacturer = []
// 函数递归对children数组进行tree2List的转换 tableStore.table.params.loadType = []
const children = tree2List(item.children, item.uId) tableStore.table.params.powerFlag = 2
// 删除item的children属性 tableStore.table.params.serverName = 'harmonicBoot'
delete item.children tableStore.table.params.searchValue = ''
// 把item和children数组添加至结果数组 provide('tableStore', tableStore)
//..children: 意思是把children数组展开 const tree2List = (list: any, id?: string) => {
arr.push(item, ...children) //存储结果的数组
}) let arr: any = []
// 返回结果数组 // 遍历 tree 数组
return arr list.forEach((item: any) => {
} item.uPid = id
item.uId = Math.random() * 1000
onMounted(() => { item.valueOver == 3.14159 ? 0 : item.valueOver >= 90 ? 1 : item.valueOver && item.valueOver < 90 ? 2 : 3
tableStore.index() // 判断item是否存在children
}) if (!item.children) return arr.push(item)
</script> // 函数递归对children数组进行tree2List的转换
<style lang="scss" scoped> const children = tree2List(item.children, item.uId)
// .online { // 删除item的children属性
// width: 100%; delete item.children
// height: 100%; // 把item和children数组添加至结果数组
// .online_header { //..children: 意思是把children数组展开
// width: 100%; arr.push(item, ...children)
// max-height: 140px; })
// padding: 10px; // 返回结果数组
// box-sizing: border-box; return arr
// } }
// .online_main {
// padding: 0 10px; onMounted(() => {
// } tableStore.index()
// } })
</style> </script>
<style lang="scss" scoped>
// .online {
// width: 100%;
// height: 100%;
// .online_header {
// width: 100%;
// max-height: 140px;
// padding: 10px;
// box-sizing: border-box;
// }
// .online_main {
// padding: 0 10px;
// }
// }
</style>

View File

@@ -6,7 +6,7 @@
<el-form-item label="筛选数据"> <el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.searchValue" placeholder="输入关键字筛选" clearable maxlength="32" show-word-limit/> <el-input v-model="tableStore.table.params.searchValue" placeholder="输入关键字筛选" clearable maxlength="32" show-word-limit/>
</el-form-item> </el-form-item>
<el-form-item label="统计类型:"> <el-form-item label="统计类型">
<el-select <el-select
v-model="tableStore.table.params.statisticalType" v-model="tableStore.table.params.statisticalType"
value-key="id" value-key="id"
@@ -21,7 +21,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="电压等级:"> <el-form-item label="电压等级">
<el-select <el-select
v-model="tableStore.table.params.scale" v-model="tableStore.table.params.scale"
multiple multiple
@@ -38,7 +38,7 @@
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="终端厂家:"> <el-form-item label="终端厂家">
<el-select <el-select
v-model="tableStore.table.params.manufacturer" v-model="tableStore.table.params.manufacturer"
multiple multiple
@@ -55,7 +55,7 @@
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="干扰源类型:"> <el-form-item label="干扰源类型">
<el-select <el-select
v-model="tableStore.table.params.loadType" v-model="tableStore.table.params.loadType"
multiple multiple
@@ -129,14 +129,22 @@ const tableStore = new TableStore({
{ field: 'subName', title: '变电站', minWidth: '150' }, { field: 'subName', title: '变电站', minWidth: '150' },
{ field: 'ip', title: '网络参数' ,width:'120px' }, { field: 'ip', title: '网络参数' ,width:'120px' },
{ field: 'scale', title: '电压等级', minWidth: '110' }, { field: 'scale', title: '电压等级', minWidth: '110' },
// { {
// field: 'advanceType', field: 'advanceType',
// title: '触发类型', title: '暂降类型',
// minWidth: '90', minWidth: '90',
// formatter: (row: any) => { formatter: (row: any) => {
// return row.cellValue || '其他' return row.cellValue || '其他'
// } }
// }, },
{
field: 'eventType',
title: '触发类型',
minWidth: '120',
formatter: (row: any) => {
return eventList.filter(item => item.id === row.cellValue)[0]?.name
}
},
{ {
field: 'advanceReason', field: 'advanceReason',
title: '暂降原因', title: '暂降原因',
@@ -145,14 +153,7 @@ const tableStore = new TableStore({
return row.cellValue || '其他' return row.cellValue || '其他'
} }
}, },
{
field: 'eventType',
title: '触发类型',
minWidth: '120',
formatter: (row: any) => {
return eventList.filter(item => item.id === row.cellValue)[0]?.name
}
},
// { // {
// field: 'severity', title: '严重度', minWidth: "80", formatter: (row: any) => { // field: 'severity', title: '严重度', minWidth: "80", formatter: (row: any) => {
// return row.cellValue.toFixed(2) // return row.cellValue.toFixed(2)

View File

@@ -3,14 +3,14 @@
<div class="online_header"> <div class="online_header">
<TableHeader date-picker ref="tableHeaderRef"> <TableHeader date-picker ref="tableHeaderRef">
<template #select> <template #select>
<el-form-item label="统计类型:"> <el-form-item label="统计类型">
<el-select v-model="formData.statisticalType" placeholder="请选择统计类型" value-key="id" <el-select v-model="formData.statisticalType" placeholder="请选择统计类型" value-key="id"
style="width: 100%"> style="width: 100%">
<el-option v-for="item in classificationData" :key="item.id" :label="item.name" <el-option v-for="item in classificationData" :key="item.id" :label="item.name"
:value="item"></el-option> :value="item"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="区域选择:"> <el-form-item label="区域选择">
<!-- <el-select ref="select1" v-model="deptName" placeholder="请选择所属部门区域" style="width: 100%"> <!-- <el-select ref="select1" v-model="deptName" placeholder="请选择所属部门区域" style="width: 100%">
<el-option :value="formData.deptIndex" style="height: auto"> --> <el-option :value="formData.deptIndex" style="height: auto"> -->
<!-- {{ formData.deptIndex }} --> <!-- {{ formData.deptIndex }} -->
@@ -33,27 +33,30 @@
<!-- </el-option> <!-- </el-option>
</el-select> --> </el-select> -->
</el-form-item> </el-form-item>
<el-form-item label="电压等级:"> <el-form-item label="电压等级">
<el-select v-model="formData.scale" multiple collapse-tags clearable placeholder="请选择电压等级" <el-select v-model="formData.scale" multiple collapse-tags clearable placeholder="请选择电压等级"
style="width: 100%" value-key="id"> style="width: 100%" value-key="id">
<el-option v-for="item in voltageleveloption" :key="item.id" :label="item.name" <el-option v-for="item in voltageleveloption" :key="item.id" :label="item.name"
:value="item"></el-option> :value="item"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="终端厂家:"> <el-form-item label="终端厂家">
<el-select v-model="formData.manufacturer" multiple collapse-tags clearable <el-select v-model="formData.manufacturer" multiple collapse-tags clearable
placeholder="请选择终端厂家" style="width: 100%" value-key="id"> placeholder="请选择终端厂家" style="width: 100%" value-key="id">
<el-option v-for="(item, index) in terminaloption" :key="index" :label="item.name" <el-option v-for="(item, index) in terminaloption" :key="index" :label="item.name"
:value="item"></el-option> :value="item"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="干扰源类型:"> <el-form-item label="干扰源类型">
<el-select v-model="formData.loadType" multiple collapse-tags clearable placeholder="请选择干扰源类型" <el-select v-model="formData.loadType" multiple collapse-tags clearable placeholder="请选择干扰源类型"
style="width: 100%" value-key="id"> style="width: 100%" value-key="id">
<el-option v-for="(item, index) in interfereoption" :key="index" :label="item.name" <el-option v-for="(item, index) in interfereoption" :key="index" :label="item.name"
:value="item"></el-option> :value="item"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.searchValue" clearable placeholder="请输入关键字"></el-input>
</el-form-item>
</template> </template>
<template #operation> <template #operation>
<el-button type="primary" icon="el-icon-Tickets" @click="makeUp" v-if="!VITE_FLAG">补招</el-button> <el-button type="primary" icon="el-icon-Tickets" @click="makeUp" v-if="!VITE_FLAG">补招</el-button>
@@ -285,7 +288,7 @@ const tableStore = new TableStore({
// tableStore.table.params.searchEndTime = tableHeaderRef.value.datePickerRef.timeValue[1] // tableStore.table.params.searchEndTime = tableHeaderRef.value.datePickerRef.timeValue[1]
}, },
loadCallback: () => { loadCallback: () => {
tableStore.table.data = tree2List(tableStore.table.data, Math.random() * 1000) tableStore.table.data = tree2List(filterTreeByKeyword( tableStore.table.data,tableStore.table.params.searchValue), Math.random() * 1000)
tableStore.table.column[0].title = formData.value.statisticalType.name tableStore.table.column[0].title = formData.value.statisticalType.name
chartsRef.value && chartsRef.value.getTableStoreParams(tableStore.table.params) chartsRef.value && chartsRef.value.getTableStoreParams(tableStore.table.params)
@@ -305,6 +308,7 @@ const tableStore = new TableStore({
tableStore.table.params.deptIndex = '' tableStore.table.params.deptIndex = ''
tableStore.table.params.filterName = '' tableStore.table.params.filterName = ''
tableStore.table.params.searchValue = ''
tableStore.table.params.statisticalType = [] tableStore.table.params.statisticalType = []
tableStore.table.params.scale = [] tableStore.table.params.scale = []
tableStore.table.params.manufacturer = [] tableStore.table.params.manufacturer = []
@@ -339,6 +343,78 @@ const tree2List = (list: any, id?: string) => {
return arr return arr
} }
/**
* 树形结构按名称筛选:保留匹配节点+所有上级+所有下级,保持原树形层级
* @param {Array} treeData - 原始嵌套树形数据(根节点数组)
* @param {string} keyword - 筛选关键词name包含该关键词即匹配
* @returns {Array} 筛选后的嵌套树形数据,保持原层级
*/
function filterTreeByKeyword(treeData, keyword) {
// 关键词为空,直接返回原树(深拷贝,避免修改原数据)
if (!keyword || keyword.trim() === '') {
return JSON.parse(JSON.stringify(treeData));
}
const targetKey = keyword.trim();
// 存储需要保留的节点ID匹配节点+所有上级+所有下级)
const keepIdSet = new Set();
// 第一步递归遍历树形标记所有需要保留的节点ID
const markKeepNodes = (node, parentNodes = []) => {
// 1. 若当前节点名称包含关键词,标记自身+所有上级+所有下级
const isMatch = node.name && node.name.includes(targetKey);
if (isMatch) {
// 标记自身
keepIdSet.add(node.id);
// 标记所有上级父节点
parentNodes.forEach(pNode => keepIdSet.add(pNode.id));
// 标记所有下级子节点(递归)
const markChildren = (childNode) => {
keepIdSet.add(childNode.id);
if (childNode.children && childNode.children.length) {
childNode.children.forEach(markChildren);
}
};
if (node.children && node.children.length) {
node.children.forEach(markChildren);
}
}
// 2. 递归遍历子节点传递当前节点的上级链parentNodes + 当前节点)
if (node.children && node.children.length) {
node.children.forEach(child => markKeepNodes(child, [...parentNodes, node]));
}
};
// 遍历根节点,开始标记
treeData.forEach(rootNode => markKeepNodes(rootNode));
// 第二步:递归重构树形,只保留标记过的节点,保持层级
const rebuildTree = (node) => {
// 若当前节点无需保留直接返回null
if (!keepIdSet.has(node.id)) {
return null;
}
// 深拷贝当前节点,避免修改原数据
const newNode = { ...node };
// 递归处理子节点,过滤掉无需保留的,只保留有效子节点
if (newNode.children && newNode.children.length) {
const newChildren = newNode.children.map(child => rebuildTree(child)).filter(Boolean);
newNode.children = newChildren;
} else {
newNode.children = [];
}
return newNode;
};
// 重构根节点过滤掉null的根节点
const filteredTree = treeData.map(rootNode => rebuildTree(rootNode)).filter(Boolean);
return filteredTree;
}
// 禁用超过当前日期的选择 // 禁用超过当前日期的选择
const disabledDate = (date: Date) => { const disabledDate = (date: Date) => {
return date > new Date() // 如果日期大于当前日期,则禁用 return date > new Date() // 如果日期大于当前日期,则禁用
@@ -351,7 +427,9 @@ const makeUp = () => {
tableRef.value tableRef.value
.getRef() .getRef()
.getCheckboxRecords() .getCheckboxRecords()
.find((item: any) => item.level == '6') || [] .filter((item: any) => item.level == '6') || []
if (list.length == 0) { if (list.length == 0) {
return ElMessage({ return ElMessage({
@@ -359,6 +437,16 @@ const makeUp = () => {
type: 'warning' type: 'warning'
}) })
} }
// 检查是否有 comFlag 等于 0 的项
const hasOfflineDevice = list.some((item: any) => item.comFlag === 0)
if (hasOfflineDevice) {
return ElMessage({
message: '请选择在线监测点进行补招',
type: 'warning'
})
}
timeData.value = [] timeData.value = []
timePopUp.value = true timePopUp.value = true
} }
@@ -385,7 +473,7 @@ const makeUpSubmit = () => {
logPopUp.value = true logPopUp.value = true
} }
const socket = async (form: any) => { const socket = async (form: any) => {
const url = (localStorage.getItem('WebSocketUrl2') || 'ws://192.168.1.67:10405/api/recell/') const url = (localStorage.getItem('WebSocketUrl2') || 'null')//'ws://192.168.1.67:10405/api/recell/')
logList.value = [] logList.value = []
await dataSocket.socketServe.connect(`${url}${adminInfo.id}`) await dataSocket.socketServe.connect(`${url}${adminInfo.id}`)
await dataSocket.socketServe.send(form) await dataSocket.socketServe.send(form)

View File

@@ -1,259 +1,275 @@
<template> <template>
<div class="default-main online"> <div class="default-main online">
<div class="online_header"> <div class="online_header">
<TableHeader date-picker area ref="tableHeaderRef"> <TableHeader date-picker area ref="tableHeaderRef">
<template #select> <template #select>
<el-form-item label="统计类型:"> <el-form-item label="统计类型">
<el-select <el-select
v-model="tableStore.table.params.statisticalType" v-model="tableStore.table.params.statisticalType"
placeholder="请选择统计类型" placeholder="请选择统计类型"
value-key="id" value-key="id"
style="width: 100%" style="width: 100%"
> >
<el-option <el-option
v-for="item in classificationData" v-for="item in classificationData"
:key="item.id" :key="item.id"
:label="item.name" :label="item.name"
:value="item" :value="item"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="电压等级:"> <el-form-item label="电压等级">
<el-select <el-select
v-model="tableStore.table.params.scale" v-model="tableStore.table.params.scale"
multiple multiple
collapse-tags collapse-tags
clearable clearable
placeholder="请选择电压等级" placeholder="请选择电压等级"
style="width: 100%" style="width: 100%"
value-key="id" value-key="id"
> >
<el-option <el-option
v-for="item in voltageleveloption" v-for="item in voltageleveloption"
:key="item.id" :key="item.id"
:label="item.name" :label="item.name"
:value="item" :value="item"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="终端厂家:"> <el-form-item label="终端厂家">
<el-select <el-select
v-model="tableStore.table.params.manufacturer" v-model="tableStore.table.params.manufacturer"
multiple multiple
collapse-tags collapse-tags
clearable clearable
placeholder="请选择终端厂家" placeholder="请选择终端厂家"
style="width: 100%" style="width: 100%"
value-key="id" value-key="id"
> >
<el-option <el-option
v-for="(item, index) in terminaloption" v-for="(item, index) in terminaloption"
:key="index" :key="index"
:label="item.name" :label="item.name"
:value="item" :value="item"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="干扰源类型:"> <el-form-item label="干扰源类型">
<el-select <el-select
v-model="tableStore.table.params.loadType" v-model="tableStore.table.params.loadType"
multiple multiple
collapse-tags collapse-tags
clearable clearable
placeholder="请选择干扰源类型" placeholder="请选择干扰源类型"
style="width: 100%" style="width: 100%"
value-key="id" value-key="id"
> >
<el-option <el-option
v-for="(item, index) in interfereoption" v-for="(item, index) in interfereoption"
:key="index" :key="index"
:label="item.name" :label="item.name"
:value="item" :value="item"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="电网标志"> <el-form-item label="电网标志">
<el-select v-model="tableStore.table.params.powerFlag" placeholder="请选择电网标志"> <el-select v-model="tableStore.table.params.powerFlag" placeholder="请选择电网标志">
<el-option <el-option
v-for="item in sign" v-for="item in sign"
:key="item.id" :key="item.id"
:label="item.name" :label="item.name"
:value="item.algoDescribe" :value="item.algoDescribe"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
</template> <el-form-item label="筛选数据">
</TableHeader> <el-input
</div> v-model.trim="tableStore.table.params.searchValue"
<div class="online_main"> clearable
<el-tabs v-model="activeName" type="border-card" @tab-click="handleClick"> style="width: 200px"
<el-tab-pane :name="0" :lazy="true" label="谐波畸变率统计表"> placeholder="请输入关键字筛选"
<Table />
ref="tableRef" </el-form-item>
:tree-config="{ transform: true, parentField: 'uPid', rowField: 'uId' }" </template>
:scroll-y="{ enabled: true }" </TableHeader>
v-if="activeName == 0" </div>
/> <div class="online_main">
</el-tab-pane> <el-tabs v-model="activeName" type="border-card" @tab-click="handleClick">
<el-tab-pane :name="1" :lazy="true" label="谐波畸变率统计"> <el-tab-pane :name="0" :lazy="true" label="谐波畸变率统计">
<charts v-if="activeName == 1" ref="chartsRef" /> <Table
</el-tab-pane> ref="tableRef"
</el-tabs> :tree-config="{ transform: true, parentField: 'uPid', rowField: 'uId' }"
</div> :scroll-y="{ enabled: true }"
</div> v-if="activeName == 0"
</template> />
<script lang="ts" setup> </el-tab-pane>
import { ref, onMounted, watch } from 'vue' <el-tab-pane :name="1" :lazy="true" label="谐波畸变率统计图">
import { useDictData } from '@/stores/dictData' <charts v-if="activeName == 1" ref="chartsRef" />
import DatePicker from '@/components/form/datePicker/index.vue' </el-tab-pane>
import { getAreaDept } from '@/api/harmonic-boot/area' </el-tabs>
import TableHeader from '@/components/table/header/index.vue' </div>
import TableStore from '@/utils/tableStore' </div>
import Table from '@/components/table/index.vue' </template>
import charts from './components/charts.vue' <script lang="ts" setup>
defineOptions({ import { ref, onMounted, watch } from 'vue'
name: 'harmonic-boot/area/harmonicDistortionRate' import { useDictData } from '@/stores/dictData'
}) import DatePicker from '@/components/form/datePicker/index.vue'
const tableRef = ref() import { getAreaDept } from '@/api/harmonic-boot/area'
const onlineChartsRef = ref() import TableHeader from '@/components/table/header/index.vue'
const dictData = useDictData() import TableStore from '@/utils/tableStore'
//字典获取电压等级 import Table from '@/components/table/index.vue'
const voltageleveloption = dictData.getBasicData('Dev_Voltage_Stand') import charts from './components/charts.vue'
//字典获取终端厂家 import { filterTree } from '@/utils/tree'
const terminaloption = dictData.getBasicData('Dev_Manufacturers') defineOptions({
//字典获取干扰源类型 name: 'harmonic-boot/area/harmonicDistortionRate'
const interfereoption = dictData.getBasicData('Interference_Source') })
//字典获取统计类型 const tableRef = ref()
const classificationData = dictData.getBasicData('Statistical_Type', ['Report_Type']) const onlineChartsRef = ref()
//调用区域接口获取区域 const dictData = useDictData()
const sign = dictData.getBasicData('power_flag') //字典获取电压等级
const treeData = ref([]) const voltageleveloption = dictData.getBasicData('Dev_Voltage_Stand')
const idArr = ref([]) //字典获取终端厂家
const activeName = ref(0) const terminaloption = dictData.getBasicData('Dev_Manufacturers')
const getTreeData = async () => { //字典获取干扰源类型
await getAreaDept().then(res => { const interfereoption = dictData.getBasicData('Interference_Source')
var data = res.data //字典获取统计类型
data.forEach(element => { const classificationData = dictData.getBasicData('Statistical_Type', ['Report_Type'])
idArr.value.push(element.id) //调用区域接口获取区域
}) const sign = dictData.getBasicData('power_flag')
treeData.value = JSON.parse(JSON.stringify(res.data)) const treeData = ref([])
}) const idArr = ref([])
} const activeName = ref(0)
getTreeData() const getTreeData = async () => {
await getAreaDept().then(res => {
const chartsRef = ref() var data = res.data
const handleClick = (tab: any, e: any) => { data.forEach(element => {
// console.log(tab,e,"??????????"); idArr.value.push(element.id)
// if(activeName.value===1){ })
tableStore.index() treeData.value = JSON.parse(JSON.stringify(res.data))
// } })
} }
getTreeData()
// const datePickerRef = ref()
const tableHeaderRef = ref() const chartsRef = ref()
const tableStore = new TableStore({ const handleClick = (tab: any, e: any) => {
publicHeight: 60, // console.log(tab,e,"??????????");
showPage: false, // if(activeName.value===1){
url: '/harmonic-boot/tHDistortion/getTHDistortionData', tableStore.index()
method: 'POST', // }
column: [ }
{
title: '', // const datePickerRef = ref()
field: 'name', const tableHeaderRef = ref()
align: 'left', const tableStore = new TableStore({
treeNode: true, publicHeight: 60,
width: 350 showPage: false,
}, url: '/harmonic-boot/tHDistortion/getTHDistortionData',
{ method: 'POST',
title: '电压等级', column: [
field: 'voltageLevel', {
align: 'center', title: '',
formatter: function (row) { field: 'name',
return row.cellValue ? row.cellValue : '/' align: 'left',
} treeNode: true,
}, width: 350
{ },
title: '网络参数', {
field: 'networkParam', title: '电压等级',
align: 'center', field: 'voltageLevel',
formatter: function (row) { align: 'center',
return row.cellValue ? row.cellValue : '/' formatter: function (row) {
} return row.cellValue ? row.cellValue : '/'
}, }
{ },
title: '监测点名称', {
field: 'lineName', title: '网络参数',
align: 'center', field: 'networkParam',
formatter: function (row) { align: 'center',
return row.cellValue ? row.cellValue : '/' formatter: function (row) {
} return row.cellValue ? row.cellValue : '/'
}, }
{ },
title: '总谐波畸变率(%)', {
field: 'distortion', title: '监测点名称',
align: 'center', field: 'lineName',
formatter: function (row) { align: 'center',
return row.cellValue == 3.14159 ? '暂无数据' : row.cellValue formatter: function (row) {
} return row.cellValue ? row.cellValue : '/'
} }
], },
{
loadCallback: () => { title: '总谐波畸变率(%)',
tableStore.table.data = tree2List(tableStore.table.data, Math.random() * 1000) field: 'distortion',
tableStore.table.column[0].title = tableStore.table.params.statisticalType.name align: 'center',
chartsRef.value && chartsRef.value.getTableStoreParams(tableStore.table.params) formatter: function (row) {
setTimeout(() => { return row.cellValue == 3.14159 ? '暂无数据' : row.cellValue
activeName.value == 0 && tableRef.value && tableRef.value.getRef().setAllTreeExpand(true) }
}, 0) }
} ],
})
loadCallback: () => {
tableStore.table.params.statisticalType = classificationData[0] tableStore.table.data = tree2List(
tableStore.table.params.scale = [] filterTree(tableStore.table.data, node => {
tableStore.table.params.manufacturer = [] // 筛选条件name 包含关键词
tableStore.table.params.loadType = [] return node.name.includes(tableStore.table.params.searchValue)
tableStore.table.params.powerFlag = sign[0]?.algoDescribe || 0 }),
tableStore.table.params.serverName = 'harmonicBoot' Math.random() * 1000
provide('tableStore', tableStore) )
const tree2List = (list: any, id?: string) => { tableStore.table.column[0].title = tableStore.table.params.statisticalType.name
//存储结果的数组 chartsRef.value && chartsRef.value.getTableStoreParams(tableStore.table.params)
let arr: any = [] setTimeout(() => {
// 遍历 tree 数组 activeName.value == 0 && tableRef.value && tableRef.value.getRef().setAllTreeExpand(true)
list.forEach((item: any) => { }, 0)
item.uPid = id }
item.uId = Math.random() * 1000 })
item.valueOver == 3.14159 ? 0 : item.valueOver >= 90 ? 1 : item.valueOver && item.valueOver < 90 ? 2 : 3
// 判断item是否存在children tableStore.table.params.statisticalType = classificationData[0]
if (!item.children) return arr.push(item) tableStore.table.params.scale = []
// 函数递归对children数组进行tree2List的转换 tableStore.table.params.manufacturer = []
const children = tree2List(item.children, item.uId) tableStore.table.params.loadType = []
// 删除item的children属性 tableStore.table.params.powerFlag = sign[0]?.algoDescribe || 0
delete item.children tableStore.table.params.serverName = 'harmonicBoot'
// 把item和children数组添加至结果数组 tableStore.table.params.searchValue = ''
//..children: 意思是把children数组展开 provide('tableStore', tableStore)
arr.push(item, ...children) const tree2List = (list: any, id?: string) => {
}) //存储结果的数组
// 返回结果数组 let arr: any = []
return arr // 遍历 tree 数组
} list.forEach((item: any) => {
item.uPid = id
onMounted(() => { item.uId = Math.random() * 1000
tableStore.index() item.valueOver == 3.14159 ? 0 : item.valueOver >= 90 ? 1 : item.valueOver && item.valueOver < 90 ? 2 : 3
}) // 判断item是否存在children
</script> if (!item.children) return arr.push(item)
<style lang="scss" scoped> // 函数递归对children数组进行tree2List的转换
// .online { const children = tree2List(item.children, item.uId)
// width: 100%; // 删除item的children属性
// height: 100%; delete item.children
// .online_header { // 把item和children数组添加至结果数组
// width: 100%; //..children: 意思是把children数组展开
// max-height: 140px; arr.push(item, ...children)
// padding: 10px; })
// box-sizing: border-box; // 返回结果数组
// } return arr
// .online_main { }
// padding: 0 10px;
// } onMounted(() => {
// } tableStore.index()
</style> })
</script>
<style lang="scss" scoped>
// .online {
// width: 100%;
// height: 100%;
// .online_header {
// width: 100%;
// max-height: 140px;
// padding: 10px;
// box-sizing: border-box;
// }
// .online_main {
// padding: 0 10px;
// }
// }
</style>

View File

@@ -2,7 +2,7 @@
<div class="default-main"> <div class="default-main">
<TableHeader date-picker area showExport> <TableHeader date-picker area showExport>
<template #select> <template #select>
<el-form-item label="统计类型:" v-if="false"> <el-form-item label="统计类型" v-if="false">
<el-select <el-select
v-model="tableStore.table.params.statisticalType" v-model="tableStore.table.params.statisticalType"
placeholder="请选择统计类型" placeholder="请选择统计类型"
@@ -18,7 +18,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="电压等级:" v-if="false"> <el-form-item label="电压等级" v-if="false">
<el-select <el-select
v-model="tableStore.table.params.scale" v-model="tableStore.table.params.scale"
multiple multiple
@@ -36,7 +36,7 @@
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="终端厂家:" v-if="false"> <el-form-item label="终端厂家" v-if="false">
<el-select <el-select
v-model="tableStore.table.params.manufacturer" v-model="tableStore.table.params.manufacturer"
multiple multiple
@@ -55,7 +55,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="干扰源类型:"> <el-form-item label="干扰源类型">
<el-select <el-select
v-model="tableStore.table.params.loadType" v-model="tableStore.table.params.loadType"
multiple multiple

View File

@@ -3,7 +3,7 @@
<div class="online_header"> <div class="online_header">
<TableHeader date-picker ref="tableHeaderRef"> <TableHeader date-picker ref="tableHeaderRef">
<template #select> <template #select>
<el-form-item label="统计类型:"> <el-form-item label="统计类型">
<el-select <el-select
v-model="formData.statisticalType" v-model="formData.statisticalType"
placeholder="请选择统计类型" placeholder="请选择统计类型"
@@ -18,7 +18,7 @@
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="区域选择:"> <el-form-item label="区域选择">
<!-- <el-select ref="select1" v-model="deptName" placeholder="请选择所属部门区域" style="width: 100%"> <!-- <el-select ref="select1" v-model="deptName" placeholder="请选择所属部门区域" style="width: 100%">
<el-option :value="formData.deptIndex" style="height: auto"> --> <el-option :value="formData.deptIndex" style="height: auto"> -->
<!-- {{ formData.deptIndex }} --> <!-- {{ formData.deptIndex }} -->
@@ -48,7 +48,7 @@
<!-- </el-option> <!-- </el-option>
</el-select> --> </el-select> -->
</el-form-item> </el-form-item>
<el-form-item label="电压等级:"> <el-form-item label="电压等级">
<el-select <el-select
v-model="formData.scale" v-model="formData.scale"
multiple multiple
@@ -66,7 +66,7 @@
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="终端厂家:"> <el-form-item label="终端厂家">
<el-select <el-select
v-model="formData.manufacturer" v-model="formData.manufacturer"
multiple multiple
@@ -84,7 +84,7 @@
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="干扰源类型:"> <el-form-item label="干扰源类型">
<el-select <el-select
v-model="formData.loadType" v-model="formData.loadType"
multiple multiple
@@ -102,6 +102,13 @@
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="筛选数据">
<el-input
v-model="tableStore.table.params.searchValue"
clearable
placeholder="请输入关键字"
></el-input>
</el-form-item>
</template> </template>
</TableHeader> </TableHeader>
</div> </div>
@@ -132,7 +139,6 @@ import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue' import Table from '@/components/table/index.vue'
import charts from './components/charts.vue' import charts from './components/charts.vue'
defineOptions({ defineOptions({
name: 'device-boot/getOnlineRateData' name: 'device-boot/getOnlineRateData'
}) })
@@ -153,7 +159,6 @@ const treeData = ref([])
const idArr = ref([]) const idArr = ref([])
const activeName = ref(0) const activeName = ref(0)
const getTreeData = async () => { const getTreeData = async () => {
await getAreaDept().then(res => { await getAreaDept().then(res => {
var data = res.data var data = res.data
data.forEach(element => { data.forEach(element => {
@@ -205,7 +210,8 @@ const tableStore = new TableStore({
{ {
title: '网络参数', title: '网络参数',
field: 'ip', field: 'ip',
align: 'center' ,width:'120px', align: 'center',
width: '120px',
formatter: function (row) { formatter: function (row) {
return row.cellValue ? row.cellValue : '/' return row.cellValue ? row.cellValue : '/'
} }
@@ -257,7 +263,7 @@ const tableStore = new TableStore({
formatter: function (row) { formatter: function (row) {
return row.cellValue == 3.14159 ? '暂无数据' : row.cellValue.toFixed(2) return row.cellValue == 3.14159 ? '暂无数据' : row.cellValue.toFixed(2)
} }
}, }
// { // {
// title: '评估', // title: '评估',
// field: 'valueOver', // field: 'valueOver',
@@ -299,23 +305,26 @@ const tableStore = new TableStore({
// let treeData = [] // let treeData = []
// treeData = tree2List(tableStore.table.data) // treeData = tree2List(tableStore.table.data)
// tableStore.table.data = JSON.parse(JSON.stringify(treeData)) // tableStore.table.data = JSON.parse(JSON.stringify(treeData))
tableStore.table.data = tree2List(tableStore.table.data, Math.random() * 1000) tableStore.table.data = tree2List(
filterTreeByKeyword(tableStore.table.data, tableStore.table.params.searchValue),
Math.random() * 1000
)
chartsRef.value && chartsRef.value.getTableStoreParams(tableStore.table.params) chartsRef.value && chartsRef.value.getTableStoreParams(tableStore.table.params)
setTimeout(() => { setTimeout(() => {
activeName.value == 0 && tableRef.value && tableRef.value.getRef().setAllTreeExpand(true) activeName.value == 0 && tableRef.value && tableRef.value.getRef().setAllTreeExpand(true)
}, 0) }, 0)
}, },
resetCallback: () => { resetCallback: () => {
// 重置表单数据到默认值 // 重置表单数据到默认值
formData.value.statisticalType = classificationData[0] formData.value.statisticalType = classificationData[0]
formData.value.deptIndex = treeData.value[0]?.id formData.value.deptIndex = treeData.value[0]?.id
formData.value.scale = voltageleveloption formData.value.scale = voltageleveloption
formData.value.manufacturer = terminaloption formData.value.manufacturer = terminaloption
formData.value.loadType = interfereoption formData.value.loadType = interfereoption
} }
}) })
tableStore.table.params.searchValue = ''
tableStore.table.params.deptIndex = '' tableStore.table.params.deptIndex = ''
tableStore.table.params.statisticalType = [] tableStore.table.params.statisticalType = []
tableStore.table.params.scale = [] tableStore.table.params.scale = []
@@ -342,7 +351,73 @@ const tree2List = (list: any, id?: string) => {
}) })
// 返回结果数组 // 返回结果数组
return arr return arr
}
/**
* 树形结构按名称筛选:保留匹配节点+所有上级+所有下级,保持原树形层级
* @param {Array} treeData - 原始嵌套树形数据(根节点数组)
* @param {string} keyword - 筛选关键词name包含该关键词即匹配
* @returns {Array} 筛选后的嵌套树形数据,保持原层级
*/
function filterTreeByKeyword(treeData, keyword) {
// 关键词为空,直接返回原树(深拷贝,避免修改原数据)
if (!keyword || keyword.trim() === '') {
return JSON.parse(JSON.stringify(treeData))
}
const targetKey = keyword.trim()
// 存储需要保留的节点ID匹配节点+所有上级+所有下级)
const keepIdSet = new Set()
// 第一步递归遍历树形标记所有需要保留的节点ID
const markKeepNodes = (node, parentNodes = []) => {
// 1. 若当前节点名称包含关键词,标记自身+所有上级+所有下级
const isMatch = node.name && node.name.includes(targetKey)
if (isMatch) {
// 标记自身
keepIdSet.add(node.id)
// 标记所有上级父节点
parentNodes.forEach(pNode => keepIdSet.add(pNode.id))
// 标记所有下级子节点(递归)
const markChildren = childNode => {
keepIdSet.add(childNode.id)
if (childNode.children && childNode.children.length) {
childNode.children.forEach(markChildren)
}
}
if (node.children && node.children.length) {
node.children.forEach(markChildren)
}
}
// 2. 递归遍历子节点传递当前节点的上级链parentNodes + 当前节点)
if (node.children && node.children.length) {
node.children.forEach(child => markKeepNodes(child, [...parentNodes, node]))
}
}
// 遍历根节点,开始标记
treeData.forEach(rootNode => markKeepNodes(rootNode))
// 第二步:递归重构树形,只保留标记过的节点,保持层级
const rebuildTree = node => {
// 若当前节点无需保留直接返回null
if (!keepIdSet.has(node.id)) {
return null
}
// 深拷贝当前节点,避免修改原数据
const newNode = { ...node }
// 递归处理子节点,过滤掉无需保留的,只保留有效子节点
if (newNode.children && newNode.children.length) {
const newChildren = newNode.children.map(child => rebuildTree(child)).filter(Boolean)
newNode.children = newChildren
} else {
newNode.children = []
}
return newNode
}
// 重构根节点过滤掉null的根节点
const filteredTree = treeData.map(rootNode => rebuildTree(rootNode)).filter(Boolean)
return filteredTree
} }
onMounted(() => {}) onMounted(() => {})

View File

@@ -1,305 +1,305 @@
<template> <template>
<div class="charts" style="position: relative; width: 100%"> <div class="charts" style="position: relative; width: 100%">
<div style="position: absolute; right: 60px; top: 5px; font-weight: bold"> <div style="position: absolute; right: 60px; top: 5px; font-weight: bold">
<el-tag <el-tag
style=" style="
background: #A52a2a; background: #A52a2a;
width: 30px; width: 30px;
height: 15px; height: 15px;
border: 1px solid #A52a2a; border: 1px solid #A52a2a;
float: left; float: left;
margin-top: 2px; margin-top: 2px;
" "
></el-tag> ></el-tag>
<span style="color: #A52a2a; font-weight: 400; float: left">&nbsp&nbsp在线<60% &nbsp&nbsp</span> <span style="color: #A52a2a; font-weight: 400; float: left">&nbsp&nbsp合格<60% &nbsp&nbsp</span>
<el-tag <el-tag
size="small" size="small"
style=" style="
background: #ffcc33; background: #ffcc33;
width: 30px; width: 30px;
height: 15px; height: 15px;
border: 1px solid #ffcc33; border: 1px solid #ffcc33;
float: left; float: left;
margin-top: 2px; margin-top: 2px;
" "
></el-tag> ></el-tag>
<span style="color: #ffcc33; font-weight: 400; float: left">&nbsp&nbsp60%在线<90% &nbsp&nbsp</span> <span style="color: #ffcc33; font-weight: 400; float: left">&nbsp&nbsp60%合格<90% &nbsp&nbsp</span>
<el-tag <el-tag
style=" style="
background: #339966; background: #339966;
width: 30px; width: 30px;
height: 15px; height: 15px;
border: 1px solid #339966; border: 1px solid #339966;
float: left; float: left;
margin-top: 2px; margin-top: 2px;
" "
></el-tag> ></el-tag>
<span style="color: #339966; font-weight: 400; float: left">&nbsp&nbsp在线90%</span> <span style="color: #339966; font-weight: 400; float: left">&nbsp&nbsp合格90%</span>
</div> </div>
<my-echart <my-echart
v-loading="loading" v-loading="loading"
class="mt10" class="mt10"
:style="`height: calc(${tableStore.table.height} - 135px)`" :style="`height: calc(${tableStore.table.height} - 135px)`"
:options="options" :options="options"
/> />
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, provide, nextTick } from 'vue' import { ref, onMounted, provide, nextTick } from 'vue'
import TableStore from '@/utils/tableStore' import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue' import Table from '@/components/table/index.vue'
import MyEchart from '@/components/echarts/MyEchart.vue' import MyEchart from '@/components/echarts/MyEchart.vue'
import TableHeader from '@/components/table/header/index.vue' import TableHeader from '@/components/table/header/index.vue'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
import * as echarts from 'echarts/core' import * as echarts from 'echarts/core'
const dictData = useDictData() const dictData = useDictData()
const options = ref({}) const options = ref({})
const TableHeaderRef = ref() const TableHeaderRef = ref()
const tableStoreParams: any = ref({}) const tableStoreParams: any = ref({})
const loading = ref(false) const loading = ref(false)
const getTableStoreParams = async (val: any) => { const getTableStoreParams = async (val: any) => {
tableStoreParams.value = val tableStoreParams.value = val
loading.value = true loading.value = true
setTimeout(() => { setTimeout(() => {
tableStore.index() tableStore.index()
}, 1500) }, 1500)
} }
const itemStyle = { const itemStyle = {
normal: { normal: {
// 随机显示 // 随机显示
//color:function(d){return "#"+Math.floor(Math.random()*(256*256*256-1)).toString(16);} //color:function(d){return "#"+Math.floor(Math.random()*(256*256*256-1)).toString(16);}
// 定制显示(按顺序) // 定制显示(按顺序)
color: function (params) { color: function (params) {
if (params.value >= 90) { if (params.value >= 90) {
return new echarts.graphic.LinearGradient( return new echarts.graphic.LinearGradient(
0, 0,
1, 1,
0, 0,
0, 0,
[ [
{ {
offset: 1, offset: 1,
color: '#339966' color: '#339966'
} }
], ],
false false
) )
} else if (params.value >= 60 && params.value <= 90) { } else if (params.value >= 60 && params.value <= 90) {
return new echarts.graphic.LinearGradient( return new echarts.graphic.LinearGradient(
0, 0,
1, 1,
0, 0,
0, 0,
[ [
{ {
offset: 1, offset: 1,
color: '#FFCC33' color: '#FFCC33'
} }
], ],
false false
) )
} else if (params.value <= 60 && params.value !== 3.14159) { } else if (params.value <= 60 && params.value !== 3.14159) {
return new echarts.graphic.LinearGradient( return new echarts.graphic.LinearGradient(
0, 0,
1, 1,
0, 0,
0, 0,
[ [
{ {
offset: 1, offset: 1,
color: '#A52a2a' color: '#A52a2a'
} }
], ],
false false
) )
} else if (params.value == 3.14159) { } else if (params.value == 3.14159) {
return new echarts.graphic.LinearGradient( return new echarts.graphic.LinearGradient(
0, 0,
1, 1,
0, 0,
0, 0,
[ [
{ {
offset: 1, offset: 1,
color: '#cccccc' color: '#cccccc'
} }
], ],
false false
) )
} }
} }
} }
} }
const tableStore = new TableStore({ const tableStore = new TableStore({
url: '/harmonic-boot/steadyQualify/getSteadyQualifyCensus', url: '/harmonic-boot/steadyQualify/getSteadyQualifyCensus',
showPage: false, showPage: false,
method: 'POST', method: 'POST',
// publicHeight: 10, // publicHeight: 10,
column: [], column: [],
beforeSearchFun: () => { beforeSearchFun: () => {
tableStore.table.params = tableStoreParams.value tableStore.table.params = tableStoreParams.value
}, },
loadCallback: () => { loadCallback: () => {
let code = tableStore.table.params.statisticalType.code let code = tableStore.table.params.statisticalType.code
let title = '', let title = '',
titleX = '' titleX = ''
if (code == 'Power_Network') { if (code == 'Power_Network') {
title = '区域' title = '区域'
titleX = '区域' titleX = '区域'
} else if (code == 'Manufacturer') { } else if (code == 'Manufacturer') {
title = '终端厂家' title = '终端厂家'
titleX = '终端\n厂家' titleX = '终端\n厂家'
} else if (code == 'Voltage_Level') { } else if (code == 'Voltage_Level') {
title = '电压等级' title = '电压等级'
titleX = '电压\n等级' titleX = '电压\n等级'
} else if (code == 'Load_Type') { } else if (code == 'Load_Type') {
title = '干扰源类型' title = '干扰源类型'
titleX = '干扰\n源类型' titleX = '干扰\n源类型'
} else if (code == 'Report_Type') { } else if (code == 'Report_Type') {
title = '上报类型' title = '上报类型'
titleX = '上报\n类型' titleX = '上报\n类型'
} }
options.value = { options.value = {
title: { title: {
text: title text: title
}, },
legend: { legend: {
show: false show: false
}, },
tooltip: { tooltip: {
formatter: function (params: any) { formatter: function (params: any) {
let tips = `<strong>${params[0]?.name}</strong></br>` // 标题加粗 let tips = `<strong>${params[0]?.name}</strong></br>` // 标题加粗
params.forEach((item: any) => { params.forEach((item: any) => {
const value = item.value === 3.14159 ? '暂无数据' : item.value // 处理特殊值 const value = item.value === 3.14159 ? '暂无数据' : item.value // 处理特殊值
tips += `<div style=" display: flex;justify-content: space-between;"> tips += `<div style=" display: flex;justify-content: space-between;">
<span>${item.marker} <span>${item.marker}
${item.seriesName}: ${item.seriesName}:
</span> ${value} </span> ${value}
</div>` // 统一格式 </div>` // 统一格式
}) })
return tips return tips
} }
}, },
xAxis: { xAxis: {
name: titleX, name: titleX,
data: tableStore.table.data.type data: tableStore.table.data.type
}, },
yAxis: { yAxis: {
name: '%', name: '%',
max: 100 max: 100
}, },
series: [ series: [
{ {
name: '频率偏差', name: '频率偏差',
type: 'bar', type: 'bar',
itemStyle: itemStyle, itemStyle: itemStyle,
data: tableStore.table.data.freqOffset, data: tableStore.table.data.freqOffset,
markLine: { markLine: {
silent: false, silent: false,
symbol: 'circle', symbol: 'circle',
data: [ data: [
{ {
name: '', name: '',
yAxis: 100, yAxis: 100,
lineStyle: { lineStyle: {
color: '#339966' color: '#339966'
}, },
label: { label: {
// position: "middle", // position: "middle",
formatter: '{b}', formatter: '{b}',
textStyle: { textStyle: {
color: '#339966' color: '#339966'
} }
} }
}, },
{ {
name: '', name: '',
yAxis: 90, yAxis: 90,
lineStyle: { lineStyle: {
color: '#FFCC33' color: '#FFCC33'
}, },
label: { label: {
// position: "middle", // position: "middle",
formatter: '{b}', formatter: '{b}',
textStyle: { textStyle: {
color: '#FFCC33' color: '#FFCC33'
} }
} }
}, },
{ {
name: '', name: '',
yAxis: 60, yAxis: 60,
lineStyle: { lineStyle: {
color: '#A52a2a' color: '#A52a2a'
}, },
label: { label: {
// position: "middle", // position: "middle",
formatter: '{b}', formatter: '{b}',
textStyle: { textStyle: {
color: '#A52a2a' color: '#A52a2a'
} }
} }
} }
] ]
} }
}, },
{ {
name: '闪变', name: '闪变',
type: 'bar', type: 'bar',
itemStyle: itemStyle, itemStyle: itemStyle,
data: tableStore.table.data.flicker data: tableStore.table.data.flicker
}, },
{ {
name: '三相电压不平衡', name: '三相电压不平衡',
type: 'bar', type: 'bar',
itemStyle: itemStyle, itemStyle: itemStyle,
data: tableStore.table.data.voltageUnbalance data: tableStore.table.data.voltageUnbalance
}, },
{ {
name: '谐波电压', name: '谐波电压',
type: 'bar', type: 'bar',
itemStyle: itemStyle, itemStyle: itemStyle,
data: tableStore.table.data.harmonicVoltage data: tableStore.table.data.harmonicVoltage
}, },
{ {
name: '电压偏差', name: '电压偏差',
type: 'bar', type: 'bar',
itemStyle: itemStyle, itemStyle: itemStyle,
data: tableStore.table.data.voltageOffset data: tableStore.table.data.voltageOffset
}, },
{ {
name: '谐波电流', name: '谐波电流',
type: 'bar', type: 'bar',
itemStyle: itemStyle, itemStyle: itemStyle,
data: tableStore.table.data.harmonicCurrent data: tableStore.table.data.harmonicCurrent
}, },
{ {
name: '负序电流', name: '负序电流',
type: 'bar', type: 'bar',
itemStyle: itemStyle, itemStyle: itemStyle,
data: tableStore.table.data.negativeCurrent data: tableStore.table.data.negativeCurrent
}, },
{ {
name: '间谐波电压含有率', name: '间谐波电压含有率',
type: 'bar', type: 'bar',
itemStyle: itemStyle, itemStyle: itemStyle,
data: tableStore.table.data.interHarmonic data: tableStore.table.data.interHarmonic
} }
] ]
} }
loading.value = false loading.value = false
} }
}) })
provide('tableStore', tableStore) provide('tableStore', tableStore)
onMounted(() => {}) onMounted(() => {})
defineExpose({ getTableStoreParams }) defineExpose({ getTableStoreParams })
</script> </script>
<style scoped lang="scss"></style> <style scoped lang="scss"></style>

View File

@@ -3,7 +3,7 @@
<div class="online_header"> <div class="online_header">
<TableHeader date-picker area ref="tableHeaderRef"> <TableHeader date-picker area ref="tableHeaderRef">
<template #select> <template #select>
<el-form-item label="统计类型:"> <el-form-item label="统计类型">
<el-select <el-select
v-model="tableStore.table.params.statisticalType" v-model="tableStore.table.params.statisticalType"
placeholder="请选择统计类型" placeholder="请选择统计类型"
@@ -19,7 +19,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="电压等级:"> <el-form-item label="电压等级">
<el-select <el-select
v-model="tableStore.table.params.scale" v-model="tableStore.table.params.scale"
multiple multiple
@@ -37,7 +37,7 @@
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="终端厂家:"> <el-form-item label="终端厂家">
<el-select <el-select
v-model="tableStore.table.params.manufacturer" v-model="tableStore.table.params.manufacturer"
multiple multiple
@@ -55,7 +55,7 @@
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="干扰源类型:"> <el-form-item label="干扰源类型">
<el-select <el-select
v-model="tableStore.table.params.loadType" v-model="tableStore.table.params.loadType"
multiple multiple
@@ -83,6 +83,14 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="筛选数据">
<el-input
v-model.trim="tableStore.table.params.searchValue"
clearable
style="width: 200px"
placeholder="请输入关键字筛选"
/>
</el-form-item>
</template> </template>
</TableHeader> </TableHeader>
</div> </div>
@@ -113,6 +121,7 @@ import TableHeader from '@/components/table/header/index.vue'
import TableStore from '@/utils/tableStore' import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue' import Table from '@/components/table/index.vue'
import charts from './components/charts.vue' import charts from './components/charts.vue'
import { filterTree } from '@/utils/tree'
defineOptions({ defineOptions({
name: 'harmonic-boot/area/qualifiedRate' name: 'harmonic-boot/area/qualifiedRate'
}) })
@@ -272,7 +281,13 @@ const tableStore = new TableStore({
], ],
loadCallback: () => { loadCallback: () => {
tableStore.table.data = tree2List(tableStore.table.data, Math.random() * 1000) tableStore.table.data = tree2List(
filterTree(tableStore.table.data, node => {
// 筛选条件name 包含关键词
return node.name.includes(tableStore.table.params.searchValue)
}),
Math.random() * 1000
)
tableStore.table.column[0].title = tableStore.table.params.statisticalType.name tableStore.table.column[0].title = tableStore.table.params.statisticalType.name
chartsRef.value && chartsRef.value.getTableStoreParams(tableStore.table.params) chartsRef.value && chartsRef.value.getTableStoreParams(tableStore.table.params)
@@ -288,6 +303,7 @@ tableStore.table.params.manufacturer = []
tableStore.table.params.loadType = [] tableStore.table.params.loadType = []
tableStore.table.params.serverName = 'harmonicBoot' tableStore.table.params.serverName = 'harmonicBoot'
tableStore.table.params.powerFlag = sign[0]?.algoDescribe || 0 tableStore.table.params.powerFlag = sign[0]?.algoDescribe || 0
tableStore.table.params.searchValue = ''
provide('tableStore', tableStore) provide('tableStore', tableStore)
// const tree2List = (list: any, pid?: string) => { // const tree2List = (list: any, pid?: string) => {
// //存储结果的数组 // //存储结果的数组

View File

@@ -1,365 +1,379 @@
<template> <template>
<div class="default-main online"> <div class="default-main online">
<div class="online_header"> <div class="online_header">
<TableHeader date-picker area ref="tableHeaderRef"> <TableHeader date-picker area ref="tableHeaderRef">
<template #select> <template #select>
<el-form-item label="统计类型:"> <el-form-item label="统计类型">
<el-select <el-select
v-model="tableStore.table.params.statisticalType" v-model="tableStore.table.params.statisticalType"
placeholder="请选择统计类型" placeholder="请选择统计类型"
value-key="id" value-key="id"
style="width: 100%" style="width: 100%"
> >
<el-option <el-option
v-for="item in classificationData" v-for="item in classificationData"
:key="item.id" :key="item.id"
:label="item.name" :label="item.name"
:value="item" :value="item"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="终端厂家:"> <el-form-item label="终端厂家">
<el-select <el-select
v-model="tableStore.table.params.manufacturer" v-model="tableStore.table.params.manufacturer"
multiple multiple
collapse-tags collapse-tags
clearable clearable
placeholder="请选择终端厂家" placeholder="请选择终端厂家"
style="width: 100%" style="width: 100%"
value-key="id" value-key="id"
> >
<el-option <el-option
v-for="(item, index) in terminaloption" v-for="(item, index) in terminaloption"
:key="index" :key="index"
:label="item.name" :label="item.name"
:value="item" :value="item"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
</template> <el-form-item label="筛选数据">
</TableHeader> <el-input
</div> v-model.trim="tableStore.table.params.searchValue"
<div class="online_main"> clearable
<el-tabs v-model="activeName" type="border-card" @tab-click="handleClick"> style="width: 200px"
<el-tab-pane :name="0" :lazy="true" label="终端状态统计表"> placeholder="请输入关键字筛选"
<div class="table_legend"> />
<ul> </el-form-item>
<li> </template>
<p style="background: #339966"> </TableHeader>
<svg </div>
t="1722910570852" <div class="online_main">
class="icon" <el-tabs v-model="activeName" type="border-card" @tab-click="handleClick">
viewBox="0 0 1336 1024" <el-tab-pane :name="0" :lazy="true" label="终端状态统计表">
version="1.1" <div class="table_legend">
xmlns="http://www.w3.org/2000/svg" <ul>
p-id="6243" <li>
width="16" <p style="background: #339966">
height="16" <svg
> t="1722910570852"
<path class="icon"
d="M49.588224 883.816448M1139.531776 883.816448M86.939648 862.977024M538.459136 960.381952c109.876224-153.544704 223.55968-289.842176 308.03968-385.787904 49.87392-56.639488 96.715776-108.155904 141.549568-154.500096 40.576-41.945088 80.805888-80.405504 119.478272-116.59264 65.92-61.693952 142.984192-130.034688 191.446016-159.30368l-61.891584-82.050048c-89.732096 56.139776-176.10752 116.103168-242.799616 162.18112-38.863872 26.855424-74.928128 52.667392-108.915712 77.252608-33.668096 24.356864-68.429824 51.106816-105.081856 79.166464-63.633408 48.712704-145.388544 114.194432-224.555008 181.860352L357.07904 374.989824 123.885568 558.770176 538.459136 960.381952zM1335.92064 862.977024" viewBox="0 0 1336 1024"
fill="#ffffff" version="1.1"
p-id="6244" xmlns="http://www.w3.org/2000/svg"
></path> p-id="6243"
</svg> width="16"
</p> height="16"
<span style="color: #339966">投运状态</span> >
</li> <path
<li> d="M49.588224 883.816448M1139.531776 883.816448M86.939648 862.977024M538.459136 960.381952c109.876224-153.544704 223.55968-289.842176 308.03968-385.787904 49.87392-56.639488 96.715776-108.155904 141.549568-154.500096 40.576-41.945088 80.805888-80.405504 119.478272-116.59264 65.92-61.693952 142.984192-130.034688 191.446016-159.30368l-61.891584-82.050048c-89.732096 56.139776-176.10752 116.103168-242.799616 162.18112-38.863872 26.855424-74.928128 52.667392-108.915712 77.252608-33.668096 24.356864-68.429824 51.106816-105.081856 79.166464-63.633408 48.712704-145.388544 114.194432-224.555008 181.860352L357.07904 374.989824 123.885568 558.770176 538.459136 960.381952zM1335.92064 862.977024"
<p style="background: #ffcc33"> fill="#ffffff"
<svg p-id="6244"
t="1722910570852" ></path>
class="icon" </svg>
viewBox="0 0 1336 1024" </p>
version="1.1" <span style="color: #339966">投运状态</span>
xmlns="http://www.w3.org/2000/svg" </li>
p-id="6243" <li>
width="16" <p style="background: #ffcc33">
height="16" <svg
> t="1722910570852"
<path class="icon"
d="M49.588224 883.816448M1139.531776 883.816448M86.939648 862.977024M538.459136 960.381952c109.876224-153.544704 223.55968-289.842176 308.03968-385.787904 49.87392-56.639488 96.715776-108.155904 141.549568-154.500096 40.576-41.945088 80.805888-80.405504 119.478272-116.59264 65.92-61.693952 142.984192-130.034688 191.446016-159.30368l-61.891584-82.050048c-89.732096 56.139776-176.10752 116.103168-242.799616 162.18112-38.863872 26.855424-74.928128 52.667392-108.915712 77.252608-33.668096 24.356864-68.429824 51.106816-105.081856 79.166464-63.633408 48.712704-145.388544 114.194432-224.555008 181.860352L357.07904 374.989824 123.885568 558.770176 538.459136 960.381952zM1335.92064 862.977024" viewBox="0 0 1336 1024"
fill="#ffffff" version="1.1"
p-id="6244" xmlns="http://www.w3.org/2000/svg"
></path> p-id="6243"
</svg> width="16"
</p> height="16"
<span style="color: #ffcc33">检修状态</span> >
</li> <path
<li> d="M49.588224 883.816448M1139.531776 883.816448M86.939648 862.977024M538.459136 960.381952c109.876224-153.544704 223.55968-289.842176 308.03968-385.787904 49.87392-56.639488 96.715776-108.155904 141.549568-154.500096 40.576-41.945088 80.805888-80.405504 119.478272-116.59264 65.92-61.693952 142.984192-130.034688 191.446016-159.30368l-61.891584-82.050048c-89.732096 56.139776-176.10752 116.103168-242.799616 162.18112-38.863872 26.855424-74.928128 52.667392-108.915712 77.252608-33.668096 24.356864-68.429824 51.106816-105.081856 79.166464-63.633408 48.712704-145.388544 114.194432-224.555008 181.860352L357.07904 374.989824 123.885568 558.770176 538.459136 960.381952zM1335.92064 862.977024"
<p style="background: #A52a2a"> fill="#ffffff"
<svg p-id="6244"
t="1722910570852" ></path>
class="icon" </svg>
viewBox="0 0 1336 1024" </p>
version="1.1" <span style="color: #ffcc33">检修状态</span>
xmlns="http://www.w3.org/2000/svg" </li>
p-id="6243" <li>
width="16" <p style="background: #a52a2a">
height="16" <svg
> t="1722910570852"
<path class="icon"
d="M49.588224 883.816448M1139.531776 883.816448M86.939648 862.977024M538.459136 960.381952c109.876224-153.544704 223.55968-289.842176 308.03968-385.787904 49.87392-56.639488 96.715776-108.155904 141.549568-154.500096 40.576-41.945088 80.805888-80.405504 119.478272-116.59264 65.92-61.693952 142.984192-130.034688 191.446016-159.30368l-61.891584-82.050048c-89.732096 56.139776-176.10752 116.103168-242.799616 162.18112-38.863872 26.855424-74.928128 52.667392-108.915712 77.252608-33.668096 24.356864-68.429824 51.106816-105.081856 79.166464-63.633408 48.712704-145.388544 114.194432-224.555008 181.860352L357.07904 374.989824 123.885568 558.770176 538.459136 960.381952zM1335.92064 862.977024" viewBox="0 0 1336 1024"
fill="#ffffff" version="1.1"
p-id="6244" xmlns="http://www.w3.org/2000/svg"
></path> p-id="6243"
</svg> width="16"
</p> height="16"
<span style="color: #A52a2a">停运状态</span> >
</li> <path
</ul> d="M49.588224 883.816448M1139.531776 883.816448M86.939648 862.977024M538.459136 960.381952c109.876224-153.544704 223.55968-289.842176 308.03968-385.787904 49.87392-56.639488 96.715776-108.155904 141.549568-154.500096 40.576-41.945088 80.805888-80.405504 119.478272-116.59264 65.92-61.693952 142.984192-130.034688 191.446016-159.30368l-61.891584-82.050048c-89.732096 56.139776-176.10752 116.103168-242.799616 162.18112-38.863872 26.855424-74.928128 52.667392-108.915712 77.252608-33.668096 24.356864-68.429824 51.106816-105.081856 79.166464-63.633408 48.712704-145.388544 114.194432-224.555008 181.860352L357.07904 374.989824 123.885568 558.770176 538.459136 960.381952zM1335.92064 862.977024"
</div> fill="#ffffff"
<Table p-id="6244"
ref="tableRef" ></path>
:tree-config="{ transform: true, parentField: 'uPid', rowField: 'uId' }" </svg>
:scroll-y="{ enabled: true }" </p>
v-if="activeName == 0" <span style="color: #a52a2a">停运状态</span>
/> </li>
</el-tab-pane> </ul>
<el-tab-pane :name="1" :lazy="true" label="终端状态统计图"> </div>
<charts v-if="activeName == 1" ref="chartsRef" /> <Table
</el-tab-pane> ref="tableRef"
</el-tabs> :tree-config="{ transform: true, parentField: 'uPid', rowField: 'uId' }"
</div> :scroll-y="{ enabled: true }"
</div> v-if="activeName == 0"
</template> />
<script lang="ts" setup> </el-tab-pane>
import { ref, onMounted, watch } from 'vue' <el-tab-pane :name="1" :lazy="true" label="终端状态统计图">
import { useDictData } from '@/stores/dictData' <charts v-if="activeName == 1" ref="chartsRef" />
import DatePicker from '@/components/form/datePicker/index.vue' </el-tab-pane>
import { getAreaDept } from '@/api/harmonic-boot/area' </el-tabs>
import TableHeader from '@/components/table/header/index.vue' </div>
import TableStore from '@/utils/tableStore' </div>
import Table from '@/components/table/index.vue' </template>
import charts from './components/charts.vue' <script lang="ts" setup>
defineOptions({ import { ref, onMounted, watch } from 'vue'
name: 'harmonic-boot/area/terminalonlinerate' import { useDictData } from '@/stores/dictData'
}) import DatePicker from '@/components/form/datePicker/index.vue'
const tableRef = ref() import { getAreaDept } from '@/api/harmonic-boot/area'
const chartsRef = ref() import TableHeader from '@/components/table/header/index.vue'
const dictData = useDictData() import TableStore from '@/utils/tableStore'
//字典获取电压等级 import Table from '@/components/table/index.vue'
const voltageleveloption = dictData.getBasicData('Dev_Voltage_Stand') import charts from './components/charts.vue'
//字典获取终端厂家 import { filterTree } from '@/utils/tree'
const terminaloption = dictData.getBasicData('Dev_Manufacturers') defineOptions({
//字典获取干扰源类型 name: 'harmonic-boot/area/terminalonlinerate'
const interfereoption = dictData.getBasicData('Interference_Source') })
//字典获取统计类型 const tableRef = ref()
const classificationData = dictData.getBasicData('Statistical_Type', ['Report_Type', 'Voltage_Level', 'Load_Type']) const chartsRef = ref()
//调用区域接口获取区域 const dictData = useDictData()
const treeData = ref([]) //字典获取电压等级
const idArr = ref([]) const voltageleveloption = dictData.getBasicData('Dev_Voltage_Stand')
const activeName = ref(0) //字典获取终端厂家
const getTreeData = async () => { const terminaloption = dictData.getBasicData('Dev_Manufacturers')
await getAreaDept().then(res => { //字典获取干扰源类型
var data = res.data const interfereoption = dictData.getBasicData('Interference_Source')
data.forEach(element => { //字典获取统计类型
idArr.value.push(element.id) const classificationData = dictData.getBasicData('Statistical_Type', ['Report_Type', 'Voltage_Level', 'Load_Type'])
}) //调用区域接口获取区域
treeData.value = JSON.parse(JSON.stringify(res.data)) const treeData = ref([])
}) const idArr = ref([])
} const activeName = ref(0)
getTreeData() const getTreeData = async () => {
await getAreaDept().then(res => {
const formData = ref({ var data = res.data
statisticalType: classificationData[0], //统计类型 data.forEach(element => {
deptIndex: treeData.value[0]?.id, //区域选择 idArr.value.push(element.id)
scale: voltageleveloption, //电压等级 })
manufacturer: terminaloption, //终端厂家 treeData.value = JSON.parse(JSON.stringify(res.data))
loadType: interfereoption //干扰源类型 })
// searchBeginTime: '', }
// searchEndTime: '' getTreeData()
})
formData.value.deptIndex = treeData.value[0]?.id const formData = ref({
const defaultProps = ref({ statisticalType: classificationData[0], //统计类型
label: 'name', deptIndex: treeData.value[0]?.id, //区域选择
value: 'id', scale: voltageleveloption, //电压等级
checkStrictly: true, manufacturer: terminaloption, //终端厂家
emitPath: false, loadType: interfereoption //干扰源类型
expandTrigger: 'click' as const // searchBeginTime: '',
}) // searchEndTime: ''
const handleClick = (tab: any, e: any) => { })
// if(activeName.value===1){ formData.value.deptIndex = treeData.value[0]?.id
tableStore.index() const defaultProps = ref({
// } label: 'name',
} value: 'id',
checkStrictly: true,
// const datePickerRef = ref() emitPath: false,
const tableHeaderRef = ref() expandTrigger: 'click' as const
const tableStore = new TableStore({ })
publicHeight: 100, const handleClick = (tab: any, e: any) => {
showPage: false, // if(activeName.value===1){
url: '/harmonic-boot/terminal/getTerminalData', tableStore.index()
method: 'POST', // }
}
column: [
{ // const datePickerRef = ref()
title: formData.value.statisticalType.name, const tableHeaderRef = ref()
field: 'name', const tableStore = new TableStore({
align: 'left', publicHeight: 100,
width: 350, showPage: false,
treeNode: true url: '/harmonic-boot/terminal/getTerminalData',
}, method: 'POST',
{
title: '终端个数(台)', column: [
field: 'number', {
align: 'center', title: formData.value.statisticalType.name,
formatter: function (row) { field: 'name',
return row.cellValue != 0 ? row.cellValue : '/' align: 'left',
} width: 350,
}, treeNode: true
{ },
title: '投运(台)', {
field: 'runFlag', title: '终端个数(台)',
type: 'html', field: 'number',
align: 'center', align: 'center',
formatter: function (row) { formatter: function (row) {
return row.cellValue == 0 return row.cellValue != 0 ? row.cellValue : '/'
? '/' }
: row.cellValue !== 0 && row.row.level !== 4 },
? row.cellValue {
: row.cellValue !== 0 && row.row.level == 4 && row.row.reaFlag == 0 && row.row.stopFlag == 0 title: '投运(台)',
? "<p class='table_icon' style='width: 18px;height: 18px;margin: 0 auto;display: flex;align-items: center;justify-content: center;border-radius: 50%;background: #339966'><svg t='1722910570852' class='icon' viewBox='0 0 1336 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='6243' width='16' height='16'><path d='M49.588224 883.816448M1139.531776 883.816448M86.939648 862.977024M538.459136 960.381952c109.876224-153.544704 223.55968-289.842176 308.03968-385.787904 49.87392-56.639488 96.715776-108.155904 141.549568-154.500096 40.576-41.945088 80.805888-80.405504 119.478272-116.59264 65.92-61.693952 142.984192-130.034688 191.446016-159.30368l-61.891584-82.050048c-89.732096 56.139776-176.10752 116.103168-242.799616 162.18112-38.863872 26.855424-74.928128 52.667392-108.915712 77.252608-33.668096 24.356864-68.429824 51.106816-105.081856 79.166464-63.633408 48.712704-145.388544 114.194432-224.555008 181.860352L357.07904 374.989824 123.885568 558.770176 538.459136 960.381952zM1335.92064 862.977024' fill='#ffffff' p-id='6244'></path></svg> </p>" field: 'runFlag',
: '/' type: 'html',
} align: 'center',
}, formatter: function (row) {
{ return row.cellValue == 0
title: '检修(台)', ? '/'
field: 'reaFlag', : row.cellValue !== 0 && row.row.level !== 4
type: 'html', ? row.cellValue
align: 'center', : row.cellValue !== 0 && row.row.level == 4 && row.row.reaFlag == 0 && row.row.stopFlag == 0
formatter: function (row) { ? "<p class='table_icon' style='width: 18px;height: 18px;margin: 0 auto;display: flex;align-items: center;justify-content: center;border-radius: 50%;background: #339966'><svg t='1722910570852' class='icon' viewBox='0 0 1336 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='6243' width='16' height='16'><path d='M49.588224 883.816448M1139.531776 883.816448M86.939648 862.977024M538.459136 960.381952c109.876224-153.544704 223.55968-289.842176 308.03968-385.787904 49.87392-56.639488 96.715776-108.155904 141.549568-154.500096 40.576-41.945088 80.805888-80.405504 119.478272-116.59264 65.92-61.693952 142.984192-130.034688 191.446016-159.30368l-61.891584-82.050048c-89.732096 56.139776-176.10752 116.103168-242.799616 162.18112-38.863872 26.855424-74.928128 52.667392-108.915712 77.252608-33.668096 24.356864-68.429824 51.106816-105.081856 79.166464-63.633408 48.712704-145.388544 114.194432-224.555008 181.860352L357.07904 374.989824 123.885568 558.770176 538.459136 960.381952zM1335.92064 862.977024' fill='#ffffff' p-id='6244'></path></svg> </p>"
return row.cellValue == 0 : '/'
? '/' }
: row.cellValue !== 0 && row.row.level !== 4 },
? row.cellValue {
: row.cellValue !== 0 && row.row.level == 4 && row.row.runFlag == 0 && row.row.stopFlag == 0 title: '检修(台)',
? "<p class='table_icon' style='width: 18px;height: 18px;margin: 0 auto;display: flex;align-items: center;justify-content: center;border-radius: 50%;background: #ffcc33'><svg t='1722910570852' class='icon' viewBox='0 0 1336 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='6243' width='16' height='16'><path d='M49.588224 883.816448M1139.531776 883.816448M86.939648 862.977024M538.459136 960.381952c109.876224-153.544704 223.55968-289.842176 308.03968-385.787904 49.87392-56.639488 96.715776-108.155904 141.549568-154.500096 40.576-41.945088 80.805888-80.405504 119.478272-116.59264 65.92-61.693952 142.984192-130.034688 191.446016-159.30368l-61.891584-82.050048c-89.732096 56.139776-176.10752 116.103168-242.799616 162.18112-38.863872 26.855424-74.928128 52.667392-108.915712 77.252608-33.668096 24.356864-68.429824 51.106816-105.081856 79.166464-63.633408 48.712704-145.388544 114.194432-224.555008 181.860352L357.07904 374.989824 123.885568 558.770176 538.459136 960.381952zM1335.92064 862.977024' fill='#ffffff' p-id='6244'></path></svg> </p>" field: 'reaFlag',
: '/' type: 'html',
} align: 'center',
}, formatter: function (row) {
{ return row.cellValue == 0
title: '停运(台)', ? '/'
field: 'stopFlag', : row.cellValue !== 0 && row.row.level !== 4
type: 'html', ? row.cellValue
align: 'center', : row.cellValue !== 0 && row.row.level == 4 && row.row.runFlag == 0 && row.row.stopFlag == 0
formatter: function (row) { ? "<p class='table_icon' style='width: 18px;height: 18px;margin: 0 auto;display: flex;align-items: center;justify-content: center;border-radius: 50%;background: #ffcc33'><svg t='1722910570852' class='icon' viewBox='0 0 1336 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='6243' width='16' height='16'><path d='M49.588224 883.816448M1139.531776 883.816448M86.939648 862.977024M538.459136 960.381952c109.876224-153.544704 223.55968-289.842176 308.03968-385.787904 49.87392-56.639488 96.715776-108.155904 141.549568-154.500096 40.576-41.945088 80.805888-80.405504 119.478272-116.59264 65.92-61.693952 142.984192-130.034688 191.446016-159.30368l-61.891584-82.050048c-89.732096 56.139776-176.10752 116.103168-242.799616 162.18112-38.863872 26.855424-74.928128 52.667392-108.915712 77.252608-33.668096 24.356864-68.429824 51.106816-105.081856 79.166464-63.633408 48.712704-145.388544 114.194432-224.555008 181.860352L357.07904 374.989824 123.885568 558.770176 538.459136 960.381952zM1335.92064 862.977024' fill='#ffffff' p-id='6244'></path></svg> </p>"
return row.cellValue == 0 : '/'
? '/' }
: row.cellValue !== 0 && row.row.level !== 4 },
? row.cellValue {
: row.cellValue !== 0 && row.row.level == 4 && row.row.runFlag == 0 && row.row.reaFlag == 0 title: '停运(台)',
? "<p class='table_icon' style='width: 18px;height: 18px;margin: 0 auto;display: flex;align-items: center;justify-content: center;border-radius: 50%;background: #A52a2a'><svg t='1722910570852' class='icon' viewBox='0 0 1336 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='6243' width='16' height='16'><path d='M49.588224 883.816448M1139.531776 883.816448M86.939648 862.977024M538.459136 960.381952c109.876224-153.544704 223.55968-289.842176 308.03968-385.787904 49.87392-56.639488 96.715776-108.155904 141.549568-154.500096 40.576-41.945088 80.805888-80.405504 119.478272-116.59264 65.92-61.693952 142.984192-130.034688 191.446016-159.30368l-61.891584-82.050048c-89.732096 56.139776-176.10752 116.103168-242.799616 162.18112-38.863872 26.855424-74.928128 52.667392-108.915712 77.252608-33.668096 24.356864-68.429824 51.106816-105.081856 79.166464-63.633408 48.712704-145.388544 114.194432-224.555008 181.860352L357.07904 374.989824 123.885568 558.770176 538.459136 960.381952zM1335.92064 862.977024' fill='#ffffff' p-id='6244'></path></svg> </p>" field: 'stopFlag',
: '/' type: 'html',
} align: 'center',
}, formatter: function (row) {
{ return row.cellValue == 0
title: '在线率(%)', ? '/'
field: 'onlineRateData', : row.cellValue !== 0 && row.row.level !== 4
align: 'center', ? row.cellValue
formatter: function (row) { : row.cellValue !== 0 && row.row.level == 4 && row.row.runFlag == 0 && row.row.reaFlag == 0
return row.cellValue == 3.14159 ? '暂无数据' : row.cellValue.toFixed(2) ? "<p class='table_icon' style='width: 18px;height: 18px;margin: 0 auto;display: flex;align-items: center;justify-content: center;border-radius: 50%;background: #A52a2a'><svg t='1722910570852' class='icon' viewBox='0 0 1336 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='6243' width='16' height='16'><path d='M49.588224 883.816448M1139.531776 883.816448M86.939648 862.977024M538.459136 960.381952c109.876224-153.544704 223.55968-289.842176 308.03968-385.787904 49.87392-56.639488 96.715776-108.155904 141.549568-154.500096 40.576-41.945088 80.805888-80.405504 119.478272-116.59264 65.92-61.693952 142.984192-130.034688 191.446016-159.30368l-61.891584-82.050048c-89.732096 56.139776-176.10752 116.103168-242.799616 162.18112-38.863872 26.855424-74.928128 52.667392-108.915712 77.252608-33.668096 24.356864-68.429824 51.106816-105.081856 79.166464-63.633408 48.712704-145.388544 114.194432-224.555008 181.860352L357.07904 374.989824 123.885568 558.770176 538.459136 960.381952zM1335.92064 862.977024' fill='#ffffff' p-id='6244'></path></svg> </p>"
} : '/'
} }
], },
// beforeSearchFun: () => { {
// tableStore.table.params.deptIndex = formData.value.deptIndex title: '在线率(%)',
// tableStore.table.params.statisticalType = formData.value.statisticalType field: 'onlineRateData',
// tableStore.table.params.scale = formData.value.scale align: 'center',
// tableStore.table.params.manufacturer = formData.value.manufacturer formatter: function (row) {
// tableStore.table.params.loadType = formData.value.loadType return row.cellValue == 3.14159 ? '暂无数据' : row.cellValue.toFixed(2)
// tableStore.table.params.serverName = 'harmonicBoot' }
// // delete tableStore.table.params.timeFlag }
// // delete tableStore.table.params.startTime ],
// // delete tableStore.table.params.endTime // beforeSearchFun: () => {
// // delete tableStore.table.params.pageNum // tableStore.table.params.deptIndex = formData.value.deptIndex
// // delete tableStore.table.params.pageSize // tableStore.table.params.statisticalType = formData.value.statisticalType
// // tableStore.table.params.searchBeginTime = tableHeaderRef.value.datePickerRef.timeValue[0] // tableStore.table.params.scale = formData.value.scale
// // tableStore.table.params.searchEndTime = tableHeaderRef.value.datePickerRef.timeValue[1] // tableStore.table.params.manufacturer = formData.value.manufacturer
// }, // tableStore.table.params.loadType = formData.value.loadType
loadCallback: () => { // tableStore.table.params.serverName = 'harmonicBoot'
tableStore.table.data = tree2List(tableStore.table.data, Math.random() * 1000) // // delete tableStore.table.params.timeFlag
tableStore.table.column[0].title = formData.value.statisticalType.name // // delete tableStore.table.params.startTime
// // delete tableStore.table.params.endTime
chartsRef.value && chartsRef.value.getTableStoreParams(tableStore.table.params) // // delete tableStore.table.params.pageNum
setTimeout(() => { // // delete tableStore.table.params.pageSize
activeName.value == 0 && tableRef.value && tableRef.value.getRef().setAllTreeExpand(true) // // tableStore.table.params.searchBeginTime = tableHeaderRef.value.datePickerRef.timeValue[0]
}, 0) // // tableStore.table.params.searchEndTime = tableHeaderRef.value.datePickerRef.timeValue[1]
} // },
}) loadCallback: () => {
tableStore.table.params.deptIndex = treeData.value[0]?.id tableStore.table.data = tree2List(
tableStore.table.params.statisticalType = classificationData[0] filterTree(tableStore.table.data, node => {
tableStore.table.params.scale = voltageleveloption return node.name.includes(tableStore.table.params.searchValue)
tableStore.table.params.manufacturer = terminaloption }),
tableStore.table.params.loadType = interfereoption Math.random() * 1000
tableStore.table.params.serverName = 'harmonicBoot' )
tableStore.table.column[0].title = formData.value.statisticalType.name
provide('tableStore', tableStore) chartsRef.value && chartsRef.value.getTableStoreParams(tableStore.table.params)
const tree2List = (list: any, id?: string) => { setTimeout(() => {
//存储结果的数组 activeName.value == 0 && tableRef.value && tableRef.value.getRef().setAllTreeExpand(true)
let arr: any = [] }, 0)
// 遍历 tree 数组 }
list.forEach((item: any) => { })
item.uPid = id tableStore.table.params.deptIndex = treeData.value[0]?.id
item.uId = Math.random() * 1000 tableStore.table.params.statisticalType = classificationData[0]
item.valueOver == 3.14159 ? 0 : item.valueOver >= 90 ? 1 : item.valueOver && item.valueOver < 90 ? 2 : 3 tableStore.table.params.scale = voltageleveloption
// 判断item是否存在children tableStore.table.params.manufacturer = terminaloption
if (!item.children) return arr.push(item) tableStore.table.params.loadType = interfereoption
// 函数递归对children数组进行tree2List的转换 tableStore.table.params.serverName = 'harmonicBoot'
const children = tree2List(item.children, item.uId) tableStore.table.params.searchValue = ''
// 删除item的children属性
delete item.children provide('tableStore', tableStore)
// 把item和children数组添加至结果数组 const tree2List = (list: any, id?: string) => {
//..children: 意思是把children数组展开 //存储结果的数组
arr.push(item, ...children) let arr: any = []
}) // 遍历 tree 数组
// 返回结果数组 list.forEach((item: any) => {
return arr item.uPid = id
} item.uId = Math.random() * 1000
item.valueOver == 3.14159 ? 0 : item.valueOver >= 90 ? 1 : item.valueOver && item.valueOver < 90 ? 2 : 3
onMounted(() => {}) // 判断item是否存在children
if (!item.children) return arr.push(item)
watch( // 函数递归对children数组进行tree2List的转换
() => treeData.value, const children = tree2List(item.children, item.uId)
(val, oldVal) => { // 删除item的children属性
if (val && val.length != 0) { delete item.children
formData.value.deptIndex = val[0].id // 把item和children数组添加至结果数组
tableStore.index() //..children: 意思是把children数组展开
} arr.push(item, ...children)
}, })
{ // 返回结果数组
immediate: true, return arr
deep: true }
}
) onMounted(() => {})
</script>
<style lang="scss" scoped> watch(
.table_legend { () => treeData.value,
width: 100%; (val, oldVal) => {
height: 40px; if (val && val.length != 0) {
display: flex; formData.value.deptIndex = val[0].id
align-items: center; tableStore.index()
justify-content: flex-end; }
align-items: center; },
ul { {
width: 280px; immediate: true,
height: 30px; deep: true
display: flex; }
justify-content: space-between; )
li { </script>
flex: 1; <style lang="scss" scoped>
list-style-type: none; .table_legend {
display: flex; width: 100%;
align-items: center; height: 40px;
justify-content: space-around; display: flex;
p { align-items: center;
width: 18px; justify-content: flex-end;
height: 18px; align-items: center;
border-radius: 50%; ul {
} width: 280px;
} height: 30px;
} display: flex;
} justify-content: space-between;
</style> li {
flex: 1;
list-style-type: none;
display: flex;
align-items: center;
justify-content: space-around;
p {
width: 18px;
height: 18px;
border-radius: 50%;
}
}
}
}
</style>

View File

@@ -9,21 +9,21 @@
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> --> </el-form-item> -->
<el-form-item label="电压等级:"> <el-form-item label="电压等级">
<el-select v-model="tableStore.table.params.scale" filterable multiple collapse-tags clearable <el-select v-model="tableStore.table.params.scale" filterable multiple collapse-tags clearable
placeholder="请选择电压等级" value-key="id"> placeholder="请选择电压等级" value-key="id">
<el-option v-for="item in voltageleveloption" :key="item.id" :label="item.name" :value="item"> <el-option v-for="item in voltageleveloption" :key="item.id" :label="item.name" :value="item">
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="终端厂家:"> <el-form-item label="终端厂家">
<el-select v-model="tableStore.table.params.manufacturer" filterable multiple collapse-tags <el-select v-model="tableStore.table.params.manufacturer" filterable multiple collapse-tags
clearable placeholder="请选择终端厂家" value-key="id"> clearable placeholder="请选择终端厂家" value-key="id">
<el-option v-for="item in terminaloption" :key="item.id" :label="item.name" :value="item"> <el-option v-for="item in terminaloption" :key="item.id" :label="item.name" :value="item">
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="干扰源类型:"> <el-form-item label="干扰源类型">
<el-select v-model="tableStore.table.params.loadType" filterable multiple collapse-tags clearable <el-select v-model="tableStore.table.params.loadType" filterable multiple collapse-tags clearable
placeholder="请选择干扰源类型" value-key="id"> placeholder="请选择干扰源类型" value-key="id">
<el-option v-for="item in interfereoption" :key="item.id" :label="item.name" :value="item"> <el-option v-for="item in interfereoption" :key="item.id" :label="item.name" :value="item">

View File

@@ -7,7 +7,7 @@
</div> </div>
<TableHeader :showReset="false" ref="TableHeaderRef"> <TableHeader :showReset="false" ref="TableHeaderRef">
<template #select> <template #select>
<el-form-item label="关键字"> <el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.searchValue" clearable placeholder="请输入关键字" maxlength="32" show-word-limit/> <el-input v-model="tableStore.table.params.searchValue" clearable placeholder="请输入关键字" maxlength="32" show-word-limit/>
</el-form-item> </el-form-item>
</template> </template>

View File

@@ -2,7 +2,7 @@
<el-dialog v-model="dialogVisible" draggable title="完整性不足详情" width="1000"> <el-dialog v-model="dialogVisible" draggable title="完整性不足详情" width="1000">
<TableHeader :showReset="false" ref="TableHeaderRef"> <TableHeader :showReset="false" ref="TableHeaderRef">
<template #select> <template #select>
<el-form-item label="关键字"> <el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.searchValue" clearable placeholder="请输入关键字" /> <el-input v-model="tableStore.table.params.searchValue" clearable placeholder="请输入关键字" />
</el-form-item> </el-form-item>
</template> </template>

View File

@@ -613,7 +613,7 @@ onMounted(() => {
.harmonicButton { .harmonicButton {
height: 42px; height: 42px;
display: flex; display: flex;
justify-content: end; justify-content: flex-end;
align-items: center; align-items: center;
} }
:deep(.el-tabs__content) { :deep(.el-tabs__content) {

View File

@@ -158,7 +158,7 @@ onMounted(() => {
<style lang="scss" scoped> <style lang="scss" scoped>
.title { .title {
display: flex; display: flex;
justify-content: end; justify-content: flex-end;
align-items: center; align-items: center;
padding: 10px; padding: 10px;
font-size: 16px; font-size: 16px;

View File

@@ -3,7 +3,7 @@
<!-- 模版 --> <!-- 模版 -->
<TableHeader datePicker showExport :showReset="false" ref="TableHeaderRef"> <TableHeader datePicker showExport :showReset="false" ref="TableHeaderRef">
<template #select> <template #select>
<!-- <el-form-item label="关键字"> <!-- <el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.searchValue" clearable placeholder="请输入关键字" /> <el-input v-model="tableStore.table.params.searchValue" clearable placeholder="请输入关键字" />
</el-form-item> --> </el-form-item> -->
</template> </template>

View File

@@ -9,26 +9,31 @@
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> --> </el-form-item> -->
<el-form-item label="电压等级:"> <el-form-item label="电压等级">
<el-select v-model="tableStore.table.params.scale" filterable multiple collapse-tags clearable <el-select v-model="tableStore.table.params.scale" filterable multiple collapse-tags clearable
placeholder="请选择电压等级" value-key="id"> placeholder="请选择电压等级" value-key="id">
<el-option v-for="item in voltageleveloption" :key="item.id" :label="item.name" :value="item"> <el-option v-for="item in voltageleveloption" :key="item.id" :label="item.name" :value="item">
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="终端厂家:"> <el-form-item label="终端厂家">
<el-select v-model="tableStore.table.params.manufacturer" filterable multiple collapse-tags <el-select v-model="tableStore.table.params.manufacturer" filterable multiple collapse-tags
clearable placeholder="请选择终端厂家" value-key="id"> clearable placeholder="请选择终端厂家" value-key="id">
<el-option v-for="item in terminaloption" :key="item.id" :label="item.name" :value="item"> <el-option v-for="item in terminaloption" :key="item.id" :label="item.name" :value="item">
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="干扰源类型:"> <el-form-item label="干扰源类型">
<el-select v-model="tableStore.table.params.loadType" filterable multiple collapse-tags clearable <el-select v-model="tableStore.table.params.loadType" filterable multiple collapse-tags clearable
placeholder="请选择干扰源类型" value-key="id"> placeholder="请选择干扰源类型" value-key="id">
<el-option v-for="item in interfereoption" :key="item.id" :label="item.name" :value="item"> <el-option v-for="item in interfereoption" :key="item.id" :label="item.name" :value="item">
</el-option> </el-option>
</el-select> </el-select>
</el-form-item>
<el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.searchValue" clearable style="width: 240px;"
placeholder="请输入变电站、监测点、监测对象" />
</el-form-item> </el-form-item>
</template> </template>
@@ -68,14 +73,14 @@ const tableStore = new TableStore({
{ field: 'lineScale', title: '电压等级', minWidth: "120px", }, { field: 'lineScale', title: '电压等级', minWidth: "120px", },
{ field: 'lineName', title: '监测点名称', minWidth: "150px", }, { field: 'lineName', title: '监测点名称', minWidth: "150px", },
{ field: 'loadType', title: '干扰源类型', minWidth: "150px", }, { field: 'loadType', title: '干扰源类型', minWidth: "150px", },
{ field: 'lineObjectName', title: '监测点对象名称', minWidth: "150px", formatter: (row: any) => { return row.cellValue == null ? '/' : row.cellValue } }, { field: 'lineObjectName', title: '监测点对象名称', minWidth: "180px", formatter: (row: any) => { return row.cellValue == null ? '/' : row.cellValue } },
{ field: 'overDay', title: '超标天数', minWidth: "80px", }, { field: 'overDay', title: '超标天数', minWidth: "80px", },
{ field: 'freqOverDay', title: '频率偏差超标天数', minWidth: "100px", }, { field: 'freqOverDay', title: '频率偏差', minWidth: "100px", },
{ field: 'volDevOverDay', title: '电压偏差超标天数', minWidth: "100px", }, { field: 'volDevOverDay', title: '电压偏差', minWidth: "100px", },
{ field: 'volDisOverDay', title: '电压总畸变率超标天数', minWidth: "100px", }, { field: 'volDisOverDay', title: '电压总畸变率', minWidth: "100px", },
{ field: 'volContainOverDay', title: '谐波电压含有率超标天数', minWidth: "110px", }, { field: 'volContainOverDay', title: '谐波电压含有率', minWidth: "100px", },
{ field: 'harmVolOverDay', title: '谐波电压超标天数', minWidth: "100px", }, { field: 'harmVolOverDay', title: '谐波电压', minWidth: "100px", },
{ field: 'harmCurOverDay', title: '谐波电流超标天数', minWidth: "100px", }, { field: 'harmCurOverDay', title: '谐波电流', minWidth: "100px", },
{ {
title: '各次谐波电压含有率超标天数', title: '各次谐波电压含有率超标天数',
children: [ children: [
@@ -104,10 +109,11 @@ const tableStore = new TableStore({
], ],
}, },
{ field: 'threeUnbalance', title: '三相电压不平衡度超标天数', minWidth: "110px", }, { field: 'intHarmOverDay', title: '间谐波电压含有率', minWidth: "100px", },
{ field: 'negativeOverDay', title: '负序电流超标天数', minWidth: "100px", }, { field: 'threeUnbalance', title: '三相电压不平衡度', minWidth: "100px", },
{ field: 'flickerOverDay', title: '闪变超标天数', minWidth: "100px", }, { field: 'negativeOverDay', title: '负序电流', minWidth: "100px", },
{ field: 'monitorNumber', title: '监测点编号', minWidth: "180px", formatter: (row: any) => { return row.cellValue == null ? '/' : row.cellValue } }, { field: 'flickerOverDay', title: '闪变', minWidth: "100px", },
{ field: 'monitorNumber', title: '监测点编号', minWidth: "100px", formatter: (row: any) => { return row.cellValue == null ? '/' : row.cellValue } },
@@ -125,6 +131,7 @@ tableStore.table.params.monitorFlag = 2
tableStore.table.params.scale = [] tableStore.table.params.scale = []
tableStore.table.params.manufacturer = [] tableStore.table.params.manufacturer = []
tableStore.table.params.loadType = [] tableStore.table.params.loadType = []
tableStore.table.params.searchValue = ''
const wp = ref({}) const wp = ref({})
provide('tableStore', tableStore) provide('tableStore', tableStore)

View File

@@ -2,7 +2,7 @@
<div class="default-main"> <div class="default-main">
<TableHeader datePicker area showExport> <TableHeader datePicker area showExport>
<template #select> <template #select>
<el-form-item label="统计类型:"> <el-form-item label="统计类型">
<el-select <el-select
v-model="tableStore.table.params.statisticalType" v-model="tableStore.table.params.statisticalType"
placeholder="请选择统计类型" placeholder="请选择统计类型"
@@ -16,7 +16,7 @@
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="电压等级:"> <el-form-item label="电压等级">
<el-select <el-select
v-model="tableStore.table.params.scale" v-model="tableStore.table.params.scale"
filterable filterable
@@ -34,7 +34,7 @@
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="终端厂家:"> <el-form-item label="终端厂家">
<el-select <el-select
v-model="tableStore.table.params.manufacturer" v-model="tableStore.table.params.manufacturer"
filterable filterable
@@ -52,7 +52,7 @@
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="干扰源类型:"> <el-form-item label="干扰源类型">
<el-select <el-select
v-model="tableStore.table.params.loadType" v-model="tableStore.table.params.loadType"
filterable filterable

View File

@@ -11,7 +11,9 @@
></DatePicker> ></DatePicker>
</el-form-item> </el-form-item>
</template> </template>
<template v-slot:operation></template> <template v-slot:operation>
<el-button type="primary" icon="el-icon-Download" @click="exportTemplate">导出</el-button>
</template>
</TableHeader> </TableHeader>
<GridLayout <GridLayout
@@ -68,9 +70,12 @@ import { useRouter, useRoute } from 'vue-router'
import { View } from '@element-plus/icons-vue' import { View } from '@element-plus/icons-vue'
import { useTimeCacheStore } from '@/stores/timeCache' import { useTimeCacheStore } from '@/stores/timeCache'
import { adminBaseRoutePath } from '@/router/static' import { adminBaseRoutePath } from '@/router/static'
import { useAdminInfo } from '@/stores/adminInfo'
import { dataVerifyExcel } from '@/api/device-boot/line'
const { push } = useRouter() const { push } = useRouter()
const datePickerRef = ref() const datePickerRef = ref()
const router = useRouter() const router = useRouter()
const adminInfo = useAdminInfo()
const route = useRoute() const route = useRoute()
const timeCacheStore = useTimeCacheStore() const timeCacheStore = useTimeCacheStore()
@@ -288,7 +293,29 @@ const fetchLayoutData = async () => {
// 可以添加错误提示逻辑 // 可以添加错误提示逻辑
} }
} }
// 导出
const exportTemplate = () => {
console.log(123)
dataVerifyExcel({
deptId: adminInfo.$state.deptId,
searchBeginTime: datePickerRef.value?.timeValue[0],
searchEndTime: datePickerRef.value?.timeValue[1]
}).then((res: any) => {
let blob = new Blob([res], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
})
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a') // 创建a标签
link.href = url
// link.download = "电压暂降事件分析报告"; // 设置下载的文件名
link.download = '数据总览' // 设置下载的文件名
document.body.appendChild(link)
link.click() //执行下载
document.body.removeChild(link)
})
}
// 窗口大小变化处理 - 使用防抖 // 窗口大小变化处理 - 使用防抖
const handleResize = useDebounceFn(() => { const handleResize = useDebounceFn(() => {
initRowHeight() initRowHeight()

View File

@@ -13,7 +13,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="筛选数据"> <el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.searchValue" clearable placeholder="请输入监测点名称" /> <el-input v-model="tableStore.table.params.searchValue" clearable style="width: 240px;" placeholder="请输入变电站、监测点、监测对象" />
</el-form-item> </el-form-item>
</template> </template>
@@ -162,14 +162,15 @@
<vxe-column field="company" title="供电公司" minWidth="110px"></vxe-column> <vxe-column field="company" title="供电公司" minWidth="110px"></vxe-column>
<vxe-column field="subStation" title="变电站" minWidth="110px"></vxe-column> <vxe-column field="subStation" title="变电站" minWidth="110px"></vxe-column>
<vxe-column field="manufacturer" title="终端厂家" minWidth="110px"></vxe-column> <vxe-column field="manufacturer" title="终端厂家" minWidth="110px"></vxe-column>
<vxe-column field="deviceName" title="终端名称" minWidth="110px"></vxe-column> <vxe-column field="deviceName" title="终端名称" minWidth="130px"></vxe-column>
<vxe-column field="ip" title="终端IP" :formatter="formatter" width="120px"></vxe-column> <vxe-column field="ip" title="终端IP" :formatter="formatter" width="120px"></vxe-column>
<vxe-column <vxe-column
field="lineName" field="lineName"
title="监测点名称" title="监测点名称"
:formatter="formatter" :formatter="formatter"
minWidth="110px" minWidth="130px"
></vxe-column> ></vxe-column>
<vxe-column v-if="VITE_FLAG" field="objName" title="监测对象" minWidth="130px"></vxe-column>
<vxe-column field="runFlag" title="运行状态" width="90px"> <vxe-column field="runFlag" title="运行状态" width="90px">
<template #default="{ row }"> <template #default="{ row }">
<el-tag <el-tag
@@ -222,6 +223,7 @@ defineOptions({
name: 'harmonic-boot/harmonic/getIntegrityData' name: 'harmonic-boot/harmonic/getIntegrityData'
}) })
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
const VITE_FLAG = import.meta.env.VITE_NAME != 'jibei'
const route = useRoute() const route = useRoute()
const dictData = useDictData() const dictData = useDictData()
//字典获取监督对象类型 //字典获取监督对象类型
@@ -275,7 +277,7 @@ const tableStore = new TableStore({
if (tableStore.table.params.statisticalType.name == '终端厂家') { if (tableStore.table.params.statisticalType.name == '终端厂家') {
return k.citTotalNum != 0 return k.citTotalNum != 0
} else { } else {
return k.citName != '上送国网' && k.citName != '上送国网' return !k.citName.includes('上送')
} }
}) })
// 合并子集数据 并去重 // 合并子集数据 并去重

View File

@@ -160,8 +160,9 @@
<vxe-column field="company" title="供电公司" minWidth="110px"></vxe-column> <vxe-column field="company" title="供电公司" minWidth="110px"></vxe-column>
<vxe-column field="subStation" title="变电站" minWidth="110px"></vxe-column> <vxe-column field="subStation" title="变电站" minWidth="110px"></vxe-column>
<vxe-column field="manufacturer" title="终端厂家" minWidth="110px"></vxe-column> <vxe-column field="manufacturer" title="终端厂家" minWidth="110px"></vxe-column>
<vxe-column field="deviceName" title="终端名称" minWidth="110px"></vxe-column> <vxe-column field="deviceName" title="终端名称" minWidth="130px"></vxe-column>
<vxe-column field="ip" title="终端IP" :formatter="formatter" width="120px"></vxe-column> <vxe-column field="ip" title="终端IP" :formatter="formatter" width="120px"></vxe-column>
<vxe-column field="runFlag" title="运行状态" width="90px"> <vxe-column field="runFlag" title="运行状态" width="90px">
<template #default="{ row }"> <template #default="{ row }">
<el-tag <el-tag
@@ -214,6 +215,7 @@ defineOptions({
name: 'harmonic-boot/harmonic/getIntegrityData' name: 'harmonic-boot/harmonic/getIntegrityData'
}) })
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
const VITE_FLAG = import.meta.env.VITE_NAME != 'jibei'
const route = useRoute() const route = useRoute()
const dictData = useDictData() const dictData = useDictData()
//字典获取监督对象类型 //字典获取监督对象类型
@@ -268,7 +270,7 @@ const tableStore = new TableStore({
if (tableStore.table.params.statisticalType.name == '终端厂家') { if (tableStore.table.params.statisticalType.name == '终端厂家') {
return k.citTotalNum != 0 return k.citTotalNum != 0
} else { } else {
return k.citName != '上送国网' && k.citName != '上送国网' return !k.citName.includes('上送')
} }
}) })
// console.log(123, tableStore.table.params.statisticalType.name) // console.log(123, tableStore.table.params.statisticalType.name)

View File

@@ -41,7 +41,7 @@
<el-tab-pane label="监测点运行状态" name="6" lazy v-if="!isReload"> <el-tab-pane label="监测点运行状态" name="6" lazy v-if="!isReload">
<Yunxingzhuangtai v-if="activeName == '6'" /> <Yunxingzhuangtai v-if="activeName == '6'" />
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="实时数据" name="7" lazy v-if="!isReload && !VITE_FLAG && !VITE_FLAG1"> <el-tab-pane label="实时数据" name="7" lazy v-if="!isReload && !VITE_FLAG1">
<Shishishuju v-if="activeName == '7'" /> <Shishishuju v-if="activeName == '7'" />
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="统计报表" name="8" lazy v-if="!isReload && VITE_FLAG"> <el-tab-pane label="统计报表" name="8" lazy v-if="!isReload && VITE_FLAG">

View File

@@ -665,7 +665,7 @@ const initEcharts = (color: string, key: number, name: string) => {
startAngle: key == 0 ? 180 : 90, startAngle: key == 0 ? 180 : 90,
endAngle: key == 0 ? 90 : 0, endAngle: key == 0 ? 90 : 0,
min: 0, min: 0,
max: key == 0 ? 12 : 400, max: key == 0 ? 12 : 200,
radius: '180%', radius: '180%',
center: key == 0 ? ['70%', '95%'] : ['30%', '95%'], center: key == 0 ? ['70%', '95%'] : ['30%', '95%'],
splitNumber: 2, //刻度数量 splitNumber: 2, //刻度数量
@@ -744,16 +744,6 @@ const initEcharts = (color: string, key: number, name: string) => {
} }
//渲染echarts //渲染echarts
const init = () => { const init = () => {
loading.value = true
const url = localStorage.getItem('WebSocketUrl') || 'ws://192.168.1.67:10407/api/pushMessage/'
echartsDataV1.value = initEcharts('#DAA520', 0, 'A相')
echartsDataV2.value = initEcharts('#2E8B57', 0, 'B相')
echartsDataV3.value = initEcharts('#A52a2a', 0, 'C相')
echartsDataA1.value = initEcharts('#DAA520', 1, 'A相')
echartsDataA2.value = initEcharts('#2E8B57', 1, 'B相')
echartsDataA3.value = initEcharts('#A52a2a', 1, 'C相')
if (!dataSocket.socketServe) { if (!dataSocket.socketServe) {
console.error('WebSocket 客户端实例不存在') console.error('WebSocket 客户端实例不存在')
return return
@@ -765,9 +755,22 @@ const init = () => {
type: 'warning' type: 'warning'
}) })
} }
loading.value = true
const url = localStorage.getItem('WebSocketUrl') || 'null' //'ws://192.168.1.68:10407/api/pushMessage/'
echartsDataV1.value = initEcharts('#DAA520', 0, 'A相')
echartsDataV2.value = initEcharts('#2E8B57', 0, 'B相')
echartsDataV3.value = initEcharts('#A52a2a', 0, 'C相')
echartsDataA1.value = initEcharts('#DAA520', 1, 'A相')
echartsDataA2.value = initEcharts('#2E8B57', 1, 'B相')
echartsDataA3.value = initEcharts('#A52a2a', 1, 'C相')
let pids = monitoringPoint.state.pid.split(',') let pids = monitoringPoint.state.pid.split(',')
dataSocket.socketServe.connect(`${url}${adminInfo.id},${monitoringPoint.state.lineId},${pids[pids.length - 2]}`) dataSocket.socketServe.connect(`${url}${adminInfo.id},${monitoringPoint.state.lineId},${pids[pids.length - 2]}`)
dataSocket.socketServe.registerCallBack('message', (res: any) => { dataSocket.socketServe.registerCallBack('message', (res: any) => {
if (res.Flag === false) {
return (loading.value = false)
}
txtContent.value = res.value txtContent.value = res.value
let data = JSON.parse(res.value) let data = JSON.parse(res.value)
time.value = data.TIME - 0 time.value = data.TIME - 0
@@ -779,12 +782,12 @@ const init = () => {
iRmsA: data.I.A?.IRMS, //A相电流 iRmsA: data.I.A?.IRMS, //A相电流
iRmsB: data.I.B?.IRMS, //B相电流 iRmsB: data.I.B?.IRMS, //B相电流
iRmsC: data.I.C?.IRMS, //C相电流 iRmsC: data.I.C?.IRMS, //C相电流
v1AngA: data.V.A?.VFUND_ANGLE, //A相基波电压相位 v1AngA: steAngle(data.V.A?.VFUND_ANGLE), //A相基波电压相位
v1AngB: data.V.B?.VFUND_ANGLE, //B相基波电压相位 v1AngB: steAngle(data.V.B?.VFUND_ANGLE), //B相基波电压相位
v1AngC: data.V.C?.VFUND_ANGLE, //C相基波电压相位 v1AngC: steAngle(data.V.C?.VFUND_ANGLE), //C相基波电压相位
i1AngA: data.I.A?.I_ANGLE, //A相基波电流相位 i1AngA: steAngle(data.I.A?.I_ANGLE), //A相基波电流相位
i1AngB: data.I.B?.I_ANGLE, //B相基波电流相位 i1AngB: steAngle(data.I.B?.I_ANGLE), //B相基波电流相位
i1AngC: data.I.C?.I_ANGLE, //C相基波电流相位 i1AngC: steAngle(data.I.C?.I_ANGLE), //C相基波电流相位
freq: data.V.T?.FREQ, //频率 freq: data.V.T?.FREQ, //频率
freqDev: data.V.T?.DELTA_FREQ, //频率偏差 freqDev: data.V.T?.DELTA_FREQ, //频率偏差
vUnbalance: data.V.T?.V_UNBAN, //电压不平衡度 vUnbalance: data.V.T?.V_UNBAN, //电压不平衡度
@@ -868,6 +871,22 @@ const setRealData = () => {
// webMsgSend.value[0].vRmsB == 0 ? 1 : Math.ceil(webMsgSend.value[0].vRmsB) // webMsgSend.value[0].vRmsB == 0 ? 1 : Math.ceil(webMsgSend.value[0].vRmsB)
// echartsDataV3.value.options.series[0].max = // echartsDataV3.value.options.series[0].max =
// webMsgSend.value[0].vRmsC == 0 ? 1 : Math.ceil(webMsgSend.value[0].vRmsC) // webMsgSend.value[0].vRmsC == 0 ? 1 : Math.ceil(webMsgSend.value[0].vRmsC)
let vMax =
Math.ceil(
(Math.max(
...[
Math.floor(webMsgSend.value[0].vRmsA * 100) / 100 || 10,
Math.floor(webMsgSend.value[0].vRmsB * 100) / 100 || 10,
Math.floor(webMsgSend.value[0].vRmsC * 100) / 100 || 10
]
) *
1.2) /
10
) * 10
echartsDataV1.value.options.series[0].max = vMax
echartsDataV2.value.options.series[0].max = vMax
echartsDataV3.value.options.series[0].max = vMax
echartsDataV1.value.options.series[0].data = [ echartsDataV1.value.options.series[0].data = [
{ {
name: ptName.value == 'star' ? 'A相' : 'AB相', //A相 name: ptName.value == 'star' ? 'A相' : 'AB相', //A相
@@ -896,6 +915,22 @@ const setRealData = () => {
// webMsgSend.value[0].iRmsB == 0 ? 1 : Math.ceil(webMsgSend.value[0].iRmsB) // webMsgSend.value[0].iRmsB == 0 ? 1 : Math.ceil(webMsgSend.value[0].iRmsB)
// echartsDataA3.value.options.series[0].max = // echartsDataA3.value.options.series[0].max =
// webMsgSend.value[0].iRmsC == 0 ? 1 : Math.ceil(webMsgSend.value[0].iRmsC) // webMsgSend.value[0].iRmsC == 0 ? 1 : Math.ceil(webMsgSend.value[0].iRmsC)
let aMax =
Math.ceil(
(Math.max(
...[
Math.floor(webMsgSend.value[0].iRmsA * 100) / 100 || 10,
Math.floor(webMsgSend.value[0].iRmsB * 100) / 100 || 10,
Math.floor(webMsgSend.value[0].iRmsC * 100) / 100 || 10
]
) *
1.2) /
10
) * 10
echartsDataA1.value.options.series[0].max = aMax
echartsDataA2.value.options.series[0].max = aMax
echartsDataA3.value.options.series[0].max = aMax
echartsDataA1.value.options.series[0].data = [ echartsDataA1.value.options.series[0].data = [
{ {
name: 'A相', name: 'A相',
@@ -918,16 +953,28 @@ const setRealData = () => {
] ]
pieChart6.value.initChart() pieChart6.value.initChart()
} }
const steAngle = (phase: any) => {
// 空值判断
if (phase === null || phase === undefined) {
return null
}
let normalizedPhase = phase % 360
if (normalizedPhase > 180) {
normalizedPhase -= 360
} else if (normalizedPhase < -180) {
normalizedPhase += 360
}
return normalizedPhase
}
defineExpose({ setRealData }) defineExpose({ setRealData })
onMounted(() => { onMounted(() => {
init() init()
initRadioCharts() initRadioCharts()
getLineDetail({ id: monitoringPoint.state.lineId }).then(res => { getLineDetail({ id: monitoringPoint.state.lineId }).then(res => {
ptName.value = connection.filter(item => item.value == res.data.ptType)[0].code || '' ptName.value = connection.filter(item => item.value == res.data.ptType)[0].code || ''
}) })
}) })
onBeforeUnmount(() => { onBeforeUnmount(() => {
dataSocket.socketServe?.closeWs() dataSocket.socketServe?.closeWs()

View File

@@ -103,7 +103,11 @@ const init = () => {
) )
} }
options.value = { options.value = {
title: {
text: formData.harmState == 0 ? '谐波电压频谱' : '谐波电流频谱'
},
xAxis: { xAxis: {
name: '次数', name: '次数',
type: 'category', type: 'category',
data: Array.from({ length: 49 }, (_, i) => `${i + 2}`) data: Array.from({ length: 49 }, (_, i) => `${i + 2}`)

View File

@@ -9,7 +9,7 @@
clearable clearable
maxlength="32" maxlength="32"
show-word-limit show-word-limit
placeholder="筛选数据" placeholder="请输入关键字"
/> />
</el-form-item> </el-form-item>
</template> </template>
@@ -35,8 +35,8 @@ defineOptions({
name: 'harmonic-boot/reate/word' name: 'harmonic-boot/reate/word'
}) })
const dictData = useDictData() const dictData = useDictData()
//区域联级选择 //行业类型选择
const industry = dictData.getBasicData('Interference_Source') const industry = dictData.getBasicData('Business_Type')
//用户信息弹出框 //用户信息弹出框
const tableRef = ref() const tableRef = ref()

View File

@@ -1,156 +1,222 @@
<template> <template>
<div class="default-main"> <div class="default-main">
<TableHeader area ref="TableHeaderRef" showExport>
<TableHeader area showExport>
<template #select> <template #select>
<!-- <el-form-item label="统计类型:"> <el-form-item label="运行状态">
<el-select v-model="tableStore.table.params.statisticalType" placeholder="请选择统计类型" value-key="id"> <el-select filterable multiple collapse-tags v-model="tableStore.table.params.runFlag" clearable
<el-option v-for="item in classificationData" :key="item.id" :label="item.name" :value="item"> placeholder="请选择运行状态">
</el-option> <el-option v-for="item in runFlagList" :key="item.id" :label="item.name"
</el-select> :value="item.id"></el-option>
</el-form-item> -->
<el-form-item label="电压等级:">
<el-select v-model="tableStore.table.params.scale" filterable multiple collapse-tags clearable
placeholder="请选择电压等级" value-key="id">
<el-option v-for="item in voltageleveloption" :key="item.id" :label="item.name" :value="item">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="终端厂家:">
<el-select v-model="tableStore.table.params.manufacturer" filterable multiple collapse-tags
clearable placeholder="请选择终端厂家" value-key="id">
<el-option v-for="item in terminaloption" :key="item.id" :label="item.name" :value="item">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="干扰源类型:">
<el-select v-model="tableStore.table.params.loadType" filterable multiple collapse-tags clearable
placeholder="请选择干扰源类型" value-key="id">
<el-option v-for="item in interfereoption" :key="item.id" :label="item.name" :value="item">
</el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="通讯状态">
<el-form-item label="通讯状态:">
<el-select v-model="tableStore.table.params.comFlag" filterable multiple collapse-tags clearable <el-select v-model="tableStore.table.params.comFlag" filterable multiple collapse-tags clearable
placeholder="请选择通讯状态"> placeholder="请选择通讯状态">
<el-option v-for="item in communicationstatus" :key="item.value" :label="item.label" <el-option v-for="item in communicationstatus" :key="item.value" :label="item.label"
:value="item.value"> :value="item.value"></el-option>
</el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="终端状态:">
<el-select v-model="tableStore.table.params.runFlag" filterable multiple collapse-tags clearable <el-form-item label="电压等级">
placeholder="请选择终端状态"> <el-select v-model="tableStore.table.params.scale" filterable multiple collapse-tags clearable
<el-option v-for="item in terminalstatus" :key="item.value" :label="item.label" placeholder="请选择电压等级" value-key="id">
:value="item.value"> <el-option v-for="item in voltageleveloption" :key="item.id" :label="item.name"
</el-option> :value="item"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="评价筛选"> <el-form-item label="终端厂家">
<el-input v-model="tableStore.table.params.evaluate" clearable placeholder="输入关键字筛选" maxlength="32" show-word-limit /> <el-select v-model="tableStore.table.params.manufacturer" filterable multiple collapse-tags
clearable placeholder="请选择终端厂家" value-key="id">
<el-option v-for="item in terminaloption" :key="item.id" :label="item.name"
:value="item"></el-option>
</el-select>
</el-form-item>
<el-form-item label="干扰源类型">
<el-select v-model="tableStore.table.params.loadType" filterable multiple collapse-tags clearable
placeholder="请选择干扰源类型" value-key="id">
<el-option v-for="item in interfereoption" :key="item.id" :label="item.name"
:value="item"></el-option>
</el-select>
</el-form-item>
<el-form-item label="数据筛选">
<el-input style="width: 240px" placeholder="电站名称,终端编号,监测点名称、电压等级、终端厂家、干扰源类型"
v-model="tableStore.table.params.searchValue" clearable maxlength="32"
show-word-limit></el-input>
</el-form-item> </el-form-item>
</template> </template>
<template #operation>
<!-- <el-button icon="el-icon-Download" type="primary">导出</el-button> -->
</template>
</TableHeader> </TableHeader>
<Table ref="tableRef" /> <Table ref="tableRef" />
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, provide } from 'vue' import { ref, onMounted, provide, nextTick, watch } from 'vue'
import TableStore from '@/utils/tableStore' import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue' import Table from '@/components/table/index.vue'
import { useDictData } from '@/stores/dictData'
import TableHeader from '@/components/table/header/index.vue' import TableHeader from '@/components/table/header/index.vue'
const dictData = useDictData() import { useDictData } from '@/stores/dictData'
defineOptions({
name: 'harmonic-boot/run/devicemessage'
})
const view = ref(true)
const classificationData = dictData.getBasicData('Statistical_Type', ["Report_Type"])
const voltageleveloption = dictData.getBasicData('Dev_Voltage_Stand')
const terminaloption = dictData.getBasicData('Dev_Manufacturers')
const interfereoption = dictData.getBasicData('Interference_Source')
const communicationstatus = [ const dictData = useDictData()
{ value: 0, label: "中断" }, const TableHeaderRef = ref()
{ value: 1, label: "正常" }, const areaOptionList = dictData.getBasicData('jibei_area')
] const interfereoption = dictData.getBasicData('Interference_Source')
const terminalstatus = [ const terminaloption = dictData.getBasicData('Dev_Manufacturers')
{ value: 0, label: "投运" }, const voltageleveloption = dictData.getBasicData('Dev_Voltage_Stand')
{ value: 1, label: "检修" },
{ value: 2, label: "停运" },
]
const tableStore = new TableStore({ const tableStore = new TableStore({
url: '/device-boot/runManage/getLineLedger', url: '/device-boot/runManage/getLineLedgerComm',
method: 'POST', method: 'POST',
isWebPaging: true, filename: '监测点台账',
column: [ column: [
{ {
field: 'index',
title: '序号', title: '序号',
width: '80', width: 80,
formatter: (row: any) => { formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1 return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
} }
}, },
{ field: 'areaName', title: '区域',minWidth: 100 },
{ field: 'gdName', title: '供电公司' ,minWidth: 100}, {
field: 'areaName',
title: '省公司',
minWidth: 100
},
{ field: 'gdName', title: '市公司', minWidth: 150 },
{ {
field: 'bdName', field: 'bdName',
title: '站', title: '所属变电站',
minWidth: 100 minWidth: 150
}, },
{ field: 'objName', title: '对象名称' , minWidth: 240}, {
{ field: 'lineName', title: '监测点名称' , minWidth: 100}, field: 'objName',
{ field: 'manufacturer', title: '厂家' , minWidth: 100}, title: '监测对象名称',
{ field: 'scale', title: '电压等级' , minWidth: 100}, minWidth: 150,
{ field: 'businessType', title: '行业类型' , minWidth: 100}, formatter: (row: any) => {
return row.cellValue ? row.cellValue : '/'
}
},
{ field: 'lineName', title: '监测点名称', minWidth: 130 },
{ field: 'scale', title: '监测点电压等级', minWidth: 120 },
{ field: 'devName', title: '终端名称', minWidth: 80 }, { field: 'loadType', title: '干扰源类型', minWidth: 120 },
{ field: 'ip', title: '网络参数' ,width:'120px'},
// { field: 'comFlag', title: '通讯状态' , minWidth: 100}, {
field: 'manufacturer',
title: '终端厂家',
minWidth: 100,
formatter: (row: any) => {
return row.cellValue ? row.cellValue : '/'
}
},
{
field: 'runFlag',
title: '运行状态',
minWidth: 80,
render: 'tag',
custom: {
投运: 'success',
停运: 'danger',
检修: 'warning',
调试: 'warning',
退运: 'danger'
}
},
{ {
field: 'comFlag', field: 'comFlag',
title: '通讯状态', title: '通讯状态',
render: 'tag', render: 'tag',
minWidth: 100,
// effect: 'dark', // effect: 'dark',
minWidth: 70,
custom: { custom: {
'正常': 'success', 正常: 'success',
'中断': 'danger', 中断: 'danger'
}
},
}, },
{ field: 'loadType', title: '干扰源类型' , minWidth: 100}, {
field: 'shortCapacity',
title: '最小短路容量(MVA)',
minWidth: 150
},
{
field: 'devCapacity',
title: '供电设备容量(MVA )',
minWidth: 160
},
{
field: 'dealCapacity',
title: '用户协议容量(MVA)',
minWidth: 150
},
{ field: 'id', title: '监测点序号', minWidth: 90 },
{ field: 'devName', title: '监测终端编号 ', minWidth: 140 },
{ field: 'ptType', title: '监测终端接线方式', minWidth: 140 },
{
field: 'voltageDev',
title: '电压偏差上限(%)',
minWidth: 140
},
{
field: 'uvoltageDev',
title: '电压偏差下限(%)',
minWidth: 140
}
/* {
title: '操作',fixed: 'right',
minWidth: 150,
fixed: 'right',
render: 'buttons',
buttons: [
{
name: 'productSetting',
title: '流程详情',
type: 'primary',
icon: 'el-icon-EditPen',
render: 'basicButton',
click: row => {
}
}
]
}*/
], ],
loadCallback: () => { beforeSearchFun: () => {
tableStore.table.data.map((item: any) => { tableStore.table.params.serverName = 'harmonic-boot'
item.onlineEvaluate == 3.14159 ? item.onlineEvaluate = '/' : item.onlineEvaluate <= 0.6 ? item.onlineEvaluate = '差' : item.onlineEvaluate <= 0.9 ? item.onlineEvaluate = '良' : item.onlineEvaluate <= 1 ? item.onlineEvaluate = '优' : '/' tableStore.table.params.statisticalType = {
}) name: '电网拓扑',
code: 'Power_Network'
}
} }
}) })
tableStore.table.params.statisticalType = classificationData[0]
tableStore.table.params.serverName = "harmonic-boot"
tableStore.table.params.comFlag = []
tableStore.table.params.runFlag = [] tableStore.table.params.runFlag = []
tableStore.table.params.evaluate = '' tableStore.table.params.comFlag = []
tableStore.table.params.powerFlag = 2 tableStore.table.params.powerFlag = 2
tableStore.table.params.monitorFlag = 2 tableStore.table.params.monitorFlag = 2
tableStore.table.params.searchValue = ''
tableStore.table.params.scale = [] tableStore.table.params.scale = []
tableStore.table.params.manufacturer = [] tableStore.table.params.manufacturer = []
tableStore.table.params.loadType = [] tableStore.table.params.loadType = []
const wp = ref({}) const runFlagList = [
{ id: 0, name: '投运' },
{ id: 1, name: '检修' },
{ id: 2, name: '停运' },
]
const communicationstatus = [
{ value: 0, label: '中断' },
{ value: 1, label: '正常' }
]
provide('tableStore', tableStore) provide('tableStore', tableStore)
onMounted(() => { onMounted(() => {
@@ -159,6 +225,4 @@ onMounted(() => {
</script> </script>

View File

@@ -3,7 +3,7 @@
<TableHeader area> <TableHeader area>
<template #select> <template #select>
<el-form-item label="监测点性质:"> <el-form-item label="监测点性质">
<el-select v-model="tableStore.table.params.powerFlag" filterable collapse-tags <el-select v-model="tableStore.table.params.powerFlag" filterable collapse-tags
placeholder="请选择监测点性质"> placeholder="请选择监测点性质">
<el-option v-for="item in terminalstatus" :key="item.value" :label="item.label" <el-option v-for="item in terminalstatus" :key="item.value" :label="item.label"
@@ -11,7 +11,7 @@
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="电压等级:"> <el-form-item label="电压等级">
<el-select v-model="tableStore.table.params.scale" filterable multiple collapse-tags clearable <el-select v-model="tableStore.table.params.scale" filterable multiple collapse-tags clearable
placeholder="请选择电压等级" value-key="id"> placeholder="请选择电压等级" value-key="id">
<el-option v-for="item in voltageleveloption" :key="item.id" :label="item.name" :value="item"> <el-option v-for="item in voltageleveloption" :key="item.id" :label="item.name" :value="item">
@@ -19,14 +19,14 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="终端厂家:"> <el-form-item label="终端厂家">
<el-select v-model="tableStore.table.params.manufacturer" filterable multiple collapse-tags <el-select v-model="tableStore.table.params.manufacturer" filterable multiple collapse-tags
clearable placeholder="请选择终端厂家" value-key="id"> clearable placeholder="请选择终端厂家" value-key="id">
<el-option v-for="item in terminaloption" :key="item.id" :label="item.name" :value="item"> <el-option v-for="item in terminaloption" :key="item.id" :label="item.name" :value="item">
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="干扰源类型:"> <el-form-item label="干扰源类型">
<el-select v-model="tableStore.table.params.loadType" filterable multiple collapse-tags clearable <el-select v-model="tableStore.table.params.loadType" filterable multiple collapse-tags clearable
placeholder="请选择干扰源类型" value-key="id"> placeholder="请选择干扰源类型" value-key="id">
<el-option v-for="item in interfereoption" :key="item.id" :label="item.name" :value="item"> <el-option v-for="item in interfereoption" :key="item.id" :label="item.name" :value="item">
@@ -37,7 +37,7 @@
<el-form-item label="上报类型:"> <el-form-item label="上报类型">
<el-select v-model="tableStore.table.params.monitorFlag" <el-select v-model="tableStore.table.params.monitorFlag"
placeholder="请选择上报类型"> placeholder="请选择上报类型">
<el-option v-for="item in communicationstatus" :key="item.value" :label="item.label" <el-option v-for="item in communicationstatus" :key="item.value" :label="item.label"

View File

@@ -1,33 +1,16 @@
<template> <template>
<div class="default-main"> <div class="default-main">
<TableHeader area showExport> <TableHeader area ref="TableHeaderRef" showExport>
<template #select> <template #select>
<!-- <el-form-item label="统计类型:"> <!-- <el-form-item label="统计类型:">
<el-select v-model="tableStore.table.params.statisticalType" placeholder="请选择统计类型" value-key="id"> <el-select v-model="tableStore.table.params.statisticalType" placeholder="请选择统计类型" value-key="id">
<el-option v-for="item in classificationData" :key="item.id" :label="item.name" :value="item"> <el-option v-for="item in classificationData" :key="item.id" :label="item.name" :value="item">
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> --> </el-form-item> -->
<el-form-item label="电压等级:">
<el-select <el-form-item label="终端厂家">
v-model="tableStore.table.params.scale"
filterable
multiple
collapse-tags
clearable
placeholder="请选择电压等级"
value-key="id"
>
<el-option
v-for="item in voltageleveloption"
:key="item.id"
:label="item.name"
:value="item"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="终端厂家:">
<el-select <el-select
v-model="tableStore.table.params.manufacturer" v-model="tableStore.table.params.manufacturer"
filterable filterable
@@ -45,7 +28,49 @@
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="干扰源类型:"> <el-form-item label="数据筛选">
<el-input
v-model="tableStore.table.params.searchValue"
clearable
placeholder="输入市公司、变电站、用户"
/>
</el-form-item>
<el-form-item label="通讯状态">
<el-select
v-model="tableStore.table.params.comF"
filterable
multiple
collapse-tags
clearable
placeholder="请选择通讯状态"
>
<el-option
v-for="item in communicationstatus"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="终端状态">
<el-select
v-model="tableStore.table.params.runF"
filterable
multiple
collapse-tags
clearable
placeholder="请选择终端状态"
>
<el-option
v-for="item in terminalstatus"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="干扰源类型">
<el-select <el-select
v-model="tableStore.table.params.loadType" v-model="tableStore.table.params.loadType"
filterable filterable
@@ -63,59 +88,41 @@
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="电压等级">
<el-form-item label="通讯状态:">
<el-select <el-select
v-model="tableStore.table.params.comFlag" v-model="tableStore.table.params.scale"
filterable filterable
multiple multiple
collapse-tags collapse-tags
clearable clearable
placeholder="请选择通讯状态" placeholder="请选择电压等级"
value-key="id"
> >
<el-option <el-option
v-for="item in communicationstatus" v-for="item in voltageleveloption"
:key="item.value" :key="item.id"
:label="item.label" :label="item.name"
:value="item.value" :value="item"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="终端状态:">
<el-select
v-model="tableStore.table.params.runFlag"
filterable
multiple
collapse-tags
clearable
placeholder="请选择终端状态"
>
<el-option
v-for="item in terminalstatus"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<!-- <el-form-item label="评价筛选">
<el-input v-model="tableStore.table.params.evaluate" clearable placeholder="输入关键字筛选" />
</el-form-item> -->
</template> </template>
</TableHeader> </TableHeader>
<Table ref="tableRef" /> <Table ref="tableRef" />
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, provide } from 'vue' import { ref, onMounted, provide, nextTick } from 'vue'
import TableStore from '@/utils/tableStore' import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue' import Table from '@/components/table/index.vue'
import { useDictData } from '@/stores/dictData'
import TableHeader from '@/components/table/header/index.vue' import TableHeader from '@/components/table/header/index.vue'
const dictData = useDictData() import { useDictData } from '@/stores/dictData'
defineOptions({ defineOptions({
name: 'harmonic-boot/run/terminalmessage' name: 'harmonic-boot/run/terminalmessage'
}) })
const dictData = useDictData()
const view = ref(true) const view = ref(true)
const classificationData = dictData.getBasicData('Statistical_Type', ['Report_Type', 'Voltage_Level', 'Load_Type']) const classificationData = dictData.getBasicData('Statistical_Type', ['Report_Type', 'Voltage_Level', 'Load_Type'])
const voltageleveloption = dictData.getBasicData('Dev_Voltage_Stand') const voltageleveloption = dictData.getBasicData('Dev_Voltage_Stand')
@@ -134,37 +141,41 @@ const terminalstatus = [
const tableStore = new TableStore({ const tableStore = new TableStore({
url: '/device-boot/runManage/getRuntimeData', url: '/device-boot/runManage/getRuntimeData',
method: 'POST', method: 'POST',
isWebPaging: true,
column: [ column: [
{ {
field: 'index', field: 'index',
title: '序号', title: '序号',
width: '80', width: '70',
formatter: (row: any) => { formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1 return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
} }
}, },
{ field: 'areaName', title: '区域', minWidth: 100 }, { field: 'areaName', title: '区域', minWidth: 90 },
{ field: 'gdName', title: '供电公司', minWidth: 100 }, { field: 'gdName', title: '公司', minWidth: 110 },
{ {
field: 'bdName', field: 'bdName',
title: '站', title: '变电站',
minWidth: 100 minWidth: 110
},
{
field: 'objName',
title: '用户对象',
minWidth: 110
}, },
{ field: 'manufacturer', title: '厂家', minWidth: 100 }, { field: 'manufacturer', title: '厂家', minWidth: 100 },
{ field: 'devName', title: '终端名称', minWidth: 80 }, { field: 'devName', title: '终端名称', minWidth: 100 },
{ field: 'ip', title: '网络参数' ,width:'120px' }, { field: 'ip', title: '网络参数', width: 110 },
{ field: 'loginTime', title: '投运时间', minWidth: 100 }, { field: 'loginTime', title: '投运时间', minWidth: 90 },
{ field: 'devType', title: '终端型号', minWidth: 100 }, { field: 'devType', title: '终端型号', minWidth: 100 },
{ field: 'port', title: '端口', minWidth: 100 }, { field: 'port', title: '端口', minWidth: 60 },
{ field: 'updateTime', title: '最新数据', minWidth: 100 }, { field: 'updateTime', title: '最新数据', minWidth: 110 },
{ {
field: 'runFlag', field: 'runFlag',
title: '终端状态', title: '终端状态',
// effect: 'dark', // effect: 'dark',
render: 'tag', render: 'tag',
minWidth: 100, minWidth: 70,
custom: { custom: {
投运: 'success', 投运: 'success',
检修: 'warning', 检修: 'warning',
@@ -176,56 +187,43 @@ const tableStore = new TableStore({
title: '通讯状态', title: '通讯状态',
render: 'tag', render: 'tag',
// effect: 'dark', // effect: 'dark',
minWidth: 100, minWidth: 70,
custom: { custom: {
正常: 'success', 正常: 'success',
中断: 'danger' 中断: 'danger'
} }
},
{
field: 'onlineEvaluate',
title: '在线率评价',
render: 'tag',
// effect: 'dark',
minWidth: 100,
custom: {
'/': 'info',
: 'success',
: 'warning',
: 'danger'
}
} }
], ],
loadCallback: () => { beforeSearchFun: () => {
tableStore.table.webPagingData.map((item1: any) => { tableStore.table.params.serverName = 'harmonic-boot'
item1.map((item: any) => { tableStore.table.params.statisticalType = {
item.onlineEvaluate == 3.14159 name: '电网拓扑',
? (item.onlineEvaluate = '/') code: 'Power_Network'
: item.onlineEvaluate <= 0.6 }
? (item.onlineEvaluate = '差')
: item.onlineEvaluate <= 0.9
? (item.onlineEvaluate = '良')
: item.onlineEvaluate <= 1
? (item.onlineEvaluate = '优')
: '/'
})
})
tableStore.table.params.runFlag = []
if (tableStore.table.params.runF != null && tableStore.table.params.runF != '') {
tableStore.table.params.runFlag = tableStore.table.params.runF
}
tableStore.table.params.comFlag = []
if (tableStore.table.params.comF != null && tableStore.table.params.comF != '') {
tableStore.table.params.comFlag = tableStore.table.params.comF
}
} }
}) })
tableStore.table.params.runF = ''
tableStore.table.params.comF = ''
tableStore.table.params.statisticalType = classificationData[0] tableStore.table.params.statisticalType = classificationData[0]
tableStore.table.params.serverName = 'harmonic-boot' tableStore.table.params.serverName = 'harmonic-boot'
tableStore.table.params.comFlag = [] tableStore.table.params.comFlag = []
tableStore.table.params.runFlag = [] tableStore.table.params.runFlag = []
// tableStore.table.params.evaluate = '' tableStore.table.params.searchValue = ''
tableStore.table.params.powerFlag = 2 tableStore.table.params.powerFlag = 2
tableStore.table.params.monitorFlag = 2 tableStore.table.params.monitorFlag = 2
tableStore.table.params.scale = [] tableStore.table.params.scale = []
tableStore.table.params.manufacturer = [] tableStore.table.params.manufacturer = []
tableStore.table.params.loadType = [] tableStore.table.params.loadType = []
const wp = ref({})
provide('tableStore', tableStore) provide('tableStore', tableStore)
onMounted(() => { onMounted(() => {

View File

@@ -8621,6 +8621,91 @@ const 葫芦岛 = [
] ]
] ]
const = [
[
{ lng: 110.106525, lat:20.026851},
{ lng: 110.161895, lat:19.977693},
{ lng: 110.143932, lat:19.889106},
{ lng: 110.186246, lat:19.864193},
{ lng: 110.228283, lat:19.753767},
{ lng: 110.208468, lat:19.716679},
{ lng: 110.222357, lat:19.67974},
{ lng: 110.262449, lat:19.687318},
{ lng: 110.314208, lat:19.697421},
{ lng: 110.340041, lat:19.720625},
{ lng: 110.393373, lat:19.698053},
{ lng: 110.372633, lat:19.654004},
{ lng: 110.401151, lat:19.606626},
{ lng: 110.455687, lat:19.574559},
{ lng: 110.486705, lat:19.593357},
{ lng: 110.519297, lat:19.563341},
{ lng: 110.540223, lat:19.535532},
{ lng: 110.611518, lat:19.526841},
{ lng: 110.641333, lat:19.549122},
{ lng: 110.636148, lat:19.593989},
{ lng: 110.672814, lat:19.647214},
{ lng: 110.623463, lat:19.664109},
{ lng: 110.623, lat:19.735461},
{ lng: 110.670314, lat:19.812776},
{ lng: 110.704665, lat:19.805992},
{ lng: 110.699573, lat:19.861512},
{ lng: 110.676147, lat:19.860092},
{ lng: 110.675314, lat:19.907868},
{ lng: 110.634666, lat:19.965401},
{ lng: 110.598, lat:19.98305},
{ lng: 110.526612, lat:20.075206},
{ lng: 110.495039, lat:20.077253},
{ lng: 110.387355, lat:20.11347},
{ lng: 110.318467, lat:20.109061},
{ lng: 110.293282, lat:20.059614},
{ lng: 110.24319, lat:20.077568},
{ lng: 110.144395, lat:20.074418},
{ lng: 110.106525, lat:20.026851}
]
]
const =[
[
{ lng: 108.932374, lat:18.335288},
{ lng: 108.956448, lat:18.307433},
{ lng: 109.006632, lat:18.323032},
{ lng: 109.108298, lat:18.323828},
{ lng: 109.138668, lat:18.267791},
{ lng: 109.174686, lat:18.260149},
{ lng: 109.28811, lat:18.264925},
{ lng: 109.355887, lat:18.214922},
{ lng: 109.441349, lat:18.199153},
{ lng: 109.4632, lat:18.177171},
{ lng: 109.527366, lat:18.169046},
{ lng: 109.561718, lat:18.143554},
{ lng: 109.63792, lat:18.171595},
{ lng: 109.72616, lat:18.177808},
{ lng: 109.749863, lat:18.19326},
{ lng: 109.783381, lat:18.337516},
{ lng: 109.805418, lat:18.347543},
{ lng: 109.785048, lat:18.426622},
{ lng: 109.809955, lat:18.459388},
{ lng: 109.781159, lat:18.51107},
{ lng: 109.725234, lat:18.493102},
{ lng: 109.710882, lat:18.426462},
{ lng: 109.665883, lat:18.391462},
{ lng: 109.539866, lat:18.396713},
{ lng: 109.515607, lat:18.429008},
{ lng: 109.536996, lat:18.490717},
{ lng: 109.535237, lat:18.53142},
{ lng: 109.506163, lat:18.551291},
{ lng: 109.423386, lat:18.574657},
{ lng: 109.405146, lat:18.623443},
{ lng: 109.332832, lat:18.575451},
{ lng: 109.313295, lat:18.517429},
{ lng: 109.246537, lat:18.558921},
{ lng: 109.203574, lat:18.553517},
{ lng: 109.185056, lat:18.507095},
{ lng: 109.195148, lat:18.469407},
{ lng: 109.072557, lat:18.452231},
{ lng: 109.015243, lat:18.422645},
{ lng: 108.932374, lat:18.335288}
]
]
export default { export default {
zjkJSON, zjkJSON,
lfJSON, lfJSON,
@@ -8640,5 +8725,7 @@ export default {
, ,
, ,
, ,
,
,
} }

File diff suppressed because it is too large Load Diff

View File

@@ -53,6 +53,10 @@
</div> </div>
<div class="collapse_none" style="color: red; cursor: pointer" @click="showWrap = false">关闭</div> <div class="collapse_none" style="color: red; cursor: pointer" @click="showWrap = false">关闭</div>
</div> </div>
<baidu-map <baidu-map
class="map" class="map"
:style="height" :style="height"
@@ -329,6 +333,16 @@ const boundaryList: any = ref([
orgName: '鞍山', orgName: '鞍山',
LngLat: [122.808845, 40.840049], LngLat: [122.808845, 40.840049],
boundary: mapJson['鞍山'] boundary: mapJson['鞍山']
},
{
orgName: '海口',
LngLat: [110.32, 20.03],
boundary: mapJson['海口']
},
{
orgName: '三亚',
LngLat: [109.51, 18.25],
boundary: mapJson['三亚']
} }
]) ])
@@ -338,8 +352,10 @@ const siteList = ref<any>([])
const polyline = ref<any>([]) const polyline = ref<any>([])
const lineId = ref('') const lineId = ref('')
const center = ref({ const center = ref({
lng: 122.42588, lng: 122.42588,
lat: 40.810977 lat: 40.810977
// lng: 109.5, // 海南经度
// lat: 18.5 // 海南纬度
}) })
const infoWindowPoint = ref<anyObj>({ const infoWindowPoint = ref<anyObj>({
lng: 0, lng: 0,

File diff suppressed because it is too large Load Diff

View File

@@ -302,7 +302,7 @@ const list: any = ref([
]) ])
const countList: any = ref([ const countList: any = ref([
{ {
title: '冀北', title: '网公司',
children: [ children: [
{ {
title: '电网侧监测点', title: '电网侧监测点',

View File

@@ -314,7 +314,7 @@ const list: any = ref([
]) ])
const countList: any = ref([ const countList: any = ref([
{ {
title: '冀北', title: '网公司',
children: [ children: [
{ {
title: '电网侧监测点', title: '电网侧监测点',

View File

@@ -27,7 +27,7 @@
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="终端厂家:"> <el-form-item label="终端厂家">
<el-select v-model="tableStore.table.params.manufacturer" clearable placeholder="请选择终端厂家"> <el-select v-model="tableStore.table.params.manufacturer" clearable placeholder="请选择终端厂家">
<el-option <el-option
v-for="item in terminaloption" v-for="item in terminaloption"

View File

@@ -363,7 +363,7 @@ defineExpose({
.actionButtons { .actionButtons {
display: flex; display: flex;
justify-content: end; justify-content: flex-end;
} }
.loading-container { .loading-container {

View File

@@ -28,6 +28,7 @@
</el-collapse-item> </el-collapse-item>
<el-collapse-item :title="item.name" v-for="(item, index) in column" :key="index" :name="index + 3"> <el-collapse-item :title="item.name" v-for="(item, index) in column" :key="index" :name="index + 3">
<div style="height: 200px"> <div style="height: 200px">
<vxe-table height="auto" :data="form[item.key]" v-bind="defaultAttribute" v-loading="item.loading"> <vxe-table height="auto" :data="form[item.key]" v-bind="defaultAttribute" v-loading="item.loading">
<vxe-column type="seq" title="序号" width="80px"></vxe-column> <vxe-column type="seq" title="序号" width="80px"></vxe-column>
<vxe-column <vxe-column

View File

@@ -32,7 +32,7 @@
<el-form-item label="用户名称" prop="assessName"> <el-form-item label="用户名称" prop="assessName">
<el-input <el-input
v-model="form.assessName" v-model="form.assessName"
placeholder="用户名称" placeholder="请输入用户名称"
clearable clearable
show-word-limit show-word-limit
maxlength="32" maxlength="32"
@@ -127,7 +127,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="变电站电压等级" prop="powerstationScale"> <el-form-item label="变电站电压等级" prop="powerstationScale">
<el-select v-model="form.powerstationScale" disabled clearable placeholder="请选择变电站"> <el-select v-model="form.powerstationScale" disabled clearable placeholder="请选择变电站电压等级">
<el-option <el-option
v-for="item in voltageleveloption" v-for="item in voltageleveloption"
:key="item.id" :key="item.id"
@@ -147,7 +147,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="母线电压等级" prop="busScale"> <el-form-item label="母线电压等级" prop="busScale">
<el-select v-model="form.busScale" disabled clearable placeholder="请选择母线"> <el-select v-model="form.busScale" disabled clearable placeholder="请选择母线电压等级">
<el-option <el-option
v-for="item in voltageleveloption" v-for="item in voltageleveloption"
:key="item.id" :key="item.id"
@@ -189,7 +189,7 @@
</el-form-item> </el-form-item>
<el-form-item label="导线类型" prop="linetypeId"> <el-form-item label="导线类型" prop="linetypeId">
<el-select v-model="form.linetypeId" clearable placeholder="请选择变电站"> <el-select v-model="form.linetypeId" clearable placeholder="请选择导线类型">
<el-option <el-option
v-for="item in linetypeList" v-for="item in linetypeList"
:key="item.linetypeId" :key="item.linetypeId"
@@ -404,7 +404,7 @@ const info = async (id?: string) => {
const getUserList = async (e?: any) => { const getUserList = async (e?: any) => {
selectUserAssessMentList({ orgId: form.value.deptId, secondAssessmentId: form.value.assessId || '' }).then(res => { selectUserAssessMentList({ orgId: form.value.deptId, secondAssessmentId: form.value.assessId || '' }).then(res => {
userList.value = res.data userList.value = res.data
console.log('🚀 ~ getUserList ~ e:', e)
if (e) { if (e) {
assessMentId.value = res.data.filter(item => item.secondAssessmentId == form.value.assessId)[0]?.id || '' assessMentId.value = res.data.filter(item => item.secondAssessmentId == form.value.assessId)[0]?.id || ''
} else { } else {
@@ -454,7 +454,7 @@ onMounted(() => {
<style lang="scss" scoped> <style lang="scss" scoped>
.actionButtons { .actionButtons {
display: flex; display: flex;
justify-content: end; justify-content: flex-end;
} }
:deep(.el-collapse-item__header) { :deep(.el-collapse-item__header) {
// font-family: AlimamaDongFangDaKai; // font-family: AlimamaDongFangDaKai;

View File

@@ -102,7 +102,7 @@ import { ElMessage, ElMessageBox, ElDatePicker } from 'element-plus'
import { cableList, batchDel } from '@/api/advance-boot/assess' import { cableList, batchDel } from '@/api/advance-boot/assess'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import Form from './form.vue' import Form from './form.vue'
import { selectUserList, bindAssessmentId } from '@/api/device-boot/Business' import { bindAssessmentId } from '@/api/device-boot/Business'
import { forEach } from 'min-dash' import { forEach } from 'min-dash'
defineOptions({ defineOptions({
name: 'runManage/addUser' name: 'runManage/addUser'

View File

@@ -467,6 +467,7 @@ const dictionary = () => {
} }
onBeforeMount(async () => { onBeforeMount(async () => {
await dictionary() await dictionary()
info(0) // 变压器参数维护 info(0) // 变压器参数维护
info(1) // 电容器参数维护 info(1) // 电容器参数维护

View File

@@ -27,7 +27,7 @@
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="终端厂家:"> <el-form-item label="终端厂家">
<el-select v-model="tableStore.table.params.manufacturer" clearable placeholder="请选择终端厂家"> <el-select v-model="tableStore.table.params.manufacturer" clearable placeholder="请选择终端厂家">
<el-option <el-option
v-for="item in terminaloption" v-for="item in terminaloption"

View File

@@ -1,231 +1,231 @@
<template> <template>
<div :style="height" style="overflow-y: auto" class="pd10"> <div :style="height" style="overflow-y: auto" class="pd10">
<!-- <MyEChart :options="options" /> --> <!-- <MyEChart :options="options" /> -->
<div v-for="(item, index) in List"> <div v-for="(item, index) in List">
<div class="box" @mouseenter="item.flag = false" @mouseleave="item.flag = true"> <div class="box" @mouseenter="item.flag = false" @mouseleave="item.flag = true">
<div class="div">{{ item.name }} <span>({{ item.count }})</span></div> <div class="div">{{ item.name }} <span>({{ item.count }})</span></div>
<!-- <el-progress style="flex: 1" :percentage="(item.count / total).toFixed(2) * 100"> <!-- <el-progress style="flex: 1" :percentage="(item.count / total).toFixed(2) * 100">
<span>{{ item.count }}</span> <span>{{ item.count }}</span>
</el-progress> --> </el-progress> -->
<el-progress style="flex: 1" :percentage="item.score" :color="ratingColor(item.score)"> <el-progress style="flex: 1" :percentage="item.score" :color="ratingColor(item.score)">
<span v-if="item.flag" :style="`color:${ratingColor(item.score)}`"> <span v-if="item.flag" :style="`color:${ratingColor(item.score)}`">
{{ ratingName(item.score) }} {{ ratingName(item.score) }}
</span> </span>
<span v-else :style="`color:${ratingColor(item.score)}`">{{ item.score }}</span> <span v-else :style="`color:${ratingColor(item.score)}`">{{ item.score }}</span>
</el-progress> </el-progress>
</div> </div>
<el-divider /> <el-divider />
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, onMounted } from 'vue' import { ref, reactive, onMounted } from 'vue'
import MyEChart from '@/components/echarts/MyEchart.vue' import MyEChart from '@/components/echarts/MyEchart.vue'
import { mainHeight } from '@/utils/layout' import { mainHeight } from '@/utils/layout'
import { areaTerminalStatistic } from '@/api/device-boot/runEvaluate' import { areaTerminalStatistic } from '@/api/device-boot/runEvaluate'
const height = mainHeight(220, 1.5) const height = mainHeight(220, 1.5)
const props = defineProps({ const props = defineProps({
params: { params: {
type: Object, type: Object,
default: () => {} default: () => {}
} }
}) })
const List: any = ref([]) const List: any = ref([])
const total: any = ref(0) const total: any = ref(0)
const options = ref({}) const options = ref({})
const format = percentage => percentage + '分' const format = percentage => percentage + '分'
const info = () => { const info = () => {
areaTerminalStatistic(props.params).then(res => { areaTerminalStatistic(props.params).then(res => {
total.value = res.data.reduce((sum, item) => sum + Number(item.count), 0) total.value = res.data.reduce((sum, item) => sum + Number(item.count), 0)
List.value = res.data List.value = res.data
List.value.forEach(item => { List.value.forEach(item => {
item.flag = true item.flag = true
}) })
}) })
// let dataSource = [ // let dataSource = [
// { value: '90', name: '张家口' }, // { value: '90', name: '张家口' },
// { value: '80', name: '廊坊' }, // { value: '80', name: '廊坊' },
// { value: '70', name: '秦皇岛' }, // { value: '70', name: '秦皇岛' },
// { value: '60', name: '唐山' }, // { value: '60', name: '唐山' },
// { value: '50', name: '承德' } // { value: '50', name: '承德' }
// ] // ]
// options.value = { // options.value = {
// grid: { // grid: {
// top: '10' // top: '10'
// }, // },
// toolbox: { // toolbox: {
// show: false // show: false
// }, // },
// options: { // options: {
// yAxis: { // yAxis: {
// type: 'category', // type: 'category',
// data: dataSource.map(item => item.name), // data: dataSource.map(item => item.name),
// // axisLabel: { // // axisLabel: {
// // color: '#fff' // // color: '#fff'
// // }, // // },
// splitLine: { // splitLine: {
// show: false // show: false
// } // }
// }, // },
// xAxis: { // xAxis: {
// type: 'value', // type: 'value',
// data: [1, 2, 3, 4], // data: [1, 2, 3, 4],
// axisLabel: { // axisLabel: {
// show: true // show: true
// // textStyle: { // // textStyle: {
// // color: '#FFF' // // color: '#FFF'
// // }, // // },
// // formatter: function (value) { // // formatter: function (value) {
// // } // // }
// }, // },
// splitLine: { // splitLine: {
// show: false // show: false
// }, // },
// axisTick: { // axisTick: {
// show: false // show: false
// }, // },
// axisLine: { // axisLine: {
// show: true // show: true
// } // }
// }, // },
// dataZoom: null, // dataZoom: null,
// series: [ // series: [
// { // {
// type: 'bar', // type: 'bar',
// itemStyle: { // itemStyle: {
// color: function (params) { // color: function (params) {
// return params.value >= 90 // return params.value >= 90
// ? '#00b07d' // ? '#00b07d'
// : params.value >= 80 // : params.value >= 80
// ? '#2b7fd3' // ? '#2b7fd3'
// : params.value >= 70 // : params.value >= 70
// ? '#ffcc33' // ? '#ffcc33'
// : '#c00' // : '#c00'
// } // }
// }, // },
// markLine: { // markLine: {
// silent: false, // silent: false,
// symbol: 'circle', // symbol: 'circle',
// data: [ // data: [
// { // {
// name: '', // name: '',
// yAxis: 100, // yAxis: 100,
// lineStyle: { // lineStyle: {
// color: '#2E8B57' // color: '#2E8B57'
// }, // },
// label: { // label: {
// show: true, // show: true,
// formatter: '优质', // formatter: '优质',
// color: '#2E8B57' // color: '#2E8B57'
// } // }
// }, // },
// { // {
// name: '', // name: '',
// yAxis: 90, // yAxis: 90,
// lineStyle: { // lineStyle: {
// color: '#77DA63' // color: '#77DA63'
// }, // },
// label: { // label: {
// show: true, // show: true,
// color: '#77DA63', // color: '#77DA63',
// formatter: '良好' // formatter: '良好'
// } // }
// }, // },
// { // {
// name: '', // name: '',
// yAxis: 60, // yAxis: 60,
// lineStyle: { // lineStyle: {
// color: '#DAA520' // color: '#DAA520'
// }, // },
// label: { // label: {
// show: true, // show: true,
// color: '#DAA520', // color: '#DAA520',
// formatter: '合格' // formatter: '合格'
// } // }
// } // }
// ] // ]
// }, // },
// data: dataSource.map(item => item.value) // data: dataSource.map(item => item.value)
// } // }
// ] // ]
// } // }
// } // }
} }
const ratingColor = (num: number) => { const ratingColor = (num: number) => {
if (num >= 90) { if (num >= 90) {
return '#00b07d' return '#00b07d'
} else if (num >= 80) { } else if (num >= 80) {
return '#2b7fd3' return '#2b7fd3'
} else if (num >= 70) { } else if (num >= 70) {
return '#ff8c00' return '#ff8c00'
} else { } else {
return '#c00' return '#c00'
} }
} }
const ratingName = (num: number) => { const ratingName = (num: number) => {
if (num >= 90) { if (num >= 90) {
return '优秀' return '优秀'
} else if (num >= 80) { } else if (num >= 80) {
return '良好' return '良好'
} else if (num >= 70) { } else if (num >= 70) {
return '一般' return '一般'
} else { } else {
return '较差' return '较差'
} }
} }
onMounted(() => { onMounted(() => {
// info() // info()
}) })
defineExpose({ defineExpose({
info info
}) })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.btnsBox { .btnsBox {
display: flex; display: flex;
justify-content: end; justify-content: flex-end;
} }
::v-deep .el-radio-button__inner { ::v-deep .el-radio-button__inner {
padding: 8px 18px; padding: 8px 18px;
background: var(--el-color-primary); background: var(--el-color-primary);
border: 1px solid #00fff4; border: 1px solid #00fff4;
border-radius: 0; border-radius: 0;
font-weight: normal; font-weight: normal;
color: #ffffff; color: #ffffff;
text-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.73); text-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.73);
opacity: 0.52; opacity: 0.52;
} }
::v-deep .el-radio-button:last-child .el-radio-button__inner { ::v-deep .el-radio-button:last-child .el-radio-button__inner {
border-radius: 0; border-radius: 0;
} }
::v-deep .el-radio-button:first-child .el-radio-button__inner { ::v-deep .el-radio-button:first-child .el-radio-button__inner {
border-radius: 0; border-radius: 0;
border-left: 1px solid #00fff4; border-left: 1px solid #00fff4;
} }
::v-deep .is-active { ::v-deep .is-active {
border: 1px solid #00fff4; border: 1px solid #00fff4;
opacity: 1 !important; opacity: 1 !important;
color: #ffffff; color: #ffffff;
background: var(--el-color-primary); background: var(--el-color-primary);
.el-radio-button__inner { .el-radio-button__inner {
opacity: 1 !important; opacity: 1 !important;
border-left: 1px solid #00fff4 !important; border-left: 1px solid #00fff4 !important;
} }
} }
.box { .box {
cursor: pointer; cursor: pointer;
// display: flex; // display: flex;
.div { .div {
// width: 100px; // width: 100px;
font-size: 16px; font-size: 16px;
span{ span{
font-size: 14px; font-size: 14px;
} }
} }
} }
:deep(.el-divider--horizontal) { :deep(.el-divider--horizontal) {
margin: 5px 0; margin: 5px 0;
} }
</style> </style>

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