You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
337 lines
8.6 KiB
337 lines
8.6 KiB
1 month ago
|
<template>
|
||
|
<div class="fault-rule-drawer">
|
||
|
<el-drawer
|
||
|
v-model="isShowDrawer"
|
||
|
:title="title"
|
||
|
direction="rtl"
|
||
|
size="90%"
|
||
|
modal-class="model-dev-opn"
|
||
|
:before-close="handleBeforeClose"
|
||
|
@opened="onDrawerOpened">
|
||
|
<main class="wh-full flex">
|
||
|
<EdfsWrap title="选择" class="p-r-4 h-full w-340 border-r-1 border-solid border-r-#e4e7ed">
|
||
|
<PointCheckbox
|
||
|
:pointList="pointList"
|
||
|
:loadingPoints="loadingPoints"
|
||
|
@onchange-points="onchangePoints"
|
||
|
ref="PointCheckboxRef"
|
||
|
>
|
||
|
</PointCheckbox>
|
||
|
</EdfsWrap>
|
||
|
<div class="flex-1 p-4 h-full overflow-hidden relative"
|
||
|
>
|
||
|
<div class="absolute w-full h-full bg-[#ffffffe5] z-99" v-if="loadingChart">
|
||
|
<div class="w-full h-full flex flex-col justify-center items-center">
|
||
|
<el-progress
|
||
|
style="width: 70%"
|
||
|
:text-inside="true"
|
||
|
:stroke-width="18"
|
||
|
:percentage="progress"
|
||
|
status="success"
|
||
|
/>
|
||
|
<div class="text-xl">
|
||
|
<div>当前加载数据量较大请稍等。。。</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<el-button class="mb-4" type="primary" @click="loadChardData">查询数据</el-button>
|
||
|
<NewDataChart
|
||
|
v-if="isShowChart"
|
||
|
:chart-datas="chartData"
|
||
|
:legends="legends"
|
||
|
:axis-data="Array.from(axisData)"
|
||
|
ref="chartRef"/>
|
||
|
</div>
|
||
|
</main>
|
||
|
</el-drawer>
|
||
|
</div>
|
||
|
</template>
|
||
|
|
||
|
<script setup lang="ts">
|
||
|
import NewDataChart from '../../component/newDataChart.vue'
|
||
|
import type { IDevice, IMyPoint, IOfflineDevice, IOnlineDevice } from '../../type'
|
||
|
import {
|
||
|
getDeviceDetails,
|
||
|
getPoints,
|
||
|
type IGetDeviceDataParams,
|
||
|
type IPointGroupOV,
|
||
|
type IPointsParams,
|
||
|
} from '@/api/module/transfer'
|
||
|
import { useMessage } from '@/composables/useMessage'
|
||
|
import dayjs from 'dayjs'
|
||
|
import { nextTick } from "vue";
|
||
|
import EdfsWrap from "@/components/Edfs-wrap.vue";
|
||
|
import PointCheckbox from "@/views/stationData/component/pointCheckbox.vue";
|
||
|
|
||
|
const env = import.meta.env
|
||
|
const isShowDrawer = defineModel<boolean>()
|
||
|
const title = computed(() => (curDevice.value?.isonLine ? '数据详情' : `已迁移数据详情`))
|
||
|
const message = useMessage()
|
||
|
const PointCheckboxRef = ref<InstanceType<typeof PointCheckbox>>()
|
||
|
|
||
|
const emit = defineEmits(['on-save'])
|
||
|
const pointList = ref<IMyPoint[]>([])
|
||
|
const curDevice = ref<IDevice & { isonLine: boolean, siteName: string }>()
|
||
|
|
||
|
async function open(device: IDevice & {
|
||
|
isonLine: boolean,
|
||
|
siteName: string
|
||
|
}, group: IPointGroupOV) {
|
||
|
curDevice.value = device
|
||
|
currentGroup.value = group
|
||
|
PointCheckboxRef.value?.clearCheck()
|
||
|
await loadPoints()
|
||
|
.then(async () => {
|
||
|
await loadDeviceDetails()
|
||
|
})
|
||
|
.catch(() => {
|
||
|
message.error('获取点位数据失败')
|
||
|
fullscreenLoading.value?.close()
|
||
|
})
|
||
|
}
|
||
|
|
||
|
|
||
|
const loadingPoints = ref(false)
|
||
|
const columParams = computed(() => ['ts', ...checkPointList.value.map(i => i.addr)])
|
||
|
|
||
|
const currentGroup = ref<IPointGroupOV>()
|
||
|
|
||
|
async function loadPoints() {
|
||
|
if (!currentGroup.value) {
|
||
|
message.error('请先选择点位组')
|
||
|
return
|
||
|
}
|
||
|
const params: IPointsParams = {
|
||
|
type: currentGroup.value.type,
|
||
|
}
|
||
|
if (curDevice.value?.isonLine) {
|
||
|
const onlineDevice = curDevice.value as IOnlineDevice
|
||
|
params.isLocal = false
|
||
|
params.host = onlineDevice.clientIp
|
||
|
} else {
|
||
|
const offlineDevice = curDevice.value as IOfflineDevice
|
||
|
params.sn = offlineDevice.sn
|
||
|
params.site = curDevice.value!.siteName
|
||
|
params.isLocal = true
|
||
|
}
|
||
|
loadingPoints.value = true
|
||
|
const res = await getPoints(params)
|
||
|
if (res.code === 0) {
|
||
|
const data = Array.isArray(res?.data) ? res.data : []
|
||
|
pointList.value = data.map((i: any) => ({
|
||
|
label: i.cnName,
|
||
|
addr: i.addr,
|
||
|
unit: i.unit || '',
|
||
|
}))
|
||
|
}
|
||
|
loadingPoints.value = false
|
||
|
return res
|
||
|
}
|
||
|
|
||
|
async function loadDeviceDetails() {
|
||
|
if (!fullscreenLoading.value) {
|
||
|
openFullScreen()
|
||
|
}
|
||
|
chartData.clear()
|
||
|
axisData.clear()
|
||
|
legends.value = []
|
||
|
const pointsRes = await loadPoints()
|
||
|
if (!pointsRes || pointsRes.code !== 0) {
|
||
|
message.error('获取点位数据失败')
|
||
|
pointList.value = []
|
||
|
chartData.clear()
|
||
|
axisData.clear()
|
||
|
fullscreenLoading.value?.close()
|
||
|
return
|
||
|
}
|
||
|
isShowDrawer.value = true
|
||
|
fullscreenLoading.value?.close()
|
||
|
}
|
||
|
|
||
|
const chartData = reactive(new Map<string, any[]>())
|
||
|
const axisData = new Set<string>()
|
||
|
const legends = ref<{ addr: string; label: string, unit: string }[]>([])
|
||
|
|
||
|
const loadingChart = ref(false)
|
||
|
const chartAllTotal = ref(0)
|
||
|
const chartLimit = ref(1000)
|
||
|
const chartOffset = ref(0)
|
||
|
const progress = ref(0)
|
||
|
|
||
|
async function loadChardData() {
|
||
|
if (!currentGroup.value) return
|
||
|
if (!columParams.value.filter(i => i !== 'ts').length) {
|
||
|
message.error('请选择点位')
|
||
|
return
|
||
|
}
|
||
|
clearData()
|
||
|
const limit = chartLimit.value
|
||
|
const offset = chartOffset.value
|
||
|
const options = {
|
||
|
columns: columParams.value,
|
||
|
isLocal: !curDevice.value?.isonLine,
|
||
|
host: curDevice.value?.isonLine ? (curDevice.value as IOnlineDevice).clientIp : '',
|
||
|
name: currentGroup.value.name as string,
|
||
|
}
|
||
|
|
||
|
const params: IGetDeviceDataParams = {
|
||
|
...options,
|
||
|
limit,
|
||
|
offset
|
||
|
}
|
||
|
|
||
|
if (env.VITE_APP_ENV !== 'local' || !curDevice.value?.isonLine) {
|
||
|
params.site_id = curDevice.value!.siteName || ''
|
||
|
params.device_id = curDevice.value?.sn || ''
|
||
|
}
|
||
|
loadingChart.value = true
|
||
|
isShowChart.value = false
|
||
|
|
||
|
const res = await getDeviceDetails(params)
|
||
|
|
||
|
if (res.code !== 0) {
|
||
|
resetChartStatus()
|
||
|
message.error('获取设备数据失败')
|
||
|
return
|
||
|
}
|
||
|
|
||
|
chartAllTotal.value = res?.data?.total ?? 0
|
||
|
if (chartAllTotal.value === 0) {
|
||
|
resetChartStatus()
|
||
|
message.info('暂无数据')
|
||
|
return
|
||
|
}
|
||
|
|
||
|
const pointData = Array.isArray(res.data.results) ? res.data.results : []
|
||
|
setChartData(pointData)
|
||
|
const pageCount = Math.ceil(chartAllTotal.value / Number(limit))
|
||
|
if (pageCount <= 1) {
|
||
|
progress.value = 100
|
||
|
setTimeout(() => {
|
||
|
resetChartStatus()
|
||
|
})
|
||
|
return
|
||
|
}
|
||
|
|
||
|
for (let i = 1; i < pageCount; i++) {
|
||
|
const params: IGetDeviceDataParams = {
|
||
|
...options,
|
||
|
limit,
|
||
|
offset: i * Number(limit)
|
||
|
}
|
||
|
const res = await getDeviceDetails(params)
|
||
|
if (res.code !== 0) {
|
||
|
clearData()
|
||
|
resetChartStatus()
|
||
|
message.error('获取设备数据失败')
|
||
|
return
|
||
|
}
|
||
|
const pointData = Array.isArray(res.data.results) ? res.data.results : []
|
||
|
setChartData(pointData)
|
||
|
progress.value = Math.min(100, Math.floor(((i + 1) / pageCount) * 100))
|
||
|
}
|
||
|
|
||
|
resetChartStatus()
|
||
|
}
|
||
|
|
||
|
|
||
|
function setChartData(pointData: any[]) {
|
||
|
for (const addr of columParams.value.filter(i => i !== 'ts')) {
|
||
|
const label = pointList.value.find(i => i.addr === addr)?.label || addr
|
||
|
const find = legends.value.find(i => i.addr === addr)
|
||
|
const unit = pointList.value.find(i => i.addr === addr)?.unit || ''
|
||
|
if (!find) {
|
||
|
legends.value.push({ addr, label, unit })
|
||
|
}
|
||
|
}
|
||
|
pointData.forEach((data: any[]) => {
|
||
|
const [ts, val, addr] = data
|
||
|
if (checkPointList.value.some(i => i.addr === addr)) {
|
||
|
const time = dayjs(Number(ts)).format('YYYY-MM-DD HH:mm:ss')
|
||
|
if (addr) {
|
||
|
const colData = chartData.get(addr)
|
||
|
if (colData) {
|
||
|
colData.push([time, val])
|
||
|
} else {
|
||
|
chartData.set(addr, [[time, val]])
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (ts) {
|
||
|
axisData.add(time)
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
function handleBeforeClose(done: () => void) {
|
||
|
isShowDrawer.value = false
|
||
|
clearData()
|
||
|
fullscreenLoading.value = null
|
||
|
done()
|
||
|
}
|
||
|
|
||
|
function clearData() {
|
||
|
chartLimit.value = 1000
|
||
|
chartOffset.value = 0
|
||
|
chartAllTotal.value = 0
|
||
|
progress.value = 0
|
||
|
legends.value = []
|
||
|
chartData.clear()
|
||
|
axisData.clear()
|
||
|
}
|
||
|
|
||
|
function resetChartStatus() {
|
||
|
loadingChart.value = false
|
||
|
nextTick(() => {
|
||
|
isShowChart.value = true
|
||
|
})
|
||
|
}
|
||
|
|
||
|
const chartRef = ref<InstanceType<typeof NewDataChart>>()
|
||
|
const isShowChart = ref(false)
|
||
|
|
||
|
function onDrawerOpened() {
|
||
|
nextTick(() => {
|
||
|
isShowChart.value = true
|
||
|
})
|
||
|
}
|
||
|
|
||
|
const fullscreenLoading = ref<any>(null)
|
||
|
const openFullScreen = () => {
|
||
|
fullscreenLoading.value = ElLoading.service({
|
||
|
lock: true,
|
||
|
text: '数据加载中,请稍后...',
|
||
|
background: 'rgba(255, 255, 255, 0.8)',
|
||
|
})
|
||
|
}
|
||
|
|
||
|
const checkPointList = ref<IMyPoint[]>([])
|
||
|
|
||
|
function onchangePoints(checkPoints: IMyPoint[]) {
|
||
|
checkPointList.value = []
|
||
|
checkPointList.value = checkPoints
|
||
|
}
|
||
|
|
||
|
defineExpose({
|
||
|
open,
|
||
|
openFullScreen,
|
||
|
})
|
||
|
</script>
|
||
|
|
||
|
<style scoped lang="scss">
|
||
|
.fault-rule-drawer {
|
||
|
font-size: 16px;
|
||
|
|
||
|
:deep(.edfs-wrap) {
|
||
|
width: auto;
|
||
|
}
|
||
|
|
||
|
:deep(.el-drawer__header) {
|
||
|
color: var(--text-color);
|
||
|
}
|
||
|
}
|
||
|
</style>
|