57 Commits

Author SHA1 Message Date
guanj
120892808b 提交代码 2026-04-25 15:21:53 +08:00
guanj
0f5cb1d3c5 提交代码 2026-04-09 11:44:06 +08:00
cdf
dbaa42ff7e 通用台账查询页面调整 2026-04-09 11:42:54 +08:00
guanj
48472bdb85 微调 2026-04-03 14:48:10 +08:00
guanj
fafc5f82c4 修改itic点击波形图 2026-03-26 14:53:34 +08:00
cdf
93ee7e4034 通用台账查询页面调整 2026-03-23 09:19:43 +08:00
guanj
7d2ce51510 修改问题 2026-03-17 08:43:51 +08:00
guanj
9202da17f1 微调 2026-03-05 15:42:15 +08:00
guanj
30eddd0572 修改用户台账管理接口 2026-03-05 11:08:36 +08:00
sjl
15bd1ac6d2 事件报告导出 2026-03-02 15:35:29 +08:00
sjl
f5c76c1b7a 报告模版配置 2026-02-27 14:46:19 +08:00
sjl
b25515b5db 系统相关配置 2026-02-27 08:49:57 +08:00
guanj
bfa061fb03 冀北数据总览添加导出功能 2026-02-06 14:45:15 +08:00
sjl
15e3d4aec8 微调 2026-02-06 10:10:24 +08:00
sjl
59489aaafa 微调 2026-01-30 15:01:19 +08:00
guanj
5d0421dd40 Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx 2026-01-29 14:10:32 +08:00
guanj
6d7ef7cf5d 修改终端型号 2026-01-29 14:10:18 +08:00
sjl
8d9ccf97a7 前置管理分配终端 2026-01-29 13:44:12 +08:00
sjl
7188e3e681 微调 2026-01-28 14:33:42 +08:00
sjl
a9fc77eb8b 区域概览未关联暂降次数和已关联处理事件合并 2026-01-28 10:33:59 +08:00
sjl
87af11288d 微调 2026-01-28 08:45:38 +08:00
sjl
0763187744 前置管理重启,稳态统计报表重置 2026-01-23 13:46:00 +08:00
sjl
ae641604ba 区域概览表格sarfi9总计 2026-01-23 09:20:57 +08:00
sjl
564e6ef4ab Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx
# Conflicts:
#	src/views/pqs/voltageSags/Region/components/echart.vue
2026-01-23 09:07:11 +08:00
sjl
c84c5dae3b 微调 2026-01-23 09:04:08 +08:00
guanj
c902dabb73 微调 2026-01-23 09:03:37 +08:00
guanj
8d1497032f Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx 2026-01-23 08:51:12 +08:00
guanj
6aeac753ef 修改触发类型 2026-01-23 08:51:03 +08:00
sjl
56d65a6c17 9000系统测试用例调整 2026-01-22 16:15:33 +08:00
sjl
8b356c87a3 微调 2026-01-20 14:33:06 +08:00
guanj
c0feeaee7b 删除海南备份技术监督 2026-01-20 14:25:24 +08:00
guanj
6a112c8ae2 修改表格操作列 2026-01-20 14:18:41 +08:00
guanj
a19952b771 调整云南曲靖问题 2026-01-16 14:03:40 +08:00
guanj
0b76347853 Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx 2026-01-12 14:49:30 +08:00
guanj
379951699d 修改日志 2026-01-12 14:49:21 +08:00
sjl
003737cf52 Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx 2026-01-12 14:02:06 +08:00
sjl
20e6d3719a 微调 2026-01-12 14:01:43 +08:00
guanj
77617412dd Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx
# Conflicts:
#	src/views/pqs/voltageSags/monitoringPoint/online/navigation/index.vue
修改冲突
2026-01-12 14:01:09 +08:00
guanj
68ea43c42b 修改在线监测数据问题 2026-01-12 13:56:49 +08:00
sjl
e65df4daad Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx
# Conflicts:
#	src/views/pqs/voltageSags/monitoringPoint/online/navigation/index.vue
2026-01-12 11:24:34 +08:00
sjl
136248eec2 角色用户管理,区域概览 2026-01-12 11:22:42 +08:00
guanj
bfafb6dc5b 修改曲靖问题 2026-01-12 11:19:05 +08:00
sjl
0b91027da4 微调 2026-01-09 11:21:07 +08:00
guanj
22aeb0bf4c Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx 2026-01-09 11:20:10 +08:00
guanj
87bc9d9017 添加绑定监测点筛选 2026-01-09 11:20:02 +08:00
sjl
43d4d37cd0 Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx 2026-01-09 10:45:07 +08:00
sjl
ad1528e53b 导出日志 2026-01-09 10:44:35 +08:00
guanj
c1e36440e7 修改实时数据 2026-01-09 10:40:55 +08:00
guanj
16f5213d7a Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx 2026-01-09 08:47:18 +08:00
guanj
ab891e6125 修改角色管理页面 2026-01-09 08:47:07 +08:00
sjl
36c8ab87a2 微调 2026-01-08 15:17:19 +08:00
guanj
6c3037f19b 修改云南曲靖项目 2026-01-08 14:52:01 +08:00
sjl
54517c0d5f 稳态合格率,畸变率表格调整 2026-01-08 14:50:29 +08:00
guanj
715cdb892f 修改树 2026-01-07 08:38:45 +08:00
sjl
953b96fe05 Merge branch 'master' of http://192.168.1.22:3000/Web/admin-sjzx
# Conflicts:
#	src/components/tree/pqs/bearingTree.vue
#	src/views/pqs/harmonicMonitoring/monitoringPoint/online/wentaizhibiaohegelv/index.vue
2026-01-06 08:38:11 +08:00
sjl
cb19fef4c6 微调 2026-01-06 08:35:36 +08:00
guanj
98c887b79d 添加云南曲靖打包命令修改5层树逻辑 2026-01-05 10:13:53 +08:00
408 changed files with 45182 additions and 67387 deletions

6
.env.qujing Normal file
View File

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

View File

@@ -7,10 +7,12 @@
"dev": "vite --mode dev", "dev": "vite --mode dev",
"dev:jibei": "vite --mode jibei", "dev:jibei": "vite --mode jibei",
"dev:hainan": "vite --mode hainan", "dev:hainan": "vite --mode hainan",
"dev:qujing": "vite --mode qujing",
"dev:removeMode": "vite --mode removeMode", "dev:removeMode": "vite --mode removeMode",
"build": "vite build --mode dev", "build": "vite build --mode dev",
"build:jibei": "vite build --mode jibei", "build:jibei": "vite build --mode jibei",
"build:hainan": "vite build --mode hainan", "build:hainan": "vite build --mode hainan",
"build:qujing": "vite build --mode qujing",
"build:removeMode": "vite build --mode removeMode", "build:removeMode": "vite build --mode removeMode",
"preview": "vite preview" "preview": "vite preview"
}, },

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

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

View File

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

View File

@@ -129,7 +129,7 @@ export function queryAllByType(params: any) {
//获取用户 //获取用户
export function selectUserList(data: any) { export function selectUserList(data: any) {
return createAxios({ return createAxios({
url: '/supervision-boot/userReport/selectUserList', url: '/device-boot/userReport/selectUserList',
method: 'post', method: 'post',
data data
}) })
@@ -206,3 +206,11 @@ export function exportTerminalBase() {
responseType: 'blob' responseType: 'blob'
}) })
} }
//一键分配终端
export function allotTerminal(data: any) {
return createAxios({
url: '/device-boot/nodeDevice/oneKeyDistribution',
method: 'post',
params: data
})
}

View File

@@ -45,3 +45,13 @@ export const getLineOverLimitData = (id: string) => {
method: 'post' method: 'post'
}) })
} }
//导出数据总览
export function dataVerifyExcel(params: any) {
return request({
url: '/device-boot/dataVerify/dataVerifyExcel',
method: 'get',
params,
responseType: 'blob'
})
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -31,7 +31,7 @@ export const uploadFile = (file: any, path: string) => {
data: form data: form
}).then(res => { }).then(res => {
if (res.code == `A0000`) { if (res.code == `A0000`) {
ElMessage.success('上传成功!') ElMessage.success('文件上传成功!')
return res return res
} }
}) })

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

File diff suppressed because one or more lines are too long

View File

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

View File

