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

View File

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

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 WebSocketUrl:any = response.headers.get('X-WebSocket-Url')
const WebSocketUrl2:any = response.headers.get('X-WebSocket-Url2')
const WebSocketUrl3:any = response.headers.get('X-WebSocket-Url3')
const MqttUrl:any = response.headers.get('X-MqttUrl-Url')
localStorage.setItem('WebSocketUrl2', WebSocketUrl2)
localStorage.setItem('WebSocketUrl', WebSocketUrl)
localStorage.setItem('WebSocketUrl2', WebSocketUrl2)
localStorage.setItem('WebSocketUrl3', WebSocketUrl3)
localStorage.setItem('MqttUrl', MqttUrl)
})
</script>

View File

@@ -1,5 +1,6 @@
import createAxios from '@/utils/request'
// 密码规则修改
export function ruleUpdate(data) {
return createAxios({
@@ -24,3 +25,77 @@ export function unlockRoot(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) {
return createAxios({
url: '/supervision-boot/userReport/selectUserList',
url: '/device-boot/userReport/selectUserList',
method: 'post',
data
})

View File

@@ -45,3 +45,13 @@ export const getLineOverLimitData = (id: string) => {
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',
})
}
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'
//事件报告
// export function getEventReport(data) {
// return createAxios({
// url: '/event-boot/report/getEventReport',
// method: 'post',
// data
// })
// }
export function getEventReport(data) {
return createAxios({
url: '/event-boot/report/getEventReport',
url: '/event-boot/report/createEventReport',
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) {
return createAxios({

View File

@@ -1,106 +1,114 @@
import request from '@/utils/request'
export function getTypeIdData(data: any) {
return request({
url: '/system-boot/dictData/getTypeIdData',
method: 'post',
data: data
})
}
export function getOnlineRateData2(data:any) {
return request({
url: '/harmonic-boot/onlineRateData/getOnlineRateData',
method: 'post',
data: data
})
}
export function getAreaDept() {
return request({
url: '/user-boot/dept/loginDeptTree',
method: 'post'
})
}
export function getOnlineRateDataCensus(data:any) {
return request({
url: '/device-boot/terminalOnlineRateData/getOnlineRateDataCensus',
method: 'post',
data: data
})
}
export function IntegrityIcon(data:any) {
return request({
url: '/harmonic-boot/integrity/getIntegrityIcon',
method: 'post',
data: data
})
}
export function getDeptIdAreaTree() {
return request({
url: '/system-boot/area/getDeptIdAreaTree',
method: 'post'
})
}
export function getOnlineRateData(data:any) {
return request({
url: '/device-boot/terminalOnlineRateData/getOnlineRateData',
method: 'post',
data: data
})
}
export function getSubstationInfoById(data:any) {
return request({
url: '/harmonic-boot/PollutionSubstation/getSubstationInfoById',
method: 'post',
data: data
})
}
export function getLineInfoById(data:any) {
return request({
url: '/harmonic-boot/PollutionSubstation/getLineInfoById',
method: 'post',
data: data
})
}
export function getLineRank(data:any) {
return request({
url: '/harmonic-boot/PollutionSubstation/getLineRank',
method: 'post',
data: data
})
}
export function deptInfo(data:any) {
return request({
url: '/harmonic-boot/detailAnalysis/deptInfo',
method: 'post',
data: data
})
}
export function getXbLineInfoById(data:any) {
return request({
url: '/harmonic-boot/detailAnalysis/getXbLineInfoById',
method: 'post',
data: data
})
}
export function getSubInfoById(data:any) {
return request({
url: '/harmonic-boot/detailAnalysis/getSubInfoById',
method: 'post',
data: data
})
}
export function getXbLineRank(data:any) {
return request({
url: '/harmonic-boot/detailAnalysis/getXbLineRank',
method: 'post',
data: data
})
}
// 数据补招
export function FullRecall(data:any) {
return request({
url: '/data-processing-boot/data/FullRecall',
method: 'post',
data: data
})
}
import request from '@/utils/request'
export function getTypeIdData(data: any) {
return request({
url: '/system-boot/dictData/getTypeIdData',
method: 'post',
data: data
})
}
export function getOnlineRateData2(data:any) {
return request({
url: '/harmonic-boot/onlineRateData/getOnlineRateData',
method: 'post',
data: data
})
}
export function getAreaDept() {
return request({
url: '/user-boot/dept/loginDeptTree',
method: 'post'
})
}
// 承载能力评估去除前缀
export function getAreaDeptRemoveMode(params) {
return request({
url: '/user-boot/dept/loginDeptTree',
method: 'GET',
params: params
})
}
export function getOnlineRateDataCensus(data:any) {
return request({
url: '/device-boot/terminalOnlineRateData/getOnlineRateDataCensus',
method: 'post',
data: data
})
}
export function IntegrityIcon(data:any) {
return request({
url: '/harmonic-boot/integrity/getIntegrityIcon',
method: 'post',
data: data
})
}
export function getDeptIdAreaTree() {
return request({
url: '/system-boot/area/getDeptIdAreaTree',
method: 'post'
})
}
export function getOnlineRateData(data:any) {
return request({
url: '/device-boot/terminalOnlineRateData/getOnlineRateData',
method: 'post',
data: data
})
}
export function getSubstationInfoById(data:any) {
return request({
url: '/harmonic-boot/PollutionSubstation/getSubstationInfoById',
method: 'post',
data: data
})
}
export function getLineInfoById(data:any) {
return request({
url: '/harmonic-boot/PollutionSubstation/getLineInfoById',
method: 'post',
data: data
})
}
export function getLineRank(data:any) {
return request({
url: '/harmonic-boot/PollutionSubstation/getLineRank',
method: 'post',
data: data
})
}
export function deptInfo(data:any) {
return request({
url: '/harmonic-boot/detailAnalysis/deptInfo',
method: 'post',
data: data
})
}
export function getXbLineInfoById(data:any) {
return request({
url: '/harmonic-boot/detailAnalysis/getXbLineInfoById',
method: 'post',
data: data
})
}
export function getSubInfoById(data:any) {
return request({
url: '/harmonic-boot/detailAnalysis/getSubInfoById',
method: 'post',
data: data
})
}
export function getXbLineRank(data:any) {
return request({
url: '/harmonic-boot/detailAnalysis/getXbLineRank',
method: 'post',
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 == '终端厂家') {
return k.citTotalNum != 0
} 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 == '终端厂家') {
return k.citTotalNum != 0
} 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 == '终端厂家') {
return k.count != 0
} else {
return k.name != '上送国网' && k.name != '上送国网'
return !k.citName.includes('上送')
}
})
}

View File

@@ -6,29 +6,40 @@
</div>
<el-tabs type="border-card">
<el-tab-pane label="暂态波形上送" :style="'height:' + vhh">
<el-table stripe :data="Data" :height="height" border style="width: 100%"
header-cell-class-name="table_header">
<el-table-column align="center" prop="number" label="事件段"></el-table-column>
<el-table-column align="center" prop="number" label="波形起始点相位(°)">
<el-table-column align="center" prop="number" label="A相"></el-table-column>
<el-table-column align="center" prop="number" label="B相"></el-table-column>
<el-table-column align="center" prop="number" label="C相"></el-table-column>
</el-table-column>
<el-table-column align="center" prop="number" label="跳变段电压变化率(V/ms)">
<el-table-column align="center" prop="number" label="A相"></el-table-column>
<el-table-column align="center" prop="number" label="B相"></el-table-column>
<el-table-column align="center" prop="number" label="C相"></el-table-column>
</el-table-column>
<el-table-column align="center" prop="number" label="相位跳变(°)">
<el-table-column align="center" prop="number" label="A相"></el-table-column>
<el-table-column align="center" prop="number" label="B相"></el-table-column>
<el-table-column align="center" prop="number" label="C相"></el-table-column>
</el-table-column>
<el-table-column align="center" prop="number" label="总分段数目"></el-table-column>
<el-table-column align="center" prop="number" label="三相电压不平衡度(%)" width="180"></el-table-column>
<el-table-column align="center" prop="number" label="触发类型"></el-table-column>
<el-table-column align="center" prop="number" label="暂降原因"></el-table-column>
</el-table>
<vxe-table
stripe
:data="Data"
:height="height"
border
style="width: 100%"
header-cell-class-name="table_header"
>
<vxe-column align="center" field="number" title="事件段"></vxe-column>
<vxe-colgroup align="center" field="number1" title="波形起始点相位(°)">
<vxe-column align="center" field="number2" title="A相"></vxe-column>
<vxe-column align="center" field="number3" title="B相"></vxe-column>
<vxe-column align="center" field="number4" title="C相"></vxe-column>
</vxe-colgroup>
<vxe-colgroup align="center" field="number" title="跳变段电压变化率(V/ms)">
<vxe-column align="center" field="number5" title="A相"></vxe-column>
<vxe-column align="center" field="number6" title="B相"></vxe-column>
<vxe-column align="center" field="number7" title="C相"></vxe-column>
</vxe-colgroup>
<vxe-colgroup align="center" field="number" title="相位跳变(°)">
<vxe-column align="center" field="number8" title="A相"></vxe-column>
<vxe-column align="center" field="number9" title="B相"></vxe-column>
<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-tabs>
</div>
@@ -73,7 +84,25 @@ export default {
subName: '',
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,
vhh: null,
ptpass: '',
@@ -88,7 +117,7 @@ export default {
zoom: ''
}
},
created() { },
created() {},
watch: {
value: function (a, b) {
if (a == 2) {
@@ -116,10 +145,10 @@ export default {
this.zoom = 1 / document.body.style.zoom
if (this.flag) {
// console.log(123);
this.vh = mainHeight(250).height
this.vh = mainHeight(280).height
} else {
// console.log(3333);
this.vh = mainHeight(270).height
this.vh = mainHeight(305).height
}
},
query() {
@@ -197,6 +226,8 @@ export default {
'#FF9999'
]
}
console.log('🚀 ~ this.boxoList:', this.boxoList)
var option = {
tooltip: {
top: '10px',
@@ -239,7 +270,7 @@ export default {
title: {
left: 'center',
text: '发生时刻:' + this.boxoList.startTime + ' PT变化:' + this.boxoList.measurementPointName,
text: '发生时刻:' + this.boxoList.startTime + ' PT变化:' + this.boxoList.pt,
textStyle: {
fontSize: 16,
color: _this.DColor ? '#fff' : echartsColor.WordColor
@@ -378,6 +409,33 @@ export default {
}
],
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相',
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"
></el-option>
</el-select>
<!-- <el-button v-if="view2 && senior" class="ml10" type="primary"
@click="AdvancedAnalytics">高级分析</el-button> -->
<!-- <el-button v-if="view2 && senior" class="ml10" type="primary" @click="AdvancedAnalytics">
高级分析
</el-button> -->
</el-col>
<el-col :span="12">
<el-button
@click="backbxlb"
class="el-icon-refresh-right"
icon="el-icon-Back"
style="float: right"
>
返回
</el-button>
<el-button @click="backbxlb" icon="el-icon-Back" style="float: right">返回</el-button>
</el-col>
</el-row>
<div v-loading="loading" style="height: calc(100vh - 190px)">
@@ -108,12 +102,12 @@ const options = ref([
const shushiboxiRef = ref()
const bxecharts = ref(mainHeight(95).height as any)
const view2 = ref(true)
const boxoList = ref(null)
const boxoList: any = ref(null)
const wp = ref(null)
const showBoxi = ref(true)
const view3 = ref(false)
const view4 = ref(false)
const GJList = ref([])
const GJList = ref({})
const open = async (row: any) => {
loading.value = true
@@ -122,6 +116,7 @@ const open = async (row: any) => {
row.loading = false
if (res != undefined) {
boxoList.value = row
boxoList.value.pt = res.data.pt
wp.value = res.data
loading.value = false
view4.value = true
@@ -129,6 +124,7 @@ const open = async (row: any) => {
})
.catch(() => {
loading.value = false
backbxlb()
})
}
const bxhandleClick = (tab: any) => {
@@ -168,10 +164,13 @@ const AdvancedAnalytics = () => {
analysis({
eventIndex: boxoList.value.eventId
}).then(res => {
GJList.value = res.data
view3.value = true
view2.value = false
// GJList.value = res.data
// view3.value = true
// view2.value = false
})
GJList.value = {}
view3.value = true
view2.value = false
}
const changeView = () => {
if (shushiboxiRef.value) shushiboxiRef.value.backbxlb()

View File

@@ -1,29 +1,20 @@
<template>
<div ref="tableHeader" class="cn-table-header">
<div class="table-header ba-scroll-style">
<el-form
style="flex: 1; height: 32px; display: flex; flex-wrap: wrap"
ref="headerForm"
@submit.prevent=""
@keyup.enter="onComSearch"
label-position="left"
:inline="true"
>
<el-form style="flex: 1; height: 32px; display: flex; flex-wrap: wrap" 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">
<template #label>
<el-checkbox v-if="showTimeAll" v-model="timeAll" label="统计时间" />
<span v-else>{{ dateLabel }}</span>
</template>
<DatePicker
ref="datePickerRef"
v-if="timeAll"
:nextFlag="nextFlag"
:theCurrentTime="theCurrentTime"
></DatePicker>
<DatePicker ref="datePickerRef" v-if="timeAll" :nextFlag="nextFlag"
:theCurrentTime="theCurrentTime"></DatePicker>
</el-form-item>
<el-form-item label="区域" v-if="area">
<Area ref="areaRef" v-model="tableStore.table.params.deptIndex" @change-value="onAreaChange" />
<Area ref="areaRef" v-model="tableStore.table.params.deptIndex" @change-value="onAreaChange"
style="width: 200px;" />
</el-form-item>
<slot name="select"></slot>
</el-form>
@@ -32,43 +23,24 @@
<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 />
</el-button>
<el-button
@click="onComSearch"
v-if="showSearch"
:loading="tableStore.table.loading"
type="primary"
:icon="Search"
>
<el-button @click="onComSearch" v-if="showSearch" :loading="tableStore.table.loading" type="primary"
:icon="Search">
查询
</el-button>
<el-button
@click="onResetForm"
v-if="showSearch && showReset"
:loading="tableStore.table.loading"
:icon="RefreshLeft"
>
<el-button @click="onResetForm" v-if="showSearch && showReset" :loading="tableStore.table.loading"
:icon="RefreshLeft">
重置
</el-button>
<el-button
@click="onExport"
v-if="showExport"
:loading="tableStore.table.exportLoading"
type="primary"
icon="el-icon-Download"
>
<el-button @click="onExport" v-if="showExport" :loading="tableStore.table.exportLoading" type="primary"
icon="el-icon-Download">
导出
</el-button>
</template>
<slot name="operation"></slot>
</div>
<el-form
:style="showSelect && showUnfoldButton ? headerFormSecondStyleOpen : headerFormSecondStyleClose"
ref="headerFormSecond"
@submit.prevent=""
@keyup.enter="onComSearch"
label-position="left"
:inline="true"
></el-form>
<el-form :style="showSelect && showUnfoldButton ? headerFormSecondStyleOpen : headerFormSecondStyleClose"
ref="headerFormSecond" @submit.prevent="" @keyup.enter="onComSearch" label-position="left"
:inline="true"></el-form>
</div>
</template>
@@ -81,7 +53,7 @@ import { mainHeight } from '@/utils/layout'
import { useDictData } from '@/stores/dictData'
import { Search, RefreshLeft } from '@element-plus/icons-vue'
import { defineProps } from 'vue'
const emit = defineEmits(['selectChange','areaChange'])
const emit = defineEmits(['selectChange', 'areaChange'])
const tableStore = inject('tableStore') as TableStore
const tableHeader = ref()
const datePickerRef = ref()
@@ -132,9 +104,8 @@ const headerFormSecondStyleClose = {
padding: '0'
}
const onAreaChange = (data) => {
emit('areaChange', {label: data.label})
const onAreaChange = data => {
emit('areaChange', { label: data.label })
}
watch(
@@ -142,7 +113,6 @@ watch(
newVal => {
setTimeout(() => {
areaRef.value && areaRef.value.change()
}, 0)
}
)
@@ -238,14 +208,14 @@ const onResetForm = () => {
//时间重置成默认值
datePickerRef.value?.setTheDate(3)
if(props.showTimeAll){
timeAll.value = false
delete tableStore.table.params.searchBeginTime
delete tableStore.table.params.searchEndTime
delete tableStore.table.params.startTime
delete tableStore.table.params.endTime
delete tableStore.table.params.timeFlag
delete tableStore.table.params.interval
if (props.showTimeAll) {
timeAll.value = false
delete tableStore.table.params.searchBeginTime
delete tableStore.table.params.searchEndTime
delete tableStore.table.params.startTime
delete tableStore.table.params.endTime
delete tableStore.table.params.timeFlag
delete tableStore.table.params.interval
}
if (props.datePicker && timeAll.value) {
@@ -264,7 +234,6 @@ const setTheDate = (val: any) => {
}
// 导出
const onExport = () => {
tableStore.onTableAction('export', { showAllFlag: true })
}
@@ -300,6 +269,7 @@ defineExpose({
padding: 13px 15px;
font-size: 14px;
overflow: hidden;
.table-header-operate-text {
margin-left: 6px;
}
@@ -327,7 +297,7 @@ defineExpose({
margin-left: 12px;
}
.mlr-12 + .el-button {
.mlr-12+.el-button {
margin-left: 12px;
}
@@ -362,7 +332,7 @@ defineExpose({
border-radius: 0;
}
.el-button + .el-button {
.el-button+.el-button {
margin: 0;
}
@@ -373,6 +343,7 @@ defineExpose({
html.dark {
.table-search-button-group {
button:focus,
button:active {
background-color: var(--el-color-info-dark-2);

View File

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

View File

@@ -50,7 +50,8 @@ import { ref, reactive, onMounted } from 'vue'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { mainHeight } from '@/utils/layout'
import { useDictData } from '@/stores/dictData'
import MQTT from '@/utils/mqtt'
// import MQTT from '@/utils/mqtt'
import socketClient from '@/utils/webSocketClient'
const dictData = useDictData()
const event = dictData.getBasicData('Event_Statis')
import { useAdminInfo } from '@/stores/adminInfo'
@@ -68,37 +69,72 @@ const handleClose = (done: any) => {
drawer.value = false
done()
}
const init = async () => {
const mqttClient = new MQTT('/sendEvent')
// 设置消息接收回调
try {
await mqttClient.init()
const dataSocket = reactive({
socketServe: socketClient.Instance
})
// const init = async () => {
// const mqttClient = new MQTT('/sendEvent')
// // 设置消息接收回调
// try {
// await mqttClient.init()
// 订阅主题
await mqttClient.subscribe()
// 设置消息接收回调
mqttClient.onMessage((topic, message) => {
const msg = JSON.parse(message.toString())
// console.log('🚀 ~ init ~ msg:', msg)
if (msg.deptList.includes(adminInfo.$state.deptId)) {
drawer.value = true
isLoading.value = true
eventList.value.unshift(msg)
setTimeout(() => {
isLoading.value = false
}, 500)
}
})
} catch (error) {
console.error('MQTT 初始化失败:', error)
}
// // 订阅主题
// await mqttClient.subscribe()
// // 设置消息接收回调
// mqttClient.onMessage((topic, message) => {
// const msg = JSON.parse(message.toString())
// // console.log('🚀 ~ init ~ msg:', msg)
// if (msg.deptList.includes(adminInfo.$state.deptId)) {
// drawer.value = true
// isLoading.value = true
// eventList.value.unshift(msg)
// setTimeout(() => {
// isLoading.value = false
// }, 500)
// }
// })
// } catch (error) {
// // console.error('MQTT 初始化失败:', error)
// }
// }
const socket = async () => {
const url = localStorage.getItem('WebSocketUrl3') || 'null' //'ws://192.168.2.130:10203/event/'
// const url = 'ws://192.168.1.68:10203/event/'
await dataSocket.socketServe.connect(`${url}${adminInfo.id}`)
await dataSocket.socketServe.registerCallBack('message', (res: any) => {
if (res.deptList.includes(adminInfo.$state.deptId)) {
drawer.value = true
isLoading.value = true
eventList.value.unshift(res)
setTimeout(() => {
isLoading.value = false
}, 500)
}
// logList.value.push({
// type: res.code == 500 ? 'error' : '',
// time: formatDate(new Date(), 'YYYY-MM-DD hh:mm:ss'),
// name: res.message
// })
})
}
onUnmounted(() => {
dataSocket.socketServe?.closeWs()
})
onMounted(() => {
// startMqtt('/sendEvent', (topic, message) => {
// const msg = JSON.parse(message.toString())
// console.log(msg)
// })
init()
setTimeout(() => {
socket()
}, 3000)
})
defineExpose({
open,

View File

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

View File

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

View File

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

View File

@@ -1,286 +1,337 @@
//指标类型
export const indexOptions = [
{
label: '电压趋势',
options: [
{
value: '10',
label: '相电压有效值'
},
{
value: '11',
label: '线电压有效值'
},
{
value: '12',
label: '电压偏差'
},
{
value: '13',
label: '三相电压不平衡'
},
{
value: '14',
label: '电压不平衡'
},
{
value: '15',
label: '电压总谐波畸变率'
}
]
},
{
label: '电流趋势',
options: [
{
value: '20',
label: '电流有效值'
},
{
value: '21',
label: '电流总谐波畸变率'
},
{
value: '22',
label: '负序电流'
}
]
},
{
label: '频率趋势',
options: [
{
value: '30',
label: '频率'
}
]
},
{
label: '谐波趋势',
options: [
{
value: '40',
label: '谐波电压含有率'
},
{
value: '43',
label: '谐波电流幅值'
},
{
value: '44',
label: '谐波电压相角'
},
{
value: '45',
label: '谐波电流相角'
},
{
value: '46',
label: '间谐波电压含有率'
},
// {
// value: '47',
// label: '间谐波电流含有率'
// },
// {
// value: '48',
// label: '间谐波电压幅值'
// },
{
value: '49',
label: '间谐波电流幅值'
}
]
},
{
label: '功率趋势',
options: [
{
value: '50',
label: '谐波有功功率'
},
{
value: '51',
label: '谐波无功功率'
},
{
value: '52',
label: '谐波视在功率'
},
{
value: '53',
label: '三相有功功率'
},
{
value: '54',
label: '三相无功功率'
},
{
value: '55',
label: '三相视在功率'
},
{
value: '56',
label: '三相总有功功率'
},
{
value: '57',
label: '三相总无功功率'
},
{
value: '58',
label: '三相总视在功率'
},
{
value: '59',
label: '视在功率因数'
},
{
value: '591',
label: '位移功率因数'
},
{
value: '592',
label: '总视在功率因数'
},
{
value: '593',
label: '总位移功率因数'
}
]
},
{
label: '闪变趋势',
options: [
{
value: '60',
label: '短时电压闪变'
},
{
value: '61',
label: '长时电压闪变'
},
{
value: '62',
label: '电压波动'
}
]
}
]
//谐波次数
export const harmonicOptions = [
{ label: '基波', value: 1 },
{ label: '2次', value: 2 },
{ label: '3次', value: 3 },
{ label: '4次', value: 4 },
{ label: '5次', value: 5 },
{ label: '6次', value: 6 },
{ label: '7次', value: 7 },
{ label: '8次', value: 8 },
{ label: '9次', value: 9 },
{ label: '10次', value: 10 },
{ label: '11次', value: 11 },
{ label: '12次', value: 12 },
{ label: '13次', value: 13 },
{ label: '14次', value: 14 },
{ label: '15次', value: 15 },
{ label: '16次', value: 16 },
{ label: '17次', value: 17 },
{ label: '18次', value: 18 },
{ label: '19次', value: 19 },
{ label: '20次', value: 20 },
{ label: '21次', value: 21 },
{ label: '22次', value: 22 },
{ label: '23次', value: 23 },
{ label: '24次', value: 24 },
{ label: '25次', value: 25 },
{ label: '26次', value: 26 },
{ label: '27次', value: 27 },
{ label: '28次', value: 28 },
{ label: '29次', value: 29 },
{ label: '30次', value: 30 },
{ label: '31次', value: 31 },
{ label: '32次', value: 32 },
{ label: '33次', value: 33 },
{ label: '34次', value: 34 },
{ label: '35次', value: 35 },
{ label: '36次', value: 36 },
{ label: '37次', value: 37 },
{ label: '38次', value: 38 },
{ label: '39次', value: 39 },
{ label: '40次', value: 40 },
{ label: '41次', value: 41 },
{ label: '42次', value: 42 },
{ label: '43次', value: 43 },
{ label: '44次', value: 44 },
{ label: '45次', value: 45 },
{ label: '46次', value: 46 },
{ label: '47次', value: 47 },
{ label: '48次', value: 48 },
{ label: '49次', value: 49 },
{ label: '50次', 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 },
{ label: '5.5次', value: 6 },
{ label: '6.5次', value: 7 },
{ label: '7.5次', value: 8 },
{ label: '8.5次', value: 9 },
{ 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 }
]
//指标类型
export const indexOptions = [
{
label: '电压趋势',
options: [
{
value: '10',
label: '相电压有效值'
},
{
value: '11',
label: '线电压有效值'
},
{
value: '12',
label: '电压偏差'
},
{
value: '13',
label: '三相电压不平衡'
},
{
value: '14',
label: '电压不平衡'
},
{
value: '15',
label: '电压总谐波畸变率'
}
]
},
{
label: '电流趋势',
options: [
{
value: '20',
label: '电流有效值'
},
{
value: '21',
label: '电流总谐波畸变率'
},
{
value: '22',
label: '负序电流'
}
]
},
{
label: '频率趋势',
options: [
{
value: '30',
label: '频率'
}
]
},
{
label: '谐波趋势',
options: [
{
value: '40',
label: '谐波电压含有率'
},
{
value: '43',
label: '谐波电流幅值'
},
{
value: '44',
label: '谐波电压相角'
},
{
value: '45',
label: '谐波电流相角'
},
{
value: '46',
label: '间谐波电压含有率'
},
// {
// value: '47',
// label: '间谐波电流含有率'
// },
// {
// value: '48',
// label: '间谐波电压幅值'
// },
{
value: '49',
label: '间谐波电流幅值'
}
]
},
{
label: '功率趋势',
options: [
{
value: '50',
label: '谐波有功功率'
},
{
value: '51',
label: '谐波无功功率'
},
{
value: '52',
label: '谐波视在功率'
},
{
value: '53',
label: '三相有功功率'
},
{
value: '54',
label: '三相无功功率'
},
{
value: '55',
label: '三相视在功率'
},
{
value: '56',
label: '三相总有功功率'
},
{
value: '57',
label: '三相总无功功率'
},
{
value: '58',
label: '三相总视在功率'
},
{
value: '59',
label: '视在功率因数'
},
{
value: '591',
label: '位移功率因数'
},
{
value: '592',
label: '总视在功率因数'
},
{
value: '593',
label: '总位移功率因数'
}
]
},
{
label: '闪变趋势',
options: [
{
value: '60',
label: '短时电压闪变'
},
{
value: '61',
label: '长时电压闪变'
},
{
value: '62',
label: '电压波动'
}
]
}
]
//谐波次数
export const harmonicOptions = [
{ label: '基波', value: 1 },
{ label: '2次', value: 2 },
{ label: '3次', value: 3 },
{ label: '4次', value: 4 },
{ label: '5次', value: 5 },
{ label: '6次', value: 6 },
{ label: '7次', value: 7 },
{ label: '8次', value: 8 },
{ label: '9次', value: 9 },
{ label: '10次', value: 10 },
{ label: '11次', value: 11 },
{ label: '12次', value: 12 },
{ label: '13次', value: 13 },
{ label: '14次', value: 14 },
{ label: '15次', value: 15 },
{ label: '16次', value: 16 },
{ label: '17次', value: 17 },
{ label: '18次', value: 18 },
{ label: '19次', value: 19 },
{ label: '20次', value: 20 },
{ label: '21次', value: 21 },
{ label: '22次', value: 22 },
{ label: '23次', value: 23 },
{ label: '24次', value: 24 },
{ label: '25次', value: 25 },
{ label: '26次', value: 26 },
{ label: '27次', value: 27 },
{ label: '28次', value: 28 },
{ label: '29次', value: 29 },
{ label: '30次', value: 30 },
{ label: '31次', value: 31 },
{ label: '32次', value: 32 },
{ label: '33次', value: 33 },
{ label: '34次', value: 34 },
{ label: '35次', value: 35 },
{ label: '36次', value: 36 },
{ label: '37次', value: 37 },
{ label: '38次', value: 38 },
{ label: '39次', value: 39 },
{ label: '40次', value: 40 },
{ label: '41次', value: 41 },
{ label: '42次', value: 42 },
{ label: '43次', value: 43 },
{ label: '44次', value: 44 },
{ label: '45次', value: 45 },
{ label: '46次', value: 46 },
{ label: '47次', value: 47 },
{ label: '48次', value: 48 },
{ label: '49次', value: 49 },
{ label: '50次', value: 50 }
]
export const harmonicOptions1 = [
{ label: '2次', value: 2 },
{ label: '3次', value: 3 },
{ label: '4次', value: 4 },
{ label: '5次', value: 5 },
{ label: '6次', value: 6 },
{ label: '7次', value: 7 },
{ label: '8次', value: 8 },
{ label: '9次', value: 9 },
{ label: '10次', value: 10 },
{ label: '11次', value: 11 },
{ label: '12次', value: 12 },
{ label: '13次', value: 13 },
{ label: '14次', value: 14 },
{ label: '15次', value: 15 },
{ label: '16次', value: 16 },
{ label: '17次', value: 17 },
{ label: '18次', value: 18 },
{ label: '19次', value: 19 },
{ label: '20次', value: 20 },
{ label: '21次', value: 21 },
{ label: '22次', value: 22 },
{ label: '23次', value: 23 },
{ label: '24次', value: 24 },
{ label: '25次', value: 25 },
{ label: '26次', value: 26 },
{ label: '27次', value: 27 },
{ label: '28次', value: 28 },
{ label: '29次', value: 29 },
{ label: '30次', value: 30 },
{ label: '31次', value: 31 },
{ label: '32次', value: 32 },
{ label: '33次', value: 33 },
{ label: '34次', value: 34 },
{ label: '35次', value: 35 },
{ label: '36次', value: 36 },
{ label: '37次', value: 37 },
{ label: '38次', value: 38 },
{ label: '39次', value: 39 },
{ label: '40次', value: 40 },
{ label: '41次', value: 41 },
{ label: '42次', value: 42 },
{ label: '43次', value: 43 },
{ label: '44次', value: 44 },
{ label: '45次', value: 45 },
{ label: '46次', value: 46 },
{ label: '47次', value: 47 },
{ label: '48次', value: 48 },
{ label: '49次', value: 49 },
{ label: '50次', 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 },
{ label: '5.5次', value: 6 },
{ label: '6.5次', value: 7 },
{ label: '7.5次', value: 8 },
{ label: '8.5次', value: 9 },
{ 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) {
return 0
}
let base
if (Math.abs(o) >= 100) {
base = 100
@@ -19,8 +20,11 @@ const calculateValue = (o: number, value: number, num: number, isMin: boolean) =
} else if (Math.abs(o) >= 1) {
base = 1
} else {
base = 0.1
const multiple = 1 / 0.1
base = Math.ceil(Math.abs(o) * multiple) / multiple
}
let calculatedValue
if (isMin) {
if (value < 0) {
@@ -35,18 +39,19 @@ const calculateValue = (o: number, value: number, num: number, isMin: boolean) =
calculatedValue = value + num * value
}
}
if (base === 0.1) {
return parseFloat(calculatedValue.toFixed(1))
// return parseFloat(calculatedValue.toFixed(1))
return Math.ceil(calculatedValue * 10) / 10
} else if (isMin) {
return Math.floor(calculatedValue / base) * base
} else {
return Math.ceil(calculatedValue / base) * base
}
}
// 处理y轴最大最小值
export const yMethod = (arr: any) => {
let num = 0.1
let num = 0.2
let numList = dataProcessing(arr)
let maxValue = 0
let minValue = 0
@@ -54,12 +59,9 @@ export const yMethod = (arr: any) => {
let min = 0
maxValue = Math.max(...numList)
minValue = Math.min(...numList)
const o = maxValue - minValue
if (Math.abs(o) >= 300) {
num = 0.02
}
const o = maxValue - minValue == 0 ? maxValue : maxValue - minValue
min = calculateValue(o, minValue, num, true)
max = calculateValue(o, maxValue, num, false)
// if (-100 >= minValue) {
// 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)
}
/**
* 补全时间序列数据中缺失的条目
* @param rawData 原始数据,格式为 [["时间字符串", "数值", "单位", "类型"], ...]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -183,7 +183,7 @@ import TableHeader from '@/components/table/header/index.vue'
import MyEChart from '@/components/echarts/MyEchart.vue'
import { useMonitoringPoint } from '@/stores/monitoringPoint'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { harmonicOptions } from '@/utils/dictionary'
import { harmonicOptions1 } from '@/utils/dictionary'
import { Select } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import {
@@ -202,7 +202,7 @@ import html2canvas from 'html2canvas'
import { yMethod } from '@/utils/echartMethod'
import { useDictData } from '@/stores/dictData'
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 monitoringPoint = useMonitoringPoint()
const size = ref(19)
@@ -844,7 +844,7 @@ onMounted(() => {
}
.btnBox {
display: flex;
justify-content: end;
justify-content: flex-end;
}
: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',
text: '禁止接入',
text: '删除',
type: 'danger',
icon: 'el-icon-Delete',
render: 'confirmButton',
@@ -165,11 +165,11 @@ const tableStore: any = new TableStore({
confirmButtonText: '确认',
cancelButtonText: '取消',
confirmButtonType: 'danger',
title: '确定禁止接入'
title: '确定删除'
},
click: row => {
remove({ ids: row.id }).then(() => {
ElMessage.success('禁止接入成功')
ElMessage.success('删除成功')
tableStore.index()
})
}

View File

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

View File

@@ -57,9 +57,15 @@
<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" :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 label="详细地址:" prop="area">
<el-input
clearable
@@ -95,7 +101,7 @@ import { mainHeight } from '@/utils/layout'
import { useDictData } from '@/stores/dictData'
import equipment from './equipment.vue'
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({
name: 'estimate/photovoltaic'
@@ -108,8 +114,9 @@ const disabled = ref(false)
const TableHeaderRef = ref()
const equipmentRef = ref()
const title = ref('')
const VITE_FLAG = import.meta.env.VITE_NAME == 'removeMode'
//const areaList: any = dictData.areaSelect()
const areaList = ref([])
const areaList: any = ref([])
const userShow: any = ref('Power_Station_Users')
const form = ref({
@@ -187,7 +194,8 @@ const tableStore: any = new TableStore({
{ field: 'createBy', title: '创建者' },
{ field: 'createTime', title: '创建日期' },
{
title: '操作',fixed: 'right',
title: '操作',
fixed: 'right',
width: '180',
render: 'buttons',
buttons: [
@@ -258,9 +266,7 @@ const tableStore: any = new TableStore({
}
],
loadCallback: () => {
}
loadCallback: () => {}
})
tableStore.table.params.userType = ''
@@ -268,8 +274,6 @@ tableStore.table.params.userType = ''
provide('tableStore', tableStore)
onMounted(() => {
tableStore.index()
})
const useChange = (e: string) => {
userShow.value = uesrList.filter(item => item.id == e)[0].code
@@ -278,10 +282,14 @@ const useChange = (e: string) => {
const add = async () => {
disabled.value = false
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
}
// 保存

View File

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

View File

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

View File

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

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 {
submitFormData,
getById,
updateFormData,
addEditor,
resend,
getByDeptDevLine
} from '@/api/supervision-boot/interfere/index'
getByDeptDevLine,
getUserReportUpdateById
} from '@/api/device-boot/sensitiveLoadMange'
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'
const route = useRoute()

View File

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

View File

@@ -34,11 +34,11 @@
</TableHeader>
<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>
</el-dialog>
<!-- 批量导入 -->
<sensitive-user-popup ref="sensitiveUserPopup" />
<!-- 批量导入
<sensitive-user-popup ref="sensitiveUserPopup" /> -->
<!-- 查看详情 detail 新增/修改 create-->
<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 DetailInfo from './components/detail.vue'
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 dictData = useDictData()
const sensitiveUserPopup = ref()
@@ -73,7 +73,7 @@ defineOptions({
//获取登陆用户姓名和部门
const adminInfo = useAdminInfo()
const tableStore = new TableStore({
url: '/supervision-boot/userReport/getUserLedgerPage',
url: '/device-boot/userReport/getUserLedgerPage',
// publicHeight: 65,
method: 'POST',
column: [

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -3,14 +3,14 @@
<div class="online_header">
<TableHeader date-picker ref="tableHeaderRef">
<template #select>
<el-form-item label="统计类型:">
<el-form-item label="统计类型">
<el-select v-model="formData.statisticalType" placeholder="请选择统计类型" value-key="id"
style="width: 100%">
<el-option v-for="item in classificationData" :key="item.id" :label="item.name"
:value="item"></el-option>
</el-select>
</el-form-item>
<el-form-item label="区域选择:">
<el-form-item label="区域选择">
<!-- <el-select ref="select1" v-model="deptName" placeholder="请选择所属部门区域" style="width: 100%">
<el-option :value="formData.deptIndex" style="height: auto"> -->
<!-- {{ formData.deptIndex }} -->
@@ -33,27 +33,30 @@
<!-- </el-option>
</el-select> -->
</el-form-item>
<el-form-item label="电压等级:">
<el-form-item label="电压等级">
<el-select v-model="formData.scale" multiple collapse-tags clearable placeholder="请选择电压等级"
style="width: 100%" value-key="id">
<el-option v-for="item in voltageleveloption" :key="item.id" :label="item.name"
:value="item"></el-option>
</el-select>
</el-form-item>
<el-form-item label="终端厂家:">
<el-form-item label="终端厂家">
<el-select v-model="formData.manufacturer" multiple collapse-tags clearable
placeholder="请选择终端厂家" style="width: 100%" value-key="id">
<el-option v-for="(item, index) in terminaloption" :key="index" :label="item.name"
:value="item"></el-option>
</el-select>
</el-form-item>
<el-form-item label="干扰源类型:">
<el-form-item label="干扰源类型">
<el-select v-model="formData.loadType" multiple collapse-tags clearable placeholder="请选择干扰源类型"
style="width: 100%" value-key="id">
<el-option v-for="(item, index) in interfereoption" :key="index" :label="item.name"
:value="item"></el-option>
</el-select>
</el-form-item>
<el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.searchValue" clearable placeholder="请输入关键字"></el-input>
</el-form-item>
</template>
<template #operation>
<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]
},
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
chartsRef.value && chartsRef.value.getTableStoreParams(tableStore.table.params)
@@ -305,6 +308,7 @@ const tableStore = new TableStore({
tableStore.table.params.deptIndex = ''
tableStore.table.params.filterName = ''
tableStore.table.params.searchValue = ''
tableStore.table.params.statisticalType = []
tableStore.table.params.scale = []
tableStore.table.params.manufacturer = []
@@ -339,6 +343,78 @@ const tree2List = (list: any, id?: string) => {
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) => {
return date > new Date() // 如果日期大于当前日期,则禁用
@@ -351,7 +427,9 @@ const makeUp = () => {
tableRef.value
.getRef()
.getCheckboxRecords()
.find((item: any) => item.level == '6') || []
.filter((item: any) => item.level == '6') || []
if (list.length == 0) {
return ElMessage({
@@ -359,6 +437,16 @@ const makeUp = () => {
type: 'warning'
})
}
// 检查是否有 comFlag 等于 0 的项
const hasOfflineDevice = list.some((item: any) => item.comFlag === 0)
if (hasOfflineDevice) {
return ElMessage({
message: '请选择在线监测点进行补招',
type: 'warning'
})
}
timeData.value = []
timePopUp.value = true
}
@@ -385,7 +473,7 @@ const makeUpSubmit = () => {
logPopUp.value = true
}
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 = []
await dataSocket.socketServe.connect(`${url}${adminInfo.id}`)
await dataSocket.socketServe.send(form)

View File

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

View File

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

View File

@@ -3,7 +3,7 @@
<div class="online_header">
<TableHeader date-picker ref="tableHeaderRef">
<template #select>
<el-form-item label="统计类型:">
<el-form-item label="统计类型">
<el-select
v-model="formData.statisticalType"
placeholder="请选择统计类型"
@@ -18,7 +18,7 @@
></el-option>
</el-select>
</el-form-item>
<el-form-item label="区域选择:">
<el-form-item label="区域选择">
<!-- <el-select ref="select1" v-model="deptName" placeholder="请选择所属部门区域" style="width: 100%">
<el-option :value="formData.deptIndex" style="height: auto"> -->
<!-- {{ formData.deptIndex }} -->
@@ -48,7 +48,7 @@
<!-- </el-option>
</el-select> -->
</el-form-item>
<el-form-item label="电压等级:">
<el-form-item label="电压等级">
<el-select
v-model="formData.scale"
multiple
@@ -66,7 +66,7 @@
></el-option>
</el-select>
</el-form-item>
<el-form-item label="终端厂家:">
<el-form-item label="终端厂家">
<el-select
v-model="formData.manufacturer"
multiple
@@ -84,7 +84,7 @@
></el-option>
</el-select>
</el-form-item>
<el-form-item label="干扰源类型:">
<el-form-item label="干扰源类型">
<el-select
v-model="formData.loadType"
multiple
@@ -102,6 +102,13 @@
></el-option>
</el-select>
</el-form-item>
<el-form-item label="筛选数据">
<el-input
v-model="tableStore.table.params.searchValue"
clearable
placeholder="请输入关键字"
></el-input>
</el-form-item>
</template>
</TableHeader>
</div>
@@ -132,7 +139,6 @@ import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import charts from './components/charts.vue'
defineOptions({
name: 'device-boot/getOnlineRateData'
})
@@ -153,7 +159,6 @@ const treeData = ref([])
const idArr = ref([])
const activeName = ref(0)
const getTreeData = async () => {
await getAreaDept().then(res => {
var data = res.data
data.forEach(element => {
@@ -205,7 +210,8 @@ const tableStore = new TableStore({
{
title: '网络参数',
field: 'ip',
align: 'center' ,width:'120px',
align: 'center',
width: '120px',
formatter: function (row) {
return row.cellValue ? row.cellValue : '/'
}
@@ -257,7 +263,7 @@ const tableStore = new TableStore({
formatter: function (row) {
return row.cellValue == 3.14159 ? '暂无数据' : row.cellValue.toFixed(2)
}
},
}
// {
// title: '评估',
// field: 'valueOver',
@@ -299,23 +305,26 @@ const tableStore = new TableStore({
// let treeData = []
// treeData = tree2List(tableStore.table.data)
// 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)
setTimeout(() => {
activeName.value == 0 && tableRef.value && tableRef.value.getRef().setAllTreeExpand(true)
}, 0)
},
resetCallback: () => {
resetCallback: () => {
// 重置表单数据到默认值
formData.value.statisticalType = classificationData[0]
formData.value.deptIndex = treeData.value[0]?.id
formData.value.scale = voltageleveloption
formData.value.manufacturer = terminaloption
formData.value.loadType = interfereoption
formData.value.loadType = interfereoption
}
})
tableStore.table.params.searchValue = ''
tableStore.table.params.deptIndex = ''
tableStore.table.params.statisticalType = []
tableStore.table.params.scale = []
@@ -342,7 +351,73 @@ const tree2List = (list: any, id?: string) => {
})
// 返回结果数组
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(() => {})

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -11,7 +11,9 @@
></DatePicker>
</el-form-item>
</template>
<template v-slot:operation></template>
<template v-slot:operation>
<el-button type="primary" icon="el-icon-Download" @click="exportTemplate">导出</el-button>
</template>
</TableHeader>
<GridLayout
@@ -68,9 +70,12 @@ import { useRouter, useRoute } from 'vue-router'
import { View } from '@element-plus/icons-vue'
import { useTimeCacheStore } from '@/stores/timeCache'
import { adminBaseRoutePath } from '@/router/static'
import { useAdminInfo } from '@/stores/adminInfo'
import { dataVerifyExcel } from '@/api/device-boot/line'
const { push } = useRouter()
const datePickerRef = ref()
const router = useRouter()
const adminInfo = useAdminInfo()
const route = useRoute()
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(() => {
initRowHeight()

View File

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

View File

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

View File

@@ -41,7 +41,7 @@
<el-tab-pane label="监测点运行状态" name="6" lazy v-if="!isReload">
<Yunxingzhuangtai v-if="activeName == '6'" />
</el-tab-pane>
<el-tab-pane label="实时数据" name="7" lazy v-if="!isReload && !VITE_FLAG && !VITE_FLAG1">
<el-tab-pane label="实时数据" name="7" lazy v-if="!isReload && !VITE_FLAG1">
<Shishishuju v-if="activeName == '7'" />
</el-tab-pane>
<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,
endAngle: key == 0 ? 90 : 0,
min: 0,
max: key == 0 ? 12 : 400,
max: key == 0 ? 12 : 200,
radius: '180%',
center: key == 0 ? ['70%', '95%'] : ['30%', '95%'],
splitNumber: 2, //刻度数量
@@ -744,16 +744,6 @@ const initEcharts = (color: string, key: number, name: string) => {
}
//渲染echarts
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) {
console.error('WebSocket 客户端实例不存在')
return
@@ -765,9 +755,22 @@ const init = () => {
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(',')
dataSocket.socketServe.connect(`${url}${adminInfo.id},${monitoringPoint.state.lineId},${pids[pids.length - 2]}`)
dataSocket.socketServe.registerCallBack('message', (res: any) => {
if (res.Flag === false) {
return (loading.value = false)
}
txtContent.value = res.value
let data = JSON.parse(res.value)
time.value = data.TIME - 0
@@ -779,12 +782,12 @@ const init = () => {
iRmsA: data.I.A?.IRMS, //A相电流
iRmsB: data.I.B?.IRMS, //B相电流
iRmsC: data.I.C?.IRMS, //C相电流
v1AngA: data.V.A?.VFUND_ANGLE, //A相基波电压相位
v1AngB: data.V.B?.VFUND_ANGLE, //B相基波电压相位
v1AngC: data.V.C?.VFUND_ANGLE, //C相基波电压相位
i1AngA: data.I.A?.I_ANGLE, //A相基波电流相位
i1AngB: data.I.B?.I_ANGLE, //B相基波电流相位
i1AngC: data.I.C?.I_ANGLE, //C相基波电流相位
v1AngA: steAngle(data.V.A?.VFUND_ANGLE), //A相基波电压相位
v1AngB: steAngle(data.V.B?.VFUND_ANGLE), //B相基波电压相位
v1AngC: steAngle(data.V.C?.VFUND_ANGLE), //C相基波电压相位
i1AngA: steAngle(data.I.A?.I_ANGLE), //A相基波电流相位
i1AngB: steAngle(data.I.B?.I_ANGLE), //B相基波电流相位
i1AngC: steAngle(data.I.C?.I_ANGLE), //C相基波电流相位
freq: data.V.T?.FREQ, //频率
freqDev: data.V.T?.DELTA_FREQ, //频率偏差
vUnbalance: data.V.T?.V_UNBAN, //电压不平衡度
@@ -868,6 +871,22 @@ const setRealData = () => {
// webMsgSend.value[0].vRmsB == 0 ? 1 : Math.ceil(webMsgSend.value[0].vRmsB)
// echartsDataV3.value.options.series[0].max =
// 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 = [
{
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)
// echartsDataA3.value.options.series[0].max =
// 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 = [
{
name: 'A相',
@@ -918,16 +953,28 @@ const setRealData = () => {
]
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 })
onMounted(() => {
init()
initRadioCharts()
getLineDetail({ id: monitoringPoint.state.lineId }).then(res => {
ptName.value = connection.filter(item => item.value == res.data.ptType)[0].code || ''
})
})
onBeforeUnmount(() => {
dataSocket.socketServe?.closeWs()

View File

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

View File

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

View File

@@ -1,156 +1,222 @@
<template>
<div class="default-main">
<TableHeader area showExport>
<TableHeader area ref="TableHeaderRef" showExport>
<template #select>
<!-- <el-form-item label="统计类型:">
<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>
</el-select>
</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-form-item label="运行状态">
<el-select filterable multiple collapse-tags v-model="tableStore.table.params.runFlag" clearable
placeholder="请选择运行状态">
<el-option v-for="item in runFlagList" :key="item.id" :label="item.name"
:value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="通讯状态:">
<el-form-item label="通讯状态">
<el-select v-model="tableStore.table.params.comFlag" filterable multiple collapse-tags clearable
placeholder="请选择通讯状态">
<el-option v-for="item in communicationstatus" :key="item.value" :label="item.label"
:value="item.value">
</el-option>
:value="item.value"></el-option>
</el-select>
</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-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-input v-model="tableStore.table.params.evaluate" clearable placeholder="输入关键字筛选" maxlength="32" show-word-limit />
<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-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>
</template>
<template #operation>
<!-- <el-button icon="el-icon-Download" type="primary">导出</el-button> -->
</template>
</TableHeader>
<Table ref="tableRef" />
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, provide } from 'vue'
import { ref, onMounted, provide, nextTick, watch } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import { useDictData } from '@/stores/dictData'
import TableHeader from '@/components/table/header/index.vue'
const dictData = useDictData()
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')
import { useDictData } from '@/stores/dictData'
const communicationstatus = [
{ value: 0, label: "中断" },
{ value: 1, label: "正常" },
]
const terminalstatus = [
{ value: 0, label: "投运" },
{ value: 1, label: "检修" },
{ value: 2, label: "停运" },
]
const dictData = useDictData()
const TableHeaderRef = ref()
const areaOptionList = dictData.getBasicData('jibei_area')
const interfereoption = dictData.getBasicData('Interference_Source')
const terminaloption = dictData.getBasicData('Dev_Manufacturers')
const voltageleveloption = dictData.getBasicData('Dev_Voltage_Stand')
const tableStore = new TableStore({
url: '/device-boot/runManage/getLineLedger',
url: '/device-boot/runManage/getLineLedgerComm',
method: 'POST',
isWebPaging: true,
filename: '监测点台账',
column: [
{
field: 'index',
title: '序号',
width: '80',
width: 80,
formatter: (row: any) => {
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',
title: '站',
minWidth: 100
title: '所属变电站',
minWidth: 150
},
{ field: 'objName', title: '对象名称' , minWidth: 240},
{ field: 'lineName', title: '监测点名称' , minWidth: 100},
{ field: 'manufacturer', title: '厂家' , minWidth: 100},
{ field: 'scale', title: '电压等级' , minWidth: 100},
{ field: 'businessType', title: '行业类型' , minWidth: 100},
{
field: 'objName',
title: '监测对象名称',
minWidth: 150,
formatter: (row: any) => {
return row.cellValue ? row.cellValue : '/'
}
},
{ field: 'lineName', title: '监测点名称', minWidth: 130 },
{ field: 'scale', title: '监测点电压等级', minWidth: 120 },
{ field: 'devName', title: '终端名称', minWidth: 80 },
{ field: 'ip', title: '网络参数' ,width:'120px'},
{ field: 'loadType', title: '干扰源类型', minWidth: 120 },
// { 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',
title: '通讯状态',
render: 'tag',
minWidth: 100,
// effect: 'dark',
minWidth: 70,
custom: {
'正常': 'success',
'中断': 'danger',
},
正常: 'success',
中断: '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: () => {
tableStore.table.data.map((item: any) => {
item.onlineEvaluate == 3.14159 ? item.onlineEvaluate = '/' : item.onlineEvaluate <= 0.6 ? item.onlineEvaluate = '差' : item.onlineEvaluate <= 0.9 ? item.onlineEvaluate = '良' : item.onlineEvaluate <= 1 ? item.onlineEvaluate = '优' : '/'
})
beforeSearchFun: () => {
tableStore.table.params.serverName = 'harmonic-boot'
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.evaluate = ''
tableStore.table.params.comFlag = []
tableStore.table.params.powerFlag = 2
tableStore.table.params.monitorFlag = 2
tableStore.table.params.searchValue = ''
tableStore.table.params.scale = []
tableStore.table.params.manufacturer = []
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)
onMounted(() => {
@@ -159,6 +225,4 @@ onMounted(() => {
</script>

View File

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

View File

@@ -1,33 +1,16 @@
<template>
<div class="default-main">
<TableHeader area showExport>
<TableHeader area ref="TableHeaderRef" showExport>
<template #select>
<!-- <el-form-item label="统计类型:">
<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>
</el-select>
</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-form-item label="终端厂家">
<el-select
v-model="tableStore.table.params.manufacturer"
filterable
@@ -45,7 +28,49 @@
></el-option>
</el-select>
</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
v-model="tableStore.table.params.loadType"
filterable
@@ -63,59 +88,41 @@
></el-option>
</el-select>
</el-form-item>
<el-form-item label="通讯状态:">
<el-form-item label="电压等级">
<el-select
v-model="tableStore.table.params.comFlag"
v-model="tableStore.table.params.scale"
filterable
multiple
collapse-tags
clearable
placeholder="请选择通讯状态"
placeholder="请选择电压等级"
value-key="id"
>
<el-option
v-for="item in communicationstatus"
:key="item.value"
:label="item.label"
:value="item.value"
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.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>
</TableHeader>
<Table ref="tableRef" />
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, provide } from 'vue'
import { ref, onMounted, provide, nextTick } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import { useDictData } from '@/stores/dictData'
import TableHeader from '@/components/table/header/index.vue'
const dictData = useDictData()
import { useDictData } from '@/stores/dictData'
defineOptions({
name: 'harmonic-boot/run/terminalmessage'
})
const dictData = useDictData()
const view = ref(true)
const classificationData = dictData.getBasicData('Statistical_Type', ['Report_Type', 'Voltage_Level', 'Load_Type'])
const voltageleveloption = dictData.getBasicData('Dev_Voltage_Stand')
@@ -134,37 +141,41 @@ const terminalstatus = [
const tableStore = new TableStore({
url: '/device-boot/runManage/getRuntimeData',
method: 'POST',
isWebPaging: true,
column: [
{
field: 'index',
title: '序号',
width: '80',
width: '70',
formatter: (row: any) => {
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: 90 },
{ field: 'gdName', title: '公司', minWidth: 110 },
{
field: 'bdName',
title: '站',
minWidth: 100
title: '变电站',
minWidth: 110
},
{
field: 'objName',
title: '用户对象',
minWidth: 110
},
{ field: 'manufacturer', title: '厂家', minWidth: 100 },
{ field: 'devName', title: '终端名称', minWidth: 80 },
{ field: 'ip', title: '网络参数' ,width:'120px' },
{ field: 'loginTime', title: '投运时间', minWidth: 100 },
{ field: 'devName', title: '终端名称', minWidth: 100 },
{ field: 'ip', title: '网络参数', width: 110 },
{ field: 'loginTime', title: '投运时间', minWidth: 90 },
{ field: 'devType', title: '终端型号', minWidth: 100 },
{ field: 'port', title: '端口', minWidth: 100 },
{ field: 'updateTime', title: '最新数据', minWidth: 100 },
{ field: 'port', title: '端口', minWidth: 60 },
{ field: 'updateTime', title: '最新数据', minWidth: 110 },
{
field: 'runFlag',
title: '终端状态',
// effect: 'dark',
render: 'tag',
minWidth: 100,
minWidth: 70,
custom: {
投运: 'success',
检修: 'warning',
@@ -176,56 +187,43 @@ const tableStore = new TableStore({
title: '通讯状态',
render: 'tag',
// effect: 'dark',
minWidth: 100,
minWidth: 70,
custom: {
正常: 'success',
中断: 'danger'
}
},
{
field: 'onlineEvaluate',
title: '在线率评价',
render: 'tag',
// effect: 'dark',
minWidth: 100,
custom: {
'/': 'info',
: 'success',
: 'warning',
: 'danger'
}
}
],
loadCallback: () => {
tableStore.table.webPagingData.map((item1: any) => {
item1.map((item: any) => {
item.onlineEvaluate == 3.14159
? (item.onlineEvaluate = '/')
: item.onlineEvaluate <= 0.6
? (item.onlineEvaluate = '差')
: item.onlineEvaluate <= 0.9
? (item.onlineEvaluate = '良')
: item.onlineEvaluate <= 1
? (item.onlineEvaluate = '优')
: '/'
})
})
beforeSearchFun: () => {
tableStore.table.params.serverName = 'harmonic-boot'
tableStore.table.params.statisticalType = {
name: '电网拓扑',
code: 'Power_Network'
}
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.serverName = 'harmonic-boot'
tableStore.table.params.comFlag = []
tableStore.table.params.runFlag = []
// tableStore.table.params.evaluate = ''
tableStore.table.params.searchValue = ''
tableStore.table.params.powerFlag = 2
tableStore.table.params.monitorFlag = 2
tableStore.table.params.scale = []
tableStore.table.params.manufacturer = []
tableStore.table.params.loadType = []
const wp = ref({})
provide('tableStore', tableStore)
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 {
zjkJSON,
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 class="collapse_none" style="color: red; cursor: pointer" @click="showWrap = false">关闭</div>
</div>
<baidu-map
class="map"
:style="height"
@@ -329,6 +333,16 @@ const boundaryList: any = ref([
orgName: '鞍山',
LngLat: [122.808845, 40.840049],
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 lineId = ref('')
const center = ref({
lng: 122.42588,
lat: 40.810977
lng: 122.42588,
lat: 40.810977
// lng: 109.5, // 海南经度
// lat: 18.5 // 海南纬度
})
const infoWindowPoint = ref<anyObj>({
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([
{
title: '冀北',
title: '网公司',
children: [
{
title: '电网侧监测点',

View File

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

View File

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

View File

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

View File

@@ -28,6 +28,7 @@
</el-collapse-item>
<el-collapse-item :title="item.name" v-for="(item, index) in column" :key="index" :name="index + 3">
<div style="height: 200px">
<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

View File

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

View File

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

View File

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

View File

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

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