| 123456789101112131415161718192021222324252627282930313233343536373839404142434445 |
- <template>
- <div>
- <div class="alarm-toolbar"><el-radio-group v-model="period" @change="load"><el-radio-button value="CURVE" label="CURVE">事件前后</el-radio-button><el-radio-button value="DAY" label="DAY">事件当天</el-radio-button><el-radio-button value="DAILY" label="DAILY">日均值</el-radio-button><el-radio-button value="MONTHLY" label="MONTHLY">月均值</el-radio-button></el-radio-group><span class="muted">{{ period === 'CURVE' ? '报警前后 60 分钟' : period === 'DAY' ? '事件当天' : period === 'DAILY' ? '截至事件日的 7 天' : '截至事件日的 6 个月' }}</span></div>
- <p v-if="result.latestSample" class="muted">最新监测值:{{ result.latestSample.value ?? '无效采样' }} {{ result.alarm?.warningUnit }} · {{ result.latestSample.time }}</p>
- <el-alert v-if="error" :title="error" type="error" show-icon :closable="false" />
- <div v-loading="loading" ref="host" class="alarm-chart"></div>
- <el-empty v-if="!loading && !validCount && !error" :description="result.message || '所选区间暂无有效采集数据'" :image-size="55" />
- <div class="muted">{{ result.message }}<template v-if="result.supported"> · 有效采样 {{ validCount }} / {{ sampleCount }} · {{ result.startTime?.replace('T', ' ') }} — {{ result.endTime?.replace('T', ' ') }}</template></div>
- </div>
- </template>
- <script setup>
- import { ref, computed, watch, nextTick, onBeforeUnmount, onMounted } from 'vue'
- import * as echarts from 'echarts'
- import { getAlarmAnalysis } from '@/api/alarm'
- import { seriesPoints, sampleTime } from './utils/alarmOperationsModel'
- const props = defineProps({ alarmId: String, scope: { type: Object, required: true } })
- const period = ref('CURVE'), host = ref(), loading = ref(false), error = ref(''), result = ref({})
- const validCount = computed(() => (result.value.samples || []).reduce((sum, p) => sum + Number(p.validCount), 0))
- const sampleCount = computed(() => (result.value.samples || []).reduce((sum, p) => sum + Number(p.sampleCount), 0))
- let generation = 0, chart, observer
- async function load() {
- const token = ++generation; result.value = {}; error.value = ''; chart?.clear()
- if (!props.alarmId) return
- loading.value = true
- try {
- const response = await getAlarmAnalysis(props.alarmId, { ...props.scope, period: period.value })
- if (token !== generation) return
- result.value = response.data || {}; await nextTick(); draw()
- } catch (e) { if (token === generation) error.value = e.message || '曲线加载失败' }
- finally { if (token === generation) loading.value = false }
- }
- function draw() {
- if (!host.value) return
- if (!chart) chart = echarts.init(host.value)
- const alarm = result.value.alarm || {}, points = result.value.samples || []
- const raw = period.value === 'CURVE' || period.value === 'DAY'
- const event = raw && alarm.actualValue != null && alarm.createTime ? [{ name: '报警触发值', type: 'scatter', symbolSize: 12, itemStyle: { color: '#f56c6c' }, data: [[sampleTime(alarm.createTime), Number(alarm.actualValue)]] }] : []
- const limits = [['下限', alarm.minValue], ['上限', alarm.maxValue]].filter(([, v]) => v !== null && v !== undefined).map(([name, v]) => ({ name, yAxis: Number(v) }))
- chart.setOption({ tooltip: { trigger: 'axis', renderMode: 'richText' }, grid: { left: 65, right: 30, bottom: 60, top: 35 }, xAxis: { type: 'time', min: result.value.startTime ? sampleTime(result.value.startTime) : undefined, max: result.value.endTime ? sampleTime(result.value.endTime) : undefined }, yAxis: { type: 'value', scale: true, name: alarm.warningUnit || '' }, dataZoom: [{ type: 'inside' }, { type: 'slider', height: 20 }], series: [{ name: alarm.warningType || '监测值', type: 'line', showSymbol: points.length < 100, connectNulls: false, data: seriesPoints(points, raw), lineStyle: { color: '#409eff', width: 2 }, markLine: { silent: true, symbol: 'none', lineStyle: { color: '#e6a23c', type: 'dashed' }, data: limits } }, ...event] }, true)
- }
- watch(() => [props.alarmId, JSON.stringify(props.scope)], () => { period.value = 'CURVE'; load() }, { immediate: true })
- onMounted(() => { observer = new ResizeObserver(() => chart?.resize()); observer.observe(host.value); if (result.value.samples) draw() })
- onBeforeUnmount(() => { ++generation; observer?.disconnect(); chart?.dispose() })
- </script>
- <style scoped>.alarm-chart{width:100%;height:360px}</style>
|