|
|
|
|
<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 border-r-1 border-solid border-r-#e4e7ed">
|
|
|
|
|
<PointGroupTree
|
|
|
|
|
v-if="isShowDrawer"
|
|
|
|
|
:data="pointGroup"
|
|
|
|
|
@device-select="onGroupChange"
|
|
|
|
|
:groupChangeLoading="groupChangeLoading"
|
|
|
|
|
@onchangePoints="onchangePoints"
|
|
|
|
|
:pointList="pointList"
|
|
|
|
|
:loadingPoints="loadingPoints"
|
|
|
|
|
:isTransfer="props.isTransfer"
|
|
|
|
|
:siteInfo="props.siteInfo"
|
|
|
|
|
ref="pointGroupTreeRef"/>
|
|
|
|
|
</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 PointGroupTree from './PointGroupTree.vue'
|
|
|
|
|
import type { IMyPoint, IOfflineDevice, IOnlineDevice } from '../../type'
|
|
|
|
|
import {
|
|
|
|
|
getDeviceDetails,
|
|
|
|
|
getPointGroup,
|
|
|
|
|
getPoints,
|
|
|
|
|
type IGetDeviceDataParams,
|
|
|
|
|
type IPointGroupOV,
|
|
|
|
|
type IPointGroupParams,
|
|
|
|
|
type IPointsParams,
|
|
|
|
|
type ISite,
|
|
|
|
|
} from '@/api/module/transfer'
|
|
|
|
|
import { useMessage } from '@/composables/useMessage'
|
|
|
|
|
import dayjs from 'dayjs'
|
|
|
|
|
import { nextTick } from "vue";
|
|
|
|
|
import EdfsWrap from "@/components/Edfs-wrap.vue";
|
|
|
|
|
|
|
|
|
|
const time = ref<[string, string]>()
|
|
|
|
|
|
|
|
|
|
const env = import.meta.env
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const isShowDrawer = defineModel<boolean>()
|
|
|
|
|
const title = computed(() => (props.isTransfer ? '数据详情' : `已迁移数据详情`))
|
|
|
|
|
const message = useMessage()
|
|
|
|
|
|
|
|
|
|
const pointGroupTreeRef = ref<InstanceType<typeof PointGroupTree>>()
|
|
|
|
|
const props = defineProps<{
|
|
|
|
|
siteInfo: ISite | null
|
|
|
|
|
isTransfer: boolean
|
|
|
|
|
}>()
|
|
|
|
|
|
|
|
|
|
const emit = defineEmits(['on-save'])
|
|
|
|
|
|
|
|
|
|
const pointList = ref<IMyPoint[]>([])
|
|
|
|
|
|
|
|
|
|
const curDevice = ref<IOfflineDevice | IOnlineDevice>()
|
|
|
|
|
|
|
|
|
|
async function open(device: IOfflineDevice | IOnlineDevice) {
|
|
|
|
|
curDevice.value = device
|
|
|
|
|
await loadPointGroup()
|
|
|
|
|
.then(async () => {
|
|
|
|
|
await loadDeviceDetails()
|
|
|
|
|
})
|
|
|
|
|
.catch(() => {
|
|
|
|
|
message.error('获取点位组数据失败')
|
|
|
|
|
fullscreenLoading.value?.close()
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const loadingPoints = ref(false)
|
|
|
|
|
const columParams = computed(() => ['ts', ...checkPointList.value.map(i => i.addr)])
|
|
|
|
|
|
|
|
|
|
async function loadPoints() {
|
|
|
|
|
if (!curGroup.value) {
|
|
|
|
|
message.error('请先选择点位组')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
const params: IPointsParams = {
|
|
|
|
|
type: curGroup.value,
|
|
|
|
|
}
|
|
|
|
|
if (props.isTransfer) {
|
|
|
|
|
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 = props.siteInfo!.name
|
|
|
|
|
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
|
|
|
|
|
groupChangeLoading.value = false
|
|
|
|
|
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 (!columParams.value.filter(i => i !== 'ts').length) {
|
|
|
|
|
message.error('请选择点位')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
clearData()
|
|
|
|
|
const limit = chartLimit.value
|
|
|
|
|
const offset = chartOffset.value
|
|
|
|
|
const options: any = {
|
|
|
|
|
columns: columParams.value,
|
|
|
|
|
isLocal: !props.isTransfer,
|
|
|
|
|
host: props.isTransfer ? (curDevice.value as IOnlineDevice).clientIp : '',
|
|
|
|
|
name: curGroupName.value as string,
|
|
|
|
|
startTime: time.value[0],
|
|
|
|
|
endTime: time.value[1],
|
|
|
|
|
}
|
|
|
|
|
if (env.VITE_APP_ENV !== 'local' || !props.isTransfer) {
|
|
|
|
|
options.site_id = props.siteInfo!.name || ''
|
|
|
|
|
options.device_id = curDevice.value?.sn || ''
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const params: IGetDeviceDataParams = {
|
|
|
|
|
...options,
|
|
|
|
|
limit,
|
|
|
|
|
offset
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
const value = parseInt((val ? Number(val) : 0).toFixed(2))
|
|
|
|
|
if (colData) {
|
|
|
|
|
colData.push([time, value])
|
|
|
|
|
} else {
|
|
|
|
|
chartData.set(addr, [[time, value]])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ts) {
|
|
|
|
|
axisData.add(time)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleBeforeClose(done: () => void) {
|
|
|
|
|
time.value = undefined
|
|
|
|
|
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 pointGroup = ref<IPointGroupOV[]>([])
|
|
|
|
|
const curGroup = ref<string>()
|
|
|
|
|
const curGroupName = ref<string>()
|
|
|
|
|
|
|
|
|
|
async function loadPointGroup() {
|
|
|
|
|
const params: IPointGroupParams = {}
|
|
|
|
|
if (props.isTransfer) {
|
|
|
|
|
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 = props.siteInfo!.name
|
|
|
|
|
params.isLocal = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const res = await getPointGroup(params)
|
|
|
|
|
if (res.code === 0) {
|
|
|
|
|
curGroup.value = res.data[0]?.type
|
|
|
|
|
curGroupName.value = res.data[0]?.name
|
|
|
|
|
pointGroup.value = Array.isArray(res?.data) ? res.data : []
|
|
|
|
|
return Promise.resolve()
|
|
|
|
|
} else {
|
|
|
|
|
return Promise.reject()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const groupChangeLoading = ref<boolean>(false)
|
|
|
|
|
|
|
|
|
|
function onGroupChange(item: IPointGroupOV) {
|
|
|
|
|
if (!item?.type) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
groupChangeLoading.value = true
|
|
|
|
|
curGroup.value = item.type
|
|
|
|
|
curGroupName.value = item.name
|
|
|
|
|
loadDeviceDetails()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const checkPointList = ref<IMyPoint[]>([])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function onchangePoints(checkPoints: IMyPoint[]) {
|
|
|
|
|
checkPointList.value = []
|
|
|
|
|
checkPointList.value = checkPoints
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const disabledDate = (time: any) => {
|
|
|
|
|
const current = dayjs(time)
|
|
|
|
|
if (props.isTransfer) 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>
|