@@ -43,7 +43,6 @@ if (VITE_FLAG) {
}) })
} else { } else {
setTimeout(async () => { setTimeout(async () => {
const previewUrl = await previewFile(currentRoute.value?.href?.split('?')[1]) const previewUrl = await previewFile(currentRoute.value?.href?.split('?')[1])
url.value = previewUrl url.value = previewUrl
excelOptions.value = ref({ excelOptions.value = ref({

View File

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

View File

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

View File

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

View File

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

View File

@@ -376,7 +376,7 @@ const openListenerForm = (listener, index?) => {
} }
// 移除监听器 // 移除监听器
const removeListener = (listener, index?) => { const removeListener = (listener, index?) => {
console.log(listener, 'listener') //console.log(listener, 'listener')
ElMessageBox.confirm('确认移除该监听器吗?', '提示', { ElMessageBox.confirm('确认移除该监听器吗?', '提示', {
confirmButtonText: '确 认', confirmButtonText: '确 认',
cancelButtonText: '取 消' cancelButtonText: '取 消'

View File

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

View File

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

View File

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

View File

@@ -223,7 +223,7 @@ const echart = () => {
series: [ series: [
{ {
name: '异常总数', name: '',
type: 'bar', type: 'bar',
barWidth: 12, barWidth: 12,
data: [100], data: [100],
@@ -240,7 +240,7 @@ const echart = () => {
colorStops: [ colorStops: [
{ {
offset: 1, offset: 1,
color: '#57bc6e' // 100% 处的颜色 color: '#FF9100' // 100% 处的颜色
} }
], ],
global: false // 缺省为 false global: false // 缺省为 false
@@ -249,7 +249,7 @@ const echart = () => {
} }
}, },
{ {
name: '异常占比', name: '',
type: 'bar', type: 'bar',
barWidth: 13, barWidth: 13,
data: [ data: [
@@ -270,11 +270,11 @@ const echart = () => {
colorStops: [ colorStops: [
{ {
offset: 0, offset: 0,
color: '#FF9100' // 0% 处的颜色 color: '#57bc6e ' // 0% 处的颜色
}, },
{ {
offset: 1, offset: 1,
color: '#FF9100' // 100% 处的颜色 color: '#57bc6e' // 100% 处的颜色
} }
], ],
global: false // 缺省为 false global: false // 缺省为 false

View File

@@ -222,7 +222,7 @@ const echart = () => {
series: [ series: [
{ {
name: '异常总数', name: '',
type: 'bar', type: 'bar',
barWidth: 12, barWidth: 12,
data: [100], data: [100],
@@ -239,7 +239,7 @@ const echart = () => {
colorStops: [ colorStops: [
{ {
offset: 1, offset: 1,
color: '#57bc6e' // 100% 处的颜色 color: '#FF9100' // 100% 处的颜色
} }
], ],
global: false // 缺省为 false global: false // 缺省为 false
@@ -248,7 +248,7 @@ const echart = () => {
} }
}, },
{ {
name: '异常占比', name: '',
type: 'bar', type: 'bar',
barWidth: 13, barWidth: 13,
data: [ data: [
@@ -269,11 +269,11 @@ const echart = () => {
colorStops: [ colorStops: [
{ {
offset: 0, offset: 0,
color: '#FF9100' // 0% 处的颜色 color: '#57bc6e' // 0% 处的颜色
}, },
{ {
offset: 1, offset: 1,
color: '#FF9100' // 100% 处的颜色 color: '#57bc6e' // 100% 处的颜色
} }
], ],
global: false // 缺省为 false global: false // 缺省为 false

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@@ -23,7 +23,7 @@
</el-form-item> </el-form-item>
<el-form-item label="区域" v-if="area"> <el-form-item label="区域" v-if="area">
<Area ref="areaRef" v-model="tableStore.table.params.deptIndex" /> <Area ref="areaRef" v-model="tableStore.table.params.deptIndex" @change-value="onAreaChange" />
</el-form-item> </el-form-item>
<slot name="select"></slot> <slot name="select"></slot>
</el-form> </el-form>
@@ -52,7 +52,7 @@
<el-button <el-button
@click="onExport" @click="onExport"
v-if="showExport" v-if="showExport"
:loading="tableStore.table.loading" :loading="tableStore.table.exportLoading"
type="primary" type="primary"
icon="el-icon-Download" icon="el-icon-Download"
> >
@@ -81,7 +81,7 @@ import { mainHeight } from '@/utils/layout'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
import { Search, RefreshLeft } from '@element-plus/icons-vue' import { Search, RefreshLeft } from '@element-plus/icons-vue'
import { defineProps } from 'vue' import { defineProps } from 'vue'
const emit = defineEmits(['selectChange']) const emit = defineEmits(['selectChange', 'areaChange'])
const tableStore = inject('tableStore') as TableStore const tableStore = inject('tableStore') as TableStore
const tableHeader = ref() const tableHeader = ref()
const datePickerRef = ref() const datePickerRef = ref()
@@ -132,6 +132,10 @@ const headerFormSecondStyleClose = {
padding: '0' padding: '0'
} }
const onAreaChange = data => {
emit('areaChange', { label: data.label })
}
watch( watch(
() => tableStore?.table.params.deptIndex, () => tableStore?.table.params.deptIndex,
newVal => { newVal => {
@@ -232,14 +236,14 @@ const onResetForm = () => {
//时间重置成默认值 //时间重置成默认值
datePickerRef.value?.setTheDate(3) datePickerRef.value?.setTheDate(3)
if(props.showTimeAll){ if (props.showTimeAll) {
timeAll.value = false timeAll.value = false
delete tableStore.table.params.searchBeginTime delete tableStore.table.params.searchBeginTime
delete tableStore.table.params.searchEndTime delete tableStore.table.params.searchEndTime
delete tableStore.table.params.startTime delete tableStore.table.params.startTime
delete tableStore.table.params.endTime delete tableStore.table.params.endTime
delete tableStore.table.params.timeFlag delete tableStore.table.params.timeFlag
delete tableStore.table.params.interval delete tableStore.table.params.interval
} }
if (props.datePicker && timeAll.value) { if (props.datePicker && timeAll.value) {
@@ -258,7 +262,6 @@ const setTheDate = (val: any) => {
} }
// 导出 // 导出
const onExport = () => { const onExport = () => {
console.log('222')
tableStore.onTableAction('export', { showAllFlag: true }) tableStore.onTableAction('export', { showAllFlag: true })
} }

View File

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

View File

@@ -22,7 +22,7 @@
<template #prefix> <template #prefix>
<Icon name="el-icon-Search" style="font-size: 16px" /> <Icon name="el-icon-Search" style="font-size: 16px" />
</template> </template>
</el-input> </el-input>
<Icon <Icon
@click="onMenuCollapse" @click="onMenuCollapse"
:name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'" :name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'"
@@ -147,7 +147,7 @@ const onMenuCollapse = () => {
} }
// 查看详情 // 查看详情
const viewDetails = (data: any) => { const viewDetails = (data: any) => {
console.log('🚀 ~ viewDetails ~ data:', data) // console.log('🚀 ~ viewDetails ~ data:', data)
if (data.level == 3) { if (data.level == 3) {
// 变电站详情 // 变电站详情
// substationDetails // substationDetails
@@ -201,7 +201,7 @@ onMounted(async () => {
}) })
const scrollToNode = (id: string) => { const scrollToNode = (id: string) => {
console.log("🚀 ~ scrollToNode ~ id:", id) // console.log("🚀 ~ scrollToNode ~ id:", id)
if (!treeRef.value) return if (!treeRef.value) return
// 获取目标节点的元素 // 获取目标节点的元素

View File

@@ -19,7 +19,6 @@ import { nextTick, onMounted, ref, useAttrs } from 'vue'
import Tree from '../index.vue' import Tree from '../index.vue'
import { useAdminInfo } from '@/stores/adminInfo' import { useAdminInfo } from '@/stores/adminInfo'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
import { getTerminalTreeForFive } from '@/api/device-boot/terminalTree'
import { useConfig } from '@/stores/config' import { useConfig } from '@/stores/config'
import { queryAllAlgorithmLibrary } from '@/api/supervision-boot/database/index' import { queryAllAlgorithmLibrary } from '@/api/supervision-boot/database/index'
defineOptions({ defineOptions({
@@ -35,7 +34,7 @@ const tree = ref()
const treeRef = ref() const treeRef = ref()
const loadData = (id?: any) => { const loadData = (id?: any) => {
console.log('🚀 ~ loadData ~ id:', id) // console.log('🚀 ~ loadData ~ id:', id)
let nodeKey = '' let nodeKey = ''
queryAllAlgorithmLibrary().then(res => { queryAllAlgorithmLibrary().then(res => {
res.data.forEach((item: any) => { res.data.forEach((item: any) => {

View File

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

View File

@@ -11,7 +11,6 @@ import { nextTick, onMounted, ref, useAttrs } from 'vue'
import Tree from '../index.vue' import Tree from '../index.vue'
import { useAdminInfo } from '@/stores/adminInfo' import { useAdminInfo } from '@/stores/adminInfo'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
import { getTerminalTreeForFive } from '@/api/device-boot/terminalTree'
import { useConfig } from '@/stores/config' import { useConfig } from '@/stores/config'
import { defineProps } from 'vue' import { defineProps } from 'vue'
import { getTree } from '@/api/advance-boot/assess' import { getTree } from '@/api/advance-boot/assess'

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,176 +1,176 @@
<template> <template>
<div class='default-main'> <div class='default-main'>
<!-- 表头 --> <!-- 表头 -->
<!-- date-picker 时间组件 area区域组件--> <!-- date-picker 时间组件 area区域组件-->
<TableHeader date-picker area> <TableHeader date-picker area>
<template v-slot:select> <template v-slot:select>
<el-form-item label='关键词:'> <el-form-item label='关键词:'>
<el-input <el-input
style='width: 240px' style='width: 240px'
v-model='tableStore.table.params.searchValue' v-model='tableStore.table.params.searchValue'
clearable clearable
placeholder='仅根据用户名/登录名' placeholder='仅根据用户名/登录名'
/> />
</el-form-item> </el-form-item>
</template> </template>
<template v-slot:operation> <template v-slot:operation>
<el-button :icon='Plus' type='primary' @click='addUser'>添加</el-button> <el-button :icon='Plus' type='primary' @click='addUser'>添加</el-button>
</template> </template>
</TableHeader> </TableHeader>
<!-- 表格 --> <!-- 表格 -->
<Table ref='tableRef' /> <Table ref='tableRef' />
<!-- 弹框 --> <!-- 弹框 -->
<PopupEdit ref='popupEdit' /> <PopupEdit ref='popupEdit' />
</div> </div>
</template> </template>
<script setup lang='ts'> <script setup lang='ts'>
import { Plus } from '@element-plus/icons-vue' import { Plus } from '@element-plus/icons-vue'
import { ref, onMounted, provide, defineOptions } from 'vue' import { ref, onMounted, provide, defineOptions } from 'vue'
import { ElMessageBox, ElMessage } from 'element-plus' import { ElMessageBox, ElMessage } from 'element-plus'
import TableStore from '@/utils/tableStore' import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue' import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue' import TableHeader from '@/components/table/header/index.vue'
import PopupEdit from './dialog.vue' import PopupEdit from './dialog.vue'
import { mainHeight } from '@/utils/layout' import { mainHeight } from '@/utils/layout'
// 注意名字不要重复若要保持页面存活名字需要和路由admin后面的字符保持一致 // 注意名字不要重复若要保持页面存活名字需要和路由admin后面的字符保持一致
defineOptions({ defineOptions({
name: 'auth/userlist' name: 'auth/userlist'
}) })
const popupEdit = ref() const popupEdit = ref()
const tableStore = new TableStore({ const tableStore = new TableStore({
// 若页面表格高度需要调整请修改publicHeight(内容区域除表格外其他内容的高度) // 若页面表格高度需要调整请修改publicHeight(内容区域除表格外其他内容的高度)
// publicHeight: 60, // publicHeight: 60,
url: '/user-boot/user/list', url: '/user-boot/user/list',
method: 'POST', method: 'POST',
column: [ column: [
{ title: '用户名称', field: 'name', minWidth: '130' }, { title: '用户名称', field: 'name', minWidth: '130' },
{ title: '登录名', field: 'loginName', minWidth: '130' }, { title: '登录名', field: 'loginName', minWidth: '130' },
{ title: '角色', field: 'roleName', minWidth: '130' }, { title: '角色', field: 'roleName', minWidth: '130' },
{ title: '部门', field: 'deptName', minWidth: '200' }, { title: '部门', field: 'deptName', minWidth: '200' },
{ title: '电话', field: 'phoneShow', minWidth: '100' }, { title: '电话', field: 'phoneShow', minWidth: '100' },
{ title: '注册时间', field: 'registerTime', minWidth: '130' }, { title: '注册时间', field: 'registerTime', minWidth: '130' },
{ title: '登录时间', field: 'loginTime', minWidth: '130' }, { title: '登录时间', field: 'loginTime', minWidth: '130' },
{ title: '类型', field: 'casualUserName', minWidth: '80' }, { title: '类型', field: 'casualUserName', minWidth: '80' },
{ {
title: '状态', title: '状态',
field: 'state', field: 'state',
width: '100', width: '100',
render: 'tag', render: 'tag',
custom: { custom: {
0: 'danger', 0: 'danger',
1: 'success', 1: 'success',
2: 'warning', 2: 'warning',
3: 'warning', 3: 'warning',
4: 'info', 4: 'info',
5: 'danger' 5: 'danger'
}, },
replaceValue: { replaceValue: {
0: '注销', 0: '注销',
1: '正常', 1: '正常',
2: '锁定', 2: '锁定',
3: '待审核', 3: '待审核',
4: '休眠', 4: '休眠',
5: '密码过期' 5: '密码过期'
} }
}, },
{ {
title: '操作', title: '操作',fixed: 'right',
width: '180', width: '180',
render: 'buttons', render: 'buttons',
fixed: 'right',
buttons: [ buttons: [
{ {
name: 'edit', name: 'edit',
title: '编辑', title: '编辑',
type: 'primary', type: 'primary',
icon: 'el-icon-EditPen', icon: 'el-icon-EditPen',
render: 'basicButton', render: 'basicButton',
disabled: row => { disabled: row => {
return row.state !== 1 return row.state !== 1
}, },
click: row => { click: row => {
} }
}, },
{ {
name: 'edit', name: 'edit',
title: '修改密码', title: '修改密码',
type: 'primary', type: 'primary',
icon: 'el-icon-Lock', icon: 'el-icon-Lock',
render: 'basicButton', render: 'basicButton',
disabled: row => { disabled: row => {
return row.state !== 1 return row.state !== 1
}, },
click: row => { click: row => {
ElMessageBox.prompt('二次校验密码确认', '注销用户', { ElMessageBox.prompt('二次校验密码确认', '注销用户', {
confirmButtonText: '确认', confirmButtonText: '确认',
cancelButtonText: '取消', cancelButtonText: '取消',
inputType: 'password' inputType: 'password'
}).then(({ value }) => { }).then(({ value }) => {
}) })
} }
}, },
{ {
name: 'edit', name: 'edit',
title: '激活', title: '激活',
type: 'primary', type: 'primary',
icon: 'el-icon-Open', icon: 'el-icon-Open',
render: 'basicButton', render: 'basicButton',
disabled: row => { disabled: row => {
return row.state !== 2 && row.state !== 5 && row.state !== 0 && row.state !== 4 return row.state !== 2 && row.state !== 5 && row.state !== 0 && row.state !== 4
}, },
click: row => { click: row => {
} }
}, },
{ {
name: 'edit', name: 'edit',
title: '注销', title: '注销',
type: 'danger', type: 'danger',
icon: 'el-icon-SwitchButton', icon: 'el-icon-SwitchButton',
render: 'basicButton', render: 'basicButton',
disabled: row => { disabled: row => {
return row.state !== 1 && row.state !== 3 return row.state !== 1 && row.state !== 3
}, },
click: row => { click: row => {
} }
} }
] ]
} }
], ],
loadCallback: () => { loadCallback: () => {
tableStore.table.data.forEach((item: any) => { tableStore.table.data.forEach((item: any) => {
item.deptName = item.deptName || '/' item.deptName = item.deptName || '/'
item.phoneShow = item.phone || '/' item.phoneShow = item.phone || '/'
item.roleName = item.role.length ? item.role : '/' item.roleName = item.role.length ? item.role : '/'
switch (item.casualUser) { switch (item.casualUser) {
case 0: case 0:
item.casualUserName = '临时用户' item.casualUserName = '临时用户'
break break
case 1: case 1:
item.casualUserName = '长期用户' item.casualUserName = '长期用户'
break break
default: default:
item.casualUserName = '/' item.casualUserName = '/'
break break
} }
}) })
} }
}) })
// 注入到子组件 // 注入到子组件
provide('tableStore', tableStore) provide('tableStore', tableStore)
// 默认参数 参数多的话可以使用Object.assign方法 // 默认参数 参数多的话可以使用Object.assign方法
tableStore.table.params.searchState = 1 tableStore.table.params.searchState = 1
tableStore.table.params.searchValue = '' tableStore.table.params.searchValue = ''
tableStore.table.params.casualUser = -1 tableStore.table.params.casualUser = -1
tableStore.table.params.orderBy = '' tableStore.table.params.orderBy = ''
onMounted(() => { onMounted(() => {
// 加载数据 // 加载数据
tableStore.index() tableStore.index()
}) })
// 弹框 // 弹框
const addUser = () => { const addUser = () => {
popupEdit.value.open('新增用户') popupEdit.value.open('新增用户')
} }
</script> </script>

View File

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

View File

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

View File

@@ -1,8 +1,13 @@
import { downloadFile } from '@/api/system-boot/file' import { downloadFile } from '@/api/system-boot/file'
const sanitizeUrl = (url: string): string => {
return url.replace(/\[/g, '(').replace(/\]/g, ')')
}
// 下载文件 // 下载文件
export const download = (urls: string) => { export const download = (urls: string) => {
//console.log('下载', urls) //console.log('下载', urls)
downloadFile({ filePath: urls }) downloadFile({ filePath: urls })
.then((res: any) => { .then((res: any) => {
// 1. 确定文件MIME类型优化用更简洁的方式 // 1. 确定文件MIME类型优化用更简洁的方式
@@ -55,10 +60,8 @@ function removeLastDotSuffix(str: string) {
export const previewFile = async (urls: any) => { export const previewFile = async (urls: any) => {
//console.log('预览', urls) //console.log('预览', urls)
let url = '' let url = ''
//console.log('urls', decodeURI(urls))
await downloadFile({ filePath: decodeURI(urls) }) await downloadFile({ filePath: decodeURI(urls) })
.then((res: any) => { .then((res: any) => {
// 1. 确定文件MIME类型优化用更简洁的方式 // 1. 确定文件MIME类型优化用更简洁的方式
const getFileType = (url: string) => { const getFileType = (url: string) => {
const ext = url.split('.').pop()?.toLowerCase() || '' const ext = url.split('.').pop()?.toLowerCase() || ''
@@ -74,11 +77,8 @@ export const previewFile = async (urls: any) => {
jpg: 'image/jpg' jpg: 'image/jpg'
} }
return mimeMap[ext] || '' return mimeMap[ext] || ''
} }
const blob = new Blob([res], { type: getFileType(decodeURI(urls)) }) const blob = new Blob([res], { type: getFileType(decodeURI(urls)) })
// 3. 创建下载链接 // 3. 创建下载链接
url = window.URL.createObjectURL(blob) url = window.URL.createObjectURL(blob)
}) })

View File

@@ -50,12 +50,16 @@ class MQTT {
if (this.client) { if (this.client) {
throw new Error('MQTT 客户端已初始化') throw new Error('MQTT 客户端已初始化')
} }
const mqttUrl = localStorage.getItem('MqttUrl')
console.log('MQTT URL:', mqttUrl)
if (!mqttUrl || mqttUrl === 'null') {
return Promise.resolve()
}
try { try {
const mqttUrl = // const mqttUrl =
localStorage.getItem('MqttUrl') == 'null' // localStorage.getItem('MqttUrl') == 'null'
? 'ws://192.168.1.68:8083/mqtt' // ? 'ws://192.168.1.68:8083/mqtt'
: localStorage.getItem('MqttUrl') // : localStorage.getItem('MqttUrl')
this.client = mqtt.connect(mqttUrl, this.defaultOptions as IClientOptions) this.client = mqtt.connect(mqttUrl, this.defaultOptions as IClientOptions)
this.setupEventListeners() this.setupEventListeners()
@@ -77,12 +81,12 @@ class MQTT {
this.client?.on('error', error => { this.client?.on('error', error => {
clearTimeout(timeout) clearTimeout(timeout)
console.error('MQTT 连接错误:', error) console.log('MQTT 连接错误:', error)
reject(error) reject(error)
}) })
}) })
} catch (error) { } catch (error) {
console.error('初始化 MQTT 失败:', error) // console.log('初始化 MQTT 失败:', error)
throw error throw error
} }
} }
@@ -131,7 +135,7 @@ class MQTT {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.client?.subscribe(this.topic, { qos: this.defaultOptions.qos, ...subscribeOptions }, error => { this.client?.subscribe(this.topic, { qos: this.defaultOptions.qos, ...subscribeOptions }, error => {
if (error) { if (error) {
console.error('订阅失败:', error) console.log('订阅失败:', error)
reject(error) reject(error)
} else { } else {
console.log('订阅成功') console.log('订阅成功')
@@ -153,7 +157,7 @@ class MQTT {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.client?.unsubscribe(this.topic, error => { this.client?.unsubscribe(this.topic, error => {
if (error) { if (error) {
console.error('取消订阅失败:', error) console.log('取消订阅失败:', error)
reject(error) reject(error)
} else { } else {
console.log('取消订阅成功') console.log('取消订阅成功')
@@ -188,7 +192,7 @@ class MQTT {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.client?.publish(this.topic, message, { qos: this.defaultOptions.qos, ...options }, error => { this.client?.publish(this.topic, message, { qos: this.defaultOptions.qos, ...options }, error => {
if (error) { if (error) {
console.error('消息发布失败:', error) console.log('消息发布失败:', error)
reject(error) reject(error)
} else { } else {
console.log('消息发布成功') console.log('消息发布成功')

View File

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

View File

@@ -19,7 +19,7 @@ interface TableStoreParams {
publicHeight?: number //计算高度 publicHeight?: number //计算高度
resetCallback?: () => void // 重置 resetCallback?: () => void // 重置
loadCallback?: () => void // 接口调用后的回调 loadCallback?: () => void // 接口调用后的回调
exportProcessingData?:() => void //导出处理数据 exportProcessingData?: () => void //导出处理数据
beforeSearchFun?: () => void // 接口调用前的回调 beforeSearchFun?: () => void // 接口调用前的回调
} }
@@ -45,8 +45,9 @@ export default class TableStore {
pageNum: 1, pageNum: 1,
pageSize: 20 pageSize: 20
}, },
filename:null, filename: null,
loading: true, loading: true,
exportLoading: false,
column: [], column: [],
loadCallback: null, loadCallback: null,
exportProcessingData: null, exportProcessingData: null,
@@ -65,7 +66,7 @@ export default class TableStore {
this.table.filename = options.filename || null this.table.filename = options.filename || null
this.table.column = options.column this.table.column = options.column
this.showPage = options.showPage !== false this.showPage = options.showPage !== false
this.table.publicHeight = options.publicHeight || 0 this.table.publicHeight = options.publicHeight || 0
this.table.resetCallback = options.resetCallback || null this.table.resetCallback = options.resetCallback || null
this.table.loadCallback = options.loadCallback || null this.table.loadCallback = options.loadCallback || null
@@ -76,6 +77,7 @@ export default class TableStore {
} }
index() { index() {
this.table.beforeSearchFun && this.table.beforeSearchFun() this.table.beforeSearchFun && this.table.beforeSearchFun()
this.table.data = [] this.table.data = []
this.table.loading = true this.table.loading = true
@@ -84,13 +86,11 @@ export default class TableStore {
this.initData = JSON.parse(JSON.stringify(this.table.params)) this.initData = JSON.parse(JSON.stringify(this.table.params))
} }
if (!this.timeAll) { if (!this.timeAll) {
delete this.table.params.startTime; delete this.table.params.startTime
delete this.table.params.endTime; delete this.table.params.endTime
delete this.table.params.searchBeginTime; delete this.table.params.searchBeginTime
delete this.table.params.searchEndTime; delete this.table.params.searchEndTime
delete this.table.params.timeFlag; delete this.table.params.timeFlag
} }
createAxios( createAxios(
Object.assign( Object.assign(
@@ -98,10 +98,12 @@ export default class TableStore {
url: this.url, url: this.url,
method: this.method method: this.method
}, },
requestPayload(this.method, this.table.params, this.paramsPOST) requestPayload(this.method, this.table.params, this.paramsPOST)
) )
) )
.then((res: any) => { .then((res: any) => {
if (res.data) { if (res.data) {
this.table.data = res.data.records || res.data this.table.data = res.data.records || res.data
this.table.total = res.data?.total || res.data.length || 0 this.table.total = res.data?.total || res.data.length || 0
@@ -130,13 +132,15 @@ export default class TableStore {
* @param data 携带数据 * @param data 携带数据
*/ */
onTableAction = (event: string, data: anyObj) => { onTableAction = (event: string, data: anyObj) => {
const actionFun = new Map([ const actionFun = new Map([
[ [
'search', 'search',
() => { () => {
this.table.params.pageNum = 1 this.table.params.pageNum = 1
this.index() this.index()
} }
], ],
[ [
@@ -202,8 +206,10 @@ export default class TableStore {
[ [
'export', 'export',
() => { () => {
this.table.exportLoading = true
// this.index() // this.index()
console.log('export')
let params = { ...this.table.params, pageNum: 1, pageSize: this.table.total } let params = { ...this.table.params, pageNum: 1, pageSize: this.table.total }
createAxios( createAxios(
Object.assign( Object.assign(
@@ -213,12 +219,17 @@ export default class TableStore {
}, },
requestPayload(this.method, params, this.paramsPOST) requestPayload(this.method, params, this.paramsPOST)
) )
).then(res => { )
this.table.allData = filtration(res.data.records || res.data) .then(res => {
console.log('11111',this.table) this.table.allData = filtration(res.data.records || res.data)
this.table.exportProcessingData && this.table.exportProcessingData() this.table.exportProcessingData && this.table.exportProcessingData()
this.table.allFlag = data.showAllFlag || true this.table.allFlag = data.showAllFlag || true
}) this.table.exportLoading = false
})
.catch(() => {
this.table.exportLoading = false
})
} }
] ]
]) ])

View File

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

View File

@@ -1,3 +1,4 @@
import { Flag } from '@element-plus/icons-vue/dist/types'
import { ElMessage, EVENT_CODE } from 'element-plus' import { ElMessage, EVENT_CODE } from 'element-plus'
// 定义消息类型,用于类型检查 // 定义消息类型,用于类型检查
@@ -43,13 +44,9 @@ export default class SocketService {
console.log('您的浏览器不支持WebSocket') console.log('您的浏览器不支持WebSocket')
return return
} }
if (url == 'null' || url == null) return
setTimeout(() => { setTimeout(() => {
// ws://192.168.1.69:10407/mgtt
// const url =
// (localStorage.getItem('WebSocketUrl') == 'null'
// ? 'ws://192.168.1.130:10405'
// : localStorage.getItem('WebSocketUrl')) + id
this.ws = new WebSocket(url) this.ws = new WebSocket(url)
this.ws.onopen = () => this.handleOpen() this.ws.onopen = () => this.handleOpen()
@@ -90,7 +87,7 @@ export default class SocketService {
if (event.data == '连接成功') { if (event.data == '连接成功') {
this.sendHeartbeat() this.sendHeartbeat()
} else if (event.data == 'connect') { } else if (event.data == 'over') {
} else if (event.data.length > 10) { } else if (event.data.length > 10) {
let message: MessageType let message: MessageType
try { try {
@@ -104,7 +101,7 @@ export default class SocketService {
// 通过接受服务端发送的type字段来回调函数 // 通过接受服务端发送的type字段来回调函数
if ((message.key || message.code) && this.callBackMapping['message']) { if ((message.key || message.code || message.time) && this.callBackMapping['message']) {
this.callBackMapping['message']!(message) this.callBackMapping['message']!(message)
} else { } else {
console.log('抛弃====>') console.log('抛弃====>')
@@ -112,6 +109,7 @@ export default class SocketService {
// 丢弃或继续写你的逻辑 // 丢弃或继续写你的逻辑
} }
} else { } else {
this.callBackMapping['message']!({ Flag: false })
ElMessage.error(event.data) ElMessage.error(event.data)
} }
} }

View File

@@ -301,7 +301,7 @@ const options1 = [
const height = mainHeight(20) const height = mainHeight(20)
const heightB = mainHeight(448) const heightB = mainHeight(448)
const heightA = mainHeight(180) const heightA = mainHeight(180)
const size = ref(23) const size = ref(19)
const TableHeaderRef = ref() const TableHeaderRef = ref()
const detailRef = ref() const detailRef = ref()
const dotList: any = ref({}) const dotList: any = ref({})
@@ -786,7 +786,7 @@ onMounted(() => {
}) })
const handleNodeClick = (data: any, node: any) => { const handleNodeClick = (data: any, node: any) => {
console.log('🚀 ~ handleNodeClick ~ data:', data) //console.log('🚀 ~ handleNodeClick ~ data:', data)
if (data.level == 6) { if (data.level == 6) {
dotList.value = data dotList.value = data
// dotList.value.id = '6469e77fda42db12c7ca6620a092f03c1' // dotList.value.id = '6469e77fda42db12c7ca6620a092f03c1'

View File

@@ -321,7 +321,7 @@ const options1 = [
] ]
const height = mainHeight(20) const height = mainHeight(20)
const heightB = mainHeight(445) const heightB = mainHeight(445)
const size = ref(23) const size = ref(19)
const TableHeaderRef = ref() const TableHeaderRef = ref()
const detailRef = ref() const detailRef = ref()
const dotList: any = ref({}) const dotList: any = ref({})
@@ -757,7 +757,7 @@ const timeClick = (row: any) => {
} }
// 点击越限 // 点击越限
const detailClick = (row: any, title: string, key: string) => { const detailClick = (row: any, title: string, key: string) => {
console.log('🚀 ~ detailClick ~ row:', row) // console.log('🚀 ~ detailClick ~ row:', row)
detailRef.value.open({ detailRef.value.open({
row: row, row: row,
title: title, title: title,
@@ -802,7 +802,7 @@ onMounted(() => {
}) })
const handleNodeClick = (data: any, node: any) => { const handleNodeClick = (data: any, node: any) => {
console.log('🚀 ~ handleNodeClick ~ data:', data) // console.log('🚀 ~ handleNodeClick ~ data:', data)
if (data.level == 6) { if (data.level == 6) {
dotList.value = data dotList.value = data
// dotList.value.id = '6469e77fda42db12c7ca6620a092f03c1' // dotList.value.id = '6469e77fda42db12c7ca6620a092f03c1'

View File

@@ -1,125 +1,125 @@
<template> <template>
<div class="default-main"> <div class="default-main">
<TableHeader ref="TableHeaderRef"> <TableHeader ref="TableHeaderRef">
<template #select> <template #select>
<el-form-item label="新能源场站名称"> <el-form-item label="新能源场站名称">
<el-input v-model="tableStore.table.params.name" clearable placeholder="输入关键字筛选" /> <el-input v-model="tableStore.table.params.name" clearable placeholder="输入关键字筛选" />
</el-form-item> </el-form-item>
</template> </template>
<template #operation> <template #operation>
<el-button icon="el-icon-Plus" type="primary" @click="add">新增</el-button> <el-button icon="el-icon-Plus" type="primary" @click="add">新增</el-button>
</template> </template>
</TableHeader> </TableHeader>
<Table ref="tableRef" /> <Table ref="tableRef" />
<!--弹框--> <!--弹框-->
<addForm ref="addFormRef" @onSubmit="tableStore.index()" /> <addForm ref="addFormRef" @onSubmit="tableStore.index()" />
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, provide, nextTick } from 'vue' import { ref, onMounted, provide, nextTick } from 'vue'
import TableStore from '@/utils/tableStore' import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue' import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue' import TableHeader from '@/components/table/header/index.vue'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import addForm from './components/addForm.vue' import addForm from './components/addForm.vue'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
import { useAdminInfo } from '@/stores/adminInfo' import { useAdminInfo } from '@/stores/adminInfo'
import { delNewStation } from '@/api/device-boot/newEnergy' import { delNewStation } from '@/api/device-boot/newEnergy'
defineOptions({ defineOptions({
name: 'newEnergy/newEnergyLedger' name: 'newEnergy/newEnergyLedger'
}) })
const dictData = useDictData() const dictData = useDictData()
//获取登陆用户姓名和部门 //获取登陆用户姓名和部门
const adminInfo = useAdminInfo() const adminInfo = useAdminInfo()
const newEnergy = dictData.getBasicData('new_station_type') const newEnergy = dictData.getBasicData('new_station_type')
const scaleList = dictData.getBasicData('Dev_Voltage_Stand') const scaleList = dictData.getBasicData('Dev_Voltage_Stand')
const tableRef = ref() const tableRef = ref()
const TableHeaderRef = ref() const TableHeaderRef = ref()
const addFormRef = ref() const addFormRef = ref()
const tableStore = new TableStore({ const tableStore = new TableStore({
url: '/device-boot/newStation/queryPage', url: '/device-boot/newStation/queryPage',
method: 'POST', method: 'POST',
column: [ column: [
{ {
title: '序号', title: '序号',
width: '80', width: '80',
formatter: (row: any) => { formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1 return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
} }
}, },
{ field: 'name', title: '新能源场站名称' }, { field: 'name', title: '新能源场站名称' },
{ {
field: 'stationType', field: 'stationType',
title: '新能源场站类型', title: '新能源场站类型',
formatter: (row: any) => newEnergy.filter(item => item.id == row.cellValue)[0]?.name formatter: (row: any) => newEnergy.filter(item => item.id == row.cellValue)[0]?.name
}, },
{ {
field: 'scale', field: 'scale',
title: '电压等级', title: '电压等级',
formatter: (row: any) => scaleList.filter(item => item.id == row.cellValue)[0]?.name formatter: (row: any) => scaleList.filter(item => item.id == row.cellValue)[0]?.name
}, },
{ field: 'ratedPower', title: '额定有功功率(kW)' }, { field: 'ratedPower', title: '额定有功功率(kW)' },
{ field: 'longitude', title: '经度' }, { field: 'longitude', title: '经度' },
{ field: 'latitude', title: '纬度' }, { field: 'latitude', title: '纬度' },
{ {
title: '操作', title: '操作',fixed: 'right',
align: 'center', align: 'center',
render: 'buttons', render: 'buttons',
fixed: 'right',
buttons: [ buttons: [
{ {
name: 'edit', name: 'edit',
title: '修改', title: '修改',
type: 'primary', type: 'primary',
icon: 'el-icon-edit', icon: 'el-icon-edit',
render: 'basicButton', render: 'basicButton',
click: row => { click: row => {
addFormRef.value.open({ addFormRef.value.open({
title: '修改', title: '修改',
row: row row: row
}) })
} }
}, },
{ {
name: 'delete', name: 'delete',
title: '删除', title: '删除',
type: 'danger', type: 'danger',
icon: 'el-icon-Delete', icon: 'el-icon-Delete',
render: 'confirmButton', render: 'confirmButton',
popconfirm: { popconfirm: {
confirmButtonText: '确认', confirmButtonText: '确认',
cancelButtonText: '取消', cancelButtonText: '取消',
confirmButtonType: 'danger', confirmButtonType: 'danger',
title: '确定删除该数据吗?' title: '确定删除该数据吗?'
}, },
click: row => { click: row => {
delNewStation({ ids: row.id }).then(() => { delNewStation({ ids: row.id }).then(() => {
ElMessage.success('删除成功') ElMessage.success('删除成功')
tableStore.index() tableStore.index()
}) })
} }
} }
] ]
} }
], ],
beforeSearchFun: () => { beforeSearchFun: () => {
tableStore.table.params.currentPage = tableStore.table.params.pageNum tableStore.table.params.currentPage = tableStore.table.params.pageNum
}, },
loadCallback: () => {} loadCallback: () => {}
}) })
tableStore.table.params.name = '' tableStore.table.params.name = ''
const add = () => { const add = () => {
addFormRef.value.open({ addFormRef.value.open({
title: '新增' title: '新增'
}) })
} }
provide('tableStore', tableStore) provide('tableStore', tableStore)
onMounted(() => { onMounted(() => {
tableStore.index() tableStore.index()
}) })
</script> </script>
<style scoped lang="scss"></style> <style scoped lang="scss"></style>

View File

@@ -38,6 +38,7 @@ const tableStore = new TableStore({
echarts.value.Grade(tableStore.table.data.voltageStatistics) echarts.value.Grade(tableStore.table.data.voltageStatistics)
echarts.value.Relation(tableStore.table.data.monthlyStatistics) echarts.value.Relation(tableStore.table.data.monthlyStatistics)
table.value.info(tableStore.table.data) table.value.info(tableStore.table.data)
} }
}) })
provide('tableStore', tableStore) provide('tableStore', tableStore)

View File

@@ -3,7 +3,7 @@
<TableHeader datePicker :showReset="false" showExport ref="TableHeaderRef"> <TableHeader datePicker :showReset="false" showExport ref="TableHeaderRef">
<template v-slot:select> <template v-slot:select>
<el-form-item label="筛选数据"> <el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.loginName" placeholder="请输入"></el-input> <el-input v-model="tableStore.table.params.loginName" placeholder="请输入" clearable maxlength="32" show-word-limit></el-input>
</el-form-item> </el-form-item>
</template> </template>
</TableHeader> </TableHeader>

View File

@@ -288,18 +288,21 @@ const equipment = (row: any) => {}
// 承载能力评估 // 承载能力评估
const assess = () => { const assess = () => {
// vxeRef.value.getRadioRecord() // vxeRef.value.getRadioRecord()
if (equipmentList.value.length == null) { if (equipmentList.value.length == 0) {
return ElMessage.warning('请选择用户') return ElMessage.warning('请选择有终端设备的用户')
} }
loading.value = true loading.value = true
formRef.value.validate((valid: any) => { formRef.value.validate((valid: any) => {
if (valid) { if (valid) {
form.value.devList = equipmentList.value form.value.devList = equipmentList.value
carryCapacityEvaluate(form.value).then(res => { carryCapacityEvaluate(form.value).then(res => {
rendering(res.data) rendering(res.data)
loading.value = false loading.value = false
}) })
}else{
loading.value = false
} }
}) })
} }
@@ -450,7 +453,7 @@ const selChange = async (e: any) => {
} }
// 导出 // 导出
const onExport = () => { const onExport = () => {
console.log("🚀 ~ onExport ~ document.getElementById('exportId'):", document.getElementById('exportId')) // console.log("🚀 ~ onExport ~ document.getElementById('exportId'):", document.getElementById('exportId'))
// 转换成canvas // 转换成canvas
html2canvas(document.getElementById('exportId'), { html2canvas(document.getElementById('exportId'), {
@@ -459,7 +462,7 @@ const onExport = () => {
logging: false, // 关闭日志 logging: false, // 关闭日志
scale: 2 // 提高缩放比例以获得更清晰的截图 scale: 2 // 提高缩放比例以获得更清晰的截图
}).then(function (canvas) { }).then(function (canvas) {
console.log('🚀 ~ onExport ~ canvas:', canvas) // console.log('🚀 ~ onExport ~ canvas:', canvas)
// 创建a标签实现下载 // 创建a标签实现下载
let creatIMg = document.createElement('a') let creatIMg = document.createElement('a')
creatIMg.download = '光伏电站承载能力评估结果.png' // 设置下载的文件名, creatIMg.download = '光伏电站承载能力评估结果.png' // 设置下载的文件名,

View File

@@ -183,7 +183,7 @@ import TableHeader from '@/components/table/header/index.vue'
import MyEChart from '@/components/echarts/MyEchart.vue' import MyEChart from '@/components/echarts/MyEchart.vue'
import { useMonitoringPoint } from '@/stores/monitoringPoint' import { useMonitoringPoint } from '@/stores/monitoringPoint'
import { defaultAttribute } from '@/components/table/defaultAttribute' import { defaultAttribute } from '@/components/table/defaultAttribute'
import { harmonicOptions } from '@/utils/dictionary' import { harmonicOptions1 } from '@/utils/dictionary'
import { Select } from '@element-plus/icons-vue' import { Select } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { import {
@@ -202,10 +202,10 @@ import html2canvas from 'html2canvas'
import { yMethod } from '@/utils/echartMethod' import { yMethod } from '@/utils/echartMethod'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
const props = defineProps(['rowList']) const props = defineProps(['rowList'])
const harmonic = harmonicOptions.filter(item => item.value < 26) const harmonic = harmonicOptions1.filter(item => item.value < 26)
const currentLod = ref(false) const currentLod = ref(false)
const monitoringPoint = useMonitoringPoint() const monitoringPoint = useMonitoringPoint()
const size = ref(23) const size = ref(19)
const dictData = useDictData() const dictData = useDictData()
const datePickerRef = ref() const datePickerRef = ref()
const height = mainHeight(80).height const height = mainHeight(80).height
@@ -734,6 +734,7 @@ const choose = (e: any) => {
uploadExcel(e.raw, form).then(res => { uploadExcel(e.raw, form).then(res => {
ElMessage.success('导入成功') ElMessage.success('导入成功')
onSubmit()
}) })
} }
const tabChange = (e: any) => { const tabChange = (e: any) => {
@@ -843,7 +844,7 @@ onMounted(() => {
} }
.btnBox { .btnBox {
display: flex; display: flex;
justify-content: end; justify-content: flex-end;
} }
:deep(.vxe-table--header thead tr:first-of-type th:first-of-type) { :deep(.vxe-table--header thead tr:first-of-type th:first-of-type) {

View File

@@ -176,7 +176,7 @@ const info = () => {
}) })
}) })
}) })
console.log('🚀 ~ queyDetail ~ photovoltaicData.value:', photovoltaicData.value) // console.log('🚀 ~ queyDetail ~ photovoltaicData.value:', photovoltaicData.value)
}) })
// 电弧炉 // 电弧炉
queyDetailDhl().then(res => { queyDetailDhl().then(res => {

View File

@@ -136,7 +136,7 @@ const tableStore: any = new TableStore({
{ field: 'evaluateDate', title: '评估日期' }, { field: 'evaluateDate', title: '评估日期' },
{ {
title: '操作', title: '操作',fixed: 'right',
width: '180', width: '180',
render: 'buttons', render: 'buttons',
buttons: [ buttons: [
@@ -157,7 +157,7 @@ const tableStore: any = new TableStore({
}, },
{ {
name: 'del', name: 'del',
text: '禁止接入', text: '删除',
type: 'danger', type: 'danger',
icon: 'el-icon-Delete', icon: 'el-icon-Delete',
render: 'confirmButton', render: 'confirmButton',
@@ -165,11 +165,11 @@ const tableStore: any = new TableStore({
confirmButtonText: '确认', confirmButtonText: '确认',
cancelButtonText: '取消', cancelButtonText: '取消',
confirmButtonType: 'danger', confirmButtonType: 'danger',
title: '确定禁止接入' title: '确定删除'
}, },
click: row => { click: row => {
remove({ ids: row.id }).then(() => { remove({ ids: row.id }).then(() => {
ElMessage.success('禁止接入成功') ElMessage.success('删除成功')
tableStore.index() tableStore.index()
}) })
} }

View File

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

View File

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

View File

@@ -8,7 +8,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="筛选数据"> <el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.searchValue" placeholder="请输入筛选数据" clearable /> <el-input v-model="tableStore.table.params.searchValue" placeholder="请输入筛选数据" clearable maxlength="32" show-word-limit/>
</el-form-item> </el-form-item>
</template> </template>
<template #operation> <template #operation>

View File

@@ -4,13 +4,13 @@
<TableHeader datePicker showExport :showReset="false"> <TableHeader datePicker showExport :showReset="false">
<template v-slot:select> <template v-slot:select>
<el-form-item label="筛选数据"> <el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.searchValue" placeholder="请输入筛选数据" clearable /> <el-input v-model="tableStore.table.params.searchValue" placeholder="请输入筛选数据" clearable maxlength="32" show-word-limit/>
</el-form-item> </el-form-item>
</template> </template>
</TableHeader> </TableHeader>
<div :key="key"> <div :key="key">
<Table ref="tableRef" :height="'49vh'"></Table> <Table ref="tableRef" :height="'calc(50vh - 100px)'"></Table>
</div> </div>
</el-dialog> </el-dialog>
</template> </template>
@@ -31,10 +31,12 @@ const dialogVisible = ref(false)
const tableStore = new TableStore({ const tableStore = new TableStore({
url: '/system-boot/frontLog/queryLogCHild', url: '/system-boot/frontLog/queryLogCHild',
method: 'POST', method: 'POST',
filename: '前置交互日志详情',
column: [ column: [
{ {
field: 'index', field: 'index',
title: '序号', title: '序号',
width: '80', width: '80',
formatter: (row: any) => { formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1 return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1

View File

@@ -3,7 +3,7 @@
<TableHeader datePicker showExport> <TableHeader datePicker showExport>
<template v-slot:select> <template v-slot:select>
<el-form-item label="筛选数据"> <el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.searchValue" placeholder="请输入筛选数据" clearable /> <el-input v-model="tableStore.table.params.searchValue" placeholder="请输入筛选数据" clearable maxlength="32" show-word-limit/>
</el-form-item> </el-form-item>
</template> </template>
</TableHeader> </TableHeader>
@@ -77,7 +77,7 @@ const tableStore = new TableStore({
} }
}, },
{ {
title: '操作', title: '操作',fixed: 'right',
width: '180', width: '180',
render: 'buttons', render: 'buttons',
buttons: [ buttons: [

View File

@@ -40,7 +40,14 @@
></Table> ></Table>
</div> </div>
<div class="pd10" style="width: 400px" v-loading="loading"> <div class="pd10" style="width: 400px" v-loading="loading">
<el-input v-model="filterText" placeholder="请输入内容" clearable show-word-limit @input="change"> <el-input
v-model="filterText"
placeholder="请输入内容"
clearable
maxlength="32"
show-word-limit
@input="change"
>
<template #prefix> <template #prefix>
<Icon name="el-icon-Search" style="font-size: 16px" /> <Icon name="el-icon-Search" style="font-size: 16px" />
</template> </template>
@@ -83,7 +90,7 @@
v-else v-else
class="box-item" class="box-item"
title="确定重启吗?" title="确定重启吗?"
placement="bottom" placement="left"
@confirm="restart(data)" @confirm="restart(data)"
> >
<template #actions="{ confirm, cancel }"> <template #actions="{ confirm, cancel }">
@@ -141,7 +148,7 @@
</el-form-item> </el-form-item>
<el-form-item label="最大终端数:" prop="nodeDevNum" class="top"> <el-form-item label="最大终端数:" prop="nodeDevNum" class="top">
<el-input <el-input
v-model="formData.nodeDevNum" v-model.trim.number="formData.nodeDevNum"
onkeyup="value = value.replace(/[^0-9]/g,'')" onkeyup="value = value.replace(/[^0-9]/g,'')"
maxlength="5" maxlength="5"
placeholder="请输入最大终端数" placeholder="请输入最大终端数"
@@ -149,7 +156,7 @@
</el-form-item> </el-form-item>
<el-form-item label="最大进程数:" prop="maxProcessNum" class="top"> <el-form-item label="最大进程数:" prop="maxProcessNum" class="top">
<el-input <el-input
v-model="formData.maxProcessNum" v-model.trim.number="formData.maxProcessNum"
onkeyup="value = value.replace(/[^0-9]/g,'')" onkeyup="value = value.replace(/[^0-9]/g,'')"
maxlength="5" maxlength="5"
placeholder="请根据监测点规模填写合适进程数1个进程最大可承载200个监测点" placeholder="请根据监测点规模填写合适进程数1个进程最大可承载200个监测点"
@@ -209,7 +216,8 @@ import {
updateNode, updateNode,
nodeDeviceTree, nodeDeviceTree,
updateDeviceProcess, updateDeviceProcess,
askRestartProcess askRestartProcess,
allotTerminal
} from '@/api/device-boot/Business' } from '@/api/device-boot/Business'
import TableStore from '@/utils/tableStore' import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue' import Table from '@/components/table/index.vue'
@@ -240,6 +248,7 @@ const tableRef = ref()
const processNo = ref('') const processNo = ref('')
const ruleFormRef = ref() const ruleFormRef = ref()
const dataSource: any = ref([]) const dataSource: any = ref([])
const deviceInfoList: any = ref([])
const defaultProps = { const defaultProps = {
children: 'deviceInfoList', children: 'deviceInfoList',
label: 'name' label: 'name'
@@ -271,7 +280,7 @@ const tableStore = new TableStore({
method: 'POST', method: 'POST',
column: [ column: [
{ title: '名称', field: 'name' }, { title: '名称', field: 'name' },
{ title: 'IP', field: 'ip' ,width:'120px' }, { title: 'IP', field: 'ip', width: '120px' },
{ {
title: '等级', title: '等级',
field: 'nodeGrade', field: 'nodeGrade',
@@ -288,7 +297,7 @@ const tableStore = new TableStore({
} }
}, },
{ {
title: '最大监测点数量', title: '最大终端数量',
field: 'nodeDevNum' field: 'nodeDevNum'
}, },
{ {
@@ -316,6 +325,7 @@ const tableStore = new TableStore({
{ {
title: '操作', title: '操作',
fixed: 'right',
align: 'center', align: 'center',
width: '180', width: '180',
render: 'buttons', render: 'buttons',
@@ -350,7 +360,7 @@ const tableStore = new TableStore({
}, },
click: row => { click: row => {
askRestartProcess({ askRestartProcess({
deviceRebootType: null, deviceRebootType: 1,
nodeId: row.id, nodeId: row.id,
processNo: 1 processNo: 1
}).then(res => { }).then(res => {
@@ -373,11 +383,41 @@ const tableStore = new TableStore({
title: '确定删除吗?' title: '确定删除吗?'
}, },
click: row => { click: row => {
if (hasDevices.value) {
ElMessage.warning('此前置机绑定了设备,无法删除!')
return
}
delNode(row.id).then(res => { delNode(row.id).then(res => {
ElMessage.success('删除成功') ElMessage.success('删除成功')
tableStore.index() tableStore.index()
}) })
} }
},
{
name: 'edit',
title: '分配终端',
type: 'primary',
icon: 'InfoFilled',
render: 'confirmButton',
popconfirm: {
confirmButtonText: '确认',
cancelButtonText: '取消',
confirmButtonType: 'primary',
title: '确定分配终端吗?'
},
click: row => {
// if (!hasDevices.value) {
// ElMessage.warning('此前置机下无设备,无法分配终端!')
// return
// }
allotTerminal({
nodeId: row.id
}).then(res => {
ElMessage.success(res.message)
tableStore.index()
})
}
} }
] ]
} }
@@ -395,12 +435,14 @@ const tableStore = new TableStore({
} }
}) })
const nodeId = ref('') const nodeId = ref('')
// 点击行 const hasDevices = ref(false)
/// 点击行
const currentChangeEvent = () => { const currentChangeEvent = () => {
// 确保 tableRef 和当前记录存在 // 确保 tableRef 和当前记录存在
if (!tableRef.value || !tableRef.value.getRef().getCurrentRecord()) { if (!tableRef.value || !tableRef.value.getRef().getCurrentRecord()) {
loading.value = false loading.value = false
dataSource.value = [] dataSource.value = []
hasDevices.value = false
return return
} }
@@ -413,15 +455,26 @@ const currentChangeEvent = () => {
nodeId.value = tableRef.value.getRef().getCurrentRecord().id nodeId.value = tableRef.value.getRef().getCurrentRecord().id
// 检查返回的数据是否存在且不为空 // 检查返回的数据是否存在且不为空
if (res.data && res.data.processDeviceList) { if (res.data && res.data.processDeviceList) {
dataSource.value = res.data.processDeviceList.filter(item => (item.name = item.processNo + '')) // 检查是否有设备绑定
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 // 保持原有的过滤逻辑
})
} else { } else {
dataSource.value = [] dataSource.value = []
hasDevices.value = false
} }
loading.value = false loading.value = false
}) })
.catch(() => { .catch(() => {
// 添加错误处理,确保 loading 状态也能关闭 // 添加错误处理,确保 loading 状态也能关闭
dataSource.value = [] dataSource.value = []
hasDevices.value = false
loading.value = false loading.value = false
}) })
@@ -430,11 +483,11 @@ const currentChangeEvent = () => {
// 重启进程 // 重启进程
const restart = (data: any) => { const restart = (data: any) => {
console.log('🚀 ~ restart ~ data:', data) // console.log('🚀 ~ restart ~ data:', data)
askRestartProcess({ askRestartProcess({
deviceRebootType: data.processNo, deviceRebootType: null,
nodeId: nodeId.value, nodeId: nodeId.value,
processNo: 2 processNo: data.processNo
}).then(res => { }).then(res => {
ElMessage.success('重启成功') ElMessage.success('重启成功')
currentChangeEvent() currentChangeEvent()
@@ -472,7 +525,7 @@ const filterNode = (value: string, data: any, node: any) => {
// 过滤父节点 / 子节点 (如果输入的参数是父节点且能匹配则返回该节点以及其下的所有子节点如果参数是子节点则返回该节点的父节点。name是中文字符enName是英文字符. // 过滤父节点 / 子节点 (如果输入的参数是父节点且能匹配则返回该节点以及其下的所有子节点如果参数是子节点则返回该节点的父节点。name是中文字符enName是英文字符.
const chooseNode = (value: string, data: any, node: any) => { const chooseNode = (value: string, data: any, node: any) => {
if (data.name.indexOf(value) !== -1) { if ((data.subName + data.name).indexOf(value) !== -1) {
return true return true
} }
const level = node.level const level = node.level
@@ -583,7 +636,7 @@ const addMenu = () => {}
:deep(.default) { :deep(.default) {
display: flex; display: flex;
.row--current { .row--current {
// background-color: var(--el-color-primary-light-8) !important; // background-color: var(--el-color-primary-light-8) !important;
} }
} }
.custom-tree-node { .custom-tree-node {

View File

@@ -3,7 +3,7 @@
<TableHeader> <TableHeader>
<template #select> <template #select>
<el-form-item label="终端型号"> <el-form-item label="终端型号">
<el-select v-model="tableStore.table.params.teriminal" clearable placeholder="请选择终端型号"> <el-select v-model="tableStore.table.params.devType" clearable placeholder="请选择终端型号">
<el-option <el-option
v-for="item in teriminaloption" v-for="item in teriminaloption"
:key="item.id" :key="item.id"
@@ -13,7 +13,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="终端状态"> <el-form-item label="终端状态">
<el-select v-model="tableStore.table.params.teriminalstatus" clearable placeholder="请选择终端状态"> <el-select v-model="tableStore.table.params.runFlag" clearable placeholder="请选择终端状态">
<el-option <el-option
v-for="item in teriminalstatusoption" v-for="item in teriminalstatusoption"
:key="item.id" :key="item.id"
@@ -23,7 +23,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="通讯状态"> <el-form-item label="通讯状态">
<el-select v-model="tableStore.table.params.state" clearable placeholder="请选择通讯状态"> <el-select v-model="tableStore.table.params.comFlag" clearable placeholder="请选择通讯状态">
<el-option <el-option
v-for="item in stateoption" v-for="item in stateoption"
:key="item.id" :key="item.id"
@@ -32,7 +32,7 @@
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="程序版本"> <!-- <el-form-item label="程序版本">
<el-select v-model="tableStore.table.params.program" clearable placeholder="请选择程序版本"> <el-select v-model="tableStore.table.params.program" clearable placeholder="请选择程序版本">
<el-option <el-option
v-for="item in programoption" v-for="item in programoption"
@@ -41,19 +41,21 @@
:value="item.id" :value="item.id"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item> -->
<el-form-item label="筛选数据"> <!-- <el-form-item label="筛选数据">
<el-input <el-input
v-model="tableStore.table.params.filterName" v-model="tableStore.table.params.filterName"
@keyup="searchEvent" @keyup="searchEvent"
maxlength="32"
show-word-limit
placeholder="输入关键字筛选" placeholder="输入关键字筛选"
/> />
</el-form-item> </el-form-item> -->
</template> </template>
<template #operation> <!-- <template #operation>
<el-button icon="el-icon-Download" @click="add">导出</el-button> <el-button icon="el-icon-Download" @click="add">导出</el-button>
<el-button icon="el-icon-Check" @click="add">批量升级</el-button> <el-button icon="el-icon-Check" @click="add">批量升级</el-button>
</template> </template> -->
</TableHeader> </TableHeader>
<div :style="`height: calc(${tableStore.table.height} + 58px)`"> <div :style="`height: calc(${tableStore.table.height} + 58px)`">
<vxe-table <vxe-table
@@ -104,7 +106,7 @@
<vxe-column field="updateTime" title="最新升级时间"></vxe-column> <vxe-column field="updateTime" title="最新升级时间"></vxe-column>
<vxe-column title="操作" min-width="100"> <vxe-column title="操作" min-width="100">
<template #default="{ row }"> <template #default="{ row }">
<el-button v-if="row.level == 4" size="small" link @click="updateprogram(row)">升级</el-button> <!-- <el-button v-if="row.level == 4" size="small" link @click="updateprogram(row)">升级</el-button> -->
<el-button <el-button
v-if="row.level == 4" v-if="row.level == 4"
:disabled="row.state == 1 ? true : false" :disabled="row.state == 1 ? true : false"
@@ -250,8 +252,9 @@ const tableStore = new TableStore({
}, 0) }, 0)
} }
}) })
tableStore.table.params.teriminal = '' tableStore.table.params.devType = ''
tableStore.table.params.state = '' tableStore.table.params.runFlag = ''
tableStore.table.params.comFlag = ''
tableStore.table.params.program = '' tableStore.table.params.program = ''
tableStore.table.params.searchEvent = '' tableStore.table.params.searchEvent = ''
tableStore.table.params.filterName = '' tableStore.table.params.filterName = ''

View File

@@ -35,7 +35,7 @@ const dialogVisible = ref(false)
const tableData = ref([]) const tableData = ref([])
const open = (e: any) => { const open = (e: any) => {
console.log("🚀 ~ open ~ e:", e) //console.log("🚀 ~ open ~ e:", e)
echartsXq.value = { echartsXq.value = {
title: { title: {
text: e.name + '性能详情' text: e.name + '性能详情'

View File

@@ -43,6 +43,8 @@
v-model="tableStore.table.params.filterName" v-model="tableStore.table.params.filterName"
@keyup="searchEvent" @keyup="searchEvent"
clearable clearable
maxlength="32"
show-word-limit
placeholder="输入关键字筛选" placeholder="输入关键字筛选"
/> />
</el-form-item> </el-form-item>
@@ -75,6 +77,7 @@
:checkbox-config="{ labelField: 'name' }" :checkbox-config="{ labelField: 'name' }"
> >
<vxe-column <vxe-column
v-if="treeData && treeData.length > 0"
field="name" field="name"
align="left" align="left"
type="checkbox" type="checkbox"
@@ -82,6 +85,15 @@
min-width="200" min-width="200"
tree-node tree-node
></vxe-column> ></vxe-column>
<!-- 没有数据时显示普通列 -->
<vxe-column
v-else
field="name"
align="left"
title="电网拓扑"
min-width="200"
tree-node
></vxe-column>
<vxe-column field="devType" title="终端型号"> <vxe-column field="devType" title="终端型号">
<template #default="{ row }"> <template #default="{ row }">
{{ teriminaloption.find((item: any) => item.id === row.devType)?.name }} {{ teriminaloption.find((item: any) => item.id === row.devType)?.name }}
@@ -223,7 +235,7 @@ const manage = (name: string, key: number) => {
.getCheckboxRecords() .getCheckboxRecords()
.filter((item: any) => item.level == 4) .filter((item: any) => item.level == 4)
.map(item => item.id) .map(item => item.id)
console.log('🚀 ~ deviceData ~ selectRecords:', selectRecords) //console.log('🚀 ~ deviceData ~ selectRecords:', selectRecords)
if (selectRecords.length == 0) { if (selectRecords.length == 0) {
return ElMessage({ return ElMessage({
message: '请至少选择一台装置', message: '请至少选择一台装置',

View File

@@ -1694,7 +1694,7 @@ import { useDictData } from '@/stores/dictData'
import { ref, reactive, onMounted } from 'vue' import { ref, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { getYwZtSubstation } from '@/api/device-boot/device' import { getYwZtSubstation } from '@/api/device-boot/device'
const size = ref(23) const size = ref(19)
const TerminalRef = ref() const TerminalRef = ref()
const pageHeight = mainHeight(20) const pageHeight = mainHeight(20)
const Height = mainHeight(100) const Height = mainHeight(100)
@@ -1740,8 +1740,8 @@ const optionarr = ref([
]) ])
/**母线类型 */ /**母线类型 */
const busBarType = ref([ const busBarType = ref([
{ name: '母线', value: 0 }, { name: '实母线', value: 1 },
{ name: '虚拟母线', value: 1 } { name: '虚拟母线', value: 0 }
]) ])
const bigList: any = ref([]) const bigList: any = ref([])
const smallList: any = ref([]) const smallList: any = ref([])
@@ -1811,7 +1811,7 @@ const busBarDetail = ref({
/**电压等级 */ /**电压等级 */
scale: '', scale: '',
/**母线类型 */ /**母线类型 */
model: 0, model: 1,
/**母线id */ /**母线id */
subvIndex: '', subvIndex: '',
/**监测点 */ /**监测点 */
@@ -2313,7 +2313,7 @@ const remove = () => {
const next = async () => { const next = async () => {
await mainForm.value.validate((valid: any) => { await mainForm.value.validate((valid: any) => {
if (valid) { if (valid) {
console.log('🚀 ~ awaitmainForm.value.validate ~ nodeLevel.value:', nodeLevel.value) // console.log('🚀 ~ awaitmainForm.value.validate ~ nodeLevel.value:', nodeLevel.value)
switch (nodeLevel.value) { switch (nodeLevel.value) {
case 100: case 100:
@@ -2397,35 +2397,45 @@ const onsubmit = () => {
/** /**
* 提交数据 * 提交数据
*/ */
const submitData = () => { const submitData = async () => {
const project = JSON.parse(JSON.stringify(AddProjectBO.value)) const project = JSON.parse(JSON.stringify(AddProjectBO.value))
await mainForm.value.validate((valid: any) => {
// project: JSON.stringify(project) if (valid) {
addTerminal(project).then((res: any) => { addTerminal(project).then((res: any) => {
ElMessage({ ElMessage({
type: 'success', type: 'success',
message: res.message message: res.message
}) })
reaseStatus() reaseStatus()
initAddProjectBo() initAddProjectBo()
initAddProjectBoId() initAddProjectBoId()
treedata() treedata()
})
}
}) })
// project: JSON.stringify(project)
} }
/** /**
* 修改数据 * 修改数据
*/ */
const updateDate = () => { const updateDate = async () => {
// console.log("updateProject:", this.updateProject); // console.log("updateProject:", this.updateProject);
let data = updateProject.value await mainForm.value.validate((valid: any) => {
updateTerminal(data).then((res: any) => { if (valid){
ElMessage({ let data = updateProject.value
type: 'success', updateTerminal(data).then((res: any) => {
message: res.message ElMessage({
}) type: 'success',
pageStatus.value = 1 message: res.message
treedata() })
pageStatus.value = 1
treedata()
})
}
}) })
} }
const updateProjectF = () => { const updateProjectF = () => {
updateProject.value = { updateProject.value = {

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

@@ -74,7 +74,7 @@
> >
<el-form :model="ruleForm" :rules="rules" ref="ruleFormRef" label-width="100px"> <el-form :model="ruleForm" :rules="rules" ref="ruleFormRef" label-width="100px">
<el-form-item label="变压器名:" prop="tfName"> <el-form-item label="变压器名:" prop="tfName">
<el-input v-model="ruleForm.tfName" placeholder="请输入" clearable></el-input> <el-input v-model="ruleForm.tfName" placeholder="请输入" clearable maxlength="32" show-word-limit></el-input>
</el-form-item> </el-form-item>
<el-form-item label="接线方式:" prop="wiring" class="top"> <el-form-item label="接线方式:" prop="wiring" class="top">
<el-select style="width: 100%" v-model="ruleForm.wiring" clearable placeholder="请选择接线方式"> <el-select style="width: 100%" v-model="ruleForm.wiring" clearable placeholder="请选择接线方式">
@@ -113,7 +113,7 @@
<el-col :span="8"> <el-col :span="8">
<div style="border-right: 1px solid; height: 100%" class="xiaoshou"> <div style="border-right: 1px solid; height: 100%" class="xiaoshou">
<div style="overflow-y: auto; height: 100%; overflow-x: auto;max-height: 350px;" class="tree mr10 xiaoshou"> <div style="overflow-y: auto; height: 100%; overflow-x: auto;max-height: 350px;" class="tree mr10 xiaoshou">
<el-input placeholder="输入关键字检索" v-model="filterText1" clearable></el-input> <el-input placeholder="输入关键字检索" v-model="filterText1" clearable maxlength="32" show-word-limit></el-input>
<el-tree <el-tree
style="cursor: pointer;display: inline-block;" style="cursor: pointer;display: inline-block;"
:data="treeMenuLeftData" :data="treeMenuLeftData"
@@ -163,7 +163,7 @@
<el-col :span="8"> <el-col :span="8">
<div style="border-left: 1px solid; height: 100%" class="xiaoshou"> <div style="border-left: 1px solid; height: 100%" class="xiaoshou">
<div style="overflow-y: auto; height: 100%;overflow-x: auto;max-height: 350px;" class="ml10 tree xiaoshou"> <div style="overflow-y: auto; height: 100%;overflow-x: auto;max-height: 350px;" class="ml10 tree xiaoshou">
<el-input placeholder="输入关键字检索" v-model="filterText2" clearable></el-input> <el-input placeholder="输入关键字检索" v-model="filterText2" clearable maxlength="32" show-word-limit></el-input>
<el-tree <el-tree
style="cursor: pointer" style="cursor: pointer"
:data="treeMenuRightData" :data="treeMenuRightData"
@@ -328,7 +328,7 @@ const tableStore = new TableStore({
field: 'tfDescribe' field: 'tfDescribe'
}, },
{ {
title: '操作', title: '操作',fixed: 'right',
align: 'center', align: 'center',
width: '180', width: '180',
render: 'buttons', render: 'buttons',
@@ -372,6 +372,7 @@ const tableStore = new TableStore({
click: row => { click: row => {
delTransformer([row.tfIndex]).then(res => { delTransformer([row.tfIndex]).then(res => {
ElMessage.success('删除成功') ElMessage.success('删除成功')
menuTree.value.loadData()
tableStore.index() tableStore.index()
}) })
} }
@@ -413,6 +414,7 @@ const transformerAdd = () => {
message: '请选择变电站' message: '请选择变电站'
}) })
} else { } else {
ruleForm.subIndex = parentId.value
transformerTitle.value = '新增变压器信息' transformerTitle.value = '新增变压器信息'
transformerInformation.value = true transformerInformation.value = true
nextTick(() => { nextTick(() => {
@@ -602,56 +604,74 @@ const maintenanceData = reactive({
//上节点选择 //上节点选择
const checkLeft = (checkedNodes: any, checkedKeys: any) => { const checkLeft = (checkedNodes: any, checkedKeys: any) => {
maintenanceData.upNode = checkedNodes.id maintenanceData.upNode = checkedNodes.id
if (maintenanceData.upNode === maintenanceData.downNode) { if (maintenanceData.upNode === maintenanceData.downNode) {
menuTreeRight.value?.setCheckedKeys([]) menuTreeRight.value?.setCheckedKeys([])
maintenanceData.downNode = '' maintenanceData.downNode = ''
} }
if (checkedKeys.checkedKeys.length > 1) { if (checkedKeys.checkedKeys.length > 1) {
menuTreeLeft.value?.setCheckedKeys([checkedNodes.id]) menuTreeLeft.value?.setCheckedKeys([checkedNodes.id])
} }
} }
//下节点选择 //下节点选择
const checkRight = (checkedNodes: any, checkedKeys: any) => { const checkRight = (checkedNodes: any, checkedKeys: any) => {
maintenanceData.downNode = checkedNodes.id maintenanceData.downNode = checkedNodes.id
if (maintenanceData.downNode === maintenanceData.upNode) {
menuTreeLeft.value?.setCheckedKeys([]) if (maintenanceData.downNode === maintenanceData.upNode) {
maintenanceData.upNode = '' menuTreeLeft.value?.setCheckedKeys([])
} maintenanceData.upNode = ''
if (checkedKeys.checkedKeys.length > 1) { }
menuTreeRight.value?.setCheckedKeys([checkedNodes.id]) if (checkedKeys.checkedKeys.length > 1) {
} menuTreeRight.value?.setCheckedKeys([checkedNodes.id])
}
} }
//节点维护提交 //节点维护提交
const maintenanceOnsubmit = () => { const maintenanceOnsubmit = () => {
for (let i = 0; i < bind.value.length; i++) {
if (bind.value[i][0] == maintenanceData.upNode) { if(maintenanceData.downNode == '' || maintenanceData.upNode == '') {
for (let j = 0; j < bind.value.length; j++) { ElMessage({
if (bind.value[j][1] == maintenanceData.downNode) { type: 'warning',
ElMessage({ message: '请确保上下节点各自选择一个母线!'
type: 'warning', })
message: '上下节点无法选择相同母线!!!' return
})
return
}
}
return
}
} }
if (bindLevel.value != 5) {
for (let i = 0; i < bind.value.length; i++) {
if (maintenanceData.upNode == bind.value[i][1] && maintenanceData.downNode == bind.value[i][0]) {
ElMessage({
type: 'warning',
message: '上下节点无法选择相同母线!!!'
})
return
}
}
}
if (maintenanceData.upNode == maintenanceData.downNode) {
ElMessage({
type: 'warning',
message: '上下节点无法选择相同母线!'
})
}
// for (let i = 0; i < bind.value.length; i++) {
// if (bind.value[i] == maintenanceData.upNode) {
// for (let j = 0; j < bind.value.length; j++) {
// if (bind.value[j] == maintenanceData.downNode) {
// ElMessage({
// type: 'warning',
// message: '上下节点无法选择相同母线!!!'
// })
// return
// }
// }
// return
// }
// }
// if (bindLevel.value != 5) {
// for (let i = 0; i < bind.value.length; i++) {
// if (maintenanceData.upNode == bind.value[i] && maintenanceData.downNode == bind.value[i]) {
// ElMessage({
// type: 'warning',
// message: '上下节点无法选择相同母线!!!'
// })
// return
// }
// }
// }
nodeMaintenance(maintenanceData).then((res: any) => { nodeMaintenance(maintenanceData).then((res: any) => {
if (res.code == 'A0000') { if (res.code == 'A0000') {
ElMessage({ ElMessage({

View File

@@ -53,12 +53,12 @@
</el-col> </el-col>
<el-col :span="14"> <el-col :span="14">
<div class="box"> <div class="box">
<el-form :model="form" label-width="100px" ref="ruleFormRef"> <el-form :model="form" label-width="100px" ref="ruleFormRef" :rules="rules">
<el-form-item label="名称:"> <el-form-item label="名称:" prop="tpName">
<el-input v-model="form.tpName" placeholder="请输入"></el-input> <el-input v-model="form.tpName" placeholder="请输入" maxlength="32" show-word-limit clearable></el-input>
</el-form-item> </el-form-item>
<el-form-item label="描述:" class="mt20"> <el-form-item label="描述:" class="mt20">
<el-input v-model="form.tfDescribe" placeholder="请输入"></el-input> <el-input v-model="form.tfDescribe" placeholder="请输入" ></el-input>
</el-form-item> </el-form-item>
<el-form-item class="mt20 ml20"> <el-form-item class="mt20 ml20">
<el-button @click="dialogFormVisible = false">取消</el-button> <el-button @click="dialogFormVisible = false">取消</el-button>
@@ -122,13 +122,8 @@ const menuTree = ref()
const TableHeaderRef = ref() const TableHeaderRef = ref()
const rules = reactive({ const rules = reactive({
name: [{ required: true, message: '名称不可为空', trigger: 'blur' }], tpName: [{ required: true, message: '名称不可为空', trigger: 'blur' }],
ip: [{ required: true, message: 'ip不可为空', trigger: 'blur' }],
nodeGrade: [{ required: true, message: '等级不可为空', trigger: 'blur' }],
nodeDevNum: [{ required: true, message: '最大终端数不可为空', trigger: 'blur' }],
maxProcessNum: [{ required: true, message: '最大进程数不可为空', trigger: 'blur' }],
sort: [{ required: true, message: '排序不可为空', trigger: 'blur' }],
remark: [{ required: true, message: '描述不可为空', trigger: 'blur' }]
}) })
const dialogFormVisible = ref(false) const dialogFormVisible = ref(false)
@@ -161,7 +156,7 @@ const tableStore = new TableStore({
field: 'tfDescribe' field: 'tfDescribe'
}, },
{ {
title: '操作', title: '操作',fixed: 'right',
align: 'center', align: 'center',
width: '180', width: '180',
render: 'buttons', render: 'buttons',

View File

@@ -48,7 +48,7 @@
v-model.trim="form.projectName" v-model.trim="form.projectName"
autocomplete="off" autocomplete="off"
placeholder="请输入项目名称" placeholder="请输入项目名称"
maxlength="64" maxlength="32"
show-word-limit show-word-limit
/> />
</el-form-item> </el-form-item>
@@ -112,7 +112,7 @@
v-model.trim="form.substation" v-model.trim="form.substation"
autocomplete="off" autocomplete="off"
placeholder="请输入厂站名称" placeholder="请输入厂站名称"
maxlength="64" maxlength="32"
show-word-limit show-word-limit
/> />
</el-form-item> </el-form-item>
@@ -364,6 +364,8 @@
v-model.trim="form.evaluationChekDept" v-model.trim="form.evaluationChekDept"
autocomplete="off" autocomplete="off"
placeholder="请输入预测评估评审单位" placeholder="请输入预测评估评审单位"
maxlength="32"
show-word-limit
/> />
</el-form-item> </el-form-item>
<el-form-item for="-" label="预测评估结论:" style="width: 100%"> <el-form-item for="-" label="预测评估结论:" style="width: 100%">
@@ -398,13 +400,12 @@ import { uploadFile } from '@/api/system-boot/file'
import { import {
submitFormData, submitFormData,
getById, getById,
updateFormData,
addEditor, addEditor,
resend, getByDeptDevLine,
getByDeptDevLine getUserReportUpdateById
} from '@/api/supervision-boot/interfere/index' } from '@/api/device-boot/sensitiveLoadMange'
import { getSubstationSelect } from '@/api/device-boot/line' import { getSubstationSelect } from '@/api/device-boot/line'
import { getUserReportUpdateById } from '@/api/supervision-boot/userReport/form' // import { getUserReportUpdateById } from '@/api/supervision-boot/userReport/form'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
const route = useRoute() const route = useRoute()
@@ -1059,7 +1060,7 @@ const filterUsers = (arr: any) => {
userTypeList.value = userTypeList.value.filter(item => !arr.includes(item.value)) userTypeList.value = userTypeList.value.filter(item => !arr.includes(item.value))
} }
const setcontroFlag = () => { const setcontroFlag = () => {
console.log(12333)
controFlag.value = true controFlag.value = true
} }

View File

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

View File

@@ -1,315 +1,315 @@
<template> <template>
<div class="default-main"> <div class="default-main">
<TableHeader ref="TableHeaderRef"> <TableHeader ref="TableHeaderRef">
<template #select> <template #select>
<el-form-item label="项目名称"> <el-form-item label="项目名称">
<el-input <el-input
style="width: 200px" style="width: 200px"
placeholder="请输入项目名称" placeholder="请输入项目名称"
v-model="tableStore.table.params.projectName" v-model="tableStore.table.params.projectName"
clearable clearable
maxlength="32" maxlength="32"
show-word-limit show-word-limit
></el-input> ></el-input>
</el-form-item> </el-form-item>
<el-form-item label="所在地市"> <el-form-item label="所在地市">
<el-select v-model="tableStore.table.params.city" clearable placeholder="请选择所在地市"> <el-select v-model="tableStore.table.params.city" clearable placeholder="请选择所在地市">
<el-option <el-option
v-for="item in areaOptionList" v-for="item in areaOptionList"
:key="item.id" :key="item.id"
:label="item.name" :label="item.name"
:value="item.name" :value="item.name"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
</template> </template>
<template #operation> <template #operation>
<el-button icon="el-icon-Plus" type="primary" @click="addFormModel">新增</el-button> <el-button icon="el-icon-Plus" type="primary" @click="addFormModel">新增</el-button>
<el-button icon="el-icon-Delete" type="primary" @click="deleteEven">删除</el-button> <el-button icon="el-icon-Delete" type="primary" @click="deleteEven">删除</el-button>
<!-- <el-button icon="el-icon-Download" type="primary" @click="exportExcelTemplate" :loading="loading"> <!-- <el-button icon="el-icon-Download" type="primary" @click="exportExcelTemplate" :loading="loading">
模板下载 模板下载
</el-button> </el-button>
<el-button icon="el-icon-Upload" type="primary" @click="importUserData">批量导入</el-button> --> <el-button icon="el-icon-Upload" type="primary" @click="importUserData">批量导入</el-button> -->
</template> </template>
</TableHeader> </TableHeader>
<Table ref="tableRef" /> <Table ref="tableRef" />
<el-dialog title="详情" width="60%" v-model="dialogShow" v-if="dialogShow"> <el-dialog title="详情" width="1000px" v-model="dialogShow" v-if="dialogShow">
<DetailInfo :id="userId" :openType="'sourcesOfInterference'"></DetailInfo> <DetailInfo :id="userId" :openType="'sourcesOfInterference'"></DetailInfo>
</el-dialog> </el-dialog>
<!-- 批量导入 --> <!-- 批量导入
<sensitive-user-popup ref="sensitiveUserPopup" /> <sensitive-user-popup ref="sensitiveUserPopup" /> -->
<!-- 查看详情 detail 新增/修改 create--> <!-- 查看详情 detail 新增/修改 create-->
<addForm ref="addForms" @onSubmit="tableStore.index()" :openType="'sourcesOfInterference'"></addForm> <addForm ref="addForms" @onSubmit="tableStore.index()" :openType="'sourcesOfInterference'"></addForm>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, provide, nextTick, watch } from 'vue' import { ref, onMounted, provide, nextTick, watch } from 'vue'
import TableStore from '@/utils/tableStore' import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue' import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue' import TableHeader from '@/components/table/header/index.vue'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import addForm from './components/addForm.vue' import addForm from './components/addForm.vue'
import SensitiveUserPopup from './components/sensitiveUserPopup.vue' import SensitiveUserPopup from './components/sensitiveUserPopup.vue'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { downloadSensitiveReportTemplate } from '@/api/supervision-boot/userReport/form' import { downloadSensitiveReportTemplate } from '@/api/supervision-boot/userReport/form'
import DetailInfo from './components/detail.vue' import DetailInfo from './components/detail.vue'
import { cancelFormData, getUserReportById } from '@/api/supervision-boot/interfere/index' import { cancelFormData, getUserReportById } from '@/api/supervision-boot/interfere/index'
import { deleteUserReport } from '@/api/supervision-boot/delete/index' import { deleteUserReport } from '@/api/device-boot/sensitiveLoadMange'
const addForms = ref() const addForms = ref()
const dictData = useDictData() const dictData = useDictData()
const sensitiveUserPopup = ref() const sensitiveUserPopup = ref()
const TableHeaderRef = ref() const TableHeaderRef = ref()
const loading = ref(false) const loading = ref(false)
const areaOptionList = dictData.getBasicData('jibei_area') const areaOptionList = dictData.getBasicData('jibei_area')
const { push, options, currentRoute } = useRouter() const { push, options, currentRoute } = useRouter()
import { useAdminInfo } from '@/stores/adminInfo' import { useAdminInfo } from '@/stores/adminInfo'
defineOptions({ defineOptions({
name: 'BusinessAdministrator/TerminalManagement/userLedger' name: 'BusinessAdministrator/TerminalManagement/userLedger'
}) })
//获取登陆用户姓名和部门 //获取登陆用户姓名和部门
const adminInfo = useAdminInfo() const adminInfo = useAdminInfo()
const tableStore = new TableStore({ const tableStore = new TableStore({
url: '/supervision-boot/userReport/getUserLedgerPage', url: '/device-boot/userReport/getUserLedgerPage',
// publicHeight: 65, // publicHeight: 65,
method: 'POST', method: 'POST',
column: [ column: [
{ {
width: '60', width: '60',
type: 'checkbox' type: 'checkbox'
}, },
{ {
title: '序号', title: '序号',
width: 80, width: 80,
formatter: (row: any) => { formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1 return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
} }
}, },
{ field: 'city', title: '所在地市', minWidth: 80 }, { field: 'city', title: '所在地市', minWidth: 80 },
{ field: 'substation', title: '厂站名称', minWidth: 100 }, { field: 'substation', title: '厂站名称', minWidth: 100 },
{ field: 'projectName', title: '项目名称', minWidth: 170 }, { field: 'projectName', title: '项目名称', minWidth: 170 },
{ {
field: 'userType', field: 'userType',
title: '用户性质', title: '用户性质',
minWidth: 150, minWidth: 150,
formatter: (obj: any) => { formatter: (obj: any) => {
const userType = obj.row.userType const userType = obj.row.userType
return getUserTypeName(userType) return getUserTypeName(userType)
} }
}, },
// { field: 'responsibleDepartment', title: '归口管理部门', minWidth: 130 }, // { field: 'responsibleDepartment', title: '归口管理部门', minWidth: 130 },
{ field: 'ratePower', title: '装机容量(MW)', minWidth: 130 }, { field: 'ratePower', title: '装机容量(MW)', minWidth: 130 },
{ {
field: 'createBy', field: 'createBy',
title: '创建人', title: '创建人',
minWidth: 80, minWidth: 80,
formatter: (row: any) => { formatter: (row: any) => {
return dictData.state.userList.filter(item => item.id == row.cellValue)[0]?.name return dictData.state.userList.filter(item => item.id == row.cellValue)[0]?.name
} }
}, },
{ {
title: '操作', title: '操作',fixed: 'right',
minWidth: 150, minWidth: 150,
fixed: 'right',
render: 'buttons', render: 'buttons',
buttons: [ buttons: [
{ {
name: 'productSetting', name: 'productSetting',
title: '详细信息', title: '详细信息',
type: 'primary', type: 'primary',
icon: 'el-icon-EditPen', icon: 'el-icon-EditPen',
render: 'basicButton', render: 'basicButton',
click: row => { click: row => {
lookInfo(row.id) lookInfo(row.id)
} }
}, },
{ {
name: 'edit', name: 'edit',
title: '编辑', title: '编辑',
type: 'primary', type: 'primary',
icon: 'el-icon-Open', icon: 'el-icon-Open',
render: 'basicButton', render: 'basicButton',
disabled: row => { disabled: row => {
return !(row.status == 0) return !(row.status == 0)
}, },
click: row => { click: row => {
addForms.value.filterUsers([6]) addForms.value.filterUsers([6])
addForms.value.open({ addForms.value.open({
title: '编辑', title: '编辑',
row: row row: row
}) })
} }
}, },
] ]
} }
], ],
beforeSearchFun: () => { beforeSearchFun: () => {
tableStore.table.params.orgNo = tableStore.table.params.deptIndex tableStore.table.params.orgNo = tableStore.table.params.deptIndex
} }
}) })
tableStore.table.params.city = '' tableStore.table.params.city = ''
tableStore.table.params.orgId = adminInfo.$state.deptId tableStore.table.params.orgId = adminInfo.$state.deptId
tableStore.table.params.projectName = '' tableStore.table.params.projectName = ''
tableStore.table.params.loadType = '' tableStore.table.params.loadType = ''
tableStore.table.params.userName = '' tableStore.table.params.userName = ''
tableStore.table.params.relationUserName = '' tableStore.table.params.relationUserName = ''
tableStore.table.params.aisFileUpload = '' tableStore.table.params.aisFileUpload = ''
const userId = ref() const userId = ref()
const dialogShow = ref(false) const dialogShow = ref(false)
const lookInfo = (id: string) => { const lookInfo = (id: string) => {
userId.value = id userId.value = id
dialogShow.value = true dialogShow.value = true
} }
provide('tableStore', tableStore) provide('tableStore', tableStore)
onMounted(() => { onMounted(() => {
tableStore.index() tableStore.index()
}) })
// 禁止点击 // 禁止点击
const checkboxConfig = reactive({ const checkboxConfig = reactive({
checkMethod: ({ row }) => { checkMethod: ({ row }) => {
return adminInfo.roleCode.includes('delete_info') return adminInfo.roleCode.includes('delete_info')
? true ? true
: row.createBy == adminInfo.$state.id && row.status == 0 : row.createBy == adminInfo.$state.id && row.status == 0
} }
}) })
const deleteEven = () => { const deleteEven = () => {
if (tableStore.table.selection.length == 0) { if (tableStore.table.selection.length == 0) {
ElMessage({ ElMessage({
type: 'warning', type: 'warning',
message: '请选择要删除的数据' message: '请选择要删除的数据'
}) })
} else { } else {
ElMessageBox.confirm('此操作将永久删除, 是否继续?', '提示', { ElMessageBox.confirm('此操作将永久删除, 是否继续?', '提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning' type: 'warning'
}).then(() => { }).then(() => {
deleteUserReport(tableStore.table.selection.map(item => item.id)).then(res => { deleteUserReport(tableStore.table.selection.map(item => item.id)).then(res => {
ElMessage({ ElMessage({
type: 'success', type: 'success',
message: '删除成功!' message: '删除成功!'
}) })
tableStore.index() tableStore.index()
}) })
}) })
} }
} }
/**取消流程操作*/ /**取消流程操作*/
const cancelLeave = async (row: any) => { const cancelLeave = async (row: any) => {
// 二次确认 // 二次确认
const { value } = await ElMessageBox.prompt('请输入取消原因', '取消流程', { const { value } = await ElMessageBox.prompt('请输入取消原因', '取消流程', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
inputType: 'textarea', inputType: 'textarea',
inputPattern: /^[\s\S]*.*\S[\s\S]*$/, // 判断非空,且非空格 inputPattern: /^[\s\S]*.*\S[\s\S]*$/, // 判断非空,且非空格
inputErrorMessage: '取消原因不能为空' inputErrorMessage: '取消原因不能为空'
}) })
// 发起取消 // 发起取消
let data = { let data = {
id: row.id, id: row.id,
processInstanceId: row.processInstanceId, processInstanceId: row.processInstanceId,
dataType: 1, dataType: 1,
reason: value reason: value
} }
await cancelFormData(data) await cancelFormData(data)
ElMessage.success('取消成功') ElMessage.success('取消成功')
// 加载数据 // 加载数据
tableStore.index() tableStore.index()
} }
// 新增 // 新增
const addFormModel = () => { const addFormModel = () => {
addForms.value.filterUsers([6]) addForms.value.filterUsers([6])
setTimeout(() => { setTimeout(() => {
addForms.value.open({ addForms.value.open({
title: '用户档案录入' title: '用户档案录入'
}) })
}) })
} }
/**获取用户性质*/ /**获取用户性质*/
const getUserTypeName = (userType: any) => { const getUserTypeName = (userType: any) => {
if (userType === 0) { if (userType === 0) {
return '新建电网工程' return '新建电网工程'
} }
if (userType === 1) { if (userType === 1) {
return '扩建电网工程' return '扩建电网工程'
} }
if (userType === 2) { if (userType === 2) {
return '新建非线性负荷用户' return '新建非线性负荷用户'
} }
if (userType === 3) { if (userType === 3) {
return '扩建非线性负荷用户' return '扩建非线性负荷用户'
} }
if (userType === 4) { if (userType === 4) {
return '新建新能源发电站' return '新建新能源发电站'
} }
if (userType === 5) { if (userType === 5) {
return '扩建新能源发电站' return '扩建新能源发电站'
} }
if (userType === 6) { if (userType === 6) {
return '敏感及重要用户' return '敏感及重要用户'
} }
return '新建电网工程' return '新建电网工程'
} }
//导出模板 //导出模板
const exportExcelTemplate = async () => { const exportExcelTemplate = async () => {
loading.value = true loading.value = true
await downloadSensitiveReportTemplate().then((res: any) => { await downloadSensitiveReportTemplate().then((res: any) => {
let blob = new Blob([res], { let blob = new Blob([res], {
type: 'application/vnd.ms-excel' type: 'application/vnd.ms-excel'
}) })
const url = window.URL.createObjectURL(blob) const url = window.URL.createObjectURL(blob)
const link = document.createElement('a') const link = document.createElement('a')
link.href = url link.href = url
link.download = '干扰源用户台账模板' link.download = '干扰源用户台账模板'
document.body.appendChild(link) document.body.appendChild(link)
link.click() link.click()
link.remove() link.remove()
}) })
await setTimeout(() => { await setTimeout(() => {
loading.value = false loading.value = false
}, 0) }, 0)
} }
//批量导入用户数据 //批量导入用户数据
const importUserData = () => { const importUserData = () => {
sensitiveUserPopup.value.open('导入干扰源用户') sensitiveUserPopup.value.open('导入干扰源用户')
} }
const props = defineProps({ id: { type: String, default: 'null' } }) const props = defineProps({ id: { type: String, default: 'null' } })
watch( watch(
() => props.id, () => props.id,
async (newValue, oldValue) => { async (newValue, oldValue) => {
if (newValue === 'null') return // 直接返回,避免后续逻辑执行 if (newValue === 'null') return // 直接返回,避免后续逻辑执行
const fullId = newValue.split('@')[0] const fullId = newValue.split('@')[0]
let nowTime = Date.now() let nowTime = Date.now()
const routeTime = Number(newValue.split('@')[1]) const routeTime = Number(newValue.split('@')[1])
if (isNaN(routeTime) || nowTime - routeTime > import.meta.env.VITE_ROUTE_TIME_OUT) return // 路由时间超过500ms则不执行 if (isNaN(routeTime) || nowTime - routeTime > import.meta.env.VITE_ROUTE_TIME_OUT) return // 路由时间超过500ms则不执行
await getUserReportById(fullId).then(res => { await getUserReportById(fullId).then(res => {
if (res && res.code == 'A0000') { if (res && res.code == 'A0000') {
addForms.value.setcontroFlag() addForms.value.setcontroFlag()
addForms.value.open({ addForms.value.open({
title: '重新发起', title: '重新发起',
row: res.data row: res.data
}) })
} }
}) })
}, },
{ immediate: true } { immediate: true }
) )
</script> </script>

View File

@@ -181,7 +181,7 @@ const zoom = (value: any) => {
component: registerComponent(item.path) component: registerComponent(item.path)
})) }))
} }
console.log('🚀 ~ zoom ~ layout.value:', layout.value) // console.log('🚀 ~ zoom ~ layout.value:', layout.value)
flag.value = !flag.value flag.value = !flag.value

View File

@@ -83,7 +83,7 @@ const cycle = [
{ value: '3', label: '年' } { value: '3', label: '年' }
] ]
const changeTree = (row: any) => { const changeTree = (row: any) => {
console.log("🚀 ~ changeTree ~ row:", row) // console.log("🚀 ~ changeTree ~ row:", row)
TreeList.value = row TreeList.value = row
if (title.value == '修改算法') { if (title.value == '修改算法') {
if (row.level != 4) { if (row.level != 4) {

View File

@@ -20,7 +20,7 @@
<el-radio-button v-for="(item, i) in dotList?.childrens" :label="item.name" :value="i" /> <el-radio-button v-for="(item, i) in dotList?.childrens" :label="item.name" :value="i" />
</el-radio-group> </el-radio-group>
</div> </div>
<div v-if="information"> <div >
<el-button icon="el-icon-Plus" type="primary" @click="addUser">新增</el-button> <el-button icon="el-icon-Plus" type="primary" @click="addUser">新增</el-button>
<el-button icon="el-icon-Edit" type="primary" @click="revise">修改</el-button> <el-button icon="el-icon-Edit" type="primary" @click="revise">修改</el-button>
<el-button icon="el-icon-Delete" type="primary" @click="deletes">删除</el-button> <el-button icon="el-icon-Delete" type="primary" @click="deletes">删除</el-button>
@@ -134,7 +134,7 @@ defineOptions({
const monitoringPoint = useMonitoringPoint() const monitoringPoint = useMonitoringPoint()
const height = mainHeight(20) const height = mainHeight(20)
const heightTab = mainHeight(82) const heightTab = mainHeight(82)
const size = ref(23) const size = ref(19)
const addTreeRef = ref() const addTreeRef = ref()
const editorRef = ref() const editorRef = ref()
const dialogVisible = ref(false) const dialogVisible = ref(false)

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