Compare commits

...

10 Commits

Author SHA1 Message Date
guanj
2e58e58c73 微调 2025-09-23 08:44:17 +08:00
sjl
50bc0f9396 修改时间控件带时分秒 2025-09-22 13:34:42 +08:00
sjl
0e485b1893 报表界面添加查询时间 2025-09-22 11:32:29 +08:00
guanj
f1b157ac26 优化页面 2025-07-18 16:27:39 +08:00
guanj
aa323c0d9c 需求变更整改 2025-07-15 16:31:06 +08:00
guanj
96518a4c9d 新增 半月报功能 2025-07-10 16:33:41 +08:00
guanj
7ab8e4ed9c 修改 模块运行状态页面添加数据展示 2025-07-09 16:48:18 +08:00
guanj
e1851f7ebb 修改 模块数据页面样式 2025-07-08 10:47:04 +08:00
guanj
7fabcb7f0f Web端添加治理模块状态展示界面、模块事件展示、主动询问模块状态功能 2025-07-08 08:44:13 +08:00
GGJ
4cde4e367e 优化 APF治理效果页面 2025-05-21 12:42:28 +08:00
64 changed files with 10157 additions and 2508 deletions

3552
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -11,21 +11,20 @@ import { provide, onMounted, ref } from 'vue'
//线上mqtt //线上mqtt
// let buildUrl = 'wss://pqmcn.com:8087/mqtt'//102 // let buildUrl = 'wss://pqmcn.com:8087/mqtt'//102
let buildUrl = 'ws://pqmcn.com:8073/mqtt'//27 let buildUrl = 'ws://pqmcn.com:8073/mqtt' //27
// 从 Nginx 获取 MQTT URL // 从 Nginx 获取 MQTT URL
const fetchMqttUrl = async () => { const fetchMqttUrl = async () => {
const response = await fetch('/') const response = await fetch('/')
const mqttUrl = response.headers.get('X-Mqtt-Url') const mqttUrl = response.headers.get('X-Mqtt-Url')
const zutai = response.headers.get('X-Mqttzutai-Url')
window.localStorage.setItem('MQTTURL', mqttUrl || buildUrl) window.localStorage.setItem('MQTTURL', mqttUrl || buildUrl)
window.localStorage.setItem('MQTTZUTAI', zutai || '')
} }
//本地mqtt //本地mqtt
// let devUrl = 'ws://192.168.1.24:8085/mqtt' // let devUrl = 'ws://192.168.1.24:8085/mqtt'
onMounted(() => { onMounted(() => {
fetchMqttUrl() fetchMqttUrl()

View File

@@ -121,8 +121,24 @@ export function getById(data?: any) {
//测试项日志修改 //测试项日志修改
export function updateRecordData(data?: any) { export function updateRecordData(data?: any) {
return createAxios({ return createAxios({
url: 'cs-device-boot/wlRecord/updateRecordData', url: '/cs-device-boot/wlRecord/updateRecordData',
method: 'POST', method: 'POST',
data data
}) })
} }
//模块数据
export function allModelData(data?: any) {
return createAxios({
url: '/cs-harmonic-boot/data/allModelData',
method: 'POST',
data
})
}
//刷新状态
export function getModuleState(data?: any) {
return createAxios({
url: '/cs-harmonic-boot/data/getModuleState',
method: 'POST',
params: data
})
}

View File

@@ -22,11 +22,21 @@ export const auditEdData = (data) => {
data: data, data: data,
}) })
} }
// 修改工程
export const auditEngineering = (data) => { export const auditEngineering = (data) => {
return request({ return request({
url: '/cs-device-boot/engineering/auditEngineering', url: '/cs-device-boot/engineering/auditEngineering',
method: 'post', method: 'post',
data: data,
})
}
// 修改项目
export const updateProject = (data) => {
return request({
url: '/cs-device-boot/project/updateProject',
method: 'post',
data: data, data: data,
}) })
} }

