提交代码

This commit is contained in:
guanj
2026-04-09 11:44:06 +08:00
parent dbaa42ff7e
commit 0f5cb1d3c5
14 changed files with 1516 additions and 1370 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -104,7 +104,7 @@ export default class SocketService {
// 通过接受服务端发送的type字段来回调函数
if ((message.key || message.code) && this.callBackMapping['message']) {
if ((message.key || message.code || message.time) && this.callBackMapping['message']) {
this.callBackMapping['message']!(message)
} else {
console.log('抛弃====>')
@@ -112,7 +112,7 @@ export default class SocketService {
// 丢弃或继续写你的逻辑
}
} else {
ElMessage.error(event.data)
// ElMessage.error(event.data)
}
}

View File

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

View File

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

View File

@@ -83,6 +83,14 @@
/>
</el-select>
</el-form-item>
<el-form-item label="关键字筛选">
<el-input
v-model.trim="tableStore.table.params.searchValue"
clearable
style="width: 200px"
placeholder="请输入关键字筛选"
/>
</el-form-item>
</template>
</TableHeader>
</div>
@@ -113,6 +121,7 @@ import TableHeader from '@/components/table/header/index.vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import charts from './components/charts.vue'
import { filterTree } from '@/utils/tree'
defineOptions({
name: 'harmonic-boot/area/qualifiedRate'
})
@@ -272,7 +281,13 @@ const tableStore = new TableStore({
],
loadCallback: () => {
tableStore.table.data = tree2List(tableStore.table.data, Math.random() * 1000)
tableStore.table.data = tree2List(
filterTree(tableStore.table.data, node => {
// 筛选条件name 包含关键词
return node.name.includes(tableStore.table.params.searchValue)
}),
Math.random() * 1000
)
tableStore.table.column[0].title = tableStore.table.params.statisticalType.name
chartsRef.value && chartsRef.value.getTableStoreParams(tableStore.table.params)
@@ -288,6 +303,7 @@ tableStore.table.params.manufacturer = []
tableStore.table.params.loadType = []
tableStore.table.params.serverName = 'harmonicBoot'
tableStore.table.params.powerFlag = sign[0]?.algoDescribe || 0
tableStore.table.params.searchValue = ''
provide('tableStore', tableStore)
// const tree2List = (list: any, pid?: string) => {
// //存储结果的数组

View File

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

View File

@@ -68,14 +68,14 @@ const tableStore = new TableStore({
{ field: 'lineScale', title: '电压等级', minWidth: "120px", },
{ field: 'lineName', title: '监测点名称', minWidth: "150px", },
{ field: 'loadType', title: '干扰源类型', minWidth: "150px", },
{ field: 'lineObjectName', title: '监测点对象名称', minWidth: "150px", formatter: (row: any) => { return row.cellValue == null ? '/' : row.cellValue } },
{ field: 'lineObjectName', title: '监测点对象名称', minWidth: "180px", formatter: (row: any) => { return row.cellValue == null ? '/' : row.cellValue } },
{ field: 'overDay', title: '超标天数', minWidth: "80px", },
{ field: 'freqOverDay', title: '频率偏差超标天数', minWidth: "100px", },
{ field: 'volDevOverDay', title: '电压偏差超标天数', minWidth: "100px", },
{ field: 'volDisOverDay', title: '电压总畸变率超标天数', minWidth: "100px", },
{ field: 'volContainOverDay', title: '谐波电压含有率超标天数', minWidth: "110px", },
{ field: 'harmVolOverDay', title: '谐波电压超标天数', minWidth: "100px", },
{ field: 'harmCurOverDay', title: '谐波电流超标天数', minWidth: "100px", },
{ field: 'freqOverDay', title: '频率偏差', minWidth: "100px", },
{ field: 'volDevOverDay', title: '电压偏差', minWidth: "100px", },
{ field: 'volDisOverDay', title: '电压总畸变率', minWidth: "100px", },
{ field: 'volContainOverDay', title: '谐波电压含有率', minWidth: "100px", },
{ field: 'harmVolOverDay', title: '谐波电压', minWidth: "100px", },
{ field: 'harmCurOverDay', title: '谐波电流', minWidth: "100px", },
{
title: '各次谐波电压含有率超标天数',
children: [
@@ -104,10 +104,11 @@ const tableStore = new TableStore({
],
},
{ field: 'threeUnbalance', title: '三相电压不平衡度超标天数', minWidth: "110px", },
{ field: 'negativeOverDay', title: '负序电流超标天数', minWidth: "100px", },
{ field: 'flickerOverDay', title: '闪变超标天数', minWidth: "100px", },
{ field: 'monitorNumber', title: '监测点编号', minWidth: "180px", formatter: (row: any) => { return row.cellValue == null ? '/' : row.cellValue } },
{ field: 'intHarmOverDay', title: '间谐波电压含有率', minWidth: "100px", },
{ field: 'threeUnbalance', title: '三相电压不平衡度', minWidth: "100px", },
{ field: 'negativeOverDay', title: '负序电流', minWidth: "100px", },
{ field: 'flickerOverDay', title: '闪变', minWidth: "100px", },
{ field: 'monitorNumber', title: '监测点编号', minWidth: "100px", formatter: (row: any) => { return row.cellValue == null ? '/' : row.cellValue } },

View File

@@ -162,14 +162,15 @@
<vxe-column field="company" title="供电公司" minWidth="110px"></vxe-column>
<vxe-column field="subStation" title="变电站" minWidth="110px"></vxe-column>
<vxe-column field="manufacturer" title="终端厂家" minWidth="110px"></vxe-column>
<vxe-column field="deviceName" title="终端名称" minWidth="110px"></vxe-column>
<vxe-column field="deviceName" title="终端名称" minWidth="130px"></vxe-column>
<vxe-column field="ip" title="终端IP" :formatter="formatter" width="120px"></vxe-column>
<vxe-column
field="lineName"
title="监测点名称"
:formatter="formatter"
minWidth="110px"
minWidth="130px"
></vxe-column>
<vxe-column v-if="VITE_FLAG" field="objName" title="监测对象" minWidth="130px"></vxe-column>
<vxe-column field="runFlag" title="运行状态" width="90px">
<template #default="{ row }">
<el-tag
@@ -222,6 +223,7 @@ defineOptions({
name: 'harmonic-boot/harmonic/getIntegrityData'
})
import { useRoute } from 'vue-router'
const VITE_FLAG = import.meta.env.VITE_NAME != 'jibei'
const route = useRoute()
const dictData = useDictData()
//字典获取监督对象类型

View File

@@ -160,8 +160,9 @@
<vxe-column field="company" title="供电公司" minWidth="110px"></vxe-column>
<vxe-column field="subStation" title="变电站" minWidth="110px"></vxe-column>
<vxe-column field="manufacturer" title="终端厂家" minWidth="110px"></vxe-column>
<vxe-column field="deviceName" title="终端名称" minWidth="110px"></vxe-column>
<vxe-column field="deviceName" title="终端名称" minWidth="130px"></vxe-column>
<vxe-column field="ip" title="终端IP" :formatter="formatter" width="120px"></vxe-column>
<vxe-column v-if="VITE_FLAG" field="objName" title="监测对象" minWidth="130px"></vxe-column>
<vxe-column field="runFlag" title="运行状态" width="90px">
<template #default="{ row }">
<el-tag
@@ -214,6 +215,7 @@ defineOptions({
name: 'harmonic-boot/harmonic/getIntegrityData'
})
import { useRoute } from 'vue-router'
const VITE_FLAG = import.meta.env.VITE_NAME != 'jibei'
const route = useRoute()
const dictData = useDictData()
//字典获取监督对象类型

View File

@@ -744,16 +744,6 @@ const initEcharts = (color: string, key: number, name: string) => {
}
//渲染echarts
const init = () => {
loading.value = true
const url = localStorage.getItem('WebSocketUrl') || 'ws://192.168.1.68:10407/api/pushMessage/'
echartsDataV1.value = initEcharts('#DAA520', 0, 'A相')
echartsDataV2.value = initEcharts('#2E8B57', 0, 'B相')
echartsDataV3.value = initEcharts('#A52a2a', 0, 'C相')
echartsDataA1.value = initEcharts('#DAA520', 1, 'A相')
echartsDataA2.value = initEcharts('#2E8B57', 1, 'B相')
echartsDataA3.value = initEcharts('#A52a2a', 1, 'C相')
if (!dataSocket.socketServe) {
console.error('WebSocket 客户端实例不存在')
return
@@ -765,6 +755,16 @@ const init = () => {
type: 'warning'
})
}
loading.value = true
const url = localStorage.getItem('WebSocketUrl') || 'ws://192.168.1.68:10407/api/pushMessage/'
echartsDataV1.value = initEcharts('#DAA520', 0, 'A相')
echartsDataV2.value = initEcharts('#2E8B57', 0, 'B相')
echartsDataV3.value = initEcharts('#A52a2a', 0, 'C相')
echartsDataA1.value = initEcharts('#DAA520', 1, 'A相')
echartsDataA2.value = initEcharts('#2E8B57', 1, 'B相')
echartsDataA3.value = initEcharts('#A52a2a', 1, 'C相')
let pids = monitoringPoint.state.pid.split(',')
dataSocket.socketServe.connect(`${url}${adminInfo.id},${monitoringPoint.state.lineId},${pids[pids.length - 2]}`)
dataSocket.socketServe.registerCallBack('message', (res: any) => {
@@ -779,12 +779,12 @@ const init = () => {
iRmsA: data.I.A?.IRMS, //A相电流
iRmsB: data.I.B?.IRMS, //B相电流
iRmsC: data.I.C?.IRMS, //C相电流
v1AngA: data.V.A?.VFUND_ANGLE, //A相基波电压相位
v1AngB: data.V.B?.VFUND_ANGLE, //B相基波电压相位
v1AngC: data.V.C?.VFUND_ANGLE, //C相基波电压相位
i1AngA: data.I.A?.I_ANGLE, //A相基波电流相位
i1AngB: data.I.B?.I_ANGLE, //B相基波电流相位
i1AngC: data.I.C?.I_ANGLE, //C相基波电流相位
v1AngA: steAngle(data.V.A?.VFUND_ANGLE), //A相基波电压相位
v1AngB: steAngle(data.V.B?.VFUND_ANGLE), //B相基波电压相位
v1AngC: steAngle(data.V.C?.VFUND_ANGLE), //C相基波电压相位
i1AngA: steAngle(data.I.A?.I_ANGLE), //A相基波电流相位
i1AngB: steAngle(data.I.B?.I_ANGLE), //B相基波电流相位
i1AngC: steAngle(data.I.C?.I_ANGLE), //C相基波电流相位
freq: data.V.T?.FREQ, //频率
freqDev: data.V.T?.DELTA_FREQ, //频率偏差
vUnbalance: data.V.T?.V_UNBAN, //电压不平衡度
@@ -950,6 +950,20 @@ const setRealData = () => {
]
pieChart6.value.initChart()
}
const steAngle = (phase: any) => {
// 空值判断
if (phase === null || phase === undefined) {
return null
}
let normalizedPhase = phase % 360
if (normalizedPhase > 180) {
normalizedPhase -= 360
} else if (normalizedPhase < -180) {
normalizedPhase += 360
}
return normalizedPhase
}
defineExpose({ setRealData })
onMounted(() => {
init()

View File

@@ -12,12 +12,12 @@
</template>
</el-page-header>
</el-form-item>
<el-form-item label="过滤筛选">
<el-form-item label="关键字筛选">
<el-input
style="width: 240px"
v-model="tableStore.table.params.searchValue"
clearable
placeholder="请输入筛选数据"
placeholder="请输入关键字筛选"
maxlength="32"
show-word-limit
/>