|
|
|
<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">
|
|
|
|
<el-select
|
|
|
|
v-if="currentGroup?.customNode"
|
|
|
|
v-model="selectValue"
|
|
|
|
placeholder="单体选择"
|
|
|
|
style="width:240px"
|
|
|
|
@change="onchangeSelect"
|
|
|
|
>
|
|
|
|
<el-option
|
|
|
|
v-for="item in currentGroup.brother"
|
|
|
|
:key="item.name"
|
|
|
|
:label="item.customCnName"
|
|
|
|
:value="item.name"
|
|
|
|
/>
|
|
|
|
</el-select>
|
|
|
|
<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>
|
|
|
|
<div class="flex w-full items-center gap-16">
|
|
|
|
<div class="w-400px">
|
|
|
|
<el-date-picker
|
|
|
|
v-model="time"
|
|
|
|
type="datetimerange"
|
|
|
|
value-format="YYYY-MM-DD HH:mm:ss"
|
|
|
|
range-separator="到"
|
|
|
|
:default-value="getBeforeMonth"
|
|
|
|
start-placeholder="开始时间"
|
|
|
|
end-placeholder="结束时间"
|
|
|
|
:disabled-date="disabledDate"
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
<el-button type="primary" @click="loadChardData">查询数据</el-button>
|
|
|
|
</div>
|
|
|
|
<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
|
|
|
|
if (
|
|
|
|
currentGroup.value.customNode &&
|
|
|
|
currentGroup.value.brother &&
|
|
|
|
currentGroup.value.brother.length
|
|
|
|
) {
|
|
|
|
selectValue.value = currentGroup.value.brother[0].name
|
|
|
|
}
|
|
|
|
PointCheckboxRef.value?.clearCheck()
|
|
|
|
await loadPoints()
|
|
|
|
.then(async () => {
|
|
|
|
await loadDeviceDetails()
|
|
|
|
})
|
|
|
|
.catch(() => {
|
|
|
|
message.error('获取点位数据失败')
|
|
|
|
fullscreenLoading.value?.close()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
const selectValue = ref()
|
|
|
|
function onchangeSelect(value: string) {
|
|
|
|
PointCheckboxRef.value?.clearCheck()
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const loadingPoints = ref(false)
|
|
|
|
const columParams = computed(() => ['ts', ...checkPointList.value.map(i => i.addr)])
|
|
|
|
|
|
|
|
const currentGroup = ref<IPointGroupOV & {
|
|
|
|
customNode?: boolean
|
|
|
|
brother?: Array<any>
|
|
|
|
}>()
|
|
|
|
|
|
|
|
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 (!time.value || time.value.length !== 2) {
|
|
|
|
message.error('请选择时间范围')
|
|
|
|
return
|
|
|
|
}
|
|
|
|
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: selectValue.value as string,
|
|
|
|
startTime: time.value[0],
|
|
|
|
endTime: time.value[1],
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
const time = ref<[string, string]>()
|
|
|
|
const disabledDate = (time: any) => {
|
|
|
|
const current = dayjs(time)
|
|
|
|
if (curDevice.value?.isonLine) {
|
|
|
|
return current.isAfter(dayjs(), 'day')
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
const deviceOff = curDevice.value as IOfflineDevice
|
|
|
|
const start = dayjs(deviceOff.start_time).format('YYYY-MM-DD')
|
|
|
|
const end = dayjs(deviceOff.end_time).format('YYYY-MM-DD')
|
|
|
|
return current.isBefore(start, 'day') || current.isAfter(end, 'day')
|
|
|
|
} catch (e) {
|
|
|
|
console.log('disableDate error', e)
|
|
|
|
return current.isAfter(dayjs(), 'day')
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
const getBeforeMonth = dayjs().startOf('month').subtract(1, 'month').startOf('month').toDate()
|
|
|
|
|
|
|
|
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>
|