1690
src/assets/map/area.json Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -51,13 +51,7 @@ const initChart = () => {
}, },
tooltip: { tooltip: {
trigger: 'axis', trigger: 'axis',
axisPointer: {
type: 'shadow',
label: {
color: '#fff',
fontSize: 16
}
},
textStyle: { textStyle: {
color: '#fff', color: '#fff',
fontStyle: 'normal', fontStyle: 'normal',
@@ -66,7 +60,7 @@ const initChart = () => {
}, },
backgroundColor: 'rgba(0,0,0,0.55)', backgroundColor: 'rgba(0,0,0,0.55)',
borderWidth: 0, borderWidth: 0,
confine: true, // confine: true,
...(props.options?.tooltip || null) ...(props.options?.tooltip || null)
}, },
toolbox: { toolbox: {
@@ -109,6 +103,7 @@ const initChart = () => {
type: 'inside', type: 'inside',
height: 13, height: 13,
start: 0, start: 0,
bottom: '20px', bottom: '20px',
end: 100 end: 100
}, },
@@ -117,7 +112,7 @@ const initChart = () => {
height: 13, height: 13,
bottom: '20px', bottom: '20px',
end: 100 end: 100
}, }
// { // {
// show: true, // show: true,
// yAxisIndex: 0, // yAxisIndex: 0,
@@ -135,7 +130,7 @@ const initChart = () => {
handlerBar(options) handlerBar(options)
// 处理柱状图 // 处理柱状图
chart.setOption(options, true) chart.setOption(options, true)
chart.group = 'group'
setTimeout(() => { setTimeout(() => {
chart.resize() chart.resize()
}, 0) }, 0)

View File

@@ -1,4 +1,4 @@
export let color = [ '#07CCCA','#00BFF5', '#FFBF00', '#77DA63', '#D5FF6B', '#Ff6600', '#FF9100', '#5B6E96', '#66FFCC', '#B3B3B3'] export let color = [ '#07CCCA','#00BFF5', '#FFBF00', '#77DA63', '#D5FF6B', '#Ff6600', '#FF9100', '#5B6E96', '#66FFCC', '#B3B3B3']
export const gradeColor3 = ['#339966', '#FFCC33', '#CC0000'] export const gradeColor3 = ['#339966', '#FFCC33', '#A52a2a']
export const gradeColor5 = ['#00CC00', '#99CC99', '#FF9900','#996600','#CC0000'] export const gradeColor5 = ['#00CC00', '#99CC99', '#FF9900','#996600','#A52a2a']

View File

@@ -745,7 +745,7 @@ export default {
zhou = waveDatas[0].RMSSMinDetail.secondeZhou; zhou = waveDatas[0].RMSSMinDetail.secondeZhou;
} }
colors.push("#FFCC00"); colors.push("#DAA520");
colors.push("#fff"); colors.push("#fff");
colors.push("#fff"); colors.push("#fff");
break; break;
@@ -783,8 +783,8 @@ export default {
rmsvY = waveDatas[0].RMSSMinDetail.rmsvSecondY; rmsvY = waveDatas[0].RMSSMinDetail.rmsvSecondY;
zhou = waveDatas[0].RMSSMinDetail.secondeZhou; zhou = waveDatas[0].RMSSMinDetail.secondeZhou;
} }
colors.push("#FFCC00"); colors.push("#DAA520");
colors.push("#009900"); colors.push("#2E8B57");
colors.push("#fff"); colors.push("#fff");
break; break;
case 3: case 3:
@@ -822,9 +822,9 @@ export default {
rmsvY = waveDatas[0].RMSSMinDetail.rmsvSecondY; rmsvY = waveDatas[0].RMSSMinDetail.rmsvSecondY;
zhou = waveDatas[0].RMSSMinDetail.secondeZhou; zhou = waveDatas[0].RMSSMinDetail.secondeZhou;
} }
colors.push("#FFCC00"); colors.push("#DAA520");
colors.push("#009900"); colors.push("#2E8B57");
colors.push("#CC0000"); colors.push("#A52a2a");
break; break;
} }
if (waveDatas[0].unit === "电压") { if (waveDatas[0].unit === "电压") {
@@ -1090,7 +1090,7 @@ export default {
symbol: "none", symbol: "none",
sampling: "average", sampling: "average",
itemStyle: { itemStyle: {
color: "#FFCC00", color: "#DAA520",
}, },
progressive: 500, progressive: 500,
// 渲染阈值,大于此值则启动渐进渲染 // 渲染阈值,大于此值则启动渐进渲染
@@ -1105,7 +1105,7 @@ export default {
symbol: "none", symbol: "none",
sampling: "average", sampling: "average",
itemStyle: { itemStyle: {
color: "#009900", color: "#2E8B57",
}, },
progressive: 500, progressive: 500,
// 渲染阈值,大于此值则启动渐进渲染 // 渲染阈值,大于此值则启动渐进渲染
@@ -1120,7 +1120,7 @@ export default {
symbol: "none", symbol: "none",
sampling: "average", sampling: "average",
itemStyle: { itemStyle: {
color: "#CC0000", color: "#A52a2a",
}, },
progressive: 500, progressive: 500,
// 渲染阈值,大于此值则启动渐进渲染 // 渲染阈值,大于此值则启动渐进渲染
@@ -1518,7 +1518,7 @@ export default {
symbol: "none", symbol: "none",
sampling: "average", sampling: "average",
itemStyle: { itemStyle: {
color: "#FFCC00", color: "#DAA520",
}, },
progressive: 500, progressive: 500,
// 渲染阈值,大于此值则启动渐进渲染 // 渲染阈值,大于此值则启动渐进渲染
@@ -1533,7 +1533,7 @@ export default {
symbol: "none", symbol: "none",
sampling: "average", sampling: "average",
itemStyle: { itemStyle: {
color: "#009900", color: "#2E8B57",
}, },
progressive: 500, progressive: 500,
// 渲染阈值,大于此值则启动渐进渲染 // 渲染阈值,大于此值则启动渐进渲染
@@ -1548,7 +1548,7 @@ export default {
symbol: "none", symbol: "none",
sampling: "average", sampling: "average",
itemStyle: { itemStyle: {
color: "#CC0000", color: "#A52a2a",
}, },
progressive: 500, progressive: 500,
// 渲染阈值,大于此值则启动渐进渲染 // 渲染阈值,大于此值则启动渐进渲染

View File

@@ -461,7 +461,7 @@ export default {
adata = waveDatas[0].shunshiS.shunshiSA adata = waveDatas[0].shunshiS.shunshiSA
} }
colors.push('#FFCC00') colors.push('#DAA520')
colors.push('#fff') colors.push('#fff')
colors.push('#fff') colors.push('#fff')
break break
@@ -481,8 +481,8 @@ export default {
adata = waveDatas[0].shunshiS.shunshiSA adata = waveDatas[0].shunshiS.shunshiSA
bdata = waveDatas[0].shunshiS.shunshiSB bdata = waveDatas[0].shunshiS.shunshiSB
} }
colors.push('#FFCC00') colors.push('#DAA520')
colors.push('#009900') colors.push('#2E8B57')
colors.push('#fff') colors.push('#fff')
break break
case 3: case 3:
@@ -505,9 +505,9 @@ export default {
cdata = waveDatas[0].shunshiS.shunshiSC cdata = waveDatas[0].shunshiS.shunshiSC
} }
colors.push('#FFCC00') colors.push('#DAA520')
colors.push('#009900') colors.push('#2E8B57')
colors.push('#CC0000') colors.push('#A52a2a')
break break
} }
@@ -754,7 +754,7 @@ export default {
symbol: 'none', symbol: 'none',
sampling: 'average', sampling: 'average',
itemStyle: { itemStyle: {
color: '#FFCC00' color: '#DAA520'
}, },
progressive: 1000, progressive: 1000,
// 渲染阈值,大于此值则启动渐进渲染 // 渲染阈值,大于此值则启动渐进渲染
@@ -770,7 +770,7 @@ export default {
symbol: 'none', symbol: 'none',
sampling: 'average', sampling: 'average',
itemStyle: { itemStyle: {
color: '#009900' color: '#2E8B57'
}, },
progressive: 1000, progressive: 1000,
// 渲染阈值,大于此值则启动渐进渲染 // 渲染阈值,大于此值则启动渐进渲染
@@ -786,7 +786,7 @@ export default {
symbol: 'none', symbol: 'none',
sampling: 'average', sampling: 'average',
itemStyle: { itemStyle: {
color: '#CC0000' color: '#A52a2a'
}, },
progressive: 1000, progressive: 1000,
// 渲染阈值,大于此值则启动渐进渲染 // 渲染阈值,大于此值则启动渐进渲染
@@ -844,24 +844,24 @@ export default {
switch (this.iphasic) { switch (this.iphasic) {
case 1: case 1:
a = waveDataTemp.title.aTitle a = waveDataTemp.title.aTitle
colors.push('#FFCC00') colors.push('#DAA520')
colors.push('#fff') colors.push('#fff')
colors.push('#fff') colors.push('#fff')
break break
case 2: case 2:
a = waveDataTemp.title.aTitle a = waveDataTemp.title.aTitle
b = waveDataTemp.title.bTitle b = waveDataTemp.title.bTitle
colors.push('#FFCC00') colors.push('#DAA520')
colors.push('#009900') colors.push('#2E8B57')
colors.push('#fff') colors.push('#fff')
break break
case 3: case 3:
a = waveDataTemp.title.aTitle a = waveDataTemp.title.aTitle
b = waveDataTemp.title.bTitle b = waveDataTemp.title.bTitle
c = waveDataTemp.title.cTitle c = waveDataTemp.title.cTitle
colors.push('#FFCC00') colors.push('#DAA520')
colors.push('#009900') colors.push('#2E8B57')
colors.push('#CC0000') colors.push('#A52a2a')
break break
} }
@@ -1123,7 +1123,7 @@ export default {
symbol: 'none', symbol: 'none',
sampling: 'average', sampling: 'average',
itemStyle: { itemStyle: {
color: '#FFCC00' color: '#DAA520'
}, },
large: true, large: true,
progressive: 1000, progressive: 1000,
@@ -1138,7 +1138,7 @@ export default {
symbol: 'none', symbol: 'none',
sampling: 'average', sampling: 'average',
itemStyle: { itemStyle: {
color: '#009900' color: '#2E8B57'
}, },
progressive: 1000, progressive: 1000,
// 渲染阈值,大于此值则启动渐进渲染 // 渲染阈值,大于此值则启动渐进渲染
@@ -1153,7 +1153,7 @@ export default {
symbol: 'none', symbol: 'none',
sampling: 'average', sampling: 'average',
itemStyle: { itemStyle: {
color: '#CC0000' color: '#A52a2a'
}, },
progressive: 1000, progressive: 1000,
// 渲染阈值,大于此值则启动渐进渲染 // 渲染阈值,大于此值则启动渐进渲染

View File

@@ -417,7 +417,7 @@ const setTime = (flag = 0, e = 0) => {
let data = '' let data = ''
if ((dd < 4 || dd == 0) && interval.value != 4 && !props.theCurrentTime) { if ((dd < 2 || dd == 0) && interval.value != 4 && !props.theCurrentTime) {
data = window.XEUtils.toDateString(new Date().getTime() - (e + dd) * 3600 * 1000 * 24, 'yyyy-MM-dd') data = window.XEUtils.toDateString(new Date().getTime() - (e + dd) * 3600 * 1000 * 24, 'yyyy-MM-dd')
} else { } else {
data = window.XEUtils.toDateString(new Date().getTime() - e * 3600 * 1000 * 24, 'yyyy-MM-dd') data = window.XEUtils.toDateString(new Date().getTime() - e * 3600 * 1000 * 24, 'yyyy-MM-dd')

View File

@@ -0,0 +1,606 @@
<template>
<div style="width: 680px">
<el-select v-model.trim="interval" style="min-width: 90px; width: 90px; margin-right: 10px"
@change="timeChange">
<el-option v-for="item in timeOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-date-picker v-model.trim="timeValue" type="datetimerange" :disabled="disabledPicker"
style="width: 360px; margin-right: 10px" unlink-panels :clearable="false" range-separator=""
start-placeholder="开始时间" end-placeholder="结束时间" value-format="YYYY-MM-DD HH:mm:ss"
:shortcuts="shortcuts" />
<el-button :disabled="backDisabled" type="primary" :icon="DArrowLeft" @click="preClick"></el-button>
<el-button type="primary" :icon="VideoPause" @click="nowTime">当前</el-button>
<el-button :disabled="preDisabled" type="primary" :icon="DArrowRight" @click="next"></el-button>
</div>
</template>
<script lang="ts" setup>
import { DArrowLeft, VideoPause, DArrowRight } from '@element-plus/icons-vue'
import { ref, onMounted } from 'vue'
interface Props {
nextFlag?: boolean
theCurrentTime?: boolean
}
const props = withDefaults(defineProps<Props>(), {
nextFlag: false,
theCurrentTime: true
})
const interval = ref(3)
const timeFlag = ref(1)
const count = ref(0)
const disabledPicker = ref(true)
const timeValue = ref()
const backDisabled = ref(false)
const preDisabled = ref(true)
const timeOptions: any = ref([
{ label: '年份', value: 1 },
{ label: '季度', value: 2 },
{ label: '月份', value: 3 },
{ label: '周', value: 4 },
{ label: '自定义', value: 5 }
])
// 添加格式化时间显示的函数
const formatDateTimeDisplay = (date: Date) => {
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
const seconds = String(date.getSeconds()).padStart(2, '0')
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
}
const shortcuts = [
{
text: '最近一周',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
// 设置开始时间为当天的00:00:00
start.setHours(0, 0, 0, 0)
// 设置结束时间为当天的23:59:59
end.setHours(23, 59, 59, 999)
return [start, end]
}
},
{
text: '最近一个月',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
// 设置开始时间为当天的00:00:00
start.setHours(0, 0, 0, 0)
// 设置结束时间为当天的23:59:59
end.setHours(23, 59, 59, 999)
return [start, end]
}
},
{
text: '最近3个月',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
// 设置开始时间为当天的00:00:00
start.setHours(0, 0, 0, 0)
// 设置结束时间为当天的23:59:59
end.setHours(23, 59, 59, 999)
return [start, end]
}
}
]
onMounted(() => {
timeChange(3)
})
// 选择时间范围
const timeChange = (e: number) => {
backDisabled.value = false
preDisabled.value = true
count.value = 0
if (e == 1) {
disabledPicker.value = true
timeValue.value = [setTime(1), setTime()]
} else if (e == 2) {
disabledPicker.value = true
timeValue.value = [setTime(2), setTime()]
} else if (e == 3) {
disabledPicker.value = true
timeValue.value = [setTime(3), setTime()]
} else if (e == 4) {
let year = parseInt(setTime().substring(0, 4))
let month = parseInt(setTime().substring(5, 7))
let date = parseInt(setTime().substring(8, 10))
var start = new Date(year, month - 1, date)
var dayOfWeek = start.getDay() == 0 ? 7 : start.getDay() - 1 // 如果为周日则置为7天
disabledPicker.value = true
timeValue.value = [setTime(0, dayOfWeek), setTime(0, -6 + dayOfWeek)]
} else if (e == 5) {
disabledPicker.value = false
backDisabled.value = true
preDisabled.value = true
timeValue.value = [setTime(), setTime()]
}
if (e == 1 || e == 2) {
timeFlag.value = 0
} else {
timeFlag.value = 1
}
// 添加时分秒
if (timeValue.value && timeValue.value.length === 2) {
if (e != 5) { // 非自定义时间
// 开始时间设置为00:00:00
if (timeValue.value[0] && typeof timeValue.value[0] === 'string' && timeValue.value[0].length === 10) {
timeValue.value[0] += ' 00:00:00'
} else if (timeValue.value[0] instanceof Date) {
timeValue.value[0].setHours(0, 0, 0, 0)
}
// 结束时间设置为23:59:59
if (timeValue.value[1] && typeof timeValue.value[1] === 'string' && timeValue.value[1].length === 10) {
timeValue.value[1] += ' 23:59:59'
} else if (timeValue.value[1] instanceof Date) {
timeValue.value[1].setHours(23, 59, 59, 999)
}
}
}
}
// 当前
const nowTime = () => {
timeChange(interval.value)
}
// 上一个
const preClick = () => {
preDisabled.value = false
let startTime = timeValue.value[0]
let endTime = timeValue.value[1]
let year = parseInt(startTime.substring(0, 4))
let month = parseInt(startTime.substring(5, 7))
let date = parseInt(startTime.substring(8, 10))
//按月
if (interval.value == 3) {
// 换年份
if (month == 1) {
year = year - 1
startTime = year + '-12-01 00:00:00'
endTime = year + '-12-31 23:59:59'
} else if (month <= 10) {
month = month - 1
startTime = year + '-0' + month + '-01 00:00:00'
let day = getDays(year, month)
endTime = year + '-0' + month + '-' + day + ' 23:59:59'
} else {
month = month - 1
startTime = year + '-' + month + '-01 00:00:00'
let day = getDays(year, month)
endTime = year + '-' + month + '-' + day + ' 23:59:59'
}
//按周
} else if (interval.value == 4) {
//根据开始时间推
let start = new Date(year, month - 1, date)
start.setDate(start.getDate() - 7)
startTime = formatTime(start) + ' 00:00:00'
var end = new Date(start)
end.setDate(start.getDate() + 6)
endTime = formatTime(end) + ' 23:59:59'
//按季度
} else if (interval.value == 2) {
// 换年份
if (month == 1) {
year = year - 1
startTime = year + '-10-01 00:00:00'
endTime = year + '-12-31 23:59:59'
} else {
// 还是本年
month = month - 3
startTime = year + '-0' + month + '-01 00:00:00'
month = month + 2
var day = getDays(year, month)
endTime = year + '-0' + month + '-' + day + ' 23:59:59'
}
//自定义
} else if (interval.value == 1) {
year = year - 1
startTime = year + '-01-01 00:00:00'
endTime = year + '-12-31 23:59:59'
}
timeValue.value = [startTime, endTime]
}
//下一个
const next = () => {
//向后
let startTime = timeValue.value[0]
let endTime = timeValue.value[1]
let year = parseInt(startTime.substring(0, 4))
let month = parseInt(startTime.substring(5, 7))
let date = parseInt(startTime.substring(8, 10))
var now = new Date()
// 获取当前年份
var presentY = now.getFullYear()
// 获取当前月份
var presentM = now.getMonth() + 1
// 获取当前日期
var presentD = now.getDate()
if (interval.value == 3) {
if (month == 12) {
year = year + 1
// 年份进位后,大于当前的年份,是不科学的
if (presentY < year && !props.nextFlag) {
startTime = presentY + '-12-01 00:00:00'
if (presentD < 10) {
endTime = presentY + '-12' + '-0' + presentD + ' 23:59:59'
} else {
endTime = presentY + '-12' + '-' + presentD + ' 23:59:59'
}
// 年份进位后,等于当前的年份
} else if (presentY == year) {
startTime = year + '-01-01 00:00:00'
if (presentM > 1) {
endTime = year + '-01-31 23:59:59'
} else {
if (presentD < 10) {
endTime = year + '-01' + '-0' + presentD + ' 23:59:59'
} else {
endTime = year + '-01' + '-' + presentD + ' 23:59:59'
}
}
// 年份进位后,依旧小于当前的年份
} else {
startTime = year + '-01-01 00:00:00'
endTime = year + '-01-31 23:59:59'
}
} else {
month = month + 1
// 年份等于当前年份
if (presentY == year) {
// 月份超过当前月份,是不科学的
if (month >= presentM && !props.nextFlag) {
if (presentM < 10) {
startTime = year + '-0' + presentM + '-01 00:00:00'
if (presentD < 10) {
endTime = year + '-0' + presentM + '-0' + presentD + ' 23:59:59'
} else {
endTime = year + '-0' + presentM + '-' + presentD + ' 23:59:59'
}
} else {
startTime = year + '-' + presentM + '-01 00:00:00'
if (presentD < 10) {
endTime = year + '-' + presentM + '-0' + presentD + ' 23:59:59'
} else {
endTime = year + '-' + presentM + '-' + presentD + ' 23:59:59'
}
}
} else {
if (month < 10) {
startTime = year + '-0' + month + '-01 00:00:00'
var day = getDays(year, month)
endTime = year + '-0' + month + '-' + day + ' 23:59:59'
} else {
startTime = year + '-' + month + '-01 00:00:00'
var day = getDays(year, month)
endTime = year + '-' + month + '-' + day + ' 23:59:59'
}
}
// 年份小于当前的年份
} else {
if (month < 10) {
startTime = year + '-0' + month + '-01 00:00:00'
var day = getDays(year, month)
endTime = year + '-0' + month + '-' + day + ' 23:59:59'
} else {
startTime = year + '-' + month + '-01 00:00:00'
var day = getDays(year, month)
endTime = year + '-' + month + '-' + day + ' 23:59:59'
}
}
}
} else if (interval.value == 2) {
// 前进需要年份进位
if (month == 10) {
year = year + 1
// 年份进位后大于当前年份是不科学的
if (year > presentY && !props.nextFlag) {
startTime = presentY + '-10-01 00:00:00'
if (presentD < 10) {
endTime = year + '-' + presentM + '-0' + presentD + ' 23:59:59'
} else {
endTime = year + '-' + presentM + '-' + presentD + ' 23:59:59'
}
} else if (year == presentY) {
startTime = year + '-01-01 00:00:00'
// 当前月份大约3月份
if (presentM > 3) {
endTime = year + '-03-31 23:59:59'
} else {
// 当前月份也在第一季度里
if (presentD < 10) {
endTime = year + '-0' + presentM + '-0' + presentD + ' 23:59:59'
} else {
endTime = year + '-0' + presentM + '-' + presentD + ' 23:59:59'
}
}
} else {
startTime = year + '-01-01 00:00:00'
endTime = year + '-03-31 23:59:59'
}
} else {
month = month + 3
// 季度进位后,超过当前月份是不科学的
if (year == presentY && !props.nextFlag) {
if (month >= presentM) {
// 当季度进位后大于当前月,以当前月的时间显示季度
if (presentM > 0 && presentM < 4) {
// 第一季度
startTime = year + '-01-01 00:00:00'
if (presentD < 10) {
endTime = year + '-0' + presentM + '-0' + presentD + ' 23:59:59'
} else {
endTime = year + '-0' + presentM + '-' + presentD + ' 23:59:59'
}
} else if (presentM > 3 && presentM < 7) {
// 第二季度
startTime = year + '-04-01 00:00:00'
if (presentD < 10) {
endTime = year + '-0' + presentM + '-0' + presentD + ' 23:59:59'
} else {
endTime = year + '-0' + presentM + '-' + presentD + ' 23:59:59'
}
} else if (presentM > 6 && presentM < 10) {
// 第三季度
startTime = year + '-07-01 00:00:00'
if (presentD < 10) {
endTime = year + '-0' + presentM + '-0' + presentD + ' 23:59:59'
} else {
endTime = year + '-0' + presentM + '-' + presentD + ' 23:59:59'
}
} else {
// 第四季度
startTime = year + '-10-01 00:00:00'
if (presentD < 10) {
endTime = year + '-' + presentM + '-0' + presentD + ' 23:59:59'
} else {
endTime = year + '-' + presentM + '-' + presentD + ' 23:59:59'
}
}
} else {
if (month == 10) {
startTime = year + '-' + month + '-01 00:00:00'
} else {
startTime = year + '-0' + month + '-01 00:00:00'
}
month = month + 2
if (month >= presentM) {
endTime = NowgetEndTime() + ' 23:59:59'
} else {
var day = getDays(year, month)
endTime = year + '-0' + month + '-' + day + ' 23:59:59'
}
}
} else {
if (month == 10) {
startTime = year + '-' + month + '-01 00:00:00'
month = month + 2
var day = getDays(year, month)
endTime = year + '-' + month + '-' + day + ' 23:59:59'
} else {
startTime = year + '-0' + month + '-01 00:00:00'
month = month + 2
var day = getDays(year, month)
endTime = year + '-0' + month + '-' + day + ' 23:59:59'
}
}
}
} else if (interval.value == 5) {
// 自定义时间保持原样
} else if (interval.value == 4) {
//根据开始时间推
var start = new Date(year, month - 1, date)
start.setDate(start.getDate() + 7)
startTime = formatTime(start) + ' 00:00:00'
var end = new Date(start)
end.setDate(start.getDate() + 6)
endTime = formatTime(end) + ' 23:59:59'
} else {
year = year + 1
// 年份进位后大于当前年份,是不科学的
if (year >= presentY && !props.nextFlag) {
startTime = presentY + '-01-01 00:00:00'
if (presentM < 10) {
if (presentD < 10) {
endTime = presentY + '-0' + presentM + '-0' + presentD + ' 23:59:59'
} else {
endTime = presentY + '-0' + presentM + '-' + presentD + ' 23:59:59'
}
} else {
if (presentD < 10) {
endTime = presentY + '-' + presentM + '-0' + presentD + ' 23:59:59'
} else {
endTime = presentY + '-' + presentM + '-' + presentD + ' 23:59:59'
}
}
} else {
startTime = year + '-01-01 00:00:00'
endTime = year + '-12-31 23:59:59'
}
}
if (!props.nextFlag) {
if (new Date(endTime).getTime() >= new Date().setHours(0, 0, 0, 0)) {
preDisabled.value = true
}
}
timeValue.value = [startTime, endTime]
}
const setTime = (flag = 0, e = 0) => {
let dd = window.XEUtils.toDateString(new Date().getTime() - e * 3600 * 1000 * 24, 'dd')
let data = ''
if ((dd < 2 || dd == 0) && interval.value != 4 && !props.theCurrentTime) {
data = window.XEUtils.toDateString(new Date().getTime() - (e + dd) * 3600 * 1000 * 24, 'yyyy-MM-dd')
} else {
data = window.XEUtils.toDateString(new Date().getTime() - e * 3600 * 1000 * 24, 'yyyy-MM-dd')
}
if (flag == 1) {
data = data.slice(0, 5) + '01-01'
} else if (flag == 2) {
let quarter = parseInt(data.slice(5, 7))
if (0 < quarter && quarter <= 3) {
data = data.slice(0, 5) + '01-01'
} else if (3 < quarter && quarter <= 6) {
data = data.slice(0, 5) + '04-01'
} else if (6 < quarter && quarter <= 9) {
data = data.slice(0, 5) + '07-01'
} else {
data = data.slice(0, 5) + '10-01'
}
}
if (flag == 3) {
data = data.slice(0, 8) + '01'
}
return data
}
// 获取月份的天数
const getDays = (year: any, month: any) => {
let max = new Date(year, month, 0).getDate()
return max
}
// 时间格式化
const formatTime = (time: any) => {
return (
time.getFullYear() +
'-' +
(time.getMonth() + 1 < 10 ? '0' : '') +
(time.getMonth() + 1) +
'-' +
(time.getDate() < 10 ? '0' : '') +
time.getDate()
)
}
const NowgetEndTime = () => {
let now = new Date()
let sep = '-'
let year = now.getFullYear()
let month: any = now.getMonth() + 1
if (month < 10) {
month = '0' + month
}
let date: any = now.getDate()
if (date < 10) {
date = '0' + date
}
// 拼接当前的日期
let endTime = year + sep + month + sep + date
return endTime
}
const setTimeOptions = (list: any) => {
timeOptions.value = list
}
const setInterval = (value: any) => {
interval.value = value
timeChange(value)
}
// 获取时间范围的同比
function getYearOnYear(startDate: string, endDate: string): [string, string] {
const startYearAgo = new Date(startDate)
startYearAgo.setFullYear(startYearAgo.getFullYear() - 1)
const endYearAgo = new Date(endDate)
endYearAgo.setFullYear(endYearAgo.getFullYear() - 1)
return [formatDate(startYearAgo), formatDate(endYearAgo)]
}
// 获取时间范围的环比
function getMonthOnMonth(startDate: string, endDate: string): [string, string] {
const start = new Date(startDate)
const end = new Date(endDate)
const diffTime = end.getTime() - start.getTime() + 60 * 60 * 24 * 1000 // 计算时间差
const startMonthAgo = new Date(start)
startMonthAgo.setTime(startMonthAgo.getTime() - diffTime) // 将开始时间向前推移相同的时间差
const endMonthAgo = new Date(start)
endMonthAgo.setDate(start.getDate() - 1) // 结束时间是开始时间的前一天
return [formatDate(startMonthAgo), formatDate(endMonthAgo)]
}
// 格式化日期为 YYYY-MM-DD
function formatDate(date: Date): string {
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
}
defineExpose({
timeValue,
interval,
timeFlag,
setTimeOptions,
setInterval,
getYearOnYear,
getMonthOnMonth,
timeChange,
formatDateTimeDisplay // 暴露格式化函数
})
</script>
<style scoped>
.demo-date-picker {
display: flex;
width: 100%;
padding: 0;
flex-wrap: wrap;
}
.demo-date-picker .block {
padding: 30px 0;
text-align: center;
border-right: solid 1px var(--el-border-color);
flex: 1;
}
.demo-date-picker .block:last-child {
border-right: none;
}
.demo-date-picker .demonstration {
display: block;
color: var(--el-text-color-secondary);
font-size: 14px;
margin-bottom: 20px;
}
</style>

View File

@@ -1,23 +1,44 @@
<template> <template>
<div :style="{ height: tableStore.table.height }"> <div :style="{ height: tableStore.table.height }">
<vxe-table ref="tableRef" height="auto" :data="tableStore.table.data" v-loading="tableStore.table.loading" <vxe-table
v-bind="Object.assign({}, defaultAttribute, $attrs)" @checkbox-all="selectChangeEvent" ref="tableRef"
@checkbox-change="selectChangeEvent" :showOverflow="showOverflow"> height="auto"
:key="key"
:data="tableStore.table.data"
v-loading="tableStore.table.loading"
v-bind="Object.assign({}, defaultAttribute, $attrs)"
@checkbox-all="selectChangeEvent"
@checkbox-change="selectChangeEvent"
:showOverflow="showOverflow"
:sort-config="{ remote: true }"
@sort-change="handleSortChange"
>
<!-- Column 组件内部是 el-table-column --> <!-- Column 组件内部是 el-table-column -->
<template v-if="isGroup"> <template v-if="isGroup">
<GroupColumn :column="tableStore.table.column" /> <GroupColumn :column="tableStore.table.column" />
</template> </template>
<template v-else> <template v-else>
<Column :attr="item" :key="key + '-column'" v-for="(item, key) in tableStore.table.column" <Column
:tree-node="item.treeNode"> :attr="item"
:key="key + '-column'"
v-for="(item, key) in tableStore.table.column"
:tree-node="item.treeNode"
>
<!-- tableStore 预设的列 render 方案 --> <!-- tableStore 预设的列 render 方案 -->
<template v-if="item.render" #default="scope"> <template v-if="item.render" #default="scope">
<FieldRender :field="item" :row="scope.row" :column="scope.column" :index="scope.rowIndex" :key="key + <FieldRender
'-' + :field="item"
item.render + :row="scope.row"
'-' + :column="scope.column"
(item.field ? '-' + item.field + '-' + scope.row[item.field] : '') :index="scope.rowIndex"
" /> :key="
key +
'-' +
item.render +
'-' +
(item.field ? '-' + item.field + '-' + scope.row[item.field] : '')
"
/>
</template> </template>
</Column> </Column>
</template> </template>
@@ -26,11 +47,16 @@
</div> </div>
<div v-if="tableStore.showPage" class="table-pagination"> <div v-if="tableStore.showPage" class="table-pagination">
<el-pagination :currentPage="tableStore.table.params!.pageNum" :page-size="tableStore.table.params!.pageSize" <el-pagination
:page-sizes="pageSizes" background :currentPage="tableStore.table.params!.pageNum"
:page-size="tableStore.table.params!.pageSize"
:page-sizes="pageSizes"
background
:layout="config.layout.shrink ? 'prev, next, jumper' : 'sizes,total, ->, prev, pager, next, jumper'" :layout="config.layout.shrink ? 'prev, next, jumper' : 'sizes,total, ->, prev, pager, next, jumper'"
:total="tableStore.table.total" @size-change="onTableSizeChange" :total="tableStore.table.total"
@current-change="onTableCurrentChange"></el-pagination> @size-change="onTableSizeChange"
@current-change="onTableCurrentChange"
></el-pagination>
</div> </div>
<slot name="footer"></slot> <slot name="footer"></slot>
</template> </template>
@@ -51,7 +77,7 @@ const config = useConfig()
const tableRef = ref<VxeTableInstance>() const tableRef = ref<VxeTableInstance>()
const tableStore = inject('tableStore') as TableStoreClass const tableStore = inject('tableStore') as TableStoreClass
const router = useRouter() const router = useRouter()
const key = ref(0)
interface Props extends /* @vue-ignore */ Partial<InstanceType<typeof ElTable>> { interface Props extends /* @vue-ignore */ Partial<InstanceType<typeof ElTable>> {
isGroup?: boolean isGroup?: boolean
showOverflow?: boolean showOverflow?: boolean
@@ -82,7 +108,31 @@ const pageSizes = computed(() => {
} }
return defaultSizes return defaultSizes
}) })
const handleSortChange = ({ field, order }: any) => {
// console.log('🚀 ~ handleSortChange ~ prop, order :', field, order)
if (field && order) {
// 根据当前排序条件对所有数据进行排序
const list = tableStore.table.copyData.sort((a, b) => {
if (order === 'asc') {
return a[field] > b[field] ? 1 : -1
} else {
return a[field] < b[field] ? 1 : -1
}
})
if (tableStore.isWebPaging) {
tableStore.table.data = JSON.parse(
JSON.stringify(
window.XEUtils.chunk(list, tableStore.table.params!.pageSize)[tableStore.table.params!.pageNum - 1]
)
)
} else {
tableStore.table.data = JSON.parse(JSON.stringify(list))
}
// key.value += 1
}
}
/* /*
* 记录选择的项 * 记录选择的项
*/ */
@@ -98,8 +148,6 @@ watch(
() => tableStore.table.allFlag, () => tableStore.table.allFlag,
newVal => { newVal => {
if (tableStore.table.allFlag) { if (tableStore.table.allFlag) {
console.log("🚀 ~ tableStore.table:", tableStore.exportName || document.querySelectorAll('.ba-nav-tab.active')[0].textContent || '')
tableRef.value?.exportData({ tableRef.value?.exportData({
filename: tableStore.exportName || document.querySelectorAll('.ba-nav-tab.active')[0].textContent || '', // 文件名字 filename: tableStore.exportName || document.querySelectorAll('.ba-nav-tab.active')[0].textContent || '', // 文件名字
sheetName: 'Sheet1', sheetName: 'Sheet1',
@@ -107,14 +155,15 @@ watch(
useStyle: true, useStyle: true,
data: tableStore.table.allData, // 数据源 // 过滤那个字段导出 data: tableStore.table.allData, // 数据源 // 过滤那个字段导出
columnFilterMethod: function (column: any) { columnFilterMethod: function (column: any) {
return !(column.column.title === undefined || column.column.title === '序号' || column.column.title === '操作') return !(
column.column.title === undefined ||
column.column.title === '序号' ||
column.column.title === '操作'
)
} }
}) })
tableStore.table.allFlag = false tableStore.table.allFlag = false
} }
} }
) )
watch( watch(

View File

@@ -1,34 +1,73 @@
<!-- 设备管理使用折叠面板渲染多个tree --> <!-- 设备管理使用折叠面板渲染多个tree -->
<template> <template>
<div :style="{ width: menuCollapse ? '40px' : props.width }" style="display: flex; overflow: hidden"> <div :style="{ width: menuCollapse ? '40px' : props.width }" style="display: flex; overflow: hidden">
<Icon v-show="menuCollapse" @click="onMenuCollapse" :name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'" <Icon
:class="menuCollapse ? 'unfold' : ''" size="18" class="fold ml10 mt20 menu-collapse" v-show="menuCollapse"
style="cursor: pointer" /> @click="onMenuCollapse"
: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 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-form-item> --> <!-- <el-form-item> -->
<el-input maxlength="32" show-word-limit v-model.trim="filterText" autocomplete="off" <el-input
placeholder="请输入内容" clearable> maxlength="32"
show-word-limit
v-model.trim="filterText"
autocomplete="off"
placeholder="请输入内容"
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>
</el-input> </el-input>
<!-- </el-form-item> --> <!-- </el-form-item> -->
<Icon @click="onMenuCollapse" :name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'" <Icon
:class="menuCollapse ? 'unfold' : ''" size="18" class="fold ml10 menu-collapse" @click="onMenuCollapse"
style="cursor: pointer" v-if="props.canExpand" /> :name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'"
:class="menuCollapse ? 'unfold' : ''"
size="18"
class="fold ml10 menu-collapse"
style="cursor: pointer"
v-if="props.canExpand"
/>
</div> </div>
<el-collapse :accordion="true" v-model.trim="activeName" style="flex: 1; height: 100%" <el-collapse
@change="changeDevice"> :accordion="true"
v-model.trim="activeName"
style="flex: 1; height: 100%"
@change="changeDevice"
>
<el-collapse-item title="治理设备" name="0" v-if="zlDeviceData.length != 0"> <el-collapse-item title="治理设备" name="0" v-if="zlDeviceData.length != 0">
<el-select v-model.trim="process" clearable placeholder="请选择状态" class="mb10">
<el-option label="功能调试" value="2"></el-option>
<el-option label="出厂调试" value="3"></el-option>
<el-option label="正式投运" value="4"></el-option>
</el-select>
<el-tree <el-tree
:style="{ height: bxsDeviceData.length != 0 ? 'calc(100vh - 300px)' : 'calc(100vh - 238px)' }" :style="{ height: bxsDeviceData.length != 0 ? 'calc(100vh - 340px)' : 'calc(100vh - 278px)' }"
ref="treeRef1" :props="defaultProps" highlight-current :filter-node-method="filterNode" ref="treeRef1"
node-key="id" default-expand-all v-bind="$attrs" :data="zlDeviceData" style="overflow: auto"> :props="defaultProps"
highlight-current
:filter-node-method="filterNode"
node-key="id"
default-expand-all
v-bind="$attrs"
:data="zlDevList"
style="overflow: auto"
>
<template #default="{ node, data }"> <template #default="{ node, data }">
<span class="custom-tree-node"> <span class="custom-tree-node">
<Icon :name="data.icon" style="font-size: 16px" :style="{ color: data.color }" <Icon
v-if="data.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 style="margin-left: 4px">{{ node.label }}</span>
</span> </span>
</template> </template>
@@ -37,13 +76,24 @@
<el-collapse-item title="便携式设备" name="1" v-if="bxsDeviceData.length != 0"> <el-collapse-item title="便携式设备" name="1" v-if="bxsDeviceData.length != 0">
<el-tree <el-tree
:style="{ height: zlDeviceData.length != 0 ? 'calc(100vh - 280px)' : 'calc(100vh - 238px)' }" :style="{ height: zlDeviceData.length != 0 ? 'calc(100vh - 280px)' : 'calc(100vh - 238px)' }"
ref="treeRef2" :props="defaultProps" highlight-current default-expand-all ref="treeRef2"
:filter-node-method="filterNode" node-key="id" :data="bxsDeviceData" v-bind="$attrs" :props="defaultProps"
style="overflow: auto"> highlight-current
default-expand-all
:filter-node-method="filterNode"
node-key="id"
:data="bxsDeviceData"
v-bind="$attrs"
style="overflow: auto"
>
<template #default="{ node, data }"> <template #default="{ node, data }">
<span class="custom-tree-node"> <span class="custom-tree-node">
<Icon :name="data.icon" style="font-size: 16px" :style="{ color: data.color }" <Icon
v-if="data.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 style="margin-left: 4px">{{ node.label }}</span>
</span> </span>
</template> </template>
@@ -84,8 +134,10 @@ const defaultProps = {
label: 'name', label: 'name',
value: 'id' value: 'id'
} }
const process = ref('')
//治理设备数据 //治理设备数据
const zlDeviceData = ref([]) const zlDeviceData = ref([])
const zlDevList = ref<any>([])
//便携式设备数据 //便携式设备数据
const bxsDeviceData = ref([]) const bxsDeviceData = ref([])
watch( watch(
@@ -118,6 +170,38 @@ watch(filterText, val => {
treeRef2.value!.filter(val) treeRef2.value!.filter(val)
} }
}) })
watch(process, val => {
if (val == '') {
zlDevList.value = JSON.parse(JSON.stringify(zlDeviceData.value))
} else {
zlDevList.value = filterProcess(JSON.parse(JSON.stringify(zlDeviceData.value)))
}
setTimeout(() => {
changeDevice(activeName.value)
}, 0)
})
function filterProcess(nodes: any) {
if (process.value == '') {
return nodes
}
return nodes
.map(node => {
// 递归处理子节点
const children = node.children ? filterProcess(node.children) : []
// 如果当前节点的process=4或者有子节点满足条件则保留当前节点
if (node.process == process.value || children.length > 0) {
return {
...node,
children: node.children
}
}
// 否则过滤掉当前节点
return null
})
.filter(Boolean) // 移除null节点
}
const onMenuCollapse = () => { const onMenuCollapse = () => {
menuCollapse.value = !menuCollapse.value menuCollapse.value = !menuCollapse.value
proxy.eventBus.emit('cnTreeCollapse', menuCollapse) proxy.eventBus.emit('cnTreeCollapse', menuCollapse)
@@ -126,14 +210,12 @@ const filterNode = (value: string, data: any, node: any) => {
if (!value) return true if (!value) return true
// return data.name.includes(value) // return data.name.includes(value)
if (data.name) { if (data.name) {
return chooseNode(value, data, node) return chooseNode(value, data, node)
} }
} }
// 过滤父节点 / 子节点 (如果输入的参数是父节点且能匹配则返回该节点以及其下的所有子节点如果参数是子节点则返回该节点的父节点。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.name.indexOf(value) !== -1) {
return true return true
} }
@@ -161,7 +243,9 @@ const chooseNode = (value: string, data: any, node: any) => {
const changeDevice = (val: any) => { const changeDevice = (val: any) => {
let arr1: any = [] let arr1: any = []
zlDeviceData.value.forEach((item: any) => {
//zlDeviceData
zlDevList.value.forEach((item: any) => {
item.children.forEach((item2: any) => { item.children.forEach((item2: any) => {
item2.children.forEach((item3: any) => { item2.children.forEach((item3: any) => {
arr1.push(item3) arr1.push(item3)
@@ -197,6 +281,7 @@ defineExpose({ treeRef1, treeRef2 })
onMounted(() => { onMounted(() => {
setTimeout(() => { setTimeout(() => {
if (zlDeviceData.value.length != 0) { if (zlDeviceData.value.length != 0) {
zlDevList.value = filterProcess(JSON.parse(JSON.stringify(zlDeviceData.value)))
activeName.value = '0' activeName.value = '0'
} }
if (zlDeviceData.value.length === 0 && bxsDeviceData.value.length != 0) { if (zlDeviceData.value.length === 0 && bxsDeviceData.value.length != 0) {
@@ -205,7 +290,9 @@ onMounted(() => {
if (!zlDeviceData.value && !bxsDeviceData.value) { if (!zlDeviceData.value && !bxsDeviceData.value) {
activeName.value = '' activeName.value = ''
} }
changeDevice(activeName.value) nextTick(() => {
changeDevice(activeName.value)
})
}, 500) }, 500)
}) })
</script> </script>

View File

@@ -32,6 +32,7 @@ const config = useConfig()
const tree = ref() const tree = ref()
const treRef = ref() const treRef = ref()
const changeDeviceType = (val: any, obj: any) => { const changeDeviceType = (val: any, obj: any) => {
console.log("🚀 ~ changeDeviceType ~ val:", val,obj)
emit('deviceTypeChange', val, obj) emit('deviceTypeChange', val, obj)
} }
getDeviceTree().then(res => { getDeviceTree().then(res => {

View File

@@ -12,11 +12,9 @@ import { useDictData } from '@/stores/dictData'
// const props = defineProps(['template']) // const props = defineProps(['template'])
interface Props { interface Props {
template?: boolean template?: boolean
} }
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
template: false, template: false
}) })
defineOptions({ defineOptions({
name: 'govern/deviceTree' name: 'govern/deviceTree'
@@ -29,29 +27,25 @@ const dictData = useDictData()
const treRef = ref() const treRef = ref()
const width = ref('') const width = ref('')
const info = () => { const info = () => {
tree.value = []
let arr1: any[] = []
let arr2: any[] = []
getLineTree().then(res => { getLineTree().then(res => {
let arr1: any[] = []
let arr2: any[] = []
//治理设备 //治理设备
res.data.map((item: any) => { res.data.map((item: any) => {
if (item.name == '治理设备') { if (item.name == '治理设备') {
item.children.forEach((item: any) => { item.children.forEach((item: any) => {
item.icon = 'el-icon-HomeFilled' item.icon = 'el-icon-HomeFilled'
item.level=1 item.level = 1
item.color = config.getColorVal('elementUiPrimary') item.color = config.getColorVal('elementUiPrimary')
item.children.forEach((item2: any) => { item.children.forEach((item2: any) => {
item2.icon = 'el-icon-List' item2.icon = 'el-icon-List'
item2.level=1 item2.level = 1
item2.color = config.getColorVal('elementUiPrimary') item2.color = config.getColorVal('elementUiPrimary')
item2.children.forEach((item3: any) => { item2.children.forEach((item3: any) => {
item3.icon = 'el-icon-Platform' item3.icon = 'el-icon-Platform'
item3.level=1 item3.level = 1
item3.color = item3.color =
item3.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important' item3.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
item3.children.forEach((item4: any) => { item3.children.forEach((item4: any) => {
@@ -71,13 +65,15 @@ const info = () => {
item.color = item.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important' item.color = item.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
item.children.forEach((item2: any) => { item.children.forEach((item2: any) => {
item2.icon = 'el-icon-Platform' item2.icon = 'el-icon-Platform'
item2.color = item2.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important' item2.color =
item2.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
arr2.push(item2) arr2.push(item2)
}) })
}) })
} }
}) })
tree.value = res.data tree.value = res.data
nextTick(() => { nextTick(() => {
if (arr1.length) { if (arr1.length) {
//初始化选中 //初始化选中
@@ -98,7 +94,6 @@ const info = () => {
// }) // })
// } // }
else { else {
emit('init', arr2[0]) emit('init', arr2[0])
} }
}) })
@@ -108,17 +103,16 @@ const changePointType = (val: any, obj: any) => {
emit('pointTypeChange', val, obj) emit('pointTypeChange', val, obj)
} }
if (props.template) { if (props.template) {
getTemplateByDept({ id: dictData.state.area[0].id }).then((res: any) => { getTemplateByDept({ id: dictData.state.area[0].id })
emit('Policy', res.data) .then((res: any) => {
info() emit('Policy', res.data)
info()
}).catch(err => { })
info() .catch(err => {
}) info()
})
} else { } else {
info() info()
} }
onMounted(() => { onMounted(() => {})
})
</script> </script>

View File

@@ -1,9 +1,16 @@
<!-- 设备监控使用折叠面板渲染多个tree --> <!-- 设备监控使用折叠面板渲染多个tree -->
<template> <template>
<div :style="{ width: menuCollapse ? '40px' : props.width }" style="display: flex; overflow: hidden"> <div :style="{ width: menuCollapse ? '40px' : props.width }" style="display: flex; overflow: hidden">
<Icon v-show="menuCollapse" @click="onMenuCollapse" :name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'" <Icon
:class="menuCollapse ? 'unfold' : ''" size="18" class="fold ml10 mt20 menu-collapse" style="cursor: pointer" v-show="menuCollapse"
v-if="route.path != '/admin/govern/reportCore/statistics/index'" /> @click="onMenuCollapse"
:name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'"
:class="menuCollapse ? 'unfold' : ''"
size="18"
class="fold ml10 mt20 menu-collapse"
style="cursor: pointer"
v-if="route.path != '/admin/govern/reportCore/statistics/index'"
/>
<div class="cn-tree" :style="{ opacity: menuCollapse ? 0 : 1, display: menuCollapse ? 'none' : '' }"> <div class="cn-tree" :style="{ opacity: menuCollapse ? 0 : 1, display: menuCollapse ? 'none' : '' }">
<div style="display: flex; align-items: center" class="mb10"> <div style="display: flex; align-items: center" class="mb10">
<el-input maxlength="32" show-word-limit v-model.trim="filterText" placeholder="请输入内容" clearable> <el-input maxlength="32" show-word-limit v-model.trim="filterText" placeholder="请输入内容" clearable>
@@ -11,22 +18,49 @@
<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 @click="onMenuCollapse" :name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'" <Icon
:class="menuCollapse ? 'unfold' : ''" size="18" class="fold ml10 menu-collapse" @click="onMenuCollapse"
:name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'"
:class="menuCollapse ? 'unfold' : ''"
size="18"
class="fold ml10 menu-collapse"
style="cursor: pointer" style="cursor: pointer"
v-if="props.canExpand && route.path != '/admin/govern/reportCore/statistics/index'" /> v-if="props.canExpand && route.path != '/admin/govern/reportCore/statistics/index'"
/>
</div> </div>
<el-collapse :accordion="true" v-model.trim="activeName" style="flex: 1; height: 100%" <el-collapse
@change="changeDevice"> :accordion="true"
v-model.trim="activeName"
style="flex: 1; height: 100%"
@change="changeDevice"
>
<el-collapse-item title="治理设备" name="0" v-if="zlDeviceData.length != 0"> <el-collapse-item title="治理设备" name="0" v-if="zlDeviceData.length != 0">
<el-select v-model.trim="process" clearable placeholder="请选择状态" class="mb10">
<el-option label="功能调试" value="2"></el-option>
<el-option label="出厂调试" value="3"></el-option>
<el-option label="正式投运" value="4"></el-option>
</el-select>
<el-tree <el-tree
:style="{ height: bxsDeviceData.length != 0 ? 'calc(100vh - 300px)' : 'calc(100vh - 238px)' }" :style="{ height: bxsDeviceData.length != 0 ? 'calc(100vh - 340px)' : 'calc(100vh - 278px)' }"
ref="treeRef1" :props="defaultProps" highlight-current :filter-node-method="filterNode" ref="treeRef1"
node-key="id" default-expand-all v-bind="$attrs" :data="zlDeviceData" style="overflow: auto"> :props="defaultProps"
highlight-current
:filter-node-method="filterNode"
node-key="id"
default-expand-all
v-bind="$attrs"
:data="zlDevList"
style="overflow: auto"
>
<template #default="{ node, data }"> <template #default="{ node, data }">
<span class="custom-tree-node"> <span class="custom-tree-node">
<Icon :name="data.icon" style="font-size: 16px" :style="{ color: data.color }" <Icon
v-if="data.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 style="margin-left: 4px">{{ node.label }}</span>
</span> </span>
</template> </template>
@@ -35,13 +69,24 @@
<el-collapse-item title="便携式设备" name="1" v-if="bxsDeviceData.length != 0"> <el-collapse-item title="便携式设备" name="1" v-if="bxsDeviceData.length != 0">
<el-tree <el-tree
:style="{ height: zlDeviceData.length != 0 ? 'calc(100vh - 280px)' : 'calc(100vh - 238px)' }" :style="{ height: zlDeviceData.length != 0 ? 'calc(100vh - 280px)' : 'calc(100vh - 238px)' }"
ref="treeRef2" :props="defaultProps" highlight-current default-expand-all ref="treeRef2"
:filter-node-method="filterNode" node-key="id" :data="bxsDeviceData" v-bind="$attrs" :props="defaultProps"
style="overflow: auto"> highlight-current
default-expand-all
:filter-node-method="filterNode"
node-key="id"
:data="bxsDeviceData"
v-bind="$attrs"
style="overflow: auto"
>
<template #default="{ node, data }"> <template #default="{ node, data }">
<span class="custom-tree-node"> <span class="custom-tree-node">
<Icon :name="data.icon" style="font-size: 16px" :style="{ color: data.color }" <Icon
v-if="data.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 style="margin-left: 4px">{{ node.label }}</span>
</span> </span>
</template> </template>
@@ -55,7 +100,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import useCurrentInstance from '@/utils/useCurrentInstance' import useCurrentInstance from '@/utils/useCurrentInstance'
import { ElTree } from 'element-plus' import { ElTree } from 'element-plus'
import { ref, watch, defineEmits, onMounted, nextTick } from 'vue' import { ref, watch, defineEmits, onMounted, nextTick, computed } from 'vue'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
defineOptions({ defineOptions({
name: 'govern/tree' name: 'govern/tree'
@@ -74,7 +119,7 @@ const props = withDefaults(defineProps<Props>(), {
type: '', type: '',
data: [] data: []
}) })
const process = ref('')
const route = useRoute() const route = useRoute()
const { proxy } = useCurrentInstance() const { proxy } = useCurrentInstance()
const menuCollapse = ref(false) const menuCollapse = ref(false)
@@ -86,6 +131,7 @@ const defaultProps = {
} }
//治理设备数据 //治理设备数据
const zlDeviceData = ref<any>([]) const zlDeviceData = ref<any>([])
const zlDevList = ref<any>([])
//便携式设备数据 //便携式设备数据
const bxsDeviceData = ref<any>([]) const bxsDeviceData = ref<any>([])
watch( watch(
@@ -97,12 +143,26 @@ watch(
item.children.map((vv: any) => { item.children.map((vv: any) => {
zlDeviceData.value.push(vv) zlDeviceData.value.push(vv)
}) })
// console.log('🚀 ~ item.children.map ~ zlDeviceData.value:', zlDeviceData.value)
} else if (item.name == '便携式设备') { } else if (item.name == '便携式设备') {
item.children.map((vv: any) => { item.children.map((vv: any) => {
bxsDeviceData.value.push(vv) bxsDeviceData.value.push(vv)
}) })
} }
}) })
if (zlDeviceData.value.length != 0) {
zlDevList.value = filterProcess(JSON.parse(JSON.stringify(zlDeviceData.value)))
activeName.value = '0'
}
if (zlDeviceData.value.length === 0 && bxsDeviceData.value.length != 0) {
activeName.value = '1'
}
if (!zlDeviceData.value && !bxsDeviceData.value) {
activeName.value = ''
}
nextTick(() => {
changeDevice(activeName.value)
})
} }
}, },
{ {
@@ -118,9 +178,21 @@ watch(filterText, val => {
treeRef2.value!.filter(val) treeRef2.value!.filter(val)
} }
}) })
watch(process, val => {
if (val == '') {
zlDevList.value = JSON.parse(JSON.stringify(zlDeviceData.value))
} else {
zlDevList.value = filterProcess(JSON.parse(JSON.stringify(zlDeviceData.value)))
}
setTimeout(() => {
changeDevice(activeName.value)
}, 0)
})
const changeDevice = (val: any) => { const changeDevice = (val: any) => {
let arr1: any = [] let arr1: any = []
zlDeviceData.value.forEach((item: any) => { //zlDeviceData
zlDevList.value.forEach((item: any) => {
item.children.forEach((item2: any) => { item.children.forEach((item2: any) => {
item2.children.forEach((item3: any) => { item2.children.forEach((item3: any) => {
item3.children.forEach((item4: any) => { item3.children.forEach((item4: any) => {
@@ -162,14 +234,34 @@ const filterNode = (value: string, data: any, node: any) => {
if (!value) return true if (!value) return true
// return data.name.includes(value) // return data.name.includes(value)
if (data.name) { if (data.name) {
return chooseNode(value, data, node) return chooseNode(value, data, node)
} }
} }
function filterProcess(nodes: any) {
if (process.value == '') {
return nodes
}
return nodes
.map(node => {
// 递归处理子节点
const children = node.children ? filterProcess(node.children) : []
// 如果当前节点的process=4或者有子节点满足条件则保留当前节点
if (node.process == process.value || children.length > 0) {
return {
...node,
children: node.children
}
}
// 否则过滤掉当前节点
return null
})
.filter(Boolean) // 移除null节点
}
// 过滤父节点 / 子节点 (如果输入的参数是父节点且能匹配则返回该节点以及其下的所有子节点如果参数是子节点则返回该节点的父节点。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.name.indexOf(value) !== -1) {
return true return true
} }
@@ -200,18 +292,10 @@ const treeRef1 = ref<InstanceType<typeof ElTree>>()
const treeRef2 = ref<InstanceType<typeof ElTree>>() const treeRef2 = ref<InstanceType<typeof ElTree>>()
defineExpose({ treeRef1, treeRef2 }) defineExpose({ treeRef1, treeRef2 })
onMounted(() => { onMounted(() => {
setTimeout(() => { // nextTick(() => {
if (zlDeviceData.value.length != 0) { // // setTimeout(() => {
activeName.value = '0' // // }, 500)
} // })
if (zlDeviceData.value.length === 0 && bxsDeviceData.value.length != 0) {
activeName.value = '1'
}
if (!zlDeviceData.value && !bxsDeviceData.value) {
activeName.value = ''
}
changeDevice(activeName.value)
}, 500)
}) })
</script> </script>

View File

@@ -1,298 +1,313 @@
import type { AxiosRequestConfig, Method } from 'axios' import type { AxiosRequestConfig, Method } from 'axios'
import axios from 'axios' import axios from 'axios'
import { ElLoading, ElMessage, ElNotification, type LoadingOptions } from 'element-plus' import { ElLoading, ElMessage, ElNotification, type LoadingOptions } from 'element-plus'
import { refreshToken } from '@/api/user-boot/user' import { refreshToken } from '@/api/user-boot/user'
import router from '@/router/index' import router from '@/router/index'
import { useAdminInfo } from '@/stores/adminInfo' import { useAdminInfo } from '@/stores/adminInfo'
import { set } from 'lodash'
window.requests = []
window.requests = [] window.tokenRefreshing = false
window.tokenRefreshing = false let loginExpireTimer:any=null
const pendingMap = new Map() const pendingMap = new Map()
const loadingInstance: LoadingInstance = { const loadingInstance: LoadingInstance = {
target: null, target: null,
count: 0 count: 0
} }
/** /**
* 根据运行环境获取基础请求URL * 根据运行环境获取基础请求URL
*/ */
export const getUrl = (): string => { export const getUrl = (): string => {
return '/api' return '/api'
} }
/** /**
* 创建`Axios` * 创建`Axios`
* 默认开启`reductDataFormat(简洁响应)`,返回类型为`ApiPromise` * 默认开启`reductDataFormat(简洁响应)`,返回类型为`ApiPromise`
* 关闭`reductDataFormat`,返回类型则为`AxiosPromise` * 关闭`reductDataFormat`,返回类型则为`AxiosPromise`
*/ */
function createAxios<Data = any, T = ApiPromise<Data>>( function createAxios<Data = any, T = ApiPromise<Data>>(
axiosConfig: AxiosRequestConfig, axiosConfig: AxiosRequestConfig,
options: Options = {}, options: Options = {},
loading: LoadingOptions = {} loading: LoadingOptions = {}
): T { ): T {
const adminInfo = useAdminInfo() const adminInfo = useAdminInfo()
const Axios = axios.create({ const Axios = axios.create({
baseURL: getUrl(), baseURL: getUrl(),
timeout: 1000 * 60 * 5, timeout: 1000 * 60 * 5,
headers: {}, headers: {},
responseType: 'json' responseType: 'json'
}) })
options = Object.assign( options = Object.assign(
{ {
CancelDuplicateRequest: true, // 是否开启取消重复请求, 默认为 true CancelDuplicateRequest: true, // 是否开启取消重复请求, 默认为 true
loading: false, // 是否开启loading层效果, 默认为false loading: false, // 是否开启loading层效果, 默认为false
reductDataFormat: true, // 是否开启简洁的数据结构响应, 默认为true reductDataFormat: true, // 是否开启简洁的数据结构响应, 默认为true
showErrorMessage: true, // 是否开启接口错误信息展示,默认为true showErrorMessage: true, // 是否开启接口错误信息展示,默认为true
showCodeMessage: true, // 是否开启code不为1时的信息提示, 默认为true showCodeMessage: true, // 是否开启code不为1时的信息提示, 默认为true
showSuccessMessage: false, // 是否开启code为1时的信息提示, 默认为false showSuccessMessage: false, // 是否开启code为1时的信息提示, 默认为false
anotherToken: '' // 当前请求使用另外的用户token anotherToken: '' // 当前请求使用另外的用户token
}, },
options options
) )
// 请求拦截 // 请求拦截
Axios.interceptors.request.use( Axios.interceptors.request.use(
config => { config => {
// if(config.url?.substring(0, 13)=='/advance-boot'){ // if(config.url?.substring(0, 13)=='/advance-boot'){
// config.url=config.url?.slice(13) // config.url=config.url?.slice(13)
// config.baseURL='/hzj' // config.baseURL='/hzj'
// } // }
// 取消重复请求 // 取消重复请求
if ( if (
!( !(
config.url == '/system-boot/file/upload' || config.url == '/system-boot/file/upload' ||
config.url == '/harmonic-boot/grid/getAssessOverview' || config.url == '/harmonic-boot/grid/getAssessOverview' ||
config.url == '/harmonic-boot/gridDiagram/getGridDiagramAreaData' config.url == '/harmonic-boot/gridDiagram/getGridDiagramAreaData'
) )
) )
removePending(config) removePending(config)
options.CancelDuplicateRequest && addPending(config) options.CancelDuplicateRequest && addPending(config)
// 创建loading实例 // 创建loading实例
if (options.loading) { if (options.loading) {
loadingInstance.count++ loadingInstance.count++
if (loadingInstance.count === 1) { if (loadingInstance.count === 1) {
loadingInstance.target = ElLoading.service(loading) loadingInstance.target = ElLoading.service(loading)
} }
} }
// 自动携带token // 自动携带token
if (config.headers) { if (config.headers) {
const token = adminInfo.getToken() const token = adminInfo.getToken()
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 bmpjbnRlc3Q6bmpjbnBxcw=='
} }
} }
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 bmpjbnRlc3Q6bmpjbnBxcw=='
} }
return config return config
}, },
error => { error => {
return Promise.reject(error) return Promise.reject(error)
} }
) )
// 响应拦截 // 响应拦截
Axios.interceptors.response.use( Axios.interceptors.response.use(
response => { response => {
removePending(response.config) removePending(response.config)
options.loading && closeLoading(options) // 关闭loading options.loading && closeLoading(options) // 关闭loading
if ( if (
response.data.code === 'A0000' || response.data.code === 'A0000' ||
response.data.type === 'application/json' || response.data.type === 'application/json' ||
Array.isArray(response.data) || Array.isArray(response.data) ||
response.data.size response.data.size
// || // ||
// response.data.type === 'application/octet-stream' || // response.data.type === 'application/octet-stream' ||
// response.data.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' // response.data.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
) { ) {
return options.reductDataFormat ? response.data : response return options.reductDataFormat ? response.data : response
} else if (response.data.code == 'A0202') { } else if (response.data.code == 'A0202') {
if (!window.tokenRefreshing) { if (!window.tokenRefreshing) {
window.tokenRefreshing = true window.tokenRefreshing = true
return refreshToken() return refreshToken()
.then(res => { .then(res => {
adminInfo.setToken(res.data.access_token, 'auth') adminInfo.setToken(res.data.access_token, 'auth')
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 => {
adminInfo.removeToken() adminInfo.removeToken()
router.push({ name: 'login' }) router.push({ name: 'login' })
return Promise.reject(err) return Promise.reject(err)
}) })
.finally(() => { .finally(() => {
window.tokenRefreshing = false window.tokenRefreshing = false
}) })
} else { } else {
return new Promise(resolve => { return new Promise(resolve => {
// 用函数形式将 resolve 存入,等待刷新后再执行 // 用函数形式将 resolve 存入,等待刷新后再执行
window.requests.push((token: string) => { window.requests.push((token: string) => {
response.headers.Authorization = `${token}` response.headers.Authorization = `${token}`
resolve(Axios(response.config)) resolve(Axios(response.config))
}) })
}) })
} }
} else if (response.data.code == 'A0024') { } else if (response.data.code == 'A0024') {
// 登录失效 // // 登录失效
ElMessage({ // 清除上一次的定时器
type: 'error', if (loginExpireTimer) {
message: response.data.message clearTimeout(loginExpireTimer)
}) }
adminInfo.removeToken() loginExpireTimer = setTimeout(() => {
router.push({ name: 'login' }) ElNotification({
return Promise.reject(response.data) type: 'error',
} else { message: response.data.message
if (options.showCodeMessage) { })
if (response.config.url == '/access-boot/device/wlRegister') { adminInfo.removeToken()
setTimeout(() => { router.push({ name: 'login' })
ElMessage.error(response.data.message || '未知错误') loginExpireTimer = null // 执行后清空定时器
}, 6000) }, 100) // 可根据实际情况调整延迟时间
} else { return Promise.reject(response.data)
ElMessage.error(response.data.message || '未知错误') // // 登录失效
} // ElMessage({
} // type: 'error',
return Promise.reject(response.data) // message: response.data.message
} // })
}, // adminInfo.removeToken()
error => { // router.push({ name: 'login' })
error.config && removePending(error.config) // return Promise.reject(response.data)
options.loading && closeLoading(options) // 关闭loading } else {
return Promise.reject(error) // 错误继续返回给到具体页面 if (options.showCodeMessage) {
} if (response.config.url == '/access-boot/device/wlRegister') {
) setTimeout(() => {
return Axios(axiosConfig) as T ElMessage.error(response.data.message || '未知错误')
} }, 6000)
} else {
export default createAxios ElMessage.error(response.data.message || '未知错误')
}
/** }
* 关闭Loading层实例 return Promise.reject(response.data)
*/ }
function closeLoading(options: Options) { },
if (options.loading && loadingInstance.count > 0) loadingInstance.count-- error => {
if (loadingInstance.count === 0) { error.config && removePending(error.config)
loadingInstance.target.close() options.loading && closeLoading(options) // 关闭loading
loadingInstance.target = null return Promise.reject(error) // 错误继续返回给到具体页面
} }
} )
return Axios(axiosConfig) as T
/** }
* 储存每个请求的唯一cancel回调, 以此为标识
*/ export default createAxios
function addPending(config: AxiosRequestConfig) {
const pendingKey = getPendingKey(config) /**
config.cancelToken = * 关闭Loading层实例
config.cancelToken || */
new axios.CancelToken(cancel => { function closeLoading(options: Options) {
if (!pendingMap.has(pendingKey)) { if (options.loading && loadingInstance.count > 0) loadingInstance.count--
pendingMap.set(pendingKey, cancel) if (loadingInstance.count === 0) {
} loadingInstance.target.close()
}) loadingInstance.target = null
} }
}
/**
* 删除重复的请求 /**
*/ * 储存每个请求的唯一cancel回调, 以此为标识
function removePending(config: AxiosRequestConfig) { */
const pendingKey = getPendingKey(config) function addPending(config: AxiosRequestConfig) {
if (pendingMap.has(pendingKey)) { const pendingKey = getPendingKey(config)
const cancelToken = pendingMap.get(pendingKey) config.cancelToken =
cancelToken(pendingKey) config.cancelToken ||
pendingMap.delete(pendingKey) new axios.CancelToken(cancel => {
} if (!pendingMap.has(pendingKey)) {
} pendingMap.set(pendingKey, cancel)
}
/** })
* 生成每个请求的唯一key }
*/
function getPendingKey(config: AxiosRequestConfig) { /**
let { data } = config * 删除重复的请求
const { url, method, params, headers } = config */
if (typeof data === 'string') data = JSON.parse(data) // response里面返回的config.data是个字符串对象 function removePending(config: AxiosRequestConfig) {
return [ const pendingKey = getPendingKey(config)
url, if (pendingMap.has(pendingKey)) {
method, const cancelToken = pendingMap.get(pendingKey)
headers && (headers as anyObj).Authorization ? (headers as anyObj).Authorization : '', cancelToken(pendingKey)
headers && (headers as anyObj)['ba-user-token'] ? (headers as anyObj)['ba-user-token'] : '', pendingMap.delete(pendingKey)
JSON.stringify(params), }
JSON.stringify(data) }
].join('&')
} /**
* 生成每个请求的唯一key
/** */
* 根据请求方法组装请求数据/参数 function getPendingKey(config: AxiosRequestConfig) {
*/ let { data } = config
export function requestPayload(method: Method, data: anyObj, paramsPOST: boolean) { const { url, method, params, headers } = config
if (method == 'GET') { if (typeof data === 'string') data = JSON.parse(data) // response里面返回的config.data是个字符串对象
return { return [
params: data url,
} method,
} else if (method == 'POST') { headers && (headers as anyObj).Authorization ? (headers as anyObj).Authorization : '',
if (paramsPOST) { headers && (headers as anyObj)['ba-user-token'] ? (headers as anyObj)['ba-user-token'] : '',
return { params: data } JSON.stringify(params),
} else { JSON.stringify(data)
return { data: data } ].join('&')
} }
}
} /**
// 适配器, 用于适配不同的请求方式 * 根据请求方法组装请求数据/参数
export function baseRequest(url, value = {}, method = 'post', options = {}) { */
url = sysConfig?.API_URL + url export function requestPayload(method: Method, data: anyObj, paramsPOST: boolean) {
if (method === 'post') { if (method == 'GET') {
return service.post(url, value, options) return {
} else if (method === 'get') { params: data
return service.get(url, { params: value, ...options }) }
} else if (method === 'formdata') { } else if (method == 'POST') {
// form-data表单提交的方式 if (paramsPOST) {
return service.post(url, qs.stringify(value), { return { params: data }
headers: { } else {
'Content-Type': 'multipart/form-data' return { data: data }
}, }
...options }
}) }
} else { // 适配器, 用于适配不同的请求方式
// 其他请求方式例如put、delete export function baseRequest(url, value = {}, method = 'post', options = {}) {
return service({ url = sysConfig?.API_URL + url
method: method, if (method === 'post') {
url: url, return service.post(url, value, options)
data: value, } else if (method === 'get') {
...options return service.get(url, { params: value, ...options })
}) } else if (method === 'formdata') {
} // form-data表单提交的方式
} return service.post(url, qs.stringify(value), {
// 模块内的请求, 会自动加上模块的前缀 headers: {
export const moduleRequest = 'Content-Type': 'multipart/form-data'
moduleUrl => },
(url, ...arg) => { ...options
return baseRequest(moduleUrl + url, ...arg) })
} } else {
// 其他请求方式例如put、delete
interface LoadingInstance { return service({
target: any method: method,
count: number url: url,
} data: value,
...options
interface Options { })
// 是否开启取消重复请求, 默认为 true }
CancelDuplicateRequest?: boolean }
// 是否开启loading层效果, 默认为false // 模块内的请求, 会自动加上模块的前缀
loading?: boolean export const moduleRequest =
// 是否开启简洁的数据结构响应, 默认为true moduleUrl =>
reductDataFormat?: boolean (url, ...arg) => {
// 是否开启code不为A0000时的信息提示, 默认为true return baseRequest(moduleUrl + url, ...arg)
showCodeMessage?: boolean }
// 是否开启code为0时的信息提示, 默认为false
showSuccessMessage?: boolean interface LoadingInstance {
// 当前请求使用另外的用户token target: any
anotherToken?: string count: number
} }
interface Options {
// 是否开启取消重复请求, 默认为 true
CancelDuplicateRequest?: boolean
// 是否开启loading层效果, 默认为false
loading?: boolean
// 是否开启简洁的数据结构响应, 默认为true
reductDataFormat?: boolean
// 是否开启code不为A0000时的信息提示, 默认为true
showCodeMessage?: boolean
// 是否开启code为0时的信息提示, 默认为false
showSuccessMessage?: boolean
// 当前请求使用另外的用户token
anotherToken?: string
}

View File

@@ -34,6 +34,7 @@ export default class TableStore {
ref: null, ref: null,
selection: [], selection: [],
data: [], data: [],
copyData: [],
allData: [], allData: [],
allFlag: false, allFlag: false,
webPagingData: [], webPagingData: [],
@@ -93,6 +94,7 @@ export default class TableStore {
this.table.data = [] this.table.data = []
this.table.total = 0 this.table.total = 0
} }
this.table.copyData = filtration(this.table.data)
if (Array.isArray(res)) { if (Array.isArray(res)) {
this.table.data = res this.table.data = res
} }
@@ -204,7 +206,7 @@ export default class TableStore {
this.table.allData = filtration(res.data.records || res.data) this.table.allData = filtration(res.data.records || res.data)
this.table.allFlag = data.showAllFlag || true this.table.allFlag = data.showAllFlag || true
}) })
},1500) }, 1500)
} }
] ]
]) ])

View File

@@ -29,7 +29,7 @@ const tableStore = new TableStore({
{ title: '角色', field: 'roleName' }, { title: '角色', field: 'roleName' },
// { title: '部门', field: 'deptId' }, // { title: '部门', field: 'deptId' },
{ title: '电话', field: 'phoneShow' }, { title: '电话', field: 'phoneShow' },
{ title: '注册时间', field: 'registerTime' }, { title: '注册时间', field: 'registerTime', sortable: true },
{ title: '类型', field: 'casualUserName' }, { title: '类型', field: 'casualUserName' },
{ title: '状态', field: 'stateName' }, { title: '状态', field: 'stateName' },
{ {

View File

@@ -53,8 +53,8 @@ const tableStore = new TableStore({
{ 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', sortable: true },
{ title: '登录时间', field: 'loginTime', minWidth: '130' }, { title: '登录时间', field: 'loginTime', minWidth: '130', sortable: true },
{ title: '类型', field: 'casualUserName', minWidth: '80' }, { title: '类型', field: 'casualUserName', minWidth: '80' },
{ {
title: '状态', title: '状态',

View File

@@ -25,8 +25,13 @@
</template> --> </template> -->
<template #select> <template #select>
<el-form-item label="设备名称"> <el-form-item label="设备名称">
<el-input maxlength="32" clearable show-word-limit v-model.trim="tableStore.table.params.searchValue" <el-input
placeholder="请输入设备名称" /> maxlength="32"
clearable
show-word-limit
v-model.trim="tableStore.table.params.searchValue"
placeholder="请输入设备名称"
/>
</el-form-item> </el-form-item>
</template> </template>
</TableHeader> </TableHeader>
@@ -80,9 +85,16 @@ const tableStore = new TableStore({
exportName: '异常事件', exportName: '异常事件',
publicHeight: 65, publicHeight: 65,
column: [ column: [
{
title: '序号',
width: 80,
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '设备名称', field: 'ndid', align: 'center' }, { title: '设备名称', field: 'ndid', align: 'center' },
{ title: '告警代码', field: 'code', align: 'center' }, { title: '异常时间', field: 'evtTime', align: 'center', sortable: true },
{ title: '异常时间', field: 'evtTime', align: 'center' } { title: '告警代码', field: 'code', align: 'center', sortable: true }
] ]
}) })
@@ -112,6 +124,6 @@ onMounted(() => {
setTimeout(() => { setTimeout(() => {
tableStore.table.height = mainHeight(200).height as any tableStore.table.height = mainHeight(200).height as any
}, 0) }, 0)
const addMenu = () => { } const addMenu = () => {}
</script> </script>
<style></style> <style></style>

View File

@@ -2,15 +2,26 @@
<TableHeader datePicker ref="refheader" showExport> <TableHeader datePicker ref="refheader" showExport>
<template v-slot:select> <template v-slot:select>
<el-form-item label="数据来源"> <el-form-item label="数据来源">
<el-cascader v-model.trim="tableStore.table.params.cascader" placeholder="请选择数据来源" <el-cascader
@change="sourceChange" :options="deviceTreeOptions" :show-all-levels="false" v-model.trim="tableStore.table.params.cascader"
:props="{ checkStrictly: true }" clearable></el-cascader> filterable
placeholder="请选择数据来源"
@change="sourceChange"
:options="deviceTreeOptions"
:show-all-levels="false"
:props="{ checkStrictly: true }"
clearable
></el-cascader>
<!-- <el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.searchValue" placeholder="请输入设备名称" /> --> <!-- <el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.searchValue" placeholder="请输入设备名称" /> -->
</el-form-item> </el-form-item>
<el-form-item label="级别"> <el-form-item label="级别">
<el-select v-model.trim="tableStore.table.params.level" placeholder="请选择级别" clearable> <el-select v-model.trim="tableStore.table.params.level" placeholder="请选择级别" clearable>
<el-option v-for="item in rankOptions" :key="item.value" :label="item.label" <el-option
:value="item.value"></el-option> v-for="item in rankOptions"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
</template> </template>
@@ -65,29 +76,64 @@ const tableStore = new TableStore({
exportName: '设备告警', exportName: '设备告警',
publicHeight: 65, publicHeight: 65,
column: [ column: [
{
title: '序号',
width: 80,
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '设备名称', field: 'equipmentName', align: 'center' }, { title: '设备名称', field: 'equipmentName', align: 'center' },
{ title: '工程名称', field: 'engineeringName', align: 'center' }, { title: '工程名称', field: 'engineeringName', align: 'center' },
{ title: '项目名称', field: 'projectName', align: 'center' }, { title: '项目名称', field: 'projectName', align: 'center' },
{ title: '发生时刻', field: 'startTime', align: 'center', minWidth: 110, sortable: true },
{ {
title: '告警代码', field: 'code', align: 'center', formatter: (row: any) => { title: '模块信息',
field: 'moduleNo',
align: 'center',
formatter: (row: any) => {
return row.cellValue ? row.cellValue : '/' return row.cellValue ? row.cellValue : '/'
} }
}, },
{ {
title: '事件描述', field: 'showName', title: '告警代码',
field: 'code',
align: 'center',
formatter: (row: any) => {
return row.cellValue ? row.cellValue : '/'
},
sortable: true
}, },
{ {
title: '级别', field: 'level', formatter: (row: any) => { title: '事件描述',
field: 'showName'
return row.cellValue == 1 ? '1级' : row.cellValue == 2 ? '2级' : row.cellValue == 3 ? '3级' : '/'
}
}, },
{ title: '发生时刻', field: 'startTime', align: 'center' } {
], title: '级别',
beforeSearchFun: () => { field: 'level',
} render: 'tag',
custom: {
1: 'danger',
2: 'warning',
3: 'success'
},
replaceValue: {
1: '1级',
2: '2级',
3: '3级'
}
}
// {
// title: '级别',
// field: 'level',
// formatter: (row: any) => {
// return row.cellValue == 1 ? '1级' : row.cellValue == 2 ? '2级' : row.cellValue == 3 ? '3级' : '/'
// }
// }
],
beforeSearchFun: () => {}
}) })
provide('tableStore', tableStore) provide('tableStore', tableStore)
@@ -129,7 +175,6 @@ const sourceChange = (e: any) => {
tableStore.table.params.deviceTypeId = e[0] || '' tableStore.table.params.deviceTypeId = e[0] || ''
tableStore.table.params.engineeringid = e[1] || '' tableStore.table.params.engineeringid = e[1] || ''
tableStore.table.params.projectId = e[2] || '' tableStore.table.params.projectId = e[2] || ''
} }
} }
} }
@@ -140,6 +185,6 @@ onMounted(() => {
setTimeout(() => { setTimeout(() => {
// tableStore.table.height = mainHeight(200).height as any // tableStore.table.height = mainHeight(200).height as any
}, 0) }, 0)
const addMenu = () => { } const addMenu = () => {}
</script> </script>
<style></style> <style></style>

View File

@@ -2,9 +2,16 @@
<TableHeader datePicker ref="refheader" showExport> <TableHeader datePicker ref="refheader" showExport>
<template v-slot:select> <template v-slot:select>
<el-form-item label="数据来源"> <el-form-item label="数据来源">
<el-cascader v-model.trim="tableStore.table.params.cascader" placeholder="请选择数据来源" <el-cascader
@change="sourceChange" :options="deviceTreeOptions" :show-all-levels="false" v-model.trim="tableStore.table.params.cascader"
:props="{ checkStrictly: true }" clearable></el-cascader> filterable
placeholder="请选择数据来源"
@change="sourceChange"
:options="deviceTreeOptions"
:show-all-levels="false"
:props="{ checkStrictly: true }"
clearable
></el-cascader>
<!-- <el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.searchValue" placeholder="请输入设备名称" /> --> <!-- <el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.searchValue" placeholder="请输入设备名称" /> -->
</el-form-item> </el-form-item>
<!-- <el-form-item label="级别"> <!-- <el-form-item label="级别">
@@ -69,15 +76,21 @@ const tableStore = new TableStore({
exportName: '稳态越限告警', exportName: '稳态越限告警',
publicHeight: 65, publicHeight: 65,
column: [ column: [
{
title: '序号',
width: 80,
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '设备名称', field: 'equipmentName', align: 'center' }, { title: '设备名称', field: 'equipmentName', align: 'center' },
{ title: '工程名称', field: 'engineeringName', align: 'center' }, { title: '工程名称', field: 'engineeringName', align: 'center' },
{ title: '项目名称', field: 'projectName', align: 'center' }, { title: '项目名称', field: 'projectName', align: 'center' },
{ title: '事件描述', field: 'showName', align: 'center' }, { title: '发生时刻', field: 'startTime', align: 'center', sortable: true },
{ title: '发生时刻', field: 'startTime', align: 'center' }
],
beforeSearchFun: () => {
} { title: '事件描述', field: 'showName', align: 'center' }
],
beforeSearchFun: () => {}
}) })
provide('tableStore', tableStore) provide('tableStore', tableStore)
@@ -120,10 +133,8 @@ const sourceChange = (e: any) => {
tableStore.table.params.deviceTypeId = e[0] || '' tableStore.table.params.deviceTypeId = e[0] || ''
tableStore.table.params.engineeringid = e[1] || '' tableStore.table.params.engineeringid = e[1] || ''
tableStore.table.params.projectId = e[2] || '' tableStore.table.params.projectId = e[2] || ''
} }
} }
} }
onMounted(() => { onMounted(() => {
tableStore.index() tableStore.index()
@@ -131,6 +142,6 @@ onMounted(() => {
setTimeout(() => { setTimeout(() => {
tableStore.table.height = mainHeight(200).height as any tableStore.table.height = mainHeight(200).height as any
}, 0) }, 0)
const addMenu = () => { } const addMenu = () => {}
</script> </script>
<style></style> <style></style>

View File

@@ -3,9 +3,16 @@
<TableHeader datePicker showExport> <TableHeader datePicker showExport>
<template v-slot:select> <template v-slot:select>
<el-form-item label="数据来源"> <el-form-item label="数据来源">
<el-cascader placeholder="请选择数据来源" @change="sourceChange" <el-cascader
v-model.trim="tableStore.table.params.cascader" :options="deviceTreeOptions" placeholder="请选择数据来源"
:show-all-levels="false" :props="{ checkStrictly: true }" clearable></el-cascader> @change="sourceChange"
filterable
v-model.trim="tableStore.table.params.cascader"
:options="deviceTreeOptions"
:show-all-levels="false"
:props="{ checkStrictly: true }"
clearable
></el-cascader>
<!-- <el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.searchValue" placeholder="请输入设备名称" /> --> <!-- <el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.searchValue" placeholder="请输入设备名称" /> -->
</el-form-item> </el-form-item>
<!-- <el-form-item label="级别"> <!-- <el-form-item label="级别">
@@ -19,8 +26,13 @@
<Table></Table> <Table></Table>
</div> </div>
<waveFormAnalysis v-loading="loading" v-if="isWaveCharts" ref="waveFormAnalysisRef" <waveFormAnalysis
@handleHideCharts="isWaveCharts = false" :wp="wp" /> v-loading="loading"
v-if="isWaveCharts"
ref="waveFormAnalysisRef"
@handleHideCharts="isWaveCharts = false"
:wp="wp"
/>
<!-- <div style="height: 300px;"> --> <!-- <div style="height: 300px;"> -->
<!-- <div style="padding: 10px" v-if="!view" v-loading="loading"> <!-- <div style="padding: 10px" v-if="!view" v-loading="loading">
@@ -61,7 +73,7 @@ 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 shushiboxi from '@/components/echarts/shushiboxi.vue' import shushiboxi from '@/components/echarts/shushiboxi.vue'
import waveFormAnalysis from '@/views/govern/device/control/tabs/components/waveFormAnalysis.vue'; import waveFormAnalysis from '@/views/govern/device/control/tabs/components/waveFormAnalysis.vue'
import rmsboxi from '@/components/echarts/rmsboxi.vue' import rmsboxi from '@/components/echarts/rmsboxi.vue'
import { analyseWave } from '@/api/common' import { analyseWave } from '@/api/common'
import { mainHeight } from '@/utils/layout' import { mainHeight } from '@/utils/layout'
@@ -109,17 +121,24 @@ const tableStore = new TableStore({
method: 'POST', method: 'POST',
publicHeight: 65, publicHeight: 65,
exportName: '暂态事件', exportName: '暂态事件',
column: [ column: [ {
title: '序号',
width: 80,
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '设备名称', field: 'equipmentName', align: 'center' }, { title: '设备名称', field: 'equipmentName', align: 'center' },
{ title: '工程名称', field: 'engineeringName', align: 'center' }, { title: '工程名称', field: 'engineeringName', align: 'center' },
{ title: '项目名称', field: 'projectName', align: 'center' }, { title: '项目名称', field: 'projectName', align: 'center' },
{ title: '发生时刻', field: 'startTime', align: 'center', width: '240',sortable: true },
{ title: '监测点名称', field: 'lineName', align: 'center' }, { title: '监测点名称', field: 'lineName', align: 'center' },
{ title: '事件描述', field: 'showName', align: 'center' }, { title: '事件描述', field: 'showName', align: 'center' },
{ title: '事件发生位置', field: 'evtParamPosition', align: 'center' }, { title: '事件发生位置', field: 'evtParamPosition', align: 'center' },
{ title: '相别', field: 'evtParamPhase', align: 'center' }, { title: '相别', field: 'evtParamPhase', align: 'center' },
{ title: '持续时间(s)', field: 'evtParamTm', align: 'center' }, { title: '持续时间(s)', field: 'evtParamTm', align: 'center',sortable: true },
{ title: '暂降(聚升)幅值(%)',minWidth: 100, field: 'evtParamVVaDepth', align: 'center' }, { title: '暂降(聚升)幅值(%)', minWidth: 100, field: 'evtParamVVaDepth', align: 'center',sortable: true },
{ title: '发生时刻', field: 'startTime', align: 'center', width: '240' },
{ {
title: '操作', title: '操作',
align: 'center', align: 'center',
@@ -145,11 +164,10 @@ const tableStore = new TableStore({
row.loading1 = false row.loading1 = false
if (res != undefined) { if (res != undefined) {
boxoList.value = row boxoList.value = row
boxoList.value.featureAmplitude = row.evtParamVVaDepth != '-' ? row.evtParamVVaDepth - 0 : null boxoList.value.featureAmplitude =
row.evtParamVVaDepth != '-' ? row.evtParamVVaDepth - 0 : null
boxoList.value.systemType = 'WX' boxoList.value.systemType = 'WX'
wp.value = res.data wp.value = res.data
} }
loading.value = false loading.value = false
}) })
@@ -159,7 +177,8 @@ const tableStore = new TableStore({
}) })
nextTick(() => { nextTick(() => {
waveFormAnalysisRef.value && waveFormAnalysisRef.value.getWpData(wp.value, boxoList.value, true) waveFormAnalysisRef.value &&
waveFormAnalysisRef.value.getWpData(wp.value, boxoList.value, true)
// waveFormAnalysisRef.value && waveFormAnalysisRef.value.setHeight(200, 190) // waveFormAnalysisRef.value && waveFormAnalysisRef.value.setHeight(200, 190)
}) })
// row.loading1 = true // row.loading1 = true
@@ -206,7 +225,6 @@ const tableStore = new TableStore({
document.body.appendChild(link) document.body.appendChild(link)
link.click() //执行下载 link.click() //执行下载
document.body.removeChild(link) //释放标签 document.body.removeChild(link) //释放标签
}) })
} }
}, },
@@ -342,6 +360,6 @@ setTimeout(() => {
tableStore.table.height = mainHeight(200).height as any tableStore.table.height = mainHeight(200).height as any
}, 0) }, 0)
const addMenu = () => { } const addMenu = () => {}
</script> </script>
<style scoped lang="scss"></style> <style scoped lang="scss"></style>

View File

@@ -1,37 +1,66 @@
<template> <template>
<div class="default-main analyze-apf" :style="{ height: pageHeight.height }" v-loading="loading"> <div class="default-main analyze-apf" :style="{ height: pageHeight.height }" v-loading="loading">
<DeviceTree @node-click="nodeClick" @init="nodeClick"></DeviceTree> <DeviceTree @node-click="nodeClick" @init="nodeClick" @deviceTypeChange="deviceTypeChange"></DeviceTree>
<div class="analyze-apf-right" v-if="formInline.devId"> <div class="analyze-apf-right" v-if="formInline.devId">
<el-form :inline="true"> <div ref="headerRef">
<el-form-item label="时间:"> <TableHeader :showSearch="false" ref="tableHeaderRef" @selectChange="selectChange">
<DatePicker ref="datePickerRef"></DatePicker> <template v-slot:select>
</el-form-item> <el-form-item label="时间:">
<el-form-item label="统计指标:"> <DatePicker ref="datePickerRef"></DatePicker>
<el-select v-model.trim="formInline.statisticalId" filterable placeholder="请选择"> </el-form-item>
<el-option v-for="item in zblist" :key="item.value" :label="item.label" <el-form-item label="统计指标:">
:value="item.value"></el-option> <el-select
</el-select> style="width: 200px"
</el-form-item> v-model.trim="formInline.statisticalId"
<el-form-item label="值类型:"> filterable
<el-select v-model.trim="formInline.valueType" filterable placeholder="请选择"> @change="frequencyFlag"
<el-option v-for="item in typelist" :key="item.value" :label="item.label" placeholder="请选择"
:value="item.value"></el-option> >
</el-select> <el-option
</el-form-item> v-for="item in zblist"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="谐波次数:" v-show="frequencyShow">
<el-select
v-model.trim="formInline.frequency"
filterable
placeholder="请选择"
style="width: 100px"
>
<el-option
v-for="item in 49"
:key="item + 1"
:label="item + 1"
:value="item + 1"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="值类型:">
<el-select v-model.trim="formInline.valueType" filterable placeholder="请选择">
<el-option
v-for="item in typelist"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
</template>
<template v-slot:operation>
<el-button type="primary" @click="search" icon="el-icon-Search">查询</el-button>
</template>
</TableHeader>
</div>
<el-form-item>
<el-button type="primary" @click="search" icon="el-icon-Search">查询</el-button>
</el-form-item>
<el-form-item>
<div style="display: flex; align-items: center">
<Icon name="el-icon-InfoFilled" style="color: #ff9912"></Icon>
总输出电流阈值和总输出电流比较
</div>
</el-form-item>
</el-form>
<el-empty description="暂无数据" v-if="!echartsData" style="flex: 1"></el-empty> <el-empty description="暂无数据" v-if="!echartsData" style="flex: 1"></el-empty>
<template v-else> <template v-else>
<MyEchart :options="echartsData" style="flex: 1" /> <div :style="echartHeight">
<MyEchart :options="echartsData" />
</div>
</template> </template>
</div> </div>
<el-empty v-else description="请选择设备" class="analyze-apf-right" /> <el-empty v-else description="请选择设备" class="analyze-apf-right" />
@@ -48,10 +77,16 @@ import { queryCommonStatisticalByTime } from '@/api/cs-harmonic-boot/stable'
import DatePicker from '@/components/form/datePicker/index.vue' import DatePicker from '@/components/form/datePicker/index.vue'
import MyEchart from '@/components/echarts/MyEchart.vue' import MyEchart from '@/components/echarts/MyEchart.vue'
import { yMethod } from '@/utils/echartMethod' import { yMethod } from '@/utils/echartMethod'
import TableHeader from '@/components/table/header/index.vue'
defineOptions({ defineOptions({
name: 'govern/analyze/APF' name: 'govern/analyze/APF'
}) })
const tableHeaderRef = ref()
const headerRef = ref()
const pageHeight = mainHeight(20) const pageHeight = mainHeight(20)
const echartHeight = ref(mainHeight(80))
const loading = ref(false) const loading = ref(false)
const echartsData = ref<any>(null) const echartsData = ref<any>(null)
const datePickerRef = ref() const datePickerRef = ref()
@@ -60,9 +95,13 @@ const formInline = reactive({
valueType: '', valueType: '',
startTime: '', startTime: '',
endTime: '', endTime: '',
devId: '' devId: '',
frequency: ''
}) })
const timeFlag = ref(true)
const frequencyShow = ref(false)
const devCapacity = ref(0) const devCapacity = ref(0)
const flag = ref(false)
const typelist = [ const typelist = [
{ {
label: '平均值', label: '平均值',
@@ -85,7 +124,7 @@ const zblist = ref<any[]>([])
const init = () => { const init = () => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
queryByCode('Harmonic_Type').then(res => { queryByCode('Web_Apf').then(res => {
queryCsDictTree(res.data?.id).then(res => { queryCsDictTree(res.data?.id).then(res => {
zblist.value = res.data.map((item: any) => { zblist.value = res.data.map((item: any) => {
return { return {
@@ -101,191 +140,78 @@ const init = () => {
}) })
}) })
} }
const deviceTypeChange = (val: any, obj: any) => {
flag.value = true
nodeClick(obj)
}
const nodeClick = async (e: anyObj) => { const nodeClick = async (e: anyObj) => {
if (e.level == 2) { if (e.level == 2 && flag.value) {
formInline.devId = e.id formInline.devId = e.id
loading.value = true loading.value = true
if (zblist.value.length === 0) { if (zblist.value.length === 0) {
await init() await init()
} }
getDevCapacity(formInline.devId).then(res => { getDevCapacity(formInline.devId)
devCapacity.value = res.data .then(res => {
search() devCapacity.value = res.data
}).catch(() => { search()
loading.value = false })
.catch(() => {
}) loading.value = false
})
} }
} }
const lineStyle = [
{ type: 'solid', width: 3 },
{ type: 'dotted', width: 3 },
{ type: 'dashed', width: 3 }
]
const search = () => { const search = () => {
if (timeFlag.value) {
datePickerRef.value && datePickerRef.value.setInterval(5)
timeFlag.value = false
}
loading.value = true loading.value = true
formInline.startTime = datePickerRef.value.timeValue[0] formInline.startTime = datePickerRef.value.timeValue[0]
formInline.endTime = datePickerRef.value.timeValue[1] formInline.endTime = datePickerRef.value.timeValue[1]
queryCommonStatisticalByTime(formInline).then(({ data }: { data: any[] }) => { if (!frequencyShow.value) {
if (data.length) { formInline.frequency = ''
echartsData.value = {} }
let legend: any[] = []
let xAxis: any[] = []
data.forEach(item => {
if (!xAxis.includes(item.time)) {
xAxis.push(item.time)
}
if (!legend.includes(item.anotherName)) {
legend.push(item.anotherName)
}
})
let aar = data
.map(item => {
if (item.statisticalName === 'Apf_RmsI_TolOut') {
return [item.time, item.statisticalData.toFixed(2)]
} else {
return ''
}
})
.filter(item => item !== '')
let aar1 = data
.map(item => {
if (item.statisticalName === 'Apf_ThdA_Load') {
return [item.time, item.statisticalData.toFixed(2)]
} else {
return ''
}
})
.filter(item => item !== '')
let aar2 = data
.map(item => {
if (item.statisticalName === 'Apf_ThdA_Sys') {
return [item.time, item.statisticalData.toFixed(2)]
} else {
return ''
}
})
.filter(item => item !== '')
queryCommonStatisticalByTime(formInline)
.then(({ data }: { data: any[] }) => {
if (data.length) {
let list = processingOfData(data, 'unit')
let series = [ echartsData.value = {}
// 总输出电流 let legend: any[] = []
{ let xAxis: any[] = []
name: data.find(item => item.statisticalName === 'Apf_RmsI_TolOut').anotherName, let yAxis: any[] = []
symbol: 'none', let series: any[] = []
smooth: true, let color: any[] = []
type: 'line', let title = ''
//stack: 'Total', data.forEach(item => {
data: aar, if (!xAxis.includes(item.time)) {
markLine: { xAxis.push(item.time)
symbol: 'none',
data: [
{
yAxis: devCapacity.value,
label: {
position: 'middle', // 表现内容展示的位置
formatter: '总输出电流阈值', // 标线展示的内容
color: '#daa569' // 展示内容颜色
}
}
]
},
yAxisIndex: 1
},
//负载电流畸变率
{
name: data.find(item => item.statisticalName === 'Apf_ThdA_Load').anotherName,
symbol: 'none',
smooth: true,
type: 'line',
data: aar1
},
// 电网电流畸变率
{
name: data.find(item => item.statisticalName === 'Apf_ThdA_Sys').anotherName,
symbol: 'none',
smooth: true,
type: 'line',
data: aar2
}
]
let [min, max] = yMethod(aar.map((item: any) => item[1]))
let [min1, max1] = yMethod([...aar1, ...aar2].map((item: any) => item[1]))
echartsData.value = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
crossStyle: {
color: '#999'
}
} }
}, // if (!legend.includes(item.anotherName)) {
legend: { // legend.push(item.anotherName)
data: legend
},
grid: {
left: '20px',
right: '40px',
bottom: '50px',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
name: '',
type: 'time',
axisLabel: {
formatter: {
day: '{MM}-{dd}',
month: '{MM}',
year: '{yyyy}',
},
},
// boundaryGap: false,
// data: xAxis,
// axisLabel: {
// formatter: function (value: string) {
// return value.split(' ').join('\n')
// }
// },
// axisLine: {
// show: true,
// // symbol: ["none", "arrow"],
// lineStyle: {
// color: '#333'
// }
// } // }
}, })
yAxis: [ let units = Object.keys(list)
{ // console.log('🚀 ~ .then ~ units:', units)
name: '畸变率:(%)', for (let unit in list) {
console.log('🚀 ~ .then ~ unit:', unit)
let [min, max] = yMethod(list[unit].map((item: any) => item.statisticalData))
yAxis.push({
name: unit == 'null' ? '' : unit,
type: 'value', type: 'value',
// max: 10, // max: 10,
min: min1,
max: max1,
splitNumber: 5,
minInterval: 1,
axisLine: {
show: true,
//symbol: ["none", "arrow"],
lineStyle: {
color: '#333'
}
}
},
{
name: '电流:(A)',
type: 'value',
min: min, min: min,
max: max, max: max,
splitNumber: 5, // splitNumber: 5,
minInterval: 1, // minInterval: 1,
splitLine: {
show: false,
},
axisLine: { axisLine: {
show: true, show: true,
//symbol: ["none", "arrow"], //symbol: ["none", "arrow"],
@@ -293,20 +219,211 @@ const search = () => {
color: '#333' color: '#333'
} }
} }
} })
], // processingOfData(list[unit], 'anotherName')
options: { let anotherList = processingOfData(list[unit], 'anotherName')
series: series for (let k in anotherList) {
} title = k
} let lineName = lineStyle[Object.keys(anotherList).indexOf(k)]
} else { let phaseList = processingOfData(anotherList[k], 'phase')
echartsData.value = null for (let j in phaseList) {
} color.push(j == 'A' ? '#DAA520' : j == 'B' ? '#2E8B57' : j == 'C' ? '#A52a2a' : '#0000CC')
loading.value = false legend.push(
}).catch(() => { j == 'M' ? k : j == 'A' ? `A相_${k}` : j == 'B' ? `B相_${k}` : j == 'C' ? `C相_${k}` : j
loading.value = false )
}) series.push({
name:
j == 'M'
? k
: j == 'A'
? `A相_${k}`
: j == 'B'
? `B相_${k}`
: j == 'C'
? `C相_${k}`
: j,
symbol: 'none',
smooth: true,
type: 'line',
data: phaseList[j].map(item => [
item.time,
Math.floor(item.statisticalData * 100) / 100,
unit,
lineName.type
]),
lineStyle: lineName,
yAxisIndex: unit.indexOf(units)
})
}
}
}
echartsData.value = {
title: {
text: zblist.value.filter(item => item.id == formInline.statisticalId)[0].name
},
tooltip: {
axisPointer: {
type: 'cross',
label: {
color: '#fff',
fontSize: 16
}
},
textStyle: {
color: '#fff',
fontStyle: 'normal',
opacity: 0.35,
fontSize: 14
},
backgroundColor: 'rgba(0,0,0,0.55)',
borderWidth: 0,
formatter(params: any) {
const xname = params[0].value[0]
let str = `${xname}<br>`
params.forEach((el: any, index: any) => {
let marker = ''
if (el.value[3] == 'dashed') {
for (let i = 0; i < 3; i++) {
marker += `<span style="display:inline-block;border: 2px ${el.color} solid;margin-right:5px;width:10px;height:0px;background-color:#ffffff00;"></span>`
}
} else {
marker = `<span style="display:inline-block;border: 2px ${el.color} ${el.value[3]};margin-right:5px;width:40px;height:0px;background-color:#ffffff00;"></span>`
}
str += `${marker}${el.seriesName.split('(')[0]}${
el.value[1] != null
? el.value[1] + ' ' + (el.value[2] == 'null' ? '' : el.value[2])
: '-'
}<br>`
})
return str
}
},
legend: {
itemWidth: 20,
itemHeight: 20,
itemStyle: { opacity: 0 }, //去圆点
type: 'scroll', // 开启滚动分页
top: 25
// data: legend
},
grid: {
left: '20px',
right: '40px',
bottom: '50px',
top: '80px',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
color: color,
xAxis: {
name: '',
type: 'time',
axisLabel: {
formatter: {
day: '{MM}-{dd}',
month: '{MM}',
year: '{yyyy}'
}
}
// boundaryGap: false,
// data: xAxis,
// axisLabel: {
// formatter: function (value: string) {
// return value.split(' ').join('\n')
// }
// },
// axisLine: {
// show: true,
// // symbol: ["none", "arrow"],
// lineStyle: {
// color: '#333'
// }
// }
},
yAxis: yAxis,
// [
// {
// name: '畸变率:(%)',
// type: 'value',
// // max: 10,
// min: min1,
// max: max1,
// splitNumber: 5,
// minInterval: 1,
// axisLine: {
// show: true,
// //symbol: ["none", "arrow"],
// lineStyle: {
// color: '#333'
// }
// }
// },
// {
// name: '电流:(A)',
// type: 'value',
// min: min,
// max: max,
// splitNumber: 5,
// minInterval: 1,
// splitLine: {
// show: false
// },
// axisLine: {
// show: true,
// //symbol: ["none", "arrow"],
// lineStyle: {
// color: '#333'
// }
// }
// }
// ],
options: {
series: series
}
}
} else {
echartsData.value = null
}
loading.value = false
})
.catch(() => {
loading.value = false
})
}
const processingOfData = (data: any, type: string) => {
let groupedData: any = {}
data.forEach(item => {
if (!groupedData[item[type]]) {
groupedData[item[type]] = []
}
groupedData[item[type]].push(item)
})
return groupedData
}
const frequencyFlag = () => {
let name = zblist.value.filter(item => item.id == formInline.statisticalId)[0].name
if (name.includes('含有率') || name.includes('幅值')) {
frequencyShow.value = true
formInline.frequency = 2
} else {
frequencyShow.value = false
}
tableHeaderRef.value && tableHeaderRef.value?.computedSearchRow()
}
const selectChange = (flag: boolean) => {
setTimeout(() => {
echartHeight.value = mainHeight(23 + headerRef.value.offsetHeight)
}, 100)
} }
</script> </script>
@@ -324,3 +441,8 @@ const search = () => {
} }
} }
</style> </style>
<style lang="scss" scoped>
.el-select {
min-width: 100px;
}
</style>

View File

@@ -1,21 +1,36 @@
<template> <template>
<div class="default-main"> <div class="default-main">
<div class="analyze-dvr" v-show="!isWaveCharts" :style="{ height: pageHeight.height }" v-loading="loading"> <div class="analyze-dvr" v-show="!isWaveCharts" :style="{ height: pageHeight.height }" v-loading="loading">
<DeviceTree @node-click="nodeClick" @init="nodeClick"></DeviceTree> <DeviceTree @node-click="nodeClick" @init="nodeClick" @deviceTypeChange="deviceTypeChange"></DeviceTree>
<div class="analyze-dvr-right" v-if="tableStore.table.params.deviceId"> <div class="analyze-dvr-right" v-if="tableStore.table.params.deviceId">
<TableHeader datePicker showExport> <TableHeader datePicker showExport>
<template v-slot:select> <template v-slot:select>
<el-form-item label="事件类型"> <el-form-item label="事件类型">
<el-select v-model.trim="tableStore.table.params.eventType" clearable placeholder="请选择事件类型"> <el-select
<el-option v-for="item in eventList" :key="item.value" :label="item.label" v-model.trim="tableStore.table.params.eventType"
:value="item.value" /> clearable
placeholder="请选择事件类型"
>
<el-option
v-for="item in eventList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="位置"> <el-form-item label="位置">
<el-select v-model.trim="tableStore.table.params.location" clearable placeholder="请选择位置"> <el-select
<el-option v-for="item in locationList" :key="item.value" :label="item.label" v-model.trim="tableStore.table.params.location"
:value="item.value" /> clearable
placeholder="请选择位置"
>
<el-option
v-for="item in locationList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
</template> </template>
@@ -24,8 +39,14 @@
</div> </div>
<el-empty v-else description="请选择设备" class="analyze-dvr-right" /> <el-empty v-else description="请选择设备" class="analyze-dvr-right" />
</div> </div>
<waveFormAnalysis v-loading="loading" v-if="isWaveCharts" ref="waveFormAnalysisRef" <waveFormAnalysis
@handleHideCharts="isWaveCharts = false" :wp="wp" style="padding: 10px;" /> v-loading="loading"
v-if="isWaveCharts"
ref="waveFormAnalysisRef"
@handleHideCharts="isWaveCharts = false"
:wp="wp"
style="padding: 10px"
/>
<!-- <div :style="{ height: pageHeight.height }" style="padding: 10px; overflow: hidden" v-if="!view"> <!-- <div :style="{ height: pageHeight.height }" style="padding: 10px; overflow: hidden" v-if="!view">
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
@@ -67,14 +88,14 @@ import { mainHeight } from '@/utils/layout'
import DeviceTree from '@/components/tree/govern/deviceTree.vue' import DeviceTree from '@/components/tree/govern/deviceTree.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 waveFormAnalysis from '@/views/govern/device/control/tabs/components/waveFormAnalysis.vue'; import waveFormAnalysis from '@/views/govern/device/control/tabs/components/waveFormAnalysis.vue'
import { analyseWave } from '@/api/common' import { analyseWave } from '@/api/common'
import TableHeader from '@/components/table/header/index.vue' import TableHeader from '@/components/table/header/index.vue'
import { getFileZip } from '@/api/cs-harmonic-boot/datatrend' import { getFileZip } from '@/api/cs-harmonic-boot/datatrend'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
defineOptions({ defineOptions({
name: 'analyze/DVR/index' name: 'govern/analyze/DVR/index'
}) })
const pageHeight = mainHeight(20) const pageHeight = mainHeight(20)
const loading = ref(false) const loading = ref(false)
@@ -85,43 +106,49 @@ const isWaveCharts = ref(false)
const bxactiveName = ref('ssbx') const bxactiveName = ref('ssbx')
const boxoList: any = ref({}) const boxoList: any = ref({})
const wp = ref({}) const wp = ref({})
const eventList = ref([{ const eventList = ref([
value: 'Evt_Sys_DipStr', {
label: '电压暂降' value: 'Evt_Sys_DipStr',
}, label: '电压暂降'
{ },
value: 'Evt_Sys_SwlStr', {
label: '电压暂升' value: 'Evt_Sys_SwlStr',
}, label: '电压暂升'
{ },
value: 'Evt_Sys_IntrStr', {
label: '电压中断' value: 'Evt_Sys_IntrStr',
}]) label: '电压中断'
const locationList = ref([{ }
value: 'grid', ])
label: '电网侧' const locationList = ref([
}, {
{ value: 'grid',
value: 'load', label: '电网侧'
label: '负载侧' },
}]) {
value: 'load',
label: '负载侧'
}
])
const waveFormAnalysisRef = ref() const waveFormAnalysisRef = ref()
const tableStore = new TableStore({ const tableStore = new TableStore({
url: '/cs-harmonic-boot/eventUser/queryEventpageWeb', url: '/cs-harmonic-boot/eventUser/queryEventpageWeb',
method: 'POST', method: 'POST',
column: [ column: [
{ title: '事件描述', field: 'showName', }, { title: '事件描述', field: 'showName' },
{ title: '发生位置', field: 'evtParamPosition' }, { title: '发生位置', field: 'evtParamPosition' },
{ title: '持续时间(s)', field: 'evtParamTm' }, { title: '持续时间(s)', field: 'evtParamTm', sortable: true },
{ {
title: '暂降(聚升)幅值(%)', field: 'evtParamVVaDepth', formatter: (row: any) => { title: '暂降(聚升)幅值(%)',
field: 'evtParamVVaDepth',
formatter: (row: any) => {
let a = row.cellValue.split('%')[0] - 0 let a = row.cellValue.split('%')[0] - 0
console.log("🚀 ~ a:", a) console.log('🚀 ~ a:', a)
return a ? a.toFixed(2) : '/' return a ? a.toFixed(2) : '/'
} }, sortable: true
}, },
{ title: '发生时刻', field: 'startTime' }, { title: '发生时刻', field: 'startTime', sortable: true },
{ {
title: '操作', title: '操作',
align: 'center', align: 'center',
@@ -147,11 +174,10 @@ const tableStore = new TableStore({
row.loading1 = false row.loading1 = false
if (res != undefined) { if (res != undefined) {
boxoList.value = row boxoList.value = row
boxoList.value.featureAmplitude = row.evtParamVVaDepth != '-' ? row.evtParamVVaDepth - 0 : null boxoList.value.featureAmplitude =
row.evtParamVVaDepth != '-' ? row.evtParamVVaDepth - 0 : null
// boxoList.value.systemType = 'WX' // boxoList.value.systemType = 'WX'
wp.value = res.data wp.value = res.data
} }
loading.value = false loading.value = false
}) })
@@ -161,7 +187,8 @@ const tableStore = new TableStore({
}) })
nextTick(() => { nextTick(() => {
waveFormAnalysisRef.value && waveFormAnalysisRef.value.getWpData(wp.value, boxoList.value, true) waveFormAnalysisRef.value &&
waveFormAnalysisRef.value.getWpData(wp.value, boxoList.value, true)
waveFormAnalysisRef.value && waveFormAnalysisRef.value.setHeight(false, 150) waveFormAnalysisRef.value && waveFormAnalysisRef.value.setHeight(false, 150)
}) })
} }
@@ -174,9 +201,7 @@ const tableStore = new TableStore({
render: 'basicButton', render: 'basicButton',
disabled: row => { disabled: row => {
return !(!row.wavePath && row.evtParamTm < 20) return !(!row.wavePath && row.evtParamTm < 20)
}, }
}, },
{ {
name: 'edit', name: 'edit',
@@ -199,10 +224,9 @@ const tableStore = new TableStore({
document.body.appendChild(link) document.body.appendChild(link)
link.click() //执行下载 link.click() //执行下载
document.body.removeChild(link) //释放标签 document.body.removeChild(link) //释放标签
}) })
} }
}, }
] ]
} }
], ],
@@ -210,17 +234,21 @@ const tableStore = new TableStore({
tableStore.table.data.forEach((item: any) => { tableStore.table.data.forEach((item: any) => {
item.loading = false item.loading = false
item.evtParamTm = item.evtParamTm.split('s')[0] item.evtParamTm = item.evtParamTm.split('s')[0]
}) })
} }
}) })
const flag = ref(false)
tableStore.table.params.type = 0 tableStore.table.params.type = 0
tableStore.table.params.eventType = '' tableStore.table.params.eventType = ''
tableStore.table.params.location = '' tableStore.table.params.location = ''
provide('tableStore', tableStore) provide('tableStore', tableStore)
const deviceTypeChange = (val: any, obj: any) => {
flag.value = true
nodeClick(obj)
}
const nodeClick = async (e: anyObj) => { const nodeClick = async (e: anyObj) => {
// console.log("🚀 ~ nodeClick ~ e:", e) // console.log("🚀 ~ nodeClick ~ e:", e)
if (e.level == 2) { if (e.level == 2&& flag.value) {
loading.value = false loading.value = false
tableStore.table.params.deviceId = e.id tableStore.table.params.deviceId = e.id
nextTick(() => { nextTick(() => {

View File

@@ -58,8 +58,8 @@ const tableStore: any = new TableStore({
} }
}, },
{ field: 'successCount', title: '成功解析数', minWidth: 150 }, { field: 'successCount', title: '成功解析数', minWidth: 150 },
{ field: 'startTime', title: '导入开始时间', minWidth: 170 }, { field: 'startTime', title: '导入开始时间', minWidth: 170, sortable: true },
{ field: 'endTime', title: '导入结束时间', minWidth: 170 }, { field: 'endTime', title: '导入结束时间', minWidth: 170 , sortable: true},
{ {
title: '解析状态', title: '解析状态',
field: 'status', field: 'status',

View File

@@ -42,9 +42,9 @@ const tableStore: any = new TableStore({
} }
}, },
{ field: 'name', title: '文件名称', minWidth: 170 }, { field: 'name', title: '文件名称', minWidth: 170 },
{ field: 'createTime', title: '导入时间', minWidth: 170 }, { field: 'createTime', title: '导入时间', minWidth: 170 , sortable: true},
{ field: 'allCount', title: '数据总数(条)', minWidth: 170 }, { field: 'allCount', title: '数据总数(条)', minWidth: 170 , sortable: true},
{ field: 'realCount', title: '已入库总数(条)', minWidth: 170 }, { field: 'realCount', title: '已入库总数(条)', minWidth: 170, sortable: true },
{ {
title: '解析状态', title: '解析状态',
field: 'state', field: 'state',

View File

@@ -270,7 +270,7 @@ const init = () => {
} }
} }
if ((echartsData.value.legend = ['A相', 'B相', 'C相'])) { if ((echartsData.value.legend = ['A相', 'B相', 'C相'])) {
echartsData.value.color = ['#FFCC00', '#009900', '#CC0000'] echartsData.value.color = ['#DAA520', '#2E8B57', '#A52a2a']
} }
} else { } else {

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,676 @@
<template>
<!-- 运行 运行(中断) 运行(故障) 离线 -->
<div :style="height" style="overflow-y: auto" v-loading="loading">
<div class="container">
<div class="tabs-container">
<!-- 左侧标签头 -->
<div class="tab-list" :style="titleHeight" style="overflow-y: auto" v-loading="loadingLeft">
<button
v-for="(item, index) in list"
:key="index"
:class="{ 'tab-button active': activeTab === index, 'tab-button': activeTab !== index }"
@click="changeTab(index)"
>
<span>{{ item.moduleName }}</span>
<el-tag class="ml10" :type="getType(item.moduleState)" size="small" effect="dark">
{{ item.moduleState }}
</el-tag>
</button>
</div>
<!-- 右侧内容区域 -->
<div class="tab-content-container flex-1" :key="activeTab">
<div v-if="echartList?.dataList != null" style="position: relative">
<el-tabs v-model="activeName" type="card" @tab-change="changeDataType">
<el-tab-pane label="状态" name="0">
<div :style="echartHeight" class="pt10">
<MyEchart :options="echartList.options" />
</div>
</el-tab-pane>
<el-tab-pane label="数据" name="1">
<div :style="echartHeight" class="pt10">
<MyEchart style="height: 100%" :options="echartsData" :key="key" />
<!-- <MyEchart style="height: 50%" :options="echartList.loadList" />
<MyEchart style="height: 50%" :options="echartList.modOutList" /> -->
</div>
</el-tab-pane>
</el-tabs>
<el-select
v-if="activeName == '1'"
v-model="dataType"
class="select"
placeholder="请选择"
multiple
collapse-tags
style="width: 150px"
@change="changeDataType"
>
<el-option label="负载电流" :value="0" />
<el-option label="输入电流" :value="1" />
<el-option label="温度" :value="2" />
</el-select>
</div>
<el-empty description="暂无数据" style="width: 100%; height: 100%" v-else></el-empty>
</div>
</div>
</div>
<!-- <el-collapse v-model="activeNames" v-loading="loading">
<el-collapse-item v-for="(item, index) in list" :key="index" :name="index">
<template #title>
<div class="header">
{{ item.moduleName }}
<el-tag
class="ml10"
:type="item.moduleState == '离线' ? 'danger' : 'success'"
size="small"
effect="dark"
>
{{ item.moduleState }}
</el-tag>
</div>
</template>
<div :style="echartHeight" style="min-height: 150px">
<MyEchart :options="item.options" v-if="item.dataList != null" />
<el-empty description="暂无数据" style="height: 130px" v-else></el-empty>
</div>
</el-collapse-item>
</el-collapse> -->
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onBeforeUnmount } from 'vue'
import { mainHeight } from '@/utils/layout'
import { WarnTriangleFilled } from '@element-plus/icons-vue'
import { getModuleState } from '@/api/cs-device-boot/EquipmentDelivery'
import MyEchart from '@/components/echarts/MyEchart.vue'
import { ElMessage } from 'element-plus'
import { yMethod } from '@/utils/echartMethod'
const list: any = ref([])
const loading = ref(false)
const loadingLeft = ref(false)
const height = ref(mainHeight(290))
const titleHeight = ref(mainHeight(302))
const echartHeight = ref(mainHeight(342))
const activeTab = ref(0)
const activeName = ref('0')
const echartList: any = ref({})
const dataType = ref([0])
const key = ref(0)
import * as echarts from 'echarts' // 全引入
import { max } from 'lodash'
const echartsData: any = ref({
title: {
show: false
},
xAxis: {
type: 'time',
name: '',
axisLabel: {
formatter: {
day: '{MM}-{dd}',
month: '{MM}',
year: '{yyyy}'
}
}
},
tooltip: {
axisPointer: {
type: 'cross',
label: {
color: '#fff',
fontSize: 16
}
},
textStyle: {
color: '#fff',
fontStyle: 'normal',
opacity: 0.35,
fontSize: 14
},
backgroundColor: 'rgba(0,0,0,0.55)',
borderWidth: 0,
formatter(params: any) {
const xname = params[0].value[0]
let str = `${xname}<br>`
params.forEach((el: any, index: any) => {
let marker = ''
if (el.value[3] == 'dashed') {
for (let i = 0; i < 3; i++) {
marker += `<span style="display:inline-block;border: 2px ${el.color} solid;margin-right:5px;width:10px;height:0px;background-color:#ffffff00;"></span>`
}
} else {
marker = `<span style="display:inline-block;border: 2px ${el.color} ${el.value[3]};margin-right:5px;width:40px;height:0px;background-color:#ffffff00;"></span>`
}
str += `${marker}${el.seriesName.split('(')[0]}${
el.value[1] != null ? el.value[1] + ' ' + (el.value[2] || '') : '-'
}<br>`
})
return str
}
},
legend: {
itemWidth: 20,
itemHeight: 20,
itemStyle: { opacity: 0 }, //去圆点
type: 'scroll', // 开启滚动分页
right: 70
},
grid: {
top: '80px',
right: '50px',
},
yAxis: [{}],
options: {
// yAxis: [{}],
series: []
}
})
const setData = (data: any) => {
// activeTab.value = 0
// echartHeight.value = mainHeight(292 + data.length * 49, data.length)
data.forEach((item: any) => {
// console.log('🚀 ~ setData ~ data:', data)
if (item.dataList == null) return
item.dataList.map((k: any, i: any) => {
k.endtime = item.dataList[i + 1]?.time
})
item.options = {
// 鼠标提示
tooltip: {
axisPointer: {
type: 'cross',
label: {
color: '#fff',
fontSize: 16
}
},
formatter: function (params) {
// console.log("🚀 ~ data.forEach ~ params:", params)
let tip = ''
for (let i = 0; i < params.length; i++) {
if (params[i].seriesName != '事件标记') {
tip +=
params[i].marker +
params[i].name +
'<br/>' +
'开始时间:' +
params[i].value[1] +
'<br/>' +
'结束时间:' +
(params[i].value[2] || '-') +
'<br/>'
if (params[i].value[3] == 1) {
tip += '事件:' + params[i].value[4] + '<br/>'
}
} else {
// if (params[i].value[3] == 1) {
// tip += '事件:' + params[i].value[1] + '<br/>'
// }
}
}
return tip
}
},
legend: {
// data: ['运行', '停止', '离线','事件标记']
data: [
{ name: '运行' },
{ name: '停止' },
{ name: '离线' },
{
name: '事件标记',
icon: 'path://M0,10 L10,10 L5,0 Z', // 自定义三角形路径
textStyle: {
color: '#333',
fontSize: 14
}
}
]
},
xAxis: {
type: 'time',
name: '时间',
axisLabel: {
formatter: {
day: '{MM}-{dd}',
month: '{MM}',
year: '{yyyy}'
}
}
},
yAxis: {
show: false,
axisPointer: {
show: false // 隐藏Y轴上的指示器
}
},
color: ['#67c23a', '#e6a23c', '#f56c6c', '#ccc'],
series: [
{
name: '运行',
type: 'custom',
renderItem: renderItem,
encode: {
x: [1, 2],
y: 0
},
data: item.dataList
.filter((k: any, i: number) => k.stateDesc == '运行')
.map((p: any) => {
return {
name: '运行',
value: [0, p.time, p.endtime, p.dataType, p.eventName],
itemStyle: {
normal: {
color: '#67c23a'
}
}
}
})
},
{
name: '停止',
type: 'custom',
renderItem: renderItem,
encode: {
x: [1, 2],
y: 0
},
data: item.dataList
.filter((k: any, i: number) => k.stateDesc != '离线' && k.stateDesc != '运行')
.map((p: any) => {
return {
name: '停止',
value: [0, p.time, p.endtime, p.dataType, p.eventName],
itemStyle: {
normal: {
color: '#e6a23c'
}
}
}
})
},
{
name: '离线',
type: 'custom',
renderItem: renderItem,
encode: {
x: [1, 2],
y: 0
},
data: item.dataList
.filter((k: any, i: number) => k.stateDesc == '离线')
.map((p: any) => {
return {
name: '离线',
value: [0, p.time, p.endtime, p.dataType, p.eventName],
itemStyle: {
normal: {
color: '#f56c6c'
}
}
}
})
// [
// {
// name: '离线',
// value: [0, '2025-07-16 01:03:00', '2025-07-16 01:06:00', 353249],
// itemStyle: {
// normal: {
// color: '#f56c6c'
// }
// }
// }
// ]
},
{
name: '事件标记',
type: 'custom',
renderItem: renderMarker,
encode: {
x: 0,
y: 1
},
data: item.dataList
.filter((k: any) => k.dataType === 1)
.map((k: any) => [
k.time,
k.eventName,
k.stateDesc == '离线' ? '#f56c6c' : k.stateDesc == '运行' ? '#67c23a' : '#e6a23c',
k.dataType
]),
// data: [['2025-07-16 01:00:00','故障发生','#bd6d6c']],
z: 10 // 确保标记显示在甘特图上方
}
]
}
})
list.value = data
echartList.value = list.value[activeTab.value]
changeDataType()
// echarts.connect('group')
}
const lineStyle = [{ type: 'solid' }, { type: 'dashed' }, { type: 'dotted' }]
const changeDataType = () => {
// loadList 负载电流
// modOutList 输入电流
// console.log('🚀 ~ changeDataType ~ val:', list.value[activeTab.value])
echartsData.value.yAxis = [{}]
echartsData.value.options.series = []
let flag = dataType.value.includes(0) || dataType.value.includes(1)
if (flag) {
let data1 = dataType.value.includes(0)
? list.value[activeTab.value].loadList.map(k => (k.data == 3.14159 ? 0 : k.data))
: [0]
let data2 = dataType.value.includes(1)
? list.value[activeTab.value].modOutList.map(k => (k.data == 3.14159 ? 0 : k.data))
: [0]
let [modOuMin, modOuMax] = yMethod([...data1, ...data2])
console.log("🚀 ~ changeDataType ~ modOuMin:", modOuMin,modOuMax)
echartsData.value.yAxis[0] = {
name: 'A',
yAxisIndex: 0,
max: modOuMax,
min: modOuMin,
splitNumber: 5,
minInterval: 1
}
if (dataType.value.includes(0)) {
echartsData.value.options.series.push(
{
name: 'A相负载电流',
type: 'line',
data: list.value[activeTab.value].loadList
.filter((k: any) => k.phasicType == 'A')
.map((k: any) => [k.time, k.data == 3.14159 ? null : k.data, 'A', lineStyle[0].type]),
smooth: true, //让线变得平滑
symbol: 'none',
color: '#DAA520',
lineStyle: lineStyle[0],
yAxisIndex: 0
},
{
name: 'B相负载电流',
type: 'line',
data: list.value[activeTab.value].loadList
.filter((k: any) => k.phasicType == 'B')
.map((k: any) => [k.time, k.data == 3.14159 ? null : k.data, 'A', lineStyle[0].type]),
smooth: true, //让线变得平滑
symbol: 'none',
color: '#2E8B57',
lineStyle: lineStyle[0],
yAxisIndex: 0
},
{
name: 'C相负载电流',
type: 'line',
data: list.value[activeTab.value].loadList
.filter((k: any) => k.phasicType == 'C')
.map((k: any) => [k.time, k.data == 3.14159 ? null : k.data, 'A', lineStyle[0].type]),
smooth: true, //让线变得平滑
symbol: 'none',
color: '#A52a2a',
lineStyle: lineStyle[0],
yAxisIndex: 0
}
)
}
if (dataType.value.includes(1)) {
echartsData.value.options.series.push(
{
name: 'A相输入电流',
type: 'line',
data: list.value[activeTab.value].modOutList
.filter((k: any) => k.phasicType == 'A')
.map((k: any) => [k.time, k.data == 3.14159 ? null : k.data, 'A', lineStyle[1].type]),
smooth: true, //让线变得平滑
symbol: 'none',
color: '#DAA520',
lineStyle: lineStyle[1],
yAxisIndex: 0
},
{
name: 'B相输入电流',
type: 'line',
data: list.value[activeTab.value].modOutList
.filter((k: any) => k.phasicType == 'B')
.map((k: any) => [k.time, k.data == 3.14159 ? null : k.data, 'A', lineStyle[1].type]),
smooth: true, //让线变得平滑
symbol: 'none',
color: '#2E8B57',
lineStyle: lineStyle[1],
yAxisIndex: 0
},
{
name: 'C相输入电流',
type: 'line',
data: list.value[activeTab.value].modOutList
.filter((k: any) => k.phasicType == 'C')
.map((k: any) => [k.time, k.data == 3.14159 ? null : k.data, 'A', lineStyle[1].type]),
smooth: true, //让线变得平滑
symbol: 'none',
color: '#A52a2a',
lineStyle: lineStyle[1],
yAxisIndex: 0
}
)
}
}
if (dataType.value.includes(2)) {
let [temperatureMin, temperatureMax] = yMethod(
list.value[activeTab.value].temperatureList.map(k => (k.data == 3.14159 ? 0 : k.data))
)
echartsData.value.yAxis[flag ? 1 : 0] = {
name: '℃',
yAxisIndex: flag ? 1 : 0,
splitNumber: 5,
max: temperatureMax,
min: temperatureMin,
minInterval: 1
}
echartsData.value.options.series.push({
name: '温度',
type: 'line',
data: list.value[activeTab.value].temperatureList.map((k: any) => [
k.time,
k.data == 3.14159 ? null : k.data,
'℃',
lineStyle[2].type
]),
smooth: true, //让线变得平滑
symbol: 'none',
color: '#DAA520',
lineStyle: lineStyle[2],
yAxisIndex: flag ? 1 : 0
})
}
key.value += 1
}
function renderItem(params, api) {
var categoryIndex = api.value(0)
var start = api.coord([api.value(1), categoryIndex])
var end = api.coord([api.value(2), categoryIndex])
var height = api.size([0, 1])[1] * 0.9
var rectShape = echarts.graphic.clipRectByRect(
{
x: start[0],
y: start[1] - height,
width: end[0] - start[0],
height: height
},
{
x: params.coordSys.x,
y: params.coordSys.y,
width: params.coordSys.width,
height: params.coordSys.height - 50
}
)
return (
rectShape && {
type: 'rect',
shape: rectShape,
style: api.style()
}
)
}
// 三角形标记渲染函数
function renderMarker(params, api) {
var point = api.coord([api.value(0), 0])
var symbolSize = 8
var offsetY = 40
// 计算三角形的三个点坐标
var points = [
[point[0], point[1] - symbolSize - offsetY], // 上顶点
[point[0] - symbolSize, point[1] + symbolSize - offsetY], // 左下顶点
[point[0] + symbolSize, point[1] + symbolSize - offsetY] // 右下顶点
]
return {
type: 'polygon',
shape: {
points: points
},
style: {
fill: api.value(2),
stroke: '#fff',
lineWidth: 1
},
label: {
position: [point[0] + symbolSize + 5, point[1]],
formatter: api.value(1),
fontSize: 12
}
}
}
const getModule = async (id: string) => {
loadingLeft.value = true
await getModuleState({ id: id }).then(res => {
res.data.forEach((item: any) => {
list.value.forEach((k: any) => {
if (k.moduleName === item.moduleName) {
k.moduleState = item.moduleState
}
})
})
ElMessage.success('刷新成功')
})
loadingLeft.value = false
}
const changeTab = (e: any) => {
echartList.value = list.value[e]
activeTab.value = e
changeDataType()
}
const getType = (type: string) => {
switch (type) {
case '运行':
return 'success'
case '离线':
return 'danger'
default:
return 'warning'
}
}
defineExpose({ setData, getModule })
onBeforeUnmount(() => {
echarts.disconnect('group')
})
</script>
<style lang="scss" scoped>
.container {
margin: 10px 10px 0 10px;
background-color: white;
border-radius: 0.5rem;
// box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
overflow: hidden;
}
.tabs-container {
display: flex;
flex-direction: column;
height: 100%;
}
@media (min-width: 768px) {
.tabs-container {
flex-direction: row;
}
}
.tab-list {
width: 100%;
border-bottom: 1px solid #e2e8f0;
background-color: #f8fafc;
}
@media (min-width: 768px) {
.tab-list {
width: 140px;
border-right: 1px solid #e2e8f0;
border-bottom: none;
}
}
.tab-button {
display: flex;
align-items: center;
width: 100%;
padding: 15px 20px;
text-align: left;
border: none;
background: none;
cursor: pointer;
font-size: 14px;
color: #64748b;
border-right: 4px solid transparent;
transition: all 0.2s ease;
}
.tab-button:hover {
background-color: #f1f5f9;
color: #475569;
}
.tab-button.active {
background-color: #e2e8f0;
color: #000;
border-right-color: var(--el-color-primary);
font-weight: 700;
}
.tab-button i {
width: 1.25rem;
margin-right: 0.75rem;
}
.tab-content-container {
flex: 1;
padding: 0 10px;
}
.select {
position: absolute;
top: 7px;
left: 150px;
}
</style>

View File

@@ -1,273 +1,281 @@
<template> <template>
<TableHeader ref="refheader" :showSearch="false"> <TableHeader ref="refheader" :showSearch="false">
<template #select> <template #select>
<el-form-item label="日期"> <el-form-item label="日期">
<DatePicker ref="datePickerRef"></DatePicker> <DatePicker ref="datePickerRef"></DatePicker>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-checkbox-group style="width: 150px" v-model.trim="checkList"> <el-checkbox-group style="width: 150px" v-model.trim="checkList">
<el-checkbox label="稳态" :value="0" /> <el-checkbox label="稳态" :value="0" />
<el-checkbox label="暂态" :value="1" /> <el-checkbox label="暂态" :value="1" />
</el-checkbox-group> </el-checkbox-group>
</el-form-item> </el-form-item>
</template> </template>
<template #operation> <template #operation>
<el-button type="primary" :icon="Search" @click="handleSearch">查询</el-button> <el-button type="primary" :icon="Search" @click="handleSearch">查询</el-button>
<el-button type="primary" :icon="Setting" @click="handleUpDevice">补召</el-button> <el-button type="primary" :icon="Setting" @click="handleUpDevice">补召</el-button>
<el-button :icon="Back" @click="go(-1)">返回</el-button> <el-button :icon="Back" @click="go(-1)">返回</el-button>
</template> </template>
</TableHeader> </TableHeader>
<!-- 设备补召 --> <!-- 设备补召 -->
<div class=" current_device" v-loading="loading"> <div class=" current_device" v-loading="loading">
<div class="current_body" ref="tbodyRef"> <div class="current_body" ref="tbodyRef">
<vxe-table border ref="tableRef" :data="dirList" align="center" height="auto" <vxe-table border ref="tableRef" :data="dirList" align="center" height="auto"
:style="{ height: tableHeight }" @radio-change="radioChangeEvent"> :style="{ height: tableHeight }" @radio-change="radioChangeEvent">
<vxe-column type="radio" width="60"> <vxe-column type="radio" width="60">
<template #header> <template #header>
<vxe-button mode="text" @click="clearRadioRowEvent" :disabled="!selectRow">取消</vxe-button> <vxe-button mode="text" @click="clearRadioRowEvent" :disabled="!selectRow">取消</vxe-button>
</template> </template>
</vxe-column> </vxe-column>
<!-- <vxe-column type="checkbox" width="60"></vxe-column> --> <!-- <vxe-column type="checkbox" width="60"></vxe-column> -->
<vxe-column field="name" title="名称"></vxe-column> <vxe-column field="name" title="名称"></vxe-column>
<vxe-column field="status" title="补召进度"> <vxe-column field="status" title="补召进度">
<template #default="{ row }"> <template #default="{ row }">
<div class="finish" v-if="row.status == 100"> <div class="finish" v-if="row.status == 100">
<SuccessFilled style="width: 16px;" /><span class="ml5">补召完成</span> <SuccessFilled style="width: 16px;" /><span class="ml5">补召完成</span>
</div> </div>
<el-progress v-model.trim="row.status" v-else :class="row.status == 100 ? 'progress' : ''" <el-progress v-model.trim="row.status" v-else :class="row.status == 100 ? 'progress' : ''"
:format="format" :stroke-width="10" striped :percentage="row.status" :duration="30" :format="format" :stroke-width="10" striped :percentage="row.status" :duration="30"
striped-flow /> striped-flow />
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="startTime" title="起始时间"></vxe-column> <vxe-column field="startTime" title="起始时间"></vxe-column>
<vxe-column field="endTime" title="结束时间"></vxe-column> <vxe-column field="endTime" title="结束时间"></vxe-column>
</vxe-table> </vxe-table>
</div> </div>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, onMounted, defineExpose, onBeforeUnmount, inject } from 'vue' import { ref, onMounted, defineExpose, onBeforeUnmount, inject } from 'vue'
import { getMakeUpData, getAskDirOrFile, offlineDataUploadMakeUp } from '@/api/cs-harmonic-boot/recruitment.ts' import { getMakeUpData, getAskDirOrFile, offlineDataUploadMakeUp } from '@/api/cs-harmonic-boot/recruitment.ts'
import DatePicker from '@/components/form/datePicker/index.vue' import DatePicker from '@/components/form/datePicker/index.vue'
import TableHeader from '@/components/table/header/index.vue' import TableHeader from '@/components/table/header/index.vue'
import { useRouter, useRoute } from 'vue-router' import { useRouter, useRoute } from 'vue-router'
import { mainHeight } from '@/utils/layout' import { mainHeight } from '@/utils/layout'
import { VxeUI, VxeTableInstance, VxeTableEvents } from 'vxe-table' import { VxeUI, VxeTableInstance, VxeTableEvents } from 'vxe-table'
import { SuccessFilled } from '@element-plus/icons-vue' import { SuccessFilled } from '@element-plus/icons-vue'
import { import {
Back, Back,
Setting, Search Setting, Search
} from '@element-plus/icons-vue' } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import mqtt from 'mqtt' import mqtt from 'mqtt'
defineOptions({ defineOptions({
name: 'supplementaryRecruitment' name: 'supplementaryRecruitment'
}) })
const checkList: any = ref([]) const checkList: any = ref([])
// const props = defineProps(['lineId']) // const props = defineProps(['lineId'])
const { go } = useRouter() // 路由 const { go } = useRouter() // 路由
const selectRow: any = ref(null) const selectRow: any = ref(null)
const loading = ref(false) const loading = ref(false)
const dirList = ref([]) const dirList = ref([])
const route: any = ref({}) const route: any = ref({})
const datePickerRef = ref() const datePickerRef = ref()
const format = (percentage) => (percentage === 100 ? '完成' : `${percentage}%`) const format = (percentage) => (percentage === 100 ? '完成' : `${percentage}%`)
const getMakeUpDataList = (row: any) => { const getMakeUpDataList = (row: any) => {
route.value = row route.value = row
loading.value = true loading.value = true
getMakeUpData(row.id).then(res => { getMakeUpData(row.id).then(res => {
res.data.map((item: any) => { res.data.map((item: any) => {
item.name = item.prjName item.name = item.prjName
? item.prjDataPath.replace('/bd0/cmn/', item.prjName + '-') ? item.prjDataPath.replace('/bd0/cmn/', item.prjName + '-')
: item.prjDataPath.replace('/bd0/cmn/', '') : item.prjDataPath.replace('/bd0/cmn/', '')
item.startTime = item.startTime ? item.startTime : '/' item.startTime = item.startTime ? item.startTime : '/'
item.endTime = item.endTime ? item.endTime : '/' item.endTime = item.endTime ? item.endTime : '/'
item.status = 0 item.status = 0
}) })
dirList.value = res.data dirList.value = res.data
loading.value = false loading.value = false
}) })
} }
// 进入文件夹 // 进入文件夹
const dirCheckedList: any = ref([]) const dirCheckedList: any = ref([])
const tbodyRef = ref() const tbodyRef = ref()
const tableHeight = mainHeight(85).height const tableHeight = mainHeight(85).height
const routes = useRoute() const routes = useRoute()
const tableRef = ref() const tableRef = ref()
const selectRowCopy: any = ref(null) const selectRowCopy: any = ref(null)
const handleUpDevice = () => { const handleUpDevice = () => {
let proList = tableRef.value.getCheckboxRecords().map((item: any) => { let proList = tableRef.value.getCheckboxRecords().map((item: any) => {
return item.prjDataPath return item.prjDataPath
}) })
if (checkList.value.length == 0) { if (checkList.value.length == 0) {
return ElMessage.warning('请选择暂态稳态') return ElMessage.warning('请选择暂态稳态')
} }
if (selectRow.value == null) { if (selectRow.value == null) {
return ElMessage.warning('请选择工程') return ElMessage.warning('请选择工程')
} }
selectRowCopy.value = JSON.parse(JSON.stringify(selectRow.value)) selectRowCopy.value = JSON.parse(JSON.stringify(selectRow.value))
let form = { let form = {
dataTypeList: checkList.value, dataTypeList: checkList.value,
startTime: datePickerRef.value && datePickerRef.value.timeValue[0], startTime: datePickerRef.value && datePickerRef.value.timeValue[0],
endTime: datePickerRef.value && datePickerRef.value.timeValue[1], endTime: datePickerRef.value && datePickerRef.value.timeValue[1],
lineId: routes.query.id, lineId: routes.query.id,
ndid: routes.query.ndid, ndid: routes.query.ndid,
proList: [selectRow.value?.prjDataPath] proList: [selectRow.value?.prjDataPath]
} }
ElMessage.warning('补召中, 请稍等...') ElMessage.warning('补召中, 请稍等...')
offlineDataUploadMakeUp(form) offlineDataUploadMakeUp(form)
.then((res: any) => { .then((res: any) => {
if (res.code == 'A0000') { if (res.code == 'A0000') {
// ElMessage.success(res.data) // ElMessage.success(res.data)
dirList.value.map((item: any) => { dirList.value.map((item: any) => {
// checkedList.map((vv: any) => { // checkedList.map((vv: any) => {
if (item.name == selectRowCopy.value?.name) { if (item.name == selectRowCopy.value?.name) {
item.status = 5 item.status = 5
} }
// }) // })
}) })
// loading.value = false // loading.value = false
} }
}) })
.catch(() => { .catch(() => {
// loading.value = false // loading.value = false
}) })
} }
const radioChangeEvent: VxeTableEvents.RadioChange = ({ row }) => { const radioChangeEvent: VxeTableEvents.RadioChange = ({ row }) => {
selectRow.value = row selectRow.value = row
// console.log('单选事件') // console.log('单选事件')
} }
const clearRadioRowEvent = () => { const clearRadioRowEvent = () => {
const $table = tableRef.value const $table = tableRef.value
if ($table) { if ($table) {
selectRow.value = null selectRow.value = null
$table.clearRadioRow() $table.clearRadioRow()
} }
} }
const mqttRef = ref() const mqttRef = ref()
const url: any = window.localStorage.getItem('MQTTURL') const url: any = window.localStorage.getItem('MQTTURL')
const connectMqtt = () => { const connectMqtt = () => {
if (mqttRef.value) { if (mqttRef.value) {
if (mqttRef.value.connected) { if (mqttRef.value.connected) {
return return
} }
} }
const options = { const options = {
protocolId: 'MQTT', protocolId: 'MQTT',
qos: 2, qos: 2,
clean: true, clean: true,
connectTimeout: 30 * 1000, connectTimeout: 30 * 1000,
clientId: 'mqttjs' + Math.random(), clientId: 'mqttjs' + Math.random(),
username: 't_user', username: 't_user',
password: 'njcnpqs' password: 'njcnpqs'
} }
mqttRef.value = mqtt.connect(url, options) mqttRef.value = mqtt.connect(url, options)
} }
const handleSearch = () => { const handleSearch = () => {
getMakeUpDataList(route.value) getMakeUpDataList(route.value)
} }
connectMqtt() function parseStringToObject(str:string) {
mqttRef.value.on('connect', () => { const content = str.replace(/^{|}$/g, '')
// ElMessage.success('连接mqtt服务器成功!') const pairs = content.split(',')
console.log('mqtt客户端已连接....') const result:any = {}
// mqttRef.value.subscribe('/Web/Progress') pairs.forEach(pair => {
// mqttRef.value.subscribe('/Web/Progress/+') const [key, value] = pair.split(':')
mqttRef.value.subscribe('/dataOnlineRecruitment/Progress/' + route.value.id) // 尝试将数字转换为Number类型
}) result[key.trim()] = isNaN(Number(value)) ? value.trim() : Number(value)
const mqttMessage = ref<any>({}) })
mqttRef.value.on('message', (topic: any, message: any) => { return result
// console.log('mqtt接收到消息', JSON.parse(JSON.stringify(JSON.parse(new TextDecoder().decode(message))))) }
loading.value = false connectMqtt()
let str = JSON.parse(JSON.stringify(JSON.parse(new TextDecoder().decode(message)))) mqttRef.value.on('connect', () => {
let regex1 = /allStep:(.*?),nowStep/ // ElMessage.success('连接mqtt服务器成功!')
let regex2 = /nowStep:(.*?)}/ console.log('mqtt客户端已连接....')
mqttMessage.value = { // mqttRef.value.subscribe('/Web/Progress')
allStep: str.match(regex1)[1], // mqttRef.value.subscribe('/Web/Progress/+')
nowStep: str.match(regex2)[1] mqttRef.value.subscribe('/dataOnlineRecruitment/Progress/' + route.value.id)
} })
// console.log(mqttMessage.value) const mqttMessage = ref<any>({})
let checkedList = tableRef.value.getCheckboxRecords().map((item: any) => { mqttRef.value.on('message', (topic: any, message: any) => {
return item.name // console.log('mqtt接收到消息', JSON.parse(JSON.stringify(JSON.parse(new TextDecoder().decode(message)))))
}) loading.value = false
dirList.value.map((item: any) => { let str = JSON.parse(JSON.stringify(JSON.parse(new TextDecoder().decode(message))))
// checkedList.map((vv: any) => { let regex1 = /allStep:(.*?),nowStep/
if (item.name == selectRowCopy.value?.name) { let regex2 = /nowStep:(.*?)}/
let percentage = parseInt(Number((mqttMessage.value.nowStep / mqttMessage.value.allStep) * 100)) || 0 mqttMessage.value = parseStringToObject(str)
if (percentage > 5) { // console.log(mqttMessage.value)
item.status = percentage let checkedList = tableRef.value.getCheckboxRecords().map((item: any) => {
return item.name
} })
} dirList.value.map((item: any) => {
// }) // checkedList.map((vv: any) => {
}) if (item.name == selectRowCopy.value?.name) {
}) let percentage = parseInt(Number((mqttMessage.value.nowStep / mqttMessage.value.allStep) * 100)) || 0
if (percentage > 5) {
mqttRef.value.on('error', (error: any) => { item.status = percentage
console.log('mqtt连接失败...', error)
mqttRef.value.end() }
}) }
// })
mqttRef.value.on('close', function () { })
console.log('mqtt客户端已断开连接.....') })
})
onMounted(() => { mqttRef.value.on('error', (error: any) => {
}) console.log('mqtt连接失败...', error)
onBeforeUnmount(() => { mqttRef.value.end()
if (mqttRef.value) { })
mqttRef.value.end()
} mqttRef.value.on('close', function () {
}) console.log('mqtt客户端已断开连接.....')
defineExpose({ getMakeUpDataList }) })
</script> onMounted(() => {
<style lang="scss" scoped> })
// .current_device { onBeforeUnmount(() => {
// width: 100%; if (mqttRef.value) {
mqttRef.value.end()
// display: flex; }
// flex-direction: column; })
defineExpose({ getMakeUpDataList })
// .current_header { </script>
// width: 100%; <style lang="scss" scoped>
// height: 60px; // .current_device {
// padding: 15px; // width: 100%;
// display: flex;
// align-items: center; // display: flex;
// box-sizing: border-box; // flex-direction: column;
// .el-form-item { // .current_header {
// display: flex; // width: 100%;
// align-items: center; // height: 60px;
// margin-bottom: 0; // padding: 15px;
// } // display: flex;
// } // align-items: center;
// box-sizing: border-box;
// .current_body {
// flex: 1; // .el-form-item {
// } // display: flex;
// } // align-items: center;
:deep(.el-progress-bar__inner--striped) { // margin-bottom: 0;
background-image: linear-gradient(45deg, rgba(255, 255, 255, .3) 25%, transparent 0, transparent 50%, rgba(255, 255, 255, .3) 0, rgba(255, 255, 255, .3) 75%, transparent 0, transparent); // }
// }
}
// .current_body {
:deep(.progress) { // flex: 1;
.el-progress__text { // }
color: green; // }
:deep(.el-progress-bar__inner--striped) {
} background-image: linear-gradient(45deg, rgba(255, 255, 255, .3) 25%, transparent 0, transparent 50%, rgba(255, 255, 255, .3) 0, rgba(255, 255, 255, .3) 75%, transparent 0, transparent);
}
}
.finish {
display: flex; :deep(.progress) {
justify-content: center; .el-progress__text {
font-weight: 550; color: green;
color: #009688
} }
</style> }
.finish {
display: flex;
justify-content: center;
font-weight: 550;
color: #009688
}
</style>

View File

@@ -210,7 +210,7 @@ const tableStore = new TableStore({
return row.cellValue === 'MQTT' ? 'MQTT' : row.cellValue === 'cloud' ? 'CLD' : row.cellValue return row.cellValue === 'MQTT' ? 'MQTT' : row.cellValue === 'cloud' ? 'CLD' : row.cellValue
} }
}, },
{ title: '录入时间', field: 'createTime' }, { title: '录入时间', field: 'createTime', sortable: true },
{ title: '网络设备ID', field: 'ndid' }, { title: '网络设备ID', field: 'ndid' },
{ {
title: '状态', title: '状态',

View File

@@ -40,7 +40,7 @@ const tableStore: any = new TableStore({
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: 'startTime', title: '发生时刻', minWidth: 170 }, { field: 'startTime', title: '发生时刻', minWidth: 170, sortable: true },
{ field: 'showName', title: '事件描述', minWidth: 170 }, { field: 'showName', title: '事件描述', minWidth: 170 },
{ {
field: 'phaseType', field: 'phaseType',
@@ -58,7 +58,7 @@ const tableStore: any = new TableStore({
formatter: (row: any) => { formatter: (row: any) => {
row.cellValue = row.cellValue ? row.cellValue.toFixed(2) : '/' row.cellValue = row.cellValue ? row.cellValue.toFixed(2) : '/'
return row.cellValue return row.cellValue
} }, sortable: true
}, },
{ {
field: 'featureAmplitude', field: 'featureAmplitude',

View File

@@ -273,21 +273,21 @@ const initRadioCharts = () => {
value: 0, value: 0,
name: 'A相', name: 'A相',
itemStyle: { itemStyle: {
color: '#FFCC00' color: '#DAA520'
} }
}, },
{ {
value: 0, value: 0,
name: 'B相', name: 'B相',
itemStyle: { itemStyle: {
color: '#009900' color: '#2E8B57'
} }
}, },
{ {
value: 0, value: 0,
name: 'C相', name: 'C相',
itemStyle: { itemStyle: {
color: '#CC0000' color: '#A52a2a'
} }
} }
] ]
@@ -373,21 +373,21 @@ const initRadioCharts = () => {
value: 0, value: 0,
name: 'A相', name: 'A相',
itemStyle: { itemStyle: {
color: '#FFCC00' color: '#DAA520'
} }
}, },
{ {
value: 0, value: 0,
name: 'B相', name: 'B相',
itemStyle: { itemStyle: {
color: '#009900' color: '#2E8B57'
} }
}, },
{ {
value: 0, value: 0,
name: 'C相', name: 'C相',
itemStyle: { itemStyle: {
color: '#CC0000' color: '#A52a2a'
} }
} }
] ]

View File

@@ -341,7 +341,7 @@ const init = async () => {
return str return str
} }
}, },
color: ['#FFCC00', '#009900', '#CC0000', ...color], color: ['#DAA520', '#2E8B57', '#A52a2a', ...color],
xAxis: { xAxis: {
type: 'time', type: 'time',
axisLabel: { axisLabel: {
@@ -461,7 +461,7 @@ const init = async () => {
: kk[0].anotherName, : kk[0].anotherName,
type: 'line', type: 'line',
smooth: true, smooth: true,
color: colorName == 'A' ? '#FFCC00' : colorName == 'B' ? '#009900' : colorName == 'C' ? '#CC0000' : '', color: colorName == 'A' ? '#DAA520' : colorName == 'B' ? '#2E8B57' : colorName == 'C' ? '#A52a2a' : '',
symbol: 'none', symbol: 'none',
data: seriesList, data: seriesList,
lineStyle: lineStyle[lineS], lineStyle: lineStyle[lineS],

File diff suppressed because it is too large Load Diff

View File

@@ -44,7 +44,7 @@ const tableStore = new TableStore({
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: 'startTime', title: '发生时刻', minWidth: 170 }, { field: 'startTime', title: '发生时刻', minWidth: 170, sortable: true },
{ field: 'showName', title: '事件描述', minWidth: 170 }, { field: 'showName', title: '事件描述', minWidth: 170 },
{ {
field: 'phaseType', field: 'phaseType',
@@ -62,7 +62,7 @@ const tableStore = new TableStore({
formatter: (row: any) => { formatter: (row: any) => {
row.cellValue = row.cellValue ? row.cellValue.toFixed(2) : '/' row.cellValue = row.cellValue ? row.cellValue.toFixed(2) : '/'
return row.cellValue return row.cellValue
} }, sortable: true
}, },
{ {
field: 'featureAmplitude', field: 'featureAmplitude',
@@ -74,7 +74,7 @@ const tableStore = new TableStore({
row.cellValue = String(row.cellValue).split('.')[0] row.cellValue = String(row.cellValue).split('.')[0]
} }
return row.cellValue return row.cellValue
} }, sortable: true
}, },
{ {
title: '操作', title: '操作',

View File

@@ -431,7 +431,7 @@ const refreshTree = () => {
const range = (start: any, end: any, step: any) => { const range = (start: any, end: any, step: any) => {
return Array.from({ length: (end - start) / step + 1 }, (_, i) => start + i * step) return Array.from({ length: (end - start) / step + 1 }, (_, i) => start + i * step)
} }
const colors = ['#FFCC00', '#009900', '#CC0000'] const colors = ['#DAA520', '#2E8B57', '#A52a2a']
const lineStyle = [{ type: 'solid', }, { type: 'dashed', }, { type: 'dotted', }] const lineStyle = [{ type: 'solid', }, { type: 'dashed', }, { type: 'dotted', }]
const titleList: any = ref('') const titleList: any = ref('')
@@ -627,7 +627,7 @@ const init = (flag: boolean) => {
return str return str
} }
}, },
// color: ['#FFCC00', '#009900', '#CC0000', ...color], // color: ['#DAA520', '#2E8B57', '#A52a2a', ...color],
xAxis: { xAxis: {
type: 'time', type: 'time',
axisLabel: { axisLabel: {
@@ -714,7 +714,7 @@ const init = (flag: boolean) => {
? kk[0].phase + '相' + kk[0].anotherName ? kk[0].phase + '相' + kk[0].anotherName
: kk[0].anotherName, : kk[0].anotherName,
type: 'line', type: 'line',
color: colorName == 'A' ? '#FFCC00' : colorName == 'B' ? '#009900' : colorName == 'C' ? '#CC0000' : '', color: colorName == 'A' ? '#DAA520' : colorName == 'B' ? '#2E8B57' : colorName == 'C' ? '#A52a2a' : '',
smooth: true, smooth: true,
symbol: 'none', symbol: 'none',
lineStyle: lineStyle[lineS], lineStyle: lineStyle[lineS],

View File

@@ -32,8 +32,8 @@ const tableStore = new TableStore({
return row.cellValue == 1 ? '设备登记' : row.cellValue == 2 ? '功能调试' : row.cellValue == 3 ? '出厂调试' : row.cellValue == 4 ? '设备投运' : '' return row.cellValue == 1 ? '设备登记' : row.cellValue == 2 ? '功能调试' : row.cellValue == 3 ? '出厂调试' : row.cellValue == 4 ? '设备投运' : ''
} }
}, },
{ title: '开始时间', field: 'startTime', align: 'center' }, { title: '开始时间', field: 'startTime', align: 'center', sortable: true },
{ title: '结束时间', field: 'endTime', align: 'center' } { title: '结束时间', field: 'endTime', align: 'center', sortable: true }
], ],
loadCallback: () => { loadCallback: () => {

View File

@@ -18,10 +18,10 @@ const tableStore = new TableStore({
url: '/cs-device-boot/cslog/queryLog', url: '/cs-device-boot/cslog/queryLog',
method: 'POST', method: 'POST',
column: [ column: [
{ title: '操作日期', field: 'createTime', align: 'center' }, { title: '操作日期', field: 'createTime', align: 'center', sortable: true },
{ title: '操作描述', field: 'operate', align: 'center', width: '300' }, { title: '操作描述', field: 'operate', align: 'center', width: '300' },
{ title: '用户名称', field: 'userName', align: 'center' }, { title: '用户名称', field: 'userName', align: 'center' },
{ title: '更新时间', field: 'updateTime', align: 'center' }, { title: '更新时间', field: 'updateTime', align: 'center', sortable: true },
{ title: '失败原因', field: 'failReason', align: 'center' }, { title: '失败原因', field: 'failReason', align: 'center' },
{ title: '状态', field: 'result', align: 'center' }, { title: '状态', field: 'result', align: 'center' },
{ title: '登录名', field: 'loginName', align: 'center' } { title: '登录名', field: 'loginName', align: 'center' }

View File

@@ -20,7 +20,7 @@ const tableStore = new TableStore({
column: [ column: [
{ title: '推送用户', field: 'userName', align: 'center' }, { title: '推送用户', field: 'userName', align: 'center' },
{ title: '推送内容', field: 'showName', align: 'center' }, { title: '推送内容', field: 'showName', align: 'center' },
{ title: '推送时间', field: 'sendTime', align: 'center' }, { title: '推送时间', field: 'sendTime', align: 'center', sortable: true },
] ]
}) })

View File

@@ -61,6 +61,7 @@ const tableStore = new TableStore({
{ title: '数据名称', field: 'name', minWidth: 220 }, { title: '数据名称', field: 'name', minWidth: 220 },
{ title: '别名', field: 'otherName', minWidth: 220 }, { title: '别名', field: 'otherName', minWidth: 220 },
{ title: '展示名称', field: 'showName', minWidth: 170 }, { title: '展示名称', field: 'showName', minWidth: 170 },
{ title: '告警码', field: 'defaultValue', minWidth: 170 },
{ title: '相别', field: 'phaseName', minWidth: 80 }, { title: '相别', field: 'phaseName', minWidth: 80 },
{ title: '单位', field: 'unit', minWidth: 80 }, { title: '单位', field: 'unit', minWidth: 80 },
{ title: '基础数据类型', field: 'type', minWidth: 170 }, { title: '基础数据类型', field: 'type', minWidth: 170 },

View File

@@ -82,52 +82,52 @@
<el-divider content-position="center">拓展数据</el-divider> <el-divider content-position="center">拓展数据</el-divider>
</div> </div>
<el-form class="form-two" :model="form" label-width="140px" ref="formRef2" :rules="rules"> <el-form class="form-two" :model="form" label-width="140px" ref="formRef2" :rules="rules">
<el-form-item label="参数缺省值:" prop="defaultValue"> <el-form-item label="告警码(缺省值):" >
<el-input maxlength="32" show-word-limit v-model.trim="form.defaultValue" autocomplete="off" <el-input maxlength="32" show-word-limit v-model.trim="form.defaultValue" autocomplete="off"
placeholder="请输入参数缺省值"></el-input> placeholder="请输入告警码(缺省值)"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="事件类别:" prop="eventType"> <el-form-item label="事件类别:" >
<el-input maxlength="32" show-word-limit v-model.trim="form.eventType" autocomplete="off" <el-input maxlength="32" show-word-limit v-model.trim="form.eventType" autocomplete="off"
placeholder="请输入事件类别"></el-input> placeholder="请输入事件类别"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="设置最大值:" prop="maxNum"> <el-form-item label="设置最大值:" >
<el-input maxlength="32" show-word-limit type="number" v-model.trim="form.maxNum" autocomplete="off" <el-input maxlength="32" show-word-limit type="number" v-model.trim="form.maxNum" autocomplete="off"
placeholder="请输入设置最大值"></el-input> placeholder="请输入设置最大值"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="设置最小值:" prop="minNum"> <el-form-item label="设置最小值:" >
<el-input maxlength="32" show-word-limit type="number" v-model.trim="form.minNum" autocomplete="off" <el-input maxlength="32" show-word-limit type="number" v-model.trim="form.minNum" autocomplete="off"
placeholder="请输入设置最小值"></el-input> placeholder="请输入设置最小值"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="枚举序列:" prop="setValue"> <el-form-item label="枚举序列:">
<el-input maxlength="32" show-word-limit v-model.trim="form.setValue" autocomplete="off" <el-input maxlength="32" show-word-limit v-model.trim="form.setValue" autocomplete="off"
placeholder="请输入枚举序列"></el-input> placeholder="请输入枚举序列"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="字符串长度上限:" prop="strlen"> <el-form-item label="字符串长度上限:" >
<el-input maxlength="32" show-word-limit type="number" v-model.trim="form.strlen" autocomplete="off" <el-input maxlength="32" show-word-limit type="number" v-model.trim="form.strlen" autocomplete="off"
placeholder="请输入字符串长度上限"></el-input> placeholder="请输入字符串长度上限"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="上送规则:" prop="tranRule"> <el-form-item label="上送规则:" >
<el-input maxlength="32" show-word-limit v-model.trim="form.tranRule" autocomplete="off" <el-input maxlength="32" show-word-limit v-model.trim="form.tranRule" autocomplete="off"
placeholder="请输入上送规则"></el-input> placeholder="请输入上送规则"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="是否可远程控制:" prop="ctlSts"> <el-form-item label="是否可远程控制:" >
<el-radio v-model.trim="form.ctlSts" :label="1"></el-radio> <el-radio v-model.trim="form.ctlSts" :label="1"></el-radio>
<el-radio v-model.trim="form.ctlSts" :label="0"></el-radio> <el-radio v-model.trim="form.ctlSts" :label="0"></el-radio>
</el-form-item> </el-form-item>
<el-form-item label="是否需遥控校验:" prop="curSts"> <el-form-item label="是否需遥控校验:" >
<el-radio v-model.trim="form.curSts" :label="1"></el-radio> <el-radio v-model.trim="form.curSts" :label="1"></el-radio>
<el-radio v-model.trim="form.curSts" :label="0"></el-radio> <el-radio v-model.trim="form.curSts" :label="0"></el-radio>
</el-form-item> </el-form-item>
<el-form-item label="是否存储:" prop="storeFlag"> <el-form-item label="是否存储:" >
<el-radio v-model.trim="form.storeFlag" :label="1"></el-radio> <el-radio v-model.trim="form.storeFlag" :label="1"></el-radio>
<el-radio v-model.trim="form.storeFlag" :label="0"></el-radio> <el-radio v-model.trim="form.storeFlag" :label="0"></el-radio>
</el-form-item> </el-form-item>
<el-form-item label="是否加密:" prop="storeFlag"> <el-form-item label="是否加密:" >
<el-radio v-model.trim="form.storeFlag" :label="1"></el-radio> <el-radio v-model.trim="form.storeFlag" :label="1"></el-radio>
<el-radio v-model.trim="form.storeFlag" :label="0"></el-radio> <el-radio v-model.trim="form.storeFlag" :label="0"></el-radio>
</el-form-item> </el-form-item>
<el-form-item label="数据是否上送:" prop="tranFlag"> <el-form-item label="数据是否上送:" >
<el-radio v-model.trim="form.tranFlag" :label="1"></el-radio> <el-radio v-model.trim="form.tranFlag" :label="1"></el-radio>
<el-radio v-model.trim="form.tranFlag" :label="0"></el-radio> <el-radio v-model.trim="form.tranFlag" :label="0"></el-radio>
</el-form-item> </el-form-item>

View File

@@ -51,7 +51,7 @@ const tableStore = new TableStore({
{ title: '装置型号', field: 'devTypeName' }, { title: '装置型号', field: 'devTypeName' },
{ title: '模板名称', field: 'name' }, { title: '模板名称', field: 'name' },
{ title: '版本号', field: 'versionNo' }, { title: '版本号', field: 'versionNo' },
{ title: '版本时间', field: 'versionDate' }, { title: '版本时间', field: 'versionDate', sortable: true },
{ {
title: '操作', title: '操作',
align: 'center', align: 'center',

View File

@@ -1,8 +1,15 @@
<template> <template>
<div class="default-main" :style="{ height: pageHeight.height }"> <div class="default-main" :style="{ height: pageHeight.height }">
<vxe-table v-loading="tableStore.table.loading" height="auto" auto-resize ref="tableRef" <vxe-table
v-bind="defaultAttribute" :data="tableStore.table.data" :column-config="{ resizable: true }" v-loading="tableStore.table.loading"
:tree-config="{ expandAll: true }"> height="auto"
auto-resize
ref="tableRef"
v-bind="defaultAttribute"
:data="tableStore.table.data"
:column-config="{ resizable: true }"
:tree-config="{ expandAll: true }"
>
<vxe-column field="name" align="left" title="名称" tree-node></vxe-column> <vxe-column field="name" align="left" title="名称" tree-node></vxe-column>
<vxe-column field="area" title="区域"> <vxe-column field="area" title="区域">
<template #default="{ row }"> <template #default="{ row }">
@@ -14,9 +21,16 @@
{{ row.remark || '/' }} {{ row.remark || '/' }}
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="remark" title="操作" width="100px"> <vxe-column field="remark" title="操作" width="150px">
<template #default="{ row }"> <template #default="{ row }">
<el-popconfirm title="确定删除吗?" confirm-button-type='danger' @confirm="deletes(row)" v-if="!row.path"> <el-button type="primary" link @click="edit(row)" v-if="!row.path">编辑</el-button>
<el-popconfirm
title="确定删除吗?"
confirm-button-type="danger"
@confirm="deletes(row)"
v-if="!row.path"
>
<template #reference> <template #reference>
<el-button type="danger" link>删除</el-button> <el-button type="danger" link>删除</el-button>
</template> </template>
@@ -24,21 +38,55 @@
</template> </template>
</vxe-column> </vxe-column>
</vxe-table> </vxe-table>
<el-dialog v-model="dialogVisible" title="编辑" width="500">
<el-form :model="form" ref="ruleFormRef" label-width="80px" :rules="rules">
<el-form-item label="名称" prop="name">
<el-input v-model="form.name" clearable placeholder="请输入名称" />
</el-form-item>
<el-form-item label="区域" :prop="form.pid == '0' ? 'city' : 'area'">
<!-- <el-input v-model="form.city" clearable placeholder="请输入区域" /> -->
<el-cascader
v-model="form.city"
v-if="form.pid == '0'"
style="width: 100%"
:options="areaTree"
:props="props"
clearable
filterable
placeholder="请输入区域"
/>
<el-input v-else v-model="form.area" clearable placeholder="请输入区域" />
</el-form-item>
<el-form-item label="备注" prop="description">
<el-input v-model="form.description" :rows="2" type="textarea" clearable placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="save">保存</el-button>
</div>
</template>
</el-dialog>
</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 { useDictData } from '@/stores/dictData'
import { defaultAttribute } from '@/components/table/defaultAttribute' import { defaultAttribute } from '@/components/table/defaultAttribute'
import { mainHeight } from '@/utils/layout' import { mainHeight } from '@/utils/layout'
import { ElMessageBox, ElMessage } from 'element-plus' import { ElMessageBox, ElMessage } from 'element-plus'
import { auditEngineering } from '@/api/cs-device-boot/edData'; import { auditEngineering, updateProject } from '@/api/cs-device-boot/edData'
import { activateUser, deluser, passwordConfirm } from '@/api/user-boot/user' import { activateUser, deluser, passwordConfirm } from '@/api/user-boot/user'
import tree from '@/assets/map/area.json'
defineOptions({ defineOptions({
name: 'govern/manage/engineering' name: 'govern/manage/engineering'
}) })
const dictData = useDictData()
const tableRef = ref() const tableRef = ref()
const dialogVisible = ref(false)
const pageHeight = mainHeight(20) const pageHeight = mainHeight(20)
const tableStore = new TableStore({ const tableStore = new TableStore({
url: '/cs-device-boot/csLedger/getProjectTree', url: '/cs-device-boot/csLedger/getProjectTree',
@@ -51,7 +99,30 @@ const tableStore = new TableStore({
}, 500) }, 500)
} }
}) })
const ruleFormRef = ref()
const rules = ref({
name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
city: [{ required: true, message: '请输入区域', trigger: 'blur' }],
area: [{ required: true, message: '请输入区域', trigger: 'blur' }],
description: [{ required: true, message: '请输入描述', trigger: 'blur' }]
})
console.log("🚀 ~ dictData.state.areaTree:", dictData.state)
const areaTree: any = tree
const props = {
label: 'text',
value: 'value',
children: 'children',
checkStrictly: true
}
const form = ref({
id: '',
pid: '',
area: '',
name: '',
city: '',
description: ''
})
provide('tableStore', tableStore) provide('tableStore', tableStore)
onMounted(() => { onMounted(() => {
@@ -67,18 +138,16 @@ const deletes = (row: any) => {
customClass: 'customInput', customClass: 'customInput',
inputType: 'text', inputType: 'text',
beforeClose: (action, instance, done) => { beforeClose: (action, instance, done) => {
if (action === 'confirm') { if (action === 'confirm') {
if (instance.inputValue == null) { if (instance.inputValue == null) {
return ElMessage.warning('请输入密码') return ElMessage.warning('请输入密码')
} else if (instance.inputValue?.length > 32) { } else if (instance.inputValue?.length > 32) {
return ElMessage.warning('密码长度不能超过32位,当前密码长度为' + instance.inputValue.length) return ElMessage.warning('密码长度不能超过32位,当前密码长度为' + instance.inputValue.length)
} else { } else {
done(); done()
} }
} else { } else {
done(); done()
} }
} }
}).then(({ value }) => { }).then(({ value }) => {
@@ -92,11 +161,48 @@ const deletes = (row: any) => {
}) })
}) })
}) })
} }
const addMenu = () => { } // 编辑
const edit = (row: any) => {
form.value = {
id: row.id,
pid: row.pid,
name: row.name,
city: row.cityId,
area: row.area,
description: row.remark
}
dialogVisible.value = true
}
const save = () => {
ruleFormRef.value.validate((valid: any) => {
if (valid) {
if (form.value.pid == '0') {
auditEngineering({ ...form.value, city: form.value.city[form.value.city.length - 1] }).then(
(res: any) => {
ElMessage.success('保存成功')
dialogVisible.value = false
tableStore.index()
}
)
} else {
let params = new FormData()
params.append('id', form.value.id)
params.append('area', form.value.area)
params.append('description', form.value.description)
params.append('name', form.value.name)
updateProject(form.value).then((res: any) => {
ElMessage.success('保存成功')
dialogVisible.value = false
tableStore.index()
})
}
}
})
}
</script> </script>
<style lang="scss"> <style lang="scss">
.customInput { .customInput {

View File

@@ -3,11 +3,37 @@
<TableHeader> <TableHeader>
<template v-slot:select> <template v-slot:select>
<el-form-item label="关键字筛选"> <el-form-item label="关键字筛选">
<el-input v-model.trim="tableStore.table.params.searchValue" style="width: 200px" clearable placeholder="请输入设备名称/网络设备ID" /> <el-input
v-model.trim="tableStore.table.params.searchValue"
style="width: 200px"
clearable
placeholder="请输入设备名称/网络设备ID"
/>
</el-form-item> </el-form-item>
<el-form-item label="设备类型"> <el-form-item label="流程阶段">
<!-- <el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.searchValue" placeholder="请输入设备类型" /> --> <el-select v-model.trim="tableStore.table.params.process" clearable placeholder="请选择状态">
<el-option label="功能调试" :value="2"></el-option>
<el-option label="出厂调试" :value="3"></el-option>
<el-option label="正式投运" :value="4"></el-option>
</el-select>
</el-form-item>
<el-form-item label="物联状态">
<el-select
v-model.trim="tableStore.table.params.connectStatus"
clearable
placeholder="请选择物联状态"
>
<el-option label="已连接" :value="1"></el-option>
<el-option label="未连接" :value="0"></el-option>
</el-select>
</el-form-item>
<el-form-item label="设备状态">
<el-select v-model.trim="tableStore.table.params.runStatus" clearable placeholder="请选择状态">
<el-option label="在线" :value="2"></el-option>
<el-option label="离线" :value="1"></el-option>
</el-select>
</el-form-item>
<!-- <el-form-item label="设备类型">
<el-select <el-select
v-model.trim="tableStore.table.params.devType" v-model.trim="tableStore.table.params.devType"
clearable clearable
@@ -46,7 +72,7 @@
<el-option label="MQTT" value="MQTT"></el-option> <el-option label="MQTT" value="MQTT"></el-option>
<el-option label="CLD" value="CLD"></el-option> <el-option label="CLD" value="CLD"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>-->
<!-- <el-form-item label="状态"> <!-- <el-form-item label="状态">
<el-select v-model.trim="tableStore.table.params.status" clearable placeholder="请选择状态"> <el-select v-model.trim="tableStore.table.params.status" clearable placeholder="请选择状态">
<el-option label="未注册" :value="1"></el-option> <el-option label="未注册" :value="1"></el-option>
@@ -76,7 +102,7 @@
class="ml10" class="ml10"
icon="el-icon-Download" icon="el-icon-Download"
@click="downLoadQrCode" @click="downLoadQrCode"
v-if="showQrCode" :disabled="!showQrCode"
> >
批量下载二维码 批量下载二维码
</el-button> </el-button>
@@ -273,6 +299,7 @@ const formDevModelOptionsFilter = computed(() => {
const tableStore = new TableStore({ const tableStore = new TableStore({
url: '/cs-device-boot/EquipmentDelivery/list', url: '/cs-device-boot/EquipmentDelivery/list',
method: 'POST', method: 'POST',
isWebPaging: true,
column: [ column: [
{ {
width: '60', width: '60',
@@ -285,15 +312,16 @@ const tableStore = new TableStore({
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
} }
}, },
{ title: '设备名称', field: 'name' }, { title: '设备名称', field: 'name', minWidth: 120 },
{ title: '网络设备ID', field: 'ndid' }, { title: '网络设备ID', field: 'ndid', minWidth: 120 },
{ {
title: '设备类型', title: '设备类型',
field: 'devType', field: 'devType',
formatter: row => { formatter: row => {
return devTypeOptions.value.find((item: any) => item.value == row.cellValue).label return devTypeOptions.value.find((item: any) => item.value == row.cellValue).label
} },
minWidth: 120
}, },
{ {
@@ -301,16 +329,18 @@ const tableStore = new TableStore({
field: 'devModel', field: 'devModel',
formatter: row => { formatter: row => {
return devModelOptions.value.find((item: any) => item.value == row.cellValue).label return devModelOptions.value.find((item: any) => item.value == row.cellValue).label
} },
minWidth: 120
}, },
{ {
title: '通讯协议', title: '通讯协议',
field: 'devAccessMethod', field: 'devAccessMethod',
formatter: row => { formatter: row => {
return row.cellValue === 'MQTT' ? 'MQTT' : row.cellValue === 'CLD' ? 'CLD' : row.cellValue return row.cellValue === 'MQTT' ? 'MQTT' : row.cellValue === 'CLD' ? 'CLD' : row.cellValue
} },
minWidth: 120
}, },
{ title: '录入时间', field: 'createTime', sortable: true }, { title: '录入时间', field: 'createTime', sortable: true, minWidth: 150 },
{ {
title: '使用状态', title: '使用状态',
@@ -359,7 +389,7 @@ const tableStore = new TableStore({
}, },
// { title: 'MQTT状态', field: 'connectStatus', width: 100, }, // { title: 'MQTT状态', field: 'connectStatus', width: 100, },
{ {
title: 'MQTT状态', title: '物联状态',
field: 'connectStatus', field: 'connectStatus',
width: 100, width: 100,
render: 'tag', render: 'tag',
@@ -370,10 +400,12 @@ const tableStore = new TableStore({
replaceValue: { replaceValue: {
未连接: '未连接', 未连接: '未连接',
已连接: '已连接' 已连接: '已连接'
} },
minWidth: 80
}, },
{ {
title: '通讯状态', title: '设备状态',
field: 'runStatus', field: 'runStatus',
width: 100, width: 100,
render: 'tag', render: 'tag',
@@ -384,13 +416,30 @@ const tableStore = new TableStore({
replaceValue: { replaceValue: {
1: '离线', 1: '离线',
2: '在线' 2: '在线'
} },
minWidth: 80
},
{
title: '流程阶段',
field: 'process',
width: 100,
render: 'tag',
custom: {
2: 'warning',
3: 'warning',
4: 'success'
},
replaceValue: {
2: '功能调试',
3: '出厂调试',
4: '正式投运'
},
minWidth: 80
}, },
{ {
title: '操作', title: '操作',
align: 'center', align: 'center',
width: '220', width: 220,
render: 'buttons', render: 'buttons',
buttons: [ buttons: [
//直连装置注册 //直连装置注册
@@ -647,11 +696,14 @@ const tableStore = new TableStore({
tableStore.table.params.orderBy = 'desc' tableStore.table.params.orderBy = 'desc'
tableStore.table.params.devType = '' tableStore.table.params.devType = ''
tableStore.table.params.devModel = '' tableStore.table.params.devModel = ''
tableStore.table.params.process = 2
tableStore.table.params.devAccessMethod = '' tableStore.table.params.devAccessMethod = ''
tableStore.table.params.status = '' tableStore.table.params.status = ''
tableStore.table.params.sortBy = '' tableStore.table.params.sortBy = ''
tableStore.table.params.orderBy = '' tableStore.table.params.orderBy = ''
tableStore.table.params.searchValue='' tableStore.table.params.searchValue = ''
tableStore.table.params.connectStatus = ''
tableStore.table.params.runStatus = ''
// 设备类型 // 设备类型
const devTypeChange = (e: any) => { const devTypeChange = (e: any) => {

View File

@@ -28,7 +28,7 @@ const tableStore = new TableStore({
column: [ column: [
{ title: '标题', field: 'title', align: 'center' }, { title: '标题', field: 'title', align: 'center' },
{ title: '描述', field: 'description', align: 'center' }, { title: '描述', field: 'description', align: 'center' },
{ title: '发布时间', field: 'createTime', align: 'center' }, { title: '发布时间', field: 'createTime', align: 'center' , sortable: true},
{ {
title: '状态', title: '状态',
field: 'status', field: 'status',

View File

@@ -0,0 +1,202 @@
<template>
<div class="default-main">
<TableHeader datePicker ref="refheader" >
<template v-slot:select>
<el-form-item label="关键字筛选">
<el-input
v-model.trim="tableStore.table.params.name"
placeholder="请输入关键字"
clearable
></el-input>
</el-form-item>
<el-form-item label="流程阶段">
<el-select v-model.trim="tableStore.table.params.process" clearable placeholder="请选择">
<el-option label="功能调试" :value="2"></el-option>
<el-option label="出厂调试" :value="3"></el-option>
<el-option label="正式投运" :value="4"></el-option>
</el-select>
</el-form-item>
</template>
<template v-slot:operation>
<el-button type="primary" icon="el-icon-Download" @click="exportTab">导出</el-button>
</template>
</TableHeader>
<Table ref="tableRef" />
</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 { queryByCode, queryByid, queryCsDictTree } from '@/api/system-boot/dictTree'
defineOptions({
name: 'manage/monthly'
})
const refheader = ref()
const devModelOptions: any = ref([])
queryByCode('Device_Type').then(res => {
queryByid(res.data.id).then(res => {
devModelOptions.value = res.data.map((item: any) => {
return {
value: item.id,
label: item.name,
...item
}
})
})
tableStore.index()
})
const tableStore = new TableStore({
url: '/cs-harmonic-boot/statisticsData/halfMonthReport',
method: 'POST',
isWebPaging: true,
exportName: '半月报功能',
column: [
{
title: '序号',
width: 80,
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '工程名称', field: 'engineeringName', minWidth: 150 },
{ title: '项目名称', field: 'projectName', minWidth: 130 },
{ title: '设备名称', field: 'devName', minWidth: 130 },
{ title: '监测点名称', field: 'lineName', minWidth: 130 },
{
title: '投运时间',
field: 'operationalTime',
width: 180,
sortable: true
},
{
title: '数据更新时间',
field: 'latestTime',
width: 180,
sortable: true
// formatter: (row: any) => {
// return row.cellValue || '/'
// }
},
{
title: '设备型号',
field: 'devType',
width: 130,
formatter: row => {
return devModelOptions.value.filter((item: any) => item.value == row.cellValue)[0]?.label
}
},
{ title: 'Mac地址', field: 'mac', width: 140 },
{
title: '流程阶段',
field: 'process',
width: 100,
fixed: 'right',
render: 'tag',
custom: {
2: 'warning',
3: 'warning',
4: 'success'
},
replaceValue: {
2: '功能调试',
3: '出厂调试',
4: '正式投运'
},
minWidth: 80
},
{
title: '运行状态',
field: 'operationalStatus',
render: 'tag',
fixed: 'right',
width: 100,
custom: {
停运: 'danger',
在运: 'success'
},
replaceValue: {
在运: '在运',
停运: '停运'
}
},
{
title: '通讯状态',
field: 'communicationStatus',
width: 100,
fixed: 'right',
render: 'tag',
custom: {
离线: 'danger',
在线: 'success'
},
replaceValue: {
离线: '离线',
在线: '在线'
}
},
{ title: '在线率(%)', fixed: 'right',width: 100, field: 'onlineRate', sortable: true },
{ title: '完整性(%)', fixed: 'right',width: 100, field: 'integrity', sortable: true }
],
beforeSearchFun: () => {},
loadCallback: () => {
let name = tableStore.table.params.name
let data = tableStore.table.copyData.filter(item => {
// 处理latestTime默认值
item.latestTime = item.latestTime || '/'
// 需要检查的字段列表
const fieldsToCheck = ['projectName', 'engineeringName', 'mac', 'devName', 'lineName']
console.log(
'🚀 ~ fieldsToCheck.some(field => item[field]?.includes(name)):',
fieldsToCheck.some(field => item[field]?.includes(name))
)
// 检查任何一个字段包含搜索名称
return fieldsToCheck.some(field => item[field]?.includes(name))
})
tableStore.table.copyData = JSON.parse(JSON.stringify(data))
tableStore.table.total = tableStore.table.copyData.length
if (data.length == 0) {
tableStore.table.data = []
} else {
tableStore.table.data = JSON.parse(
JSON.stringify(
window.XEUtils.chunk(data, tableStore.table.params.pageSize)[tableStore.table.params.pageNum - 1]
)
)
}
}
})
provide('tableStore', tableStore)
tableStore.table.params.process = 4
tableStore.table.params.name = ''
const tableRef = ref()
const exportTab = () => {
tableRef.value.getRef()?.exportData({
filename: '半月报功能', // 文件名字
sheetName: 'Sheet1',
type: 'xlsx', //导出文件类型 xlsx 和 csv
useStyle: true,
data: tableStore.table.copyData, // 数据源 // 过滤那个字段导出
columnFilterMethod: function (column: any) {
return !(
column.column.title === undefined ||
column.column.title === '序号' ||
column.column.title === '操作'
)
}
})
}
onMounted(() => {})
setTimeout(() => {
// tableStore.table.height = mainHeight(200).height as any
}, 0)
const addMenu = () => {}
</script>
<style></style>

View File

@@ -1,24 +1,57 @@
<template> <template>
<el-dialog draggable :title="title" v-model.trim="dialogVisible" width="500px" :before-close="handleClose" <el-dialog
:close-on-click-modal="false"> draggable
:title="title"
v-model.trim="dialogVisible"
width="500px"
:before-close="handleClose"
:close-on-click-modal="false"
>
<el-form ref="formRef" :rules="rules" :model="form" label-width="90px" class="form"> <el-form ref="formRef" :rules="rules" :model="form" label-width="90px" class="form">
<el-form-item label="项目名称:" prop="name"> <el-form-item label="项目名称:" prop="name">
<el-input maxlength="32" show-word-limit v-model.trim="form.name" placeholder="请输入项目名称"></el-input> <el-input
maxlength="32"
show-word-limit
v-model.trim="form.name"
placeholder="请输入项目名称"
></el-input>
</el-form-item> </el-form-item>
<el-form-item label="工程项目:" class="top" prop="projectIds"> <el-form-item label="工程项目:" class="top" prop="projectIds">
<el-tree-select v-model.trim="form.projectIds" default-expand-all show-checkbox node-key="id" <el-tree-select
:props="defaultProps" multiple :data="Engineering" collapse-tags style="width: 100%" /> v-model.trim="form.projectIds"
default-expand-all
show-checkbox
node-key="id"
:props="defaultProps"
multiple
:data="Engineering"
collapse-tags
style="width: 100%"
/>
<!-- <el-cascader v-model.trim="form.projectIds" :options="Engineering" :props="defaultProps" <!-- <el-cascader v-model.trim="form.projectIds" :options="Engineering" :props="defaultProps"
:show-all-levels="false" collapse-tags collapse-tags-tooltip clearable style="width: 100%;"/> --> :show-all-levels="false" collapse-tags collapse-tags-tooltip clearable style="width: 100%;"/> -->
</el-form-item> </el-form-item>
<el-form-item label="项目排序:" prop="orderBy"> <el-form-item label="项目排序:" prop="orderBy">
<el-input maxlength="32" show-word-limit-number v-model.trim="form.orderBy" :min="0" :step="1" <el-input
step-strictly style="width: 100%" /> maxlength="32"
show-word-limit-number
v-model.trim="form.orderBy"
:min="0"
:step="1"
step-strictly
style="width: 100%"
/>
</el-form-item> </el-form-item>
<el-form-item label="备注:" class="top"> <el-form-item label="备注:" class="top">
<el-input maxlength="300" show-word-limit type="textarea" :rows="2" placeholder="请输入内容" <el-input
v-model.trim="form.remark"></el-input> maxlength="300"
show-word-limit
type="textarea"
:rows="2"
placeholder="请输入内容"
v-model.trim="form.remark"
></el-input>
</el-form-item> </el-form-item>
</el-form> </el-form>
@@ -58,6 +91,8 @@ const rules = {
orderBy: [{ required: true, message: '请输入排序', trigger: 'blur' }] orderBy: [{ required: true, message: '请输入排序', trigger: 'blur' }]
} }
const addFn = () => { const addFn = () => {
console.log('🚀 ~ add ~ form:', form)
formRef.value.validate((valid: boolean) => { formRef.value.validate((valid: boolean) => {
if (valid) { if (valid) {
if (title.value == '新增项目') { if (title.value == '新增项目') {
@@ -144,7 +179,7 @@ const open = ref((row: any) => {
}) })
} }
}) })
Engineering.value = res.data Engineering.value = removeData(res.data)
}) })
title.value = row.title title.value = row.title
dialogVisible.value = true dialogVisible.value = true
@@ -160,6 +195,17 @@ const open = ref((row: any) => {
form.id = row.row.id form.id = row.row.id
} }
}) })
const removeData = arr => {
return arr
.map(item => {
if (item.children) {
item.children = removeData(item.children)
}
return item.level <= 1 ? item : {}
})
.filter(item => Object.keys(item).length > 0)
}
const handleClose = () => { const handleClose = () => {
dialogVisible.value = false dialogVisible.value = false
} }

View File

@@ -1,261 +1,254 @@
<template> <template>
<div class="default-main"> <div class="default-main">
<TableHeader> <TableHeader>
<template v-slot:select> <template v-slot:select>
<el-form-item label="项目名称"> <el-form-item label="项目名称">
<el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.searchValue" <el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.searchValue"
placeholder="请输入项目名称"></el-input> placeholder="请输入项目名称"></el-input>
</el-form-item> </el-form-item>
</template> </template>
<template v-slot:operation> <template v-slot:operation>
<el-button type="primary" @click="onSubmitadd" icon="el-icon-Plus">新增</el-button> <el-button type="primary" @click="onSubmitadd" icon="el-icon-Plus">新增</el-button>
</template> </template>
</TableHeader> </TableHeader>
<!-- <Table ref="tableRef" /> --> <!-- <Table ref="tableRef" /> -->
<div style="overflow-x: hidden; overflow-y: scroll;padding: 0 10px;" v-loading="tableStore.table.loading" <div style="overflow-x: hidden; overflow-y: scroll;padding: 0 10px;" v-loading="tableStore.table.loading"
:style="{ height: tableStore.table.height }"> :style="{ height: tableStore.table.height }">
<el-row :gutter="12"> <el-row :gutter="12">
<el-col :span="6" v-for="item in tableStore.table.data" :key="item.id" class="mt10"> <el-col :span="6" v-for="item in tableStore.table.data" :key="item.id" class="mt10">
<el-card class="box-card" @click="querdata(item)" shadow="hover"> <el-card class="box-card" @click="querdata(item)" shadow="hover">
<div slot="header" class="clearfix"> <div slot="header" class="clearfix">
<span style="display: flex;align-items: center">{{ item.name }} <span style="display: flex;align-items: center">{{ item.name }}
<el-tooltip class="item" effect="dark" content="修改项目" placement="top"> <el-tooltip class="item" effect="dark" content="修改项目" placement="top">
<Edit style="margin-left: 5px;width: 16px;" class=" xiaoshou color" <Edit style="margin-left: 5px;width: 16px;" class=" xiaoshou color"
@click="editd(item)" /> @click="editd(item)" />
</el-tooltip></span> </el-tooltip></span>
<div style="display: flex;justify-content: end;"> <div style="display: flex;justify-content: end;">
<el-button class="color" icon="el-icon-Share" style="padding: 3px 0" type="text" <el-button class="color" icon="el-icon-Share" style="padding: 3px 0" type="text"
@click="Aclick(item)">设计</el-button> @click="Aclick(item)">设计</el-button>
<!-- <el-button icon="el-icon-share" style="padding: 3px 0; color: green" <!-- <el-button icon="el-icon-share" style="padding: 3px 0; color: green"
type="text" @click="shejid(item)">设计</el-button> --> type="text" @click="shejid(item)">设计</el-button> -->
<!-- <el-button icon="el-icon-edit" style="padding: 3px 0; color: blue" type="text" <!-- <el-button icon="el-icon-edit" style="padding: 3px 0; color: blue" type="text"
@click="shejid(item)">编辑</el-button> --> @click="shejid(item)">编辑</el-button> -->
<el-button icon="el-icon-Delete" style="padding: 3px 0; color: red" type="text" <el-button icon="el-icon-Delete" style="padding: 3px 0; color: red" type="text"
@click="deleted(item)">删除</el-button> @click="deleted(item)">删除</el-button>
</div> </div>
</div> </div>
<img :src="item.fileContent" class="image xiaoshou" @click="imgData(item)" /> <img v-if="item.fileContent" :src="item.fileContent" class="image xiaoshou" @click="imgData(item)" />
</el-card> <el-empty v-else description="暂无设计" style="height: 220px;"/>
</el-col> </el-card>
</el-row> </el-col>
</div> </el-row>
<div class="table-pagination"> </div>
<el-pagination :currentPage="tableStore.table.params!.pageNum" <div class="table-pagination">
:page-size="tableStore.table.params!.pageSize" :page-sizes="[10, 20, 50, 100]" background <el-pagination :currentPage="tableStore.table.params!.pageNum"
:layout="'sizes,total, ->, prev, pager, next, jumper'" :total="tableStore.table.total" :page-size="tableStore.table.params!.pageSize" :page-sizes="[10, 20, 50, 100]" background
@size-change="onTableSizeChange" @current-change="onTableCurrentChange"></el-pagination> :layout="'sizes,total, ->, prev, pager, next, jumper'" :total="tableStore.table.total"
</div> @size-change="onTableSizeChange" @current-change="onTableCurrentChange"></el-pagination>
</div>
<popup ref="popupRef" @submit="tableStore.index()" />
<popup ref="popupRef" @submit="tableStore.index()" />
</div>
</template> </div>
<script setup lang="ts"> </template>
import { Plus } from '@element-plus/icons-vue' <script setup lang="ts">
import { ref, onMounted, provide } from 'vue' import { Plus } from '@element-plus/icons-vue'
import TableStore from '@/utils/tableStore' import { ref, onMounted, provide } from 'vue'
// import Table from '@/components/table/index.vue' import TableStore from '@/utils/tableStore'
import TableHeader from '@/components/table/header/index.vue' // import Table from '@/components/table/index.vue'
import { deleteTopoTemplate, uploadTopo } from '@/api/cs-device-boot/topologyTemplate' import TableHeader from '@/components/table/header/index.vue'
import { ElMessage, ElMessageBox } from 'element-plus' import { deleteTopoTemplate, uploadTopo } from '@/api/cs-device-boot/topologyTemplate'
import { audit, add } from '@/api/cs-harmonic-boot/mxgraph'; import { ElMessage, ElMessageBox } from 'element-plus'
import { Edit } from '@element-plus/icons-vue' import { audit, add } from '@/api/cs-harmonic-boot/mxgraph';
import popup from './components/popup.vue' import { Edit } from '@element-plus/icons-vue'
defineOptions({ import popup from './components/popup.vue'
name: 'mxgraph/graph-list' defineOptions({
}) name: 'mxgraph/graph-list'
const tableRef = ref() })
const popupRef = ref() const tableRef = ref()
let DOMIN = window.location.origin const popupRef = ref()
let DOMIN = window.location.origin
let STATIC_URL = DOMIN + '/api/system-boot/file/download?filePath='
localStorage.setItem('STATIC_URL', STATIC_URL) let STATIC_URL = DOMIN + '/api/system-boot/file/download?filePath='
const tableStore = new TableStore({ localStorage.setItem('STATIC_URL', STATIC_URL)
showPage: false, const tableStore = new TableStore({
url: '/cs-harmonic-boot/csconfiguration/queryPage', showPage: false,
method: 'POST', url: '/cs-harmonic-boot/csconfiguration/queryPage',
publicHeight: 60, method: 'POST',
column: [ publicHeight: 60,
], column: [
loadCallback: () => { ],
loadCallback: () => {
}
}) }
provide('tableStore', tableStore) })
tableStore.table.params.searchValue = '' provide('tableStore', tableStore)
onMounted(() => { tableStore.table.params.searchValue = ''
tableStore.table.ref = tableRef.value onMounted(() => {
tableStore.index() tableStore.table.ref = tableRef.value
tableStore.table.loading = false tableStore.index()
}) tableStore.table.loading = false
// 查询 })
const onSubmitadd = () => { // 查询
const onSubmitadd = () => {
popupRef.value.open({
title: '新增项目' popupRef.value.open({
}) title: '新增项目'
} })
const querdata = (e: any) => { } }
const editd = (e: any) => { const querdata = (e: any) => { }
popupRef.value.open({ const editd = (e: any) => {
title: '修改项目', popupRef.value.open({
row: e title: '修改项目',
}) row: e
} })
// 设计 }
const Aclick = (e: any) => { // 设计
window.open(window.location.origin + `/zutai/?id=${e.id}&&name=decodeURI(${e.name})&&flag=false`) const Aclick = (e: any) => {
// const link = document.createElement("a"); //创建下载a标签 window.open(window.location.origin + `/zutai/?id=${e.id}&&name=${e.name}&&preview=false`)
// link.target = `_blank`; // window.open('http://192.168.1.128:4001' + `/zutai/?id=${e.id}&&name=${e.name}&&preview=false`)
// link.href = `http://192.168.1.128:3001/zutai/?id=${e.id}&&name=decodeURI(${e.name})&&flag=false`;
// link.style.display = "none"; //默认隐藏元素 }
// document.body.appendChild(link); // body中添加元素 const shejid = (e: any) => { }
// link.click(); // 执行点击事件 // 删除
} const deleted = (e: any) => {
const shejid = (e: any) => { } ElMessageBox.confirm("此操作将永久删除该项目, 是否继续?", "提示", {
// 删除 confirmButtonText: "确定",
const deleted = (e: any) => { cancelButtonText: "取消",
ElMessageBox.confirm("此操作将永久删除该项目, 是否继续?", "提示", { type: "warning",
confirmButtonText: "确定", })
cancelButtonText: "取消", .then(() => {
type: "warning", let data = {
}) id: e.id,
.then(() => { name: e.name,
let data = { status: "0",
id: e.id, };
name: e.name, audit(data).then((res: any) => {
status: "0", if (res.code == "A0000") {
}; ElMessage({
audit(data).then((res: any) => { type: "success",
if (res.code == "A0000") { message: "删除项目成功!",
ElMessage({ });
type: "success", }
message: "删除项目成功!", tableStore.index()
}); });
} })
tableStore.index() .catch(() => {
}); ElMessage({
}) type: "info",
.catch(() => { message: "已取消删除",
ElMessage({ });
type: "info", });
message: "已取消删除", }
});
}); const imgData = (e: any) => {
} window.open(window.location.origin + `/zutai/?id=${e.id}&&name=${e.name}&&preview=true#/preview`)
// window.open('http://192.168.1.128:4001' + `/zutai/?id=${e.id}&&name=${e.name}&&preview=true#/preview`)
const imgData = (e: any) => {
window.open(window.location.origin + `/zutai/?id=${e.id}&&name=decodeURI(${e.name})&&flag=true`) }
// const link = document.createElement("a"); //创建下载a标签
// link.target = `_blank`; const onTableSizeChange = (val: number) => {
// link.href = `http://192.168.1.128:3001/zutai/#/?id=${e.id}&&name=decodeURI(${e.name})&&flag=true`; tableStore.onTableAction('page-size-change', { size: val })
// link.style.display = "none"; //默认隐藏元素 }
// document.body.appendChild(link); // body中添加元素
// link.click(); // 执行点击事件 const onTableCurrentChange = (val: number) => {
} tableStore.onTableAction('current-page-change', { page: val })
}
const onTableSizeChange = (val: number) => {
tableStore.onTableAction('page-size-change', { size: val }) </script>
} <style lang="scss" scoped>
.text {
const onTableCurrentChange = (val: number) => { font-size: 14px;
tableStore.onTableAction('current-page-change', { page: val }) }
}
span {
</script> font-size: 16px;
<style lang="scss" scoped> }
.text {
font-size: 14px; .item {
} margin-bottom: 18px;
}
span {
font-size: 16px; .image {
} display: block;
width: 100%;
.item { height: 220px;
margin-bottom: 18px; }
}
.clearfix::before,
.image { .clearfix::after {
display: block; display: table;
width: 100%; content: "";
height: 220px; }
}
.clearfix::after {
.clearfix::before, clear: both;
.clearfix::after { }
display: table;
content: ""; .box-card {
} width: 100%;
// border: 1px solid #000;
.clearfix::after { box-shadow: var(--el-box-shadow-light)
clear: both; }
}
.xiaoshou {
.box-card { cursor: pointer;
width: 100%; }
// border: 1px solid #000;
box-shadow: var(--el-box-shadow-light) .setstyle {
} min-height: 200px;
padding: 0 !important;
.xiaoshou { margin: 0;
cursor: pointer; overflow: auto;
} cursor: default !important;
}
.setstyle {
min-height: 200px; .color {
padding: 0 !important; color: var(--el-color-primary);
margin: 0; }
overflow: auto;
cursor: default !important; :deep(.el-select-dropdown__wrap) {
} max-height: 300px;
}
.color {
color: var(--el-color-primary); :deep(.el-tree) {
} padding-top: 15px;
padding-left: 10px;
:deep(.el-select-dropdown__wrap) {
max-height: 300px; // 不可全选样式
} .el-tree-node {
.is-leaf+.el-checkbox .el-checkbox__inner {
:deep(.el-tree) { display: inline-block;
padding-top: 15px; }
padding-left: 10px;
.el-checkbox .el-checkbox__inner {
// 不可全选样式 display: none;
.el-tree-node { }
.is-leaf+.el-checkbox .el-checkbox__inner { }
display: inline-block; }
}
:deep(.el-card__header) {
.el-checkbox .el-checkbox__inner { padding: 13px 20px;
display: none; height: 44px;
} }
}
} .table-pagination {
height: 58px;
:deep(.el-card__header) { box-sizing: border-box;
padding: 13px 20px; width: 100%;
height: 44px; max-width: 100%;
} background-color: var(--ba-bg-color-overlay);
padding: 13px 15px;
.table-pagination { border-left: 1px solid #e4e7e9;
height: 58px; border-right: 1px solid #e4e7e9;
box-sizing: border-box; border-bottom: 1px solid #e4e7e9;
width: 100%; }
max-width: 100%;
background-color: var(--ba-bg-color-overlay); :deep(.el-pagination__sizes) {
padding: 13px 15px; .el-select {
border-left: 1px solid #e4e7e9; min-width: 128px;
border-right: 1px solid #e4e7e9; }
border-bottom: 1px solid #e4e7e9; }
} </style>
:deep(.el-pagination__sizes) {
.el-select {
min-width: 128px;
}
}
</style>

View File

@@ -9,6 +9,9 @@
<pane :size="(100 - size)" style="background: #fff" :style="height"> <pane :size="(100 - size)" style="background: #fff" :style="height">
<TableHeader ref="TableHeaderRef" :showReset="false"> <TableHeader ref="TableHeaderRef" :showReset="false">
<template v-slot:select> <template v-slot:select>
<el-form-item label="时间:">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item label="模板策略"> <el-form-item label="模板策略">
<el-select v-model.trim="Template" @change="changetype" placeholder="请选择模版" value-key="id"> <el-select v-model.trim="Template" @change="changetype" placeholder="请选择模版" value-key="id">
<el-option v-for="item in templatePolicy" :key="item.id" :label="item.name" <el-option v-for="item in templatePolicy" :key="item.id" :label="item.name"
@@ -40,6 +43,7 @@ import { mainHeight } from '@/utils/layout'
import { getTemplateByDept } from '@/api/harmonic-boot/luckyexcel' import { getTemplateByDept } from '@/api/harmonic-boot/luckyexcel'
import { exportExcel } from '@/views/system/reportForms/export.js' import { exportExcel } from '@/views/system/reportForms/export.js'
import 'splitpanes/dist/splitpanes.css' import 'splitpanes/dist/splitpanes.css'
import DatePicker from '@/components/form/datePicker/time.vue'
import { Splitpanes, Pane } from 'splitpanes' import { Splitpanes, Pane } from 'splitpanes'
// import data from './123.json' // import data from './123.json'
defineOptions({ defineOptions({
@@ -52,7 +56,7 @@ const TableHeaderRef = ref()
const dotList: any = ref({}) const dotList: any = ref({})
const Template: any = ref({}) const Template: any = ref({})
const reportForm: any = ref('') const reportForm: any = ref('')
const datePickerRef = ref()
const templatePolicy: any = ref([]) const templatePolicy: any = ref([])
const tableStore = new TableStore({ const tableStore = new TableStore({
@@ -62,6 +66,11 @@ const tableStore = new TableStore({
beforeSearchFun: () => { beforeSearchFun: () => {
tableStore.table.params.tempId = Template.value.id tableStore.table.params.tempId = Template.value.id
tableStore.table.params.lineId = dotList.value.id tableStore.table.params.lineId = dotList.value.id
tableStore.table.params.startTime = datePickerRef.value.timeValue[0],
tableStore.table.params.endTime = datePickerRef.value.timeValue[1],
delete tableStore.table.params.searchBeginTime
delete tableStore.table.params.searchEndTime
delete tableStore.table.params.timeFlag
}, },
loadCallback: () => { loadCallback: () => {
tableStore.table.data.forEach((item: any) => { tableStore.table.data.forEach((item: any) => {

View File

@@ -44,8 +44,8 @@ const tableStore: any = new TableStore({
return row.cellValue == 1 ? '电能质量报表类型' : row.cellValue == 2 ? '用能报表类型' : '' return row.cellValue == 1 ? '电能质量报表类型' : row.cellValue == 2 ? '用能报表类型' : ''
} }, } },
{ field: 'updateBy', title: '更新用户' }, { field: 'updateBy', title: '更新用户' },
{ field: 'createTime', title: '创建时间' }, { field: 'createTime', title: '创建时间' , sortable: true},
{ field: 'updateTime', title: '更新时间' }, { field: 'updateTime', title: '更新时间', sortable: true },
{ {
title: '操作', title: '操作',
width: '220', width: '220',

View File

@@ -203,7 +203,7 @@ const tableStore = new TableStore({
return row.cellValue === 'MQTT' ? 'MQTT' : row.cellValue === 'cloud' ? 'CLD' : row.cellValue return row.cellValue === 'MQTT' ? 'MQTT' : row.cellValue === 'cloud' ? 'CLD' : row.cellValue
} }
}, },
{ title: '录入时间', field: 'createTime' }, { title: '录入时间', field: 'createTime' , sortable: true},
{ title: '网络设备ID', field: 'ndid' }, { title: '网络设备ID', field: 'ndid' },
{ {
title: '状态', title: '状态',

View File

@@ -204,7 +204,7 @@ const tableStore = new TableStore({
return row.cellValue === 'MQTT' ? 'MQTT' : row.cellValue === 'cloud' ? 'CLD' : row.cellValue return row.cellValue === 'MQTT' ? 'MQTT' : row.cellValue === 'cloud' ? 'CLD' : row.cellValue
} }
}, },
{ title: '录入时间', field: 'createTime' }, { title: '录入时间', field: 'createTime', sortable: true },
{ title: '网络设备ID', field: 'ndid' }, { title: '网络设备ID', field: 'ndid' },
{ {
title: '状态', title: '状态',

View File

@@ -252,9 +252,9 @@ const histogram = (res: any) => {
} else if (0.4 < params.value && params.value <= 0.8 && params.value !== 0.05) { } else if (0.4 < params.value && params.value <= 0.8 && params.value !== 0.05) {
return '#FF9900' return '#FF9900'
} else if (0 < params.value && params.value <= 0.4 && params.value !== 0.05) { } else if (0 < params.value && params.value <= 0.4 && params.value !== 0.05) {
return '#CC0000' return '#A52a2a'
} else if (params.value == 0.05) { } else if (params.value == 0.05) {
return '#CC0000' return '#A52a2a'
} }
} }
} }
@@ -276,13 +276,13 @@ const histogram = (res: any) => {
name: '', name: '',
yAxis: 0.4, yAxis: 0.4,
lineStyle: { lineStyle: {
color: '#CC0000' color: '#A52a2a'
}, },
label: { label: {
// position: "middle", // position: "middle",
formatter: '{b}', formatter: '{b}',
textStyle: { textStyle: {
color: '#CC0000' color: '#A52a2a'
} }
} }
}, },

View File

@@ -163,7 +163,7 @@ const map = (res: any) => {
} }
], ],
inRange: { inRange: {
color: ['#ccc', '#CC0000', '#FF9900', '#3399CC', '#339966'] color: ['#ccc', '#A52a2a', '#FF9900', '#3399CC', '#339966']
} }
}, },
@@ -284,9 +284,9 @@ const histogram = (res: any) => {
} else if (0.4 < params.value && params.value <= 0.8 && params.value !== 0.05) { } else if (0.4 < params.value && params.value <= 0.8 && params.value !== 0.05) {
return '#FF9900' return '#FF9900'
} else if (0 < params.value && params.value <= 0.4 && params.value !== 0.05) { } else if (0 < params.value && params.value <= 0.4 && params.value !== 0.05) {
return '#CC0000' return '#A52a2a'
} else if (params.value == 0.05) { } else if (params.value == 0.05) {
return '#CC0000' return '#A52a2a'
} }
} }
} }
@@ -308,13 +308,13 @@ const histogram = (res: any) => {
name: '', name: '',
yAxis: 0.4, yAxis: 0.4,
lineStyle: { lineStyle: {
color: '#CC0000' color: '#A52a2a'
}, },
label: { label: {
// position: "middle", // position: "middle",
formatter: '{b}', formatter: '{b}',
textStyle: { textStyle: {
color: '#CC0000' color: '#A52a2a'
} }
} }
}, },

View File

@@ -33,7 +33,7 @@ const tableStore = new TableStore({
url: '/system-boot/audit/getAuditLog', url: '/system-boot/audit/getAuditLog',
method: 'POST', method: 'POST',
column: [ column: [
{ title: '操作时间', field: 'time', align: 'center', width: 200 }, { title: '操作时间', field: 'time', align: 'center', width: 200 , sortable: true},
{ title: '操作人员', field: 'userName', align: 'center', width: 120 }, { title: '操作人员', field: 'userName', align: 'center', width: 120 },
{ title: '操作类型', field: 'operate', align: 'center', width: 220 }, { title: '操作类型', field: 'operate', align: 'center', width: 220 },
{ title: '事件描述', field: 'describe', align: 'center', showOverflow: true, minWidth: 200 }, { title: '事件描述', field: 'describe', align: 'center', showOverflow: true, minWidth: 200 },

View File

@@ -61,14 +61,14 @@ const tableStore = new TableStore({
{ title: '供电公司', field: 'gdName', align: 'center', width: 120 }, { title: '供电公司', field: 'gdName', align: 'center', width: 120 },
{ title: '变电站', field: 'bdName', align: 'center', showOverflow: true, minWidth: 100 }, { title: '变电站', field: 'bdName', align: 'center', showOverflow: true, minWidth: 100 },
{ title: '终端编号', field: 'devName', align: 'center', width: 160 }, { title: '终端编号', field: 'devName', align: 'center', width: 160 },
{ title: '投运时间', field: 'loginTime', align: 'center', width: 200 }, { title: '投运时间', field: 'loginTime', align: 'center', width: 200 , sortable: true},
{ title: '厂家', field: 'manufacturer', align: 'center', width: 160 }, { title: '厂家', field: 'manufacturer', align: 'center', width: 160 },
{ title: '型号', field: 'devType', align: 'center', width: 200 }, { title: '型号', field: 'devType', align: 'center', width: 200 },
{ title: '网络参数', field: 'ip', align: 'center', width: 200 }, { title: '网络参数', field: 'ip', align: 'center', width: 200 },
{ title: '端口', field: 'port', align: 'center', width: 100 }, { title: '端口', field: 'port', align: 'center', width: 100 },
{ title: '终端状态', field: 'runFlag', align: 'center', width: 100 }, { title: '终端状态', field: 'runFlag', align: 'center', width: 100 },
{ title: '通讯状态', field: 'comFlag', align: 'center', width: 100 }, { title: '通讯状态', field: 'comFlag', align: 'center', width: 100 },
{ title: '最新数据', field: 'updateTime', align: 'center', width: 200 }, { title: '最新数据', field: 'updateTime', align: 'center', width: 200, sortable: true },
{ {
title: '评价', title: '评价',
field: 'onlineEvaluate', field: 'onlineEvaluate',

View File

@@ -18,8 +18,8 @@
<span class="smallBlock" style="background: #996600"></span> <span class="smallBlock" style="background: #996600"></span>
热备用 热备用
</span> </span>
<span style="color: #cc0000"> <span style="color: #A52a2a">
<span class="smallBlock" style="background: #cc0000"></span> <span class="smallBlock" style="background: #A52a2a"></span>
停运 停运
</span> </span>
</span> </span>
@@ -33,8 +33,8 @@
<span style="color: #daa520"> <span style="color: #daa520">
<span class="smallBlock" style="background: #daa520"></span> <span class="smallBlock" style="background: #daa520"></span>
{{ '60 %≤在线率 < 90 %' }} </span> {{ '60 %≤在线率 < 90 %' }} </span>
<span style="color: #cc0000"> <span style="color: #A52a2a">
<span class="smallBlock" style="background: #cc0000"></span> <span class="smallBlock" style="background: #A52a2a"></span>
{{ '在线率 < 60 %' }} </span> {{ '在线率 < 60 %' }} </span>
</span> </span>
</div> </div>
@@ -174,7 +174,7 @@ const tableStore = new TableStore({
return new echarts.graphic.LinearGradient(0, 1, 0, 0, [ return new echarts.graphic.LinearGradient(0, 1, 0, 0, [
{ {
offset: 1, offset: 1,
color: '#cc0000' color: '#A52a2a'
} }
]) ])
} else if ((params.value = 3.14159)) { } else if ((params.value = 3.14159)) {
@@ -216,7 +216,7 @@ const tableStore = new TableStore({
return new echarts.graphic.LinearGradient(0, 1, 0, 0, [ return new echarts.graphic.LinearGradient(0, 1, 0, 0, [
{ {
offset: 1, offset: 1,
color: '#CC0000' color: '#A52a2a'
} }
]) ])
} else if ((params.value = 3.14159)) { } else if ((params.value = 3.14159)) {
@@ -309,7 +309,7 @@ const tableStore = new TableStore({
return new echarts.graphic.LinearGradient(0, 1, 0, 0, [ return new echarts.graphic.LinearGradient(0, 1, 0, 0, [
{ {
offset: 1, offset: 1,
color: '#cc0000' color: '#A52a2a'
} }
]) ])
} else if ((params.value = 3.14159)) { } else if ((params.value = 3.14159)) {
@@ -351,7 +351,7 @@ const tableStore = new TableStore({
return new echarts.graphic.LinearGradient(0, 1, 0, 0, [ return new echarts.graphic.LinearGradient(0, 1, 0, 0, [
{ {
offset: 1, offset: 1,
color: '#CC0000' color: '#A52a2a'
} }
]) ])
} else if ((params.value = 3.14159)) { } else if ((params.value = 3.14159)) {

View File

@@ -46,8 +46,8 @@ const tableStore = new TableStore({
{ title: '开启等级', field: 'openLevelName' }, { title: '开启等级', field: 'openLevelName' },
{ title: '开启算法', field: 'openDescribeName' }, { title: '开启算法', field: 'openDescribeName' },
{ title: '字典描述', field: 'remark' }, { title: '字典描述', field: 'remark' },
{ title: '创建时间', field: 'createTime' }, { title: '创建时间', field: 'createTime', sortable: true },
{ title: '更新时间', field: 'updateTime' }, { title: '更新时间', field: 'updateTime', sortable: true},
{ {
title: '状态', title: '状态',
field: 'stateName', field: 'stateName',

View File

@@ -78,7 +78,7 @@ const tableStore = new TableStore({
}, },
{ title: '版本号', field: 'versionName', width: '150' }, { title: '版本号', field: 'versionName', width: '150' },
{ title: '创建时间', field: 'createTime', width: '220' }, { title: '创建时间', field: 'createTime', width: '220', sortable: true },
{ {
title: '发布类型', field: 'sev', formatter: (row,) => { title: '发布类型', field: 'sev', formatter: (row,) => {
return row.cellValue == 0 ? '优化' : 'bug调整' return row.cellValue == 0 ? '优化' : 'bug调整'

View File

@@ -42,8 +42,8 @@ const tableStore: any = new TableStore({
{ field: 'name', title: '模板名称' }, { field: 'name', title: '模板名称' },
{ field: 'createBy', title: '创建用户' }, { field: 'createBy', title: '创建用户' },
{ field: 'updateBy', title: '更新用户' }, { field: 'updateBy', title: '更新用户' },
{ field: 'createTime', title: '创建时间' }, { field: 'createTime', title: '创建时间', sortable: true },
{ field: 'updateTime', title: '更新时间' }, { field: 'updateTime', title: '更新时间', sortable: true },
{ {
title: '操作', title: '操作',
width: '220', width: '220',

1
types/table.d.ts vendored
View File

@@ -8,6 +8,7 @@ declare global {
interface CnTable { interface CnTable {
ref: VxeTableInstance | null ref: VxeTableInstance | null
data: TableRow[] | any data: TableRow[] | any
copyData: TableRow[] | any
allData: TableRow[] | any allData: TableRow[] | any
allFlag: Boolean allFlag: Boolean
// 前端分页数据 // 前端分页数据