Browse Source

feat:集中告警增加趋势功能

pull/86/head
xjf 4 weeks ago
parent
commit
9fb490a1a2
  1. 11
      src/api/alert/warn/index.ts
  2. 36
      src/views/exa/HistoryLine.vue
  3. 9
      src/views/exa/history/index.vue
  4. 7
      src/views/run/calc/index.vue
  5. 13
      src/views/run/instant/detail.vue
  6. 28
      src/views/run/instant/instant.data.ts
  7. 70
      src/views/warn/alarm/TrendModal.vue
  8. 40
      src/views/warn/alarm/alarm.data.ts
  9. 18
      src/views/warn/alarm/index.vue

11
src/api/alert/warn/index.ts

@ -40,3 +40,14 @@ export function getWarn(id: number) {
export function getAlarmLevelList() { export function getAlarmLevelList() {
return defHttp.get({ url: '/alert/warn/alarmlevel/list'}) return defHttp.get({ url: '/alert/warn/alarmlevel/list'})
} }
export interface WarnTrendReqVO {
id?:string,
exaHistoryReqVO?: EXAHistoryReqVO
}
// 查询预警趋势
export function getWarnTrend(params: WarnTrendReqVO) {
return defHttp.get({ url: '/alert/warn/alarm/trend', params })
}

36
src/views/exa/HistoryLine.vue

@ -14,21 +14,24 @@ const props = defineProps({
}, },
height: { height: {
type: String, type: String,
default: propTypes.string.def('500px'), default: '500px',
},
width: {
type: String,
default: '100%',
}, },
title: { title: {
type: String, type: String,
default: '', default: '',
}, },
name: { name: {
type: Array<string>, type: Array as PropType<string[]>,
default: [], default: () => [],
}, },
data: { data: {
type: Array<Array<number>>, type: Array as PropType<number[][]>,
default: () => [[]], default: () => [],
}, },
width: propTypes.string.def('100%'),
// height: propTypes.string.def('70vh'), // height: propTypes.string.def('70vh'),
}) })
const chartRef = ref<HTMLDivElement | null>(null) const chartRef = ref<HTMLDivElement | null>(null)
@ -51,7 +54,7 @@ watch(
const series = ref<any[]>([]) const series = ref<any[]>([])
const title = ref<any>({}) const title = ref<any>({})
for (let i = 0; i < props.data.length; i++) { for (let i = 0; i < props.data?.length; i++) {
title.value = { title.value = {
left: 'left', left: 'left',
text: props.title, text: props.title,
@ -70,11 +73,11 @@ watch(
scale: true, // scale: true, //
}) })
series.value.push({ series.value.push({
name: props.name[i], name: props.name?.[i] || '',
type: 'line', type: 'line',
smooth: true, smooth: true,
showSymbol: false, showSymbol: false,
data: props.data[i], data: props.data?.[i] || [],
yAxisIndex: i, yAxisIndex: i,
}) })
} }
@ -100,6 +103,9 @@ watch(
position(pt) { position(pt) {
return [pt[0], '10%'] return [pt[0], '10%']
}, },
confine: true, // tooltip
backgroundColor: 'rgba(255, 255, 255, 0.5)', // 0~1
}, },
title: title.value, title: title.value,
toolbox: { toolbox: {
@ -130,15 +136,14 @@ watch(
function convertToCSV(data) { function convertToCSV(data) {
let csv = '' let csv = ''
// //
const name = props.name.join(',') const name = props.name?.join(',') || ''
csv += `时间,${name}\n` csv += `时间,${name}\n`
// CSV // CSV
for (let i = 0; i < props.data[0].length; i++) { for (let i = 0; i < props.data?.[0]?.length || 0; i++) {
let data = '' let data = ''
for (let j = 0; j < props.data.length; j++) for (let j = 0; j < props.data?.length || 0; j++)
data += `,${props.data[j][i][1]}` data += `,${props.data?.[j]?.[i]?.[1] || ''}`
csv += `${moment(props.data?.[0]?.[i]?.[0] || 0).format('YYYY-MM-DD HH:mm:ss')}${data}\n`
csv += `${moment(props.data[0][i][0]).format('YYYY-MM-DD HH:mm:ss')}${data}\n`
// props.data[i].map((item, index) => { // props.data[i].map((item, index) => {
// csv += 'x' + ',' + 'y' + '\n' // csv += 'x' + ',' + 'y' + '\n'
// }) // })
@ -156,7 +161,6 @@ watch(
length: 6, length: 6,
lineStyle: { lineStyle: {
type: 'dashed', type: 'dashed',
// ...
}, },
}, },
// boundaryGap: false, // boundaryGap: false,

9
src/views/exa/history/index.vue

@ -7,6 +7,9 @@ import HistoryLine from '../HistoryLine.vue'
import PointModal from './PointModal.vue' import PointModal from './PointModal.vue'
import { getExaHistorys } from '@/api/alert/exa' import { getExaHistorys } from '@/api/alert/exa'
import { useModal } from '@/components/Modal' import { useModal } from '@/components/Modal'
import {useForm} from "@/components/Form";
import {calcFormSchemas} from "@/views/run/calc/calc.data";
interface FormState { interface FormState {
publishTime: any[] publishTime: any[]
@ -35,6 +38,7 @@ const state = reactive<RowKeys>({
selectedRowKeys: [], selectedRowKeys: [],
}) })
onMounted(() => { onMounted(() => {
searchForm.publishTime = [moment().subtract(1, 'day').format('YYYY-MM-DD HH:mm:ss'), moment().format('YYYY-MM-DD HH:mm:ss')]
getHistoryChart() getHistoryChart()
}) })
@ -44,7 +48,6 @@ const legendName = ref<any[]>([])
async function getHistoryChart() { async function getHistoryChart() {
state.selectedRowKeys = localStorage.getItem('pointInfo') ? JSON.parse(localStorage.getItem('pointInfo') || '') : [] state.selectedRowKeys = localStorage.getItem('pointInfo') ? JSON.parse(localStorage.getItem('pointInfo') || '') : []
selectedData.value = localStorage.getItem('pointInfoList') ? JSON.parse(localStorage.getItem('pointInfoList') || '') : [] selectedData.value = localStorage.getItem('pointInfoList') ? JSON.parse(localStorage.getItem('pointInfoList') || '') : []
searchForm.publishTime = [moment().subtract(1, 'day').format('YYYY-MM-DD HH:mm:ss'), moment().format('YYYY-MM-DD HH:mm:ss')]
const pointCodeList = selectedData.value.map(item => (item.itemName)) const pointCodeList = selectedData.value.map(item => (item.itemName))
loading.value = true loading.value = true
@ -53,7 +56,7 @@ async function getHistoryChart() {
message.info('暂无测点') message.info('暂无测点')
const pointCode = selectedData.value.map(item => (item.itemName)).join(',') const pointCode = selectedData.value.map(item => (item.itemName)).join(',')
const pointDesc: any[] = selectedData.value.map(item => (item.descriptor)) const pointDesc: any[] = selectedData.value.map(item => (item.descriptor+'('+item.itemName+')'))
const exaHistoryReqVO = { const exaHistoryReqVO = {
startTime: searchForm.publishTime[0], startTime: searchForm.publishTime[0],
@ -62,7 +65,7 @@ async function getHistoryChart() {
interval: 100, interval: 100,
} }
historyData.value = await getExaHistorys(exaHistoryReqVO) historyData.value = await getExaHistorys(exaHistoryReqVO)
legendName.value = pointDesc legendName.value = pointDesc;
loading.value = false loading.value = false
} }

7
src/views/run/calc/index.vue

@ -145,28 +145,23 @@ async function handlebeforeCalc(record?: Recordable) {
// //
async function handleCalc(formData: any) { async function handleCalc(formData: any) {
calcLoading.value = true calcLoading.value = true
console.log('点击回算按钮数据::::', formData)
// //
for (const record of formData.records) { for (const record of formData.records) {
updateTableDataRecord(record.mpId, {calcStatus:1}) updateTableDataRecord(record.mpId, {calcStatus:1})
rowCalcLoading[record.mpId] = true rowCalcLoading[record.mpId] = true
console.log('行内回算loading状态:', record.mpId, rowCalcLoading[record.mpId])
try { try {
// - // -
formData.mpId = record.mpId formData.mpId = record.mpId
// - // -
console.log(formData) console.log(formData)
const res = await calcInstant(formData) const res = await calcInstant(formData)
console.log('回算结果:', res)
console.log(record)
res.calcStatus = 2 res.calcStatus = 2
// //
updateTableDataRecord(record.mpId, res) updateTableDataRecord(record.mpId, res)
createMessage.success(t('common.successText')) createMessage.success(t('common.successText'))
} catch (error) { } catch (error) {
updateTableDataRecord(record.mpId, {calcStatus:3}) updateTableDataRecord(record.mpId, {calcStatus:3})
createMessage.error(t('common.failText')) createMessage.error(t('common.errorText'))
} finally { } finally {
rowCalcLoading[record.mpId] = false rowCalcLoading[record.mpId] = false
} }

13
src/views/run/instant/detail.vue

@ -48,7 +48,11 @@ const [registerForm, { getFieldsValue, setProps }] = useForm({
// datastartTimeendTime // datastartTimeendTime
['time', ['startTime', 'endTime'], 'YYYY-MM-DD HH:mm:ss'], ['time', ['startTime', 'endTime'], 'YYYY-MM-DD HH:mm:ss'],
], ],
actionColOptions: { span: 2 }, actionColOptions: {
span: 2,
style:{
marginLeft:'5px'
}},
}) })
const instantId = ref<any>(route.query.mpId) // URLquery const instantId = ref<any>(route.query.mpId) // URLquery
@ -111,8 +115,9 @@ function handleDetail(record) {
router.push('/run/instant/detail') router.push('/run/instant/detail')
} }
function config(value) {
console.log(value) function handleFaultConfig(field) {
console.log(field)
} }
</script> </script>
@ -169,7 +174,7 @@ function config(value) {
<BasicForm @register="registerForm" @submit="handleSubmitR"> <BasicForm @register="registerForm" @submit="handleSubmitR">
<!-- 添加button的插槽 --> <!-- 添加button的插槽 -->
<template #configButton="{ field }"> <template #configButton="{ field }">
<a-button style="margin-left:20px" @click="config"> <a-button @click="handleFaultConfig(field)">
故障配置 故障配置
</a-button> </a-button>
</template> </template>

28
src/views/run/instant/instant.data.ts

@ -269,6 +269,9 @@ export const instantForm: FormSchema[] = [
onChange: (e: any) => { onChange: (e: any) => {
console.log(e) console.log(e)
}, },
colProps: {
span: 8,
},
}, },
}, },
{ {
@ -276,6 +279,7 @@ export const instantForm: FormSchema[] = [
field: 'interval', field: 'interval',
component: 'Select', component: 'Select',
defaultValue: 300, defaultValue: 300,
labelWidth:100,
componentProps: { componentProps: {
options: [{ value: 1, label: '1秒' }, { value: 10, label: '10秒' }, { value: 100, label: '100秒' }, { value: 300, label: '300秒' }], options: [{ value: 1, label: '1秒' }, { value: 10, label: '10秒' }, { value: 100, label: '100秒' }, { value: 300, label: '300秒' }],
@ -285,24 +289,17 @@ export const instantForm: FormSchema[] = [
span: 3, span: 3,
}, },
}, },
{
label: '',
field: '0',
component: 'Input',
slot: 'configButton',
colProps: {
span: 2,
},
},
{ {
label: '复盘', label: '复盘',
field: 'fp', field: 'fp',
labelWidth:100,
component: 'RadioGroup', component: 'RadioGroup',
defaultValue: 0, defaultValue: 0,
colProps: {
span: 5,
},
componentProps: { componentProps: {
options: [ options: [
{ {
label: '是', label: '是',
@ -317,6 +314,15 @@ export const instantForm: FormSchema[] = [
required: true, required: true,
}, },
{
label: '',
field: 'faultConfig',
component: 'Input',
slot: 'configButton',
colProps: {
span: 2,
}
}
] ]
export const searchFormSchemaModel: FormSchema[] = [ export const searchFormSchemaModel: FormSchema[] = [

70
src/views/warn/alarm/TrendModal.vue

@ -0,0 +1,70 @@
<script lang="ts" setup>
import { ref } from 'vue'
import moment from 'moment'
import { Card } from 'ant-design-vue'
import { formTrend } from './alarm.data'
import HistoryLine from '../../exa/HistoryLine.vue'
import { BasicModal, useModalInner } from '@/components/Modal'
import { BasicForm, useForm } from '@/components/Form'
import { getExaHistorys } from '@/api/alert/exa'
import {WarnTrendReqVO, getWarnTrend, EXAHistoryReqVO} from "@/api/alert/warn";
const props = defineProps<{
warnId: string,
}>()
const loading = ref(true)
const [registerForm, { getFieldsValue }] = useForm({
labelWidth: 100,
// baseColProps: { span: 24 },
schemas: formTrend,
showResetButton: false,
layout: 'horizontal',
model: { time: [moment().subtract(1, 'day').format('YYYY-MM-DD HH:mm:ss'), moment().format('YYYY-MM-DD HH:mm:ss')] },
fieldMapToTime: [
// datastartTimeendTime
['time', ['startTime', 'endTime'], 'YYYY-MM-DD HH:mm:ss'],
],
actionColOptions: { span: 3 },
})
const trendData = ref([])
const legendName = ref([])
const title = ref('')
const [registerHistoryModal, { setModalProps }] = useModalInner(async (data) => {
console.log(543)
setModalProps({ confirmLoading: false, showCancelBtn: false, showOkBtn: false })
handleSubmitR()
})
async function handleSubmitR() {
const serachFormData = getFieldsValue() as EXAHistoryReqVO
loading.value = true
//
const params:WarnTrendReqVO={
id:props.warnId,
exaHistoryReqVO:serachFormData
}
const result = await getWarnTrend(params)
console.log(result)
trendData.value=result.valueList;
legendName.value=result.tagList;
title.value=result.gzpName;
loading.value = false
}
</script>
<template>
<BasicModal :min-height="300" v-bind="$attrs" :title="title" width="60%" @register="registerHistoryModal">
<BasicForm @register="registerForm" @submit="handleSubmitR" />
<Card :loading="loading">
<HistoryLine :data="trendData" :name="legendName" height="40vh" />
</Card>
</BasicModal>
</template>

40
src/views/warn/alarm/alarm.data.ts

@ -4,6 +4,7 @@ import {h, ref} from "vue";
import {systemSelectParams} from "@/api/alert/model/model/optionsModel"; import {systemSelectParams} from "@/api/alert/model/model/optionsModel";
import {FileItem, UploadResultStatus} from "@/components/Upload/src/typing"; import {FileItem, UploadResultStatus} from "@/components/Upload/src/typing";
import {Progress} from "ant-design-vue"; import {Progress} from "ant-design-vue";
import moment from "moment/moment";
const optionList = await optionListApi() const optionList = await optionListApi()
const systemOptions = ref<any>([]) const systemOptions = ref<any>([])
@ -189,3 +190,42 @@ export const columns: BasicColumn[] = [
width: 100, width: 100,
} }
] ]
export const formTrend: FormSchema[] = [
{
label: '时间',
field: 'time',
show: true,
component: 'RangePicker',
componentProps: {
placeholder: ['开始时间', '结束时间'],
defaultValue: [moment().subtract(1, 'day').format('YYYY-MM-DD HH:mm:ss'), moment().format('YYYY-MM-DD HH:mm:ss')],
valueFormat: 'YYYY-MM-DD HH:mm:ss',
showTime: {
defaultValue: [moment().subtract(1, 'day').format('YYYY-MM-DD HH:mm:ss'), moment().format('YYYY-MM-DD HH:mm:ss')],
},
onChange: (e: any) => {
console.log(e)
},
colProps: {
span: 8,
},
},
},
{
label: '时间间隔',
field: 'interval',
component: 'Select',
defaultValue: 60,
labelWidth:100,
componentProps: {
options: [{ value: 60, label: '60秒' }, { value: 100, label: '100秒' }, { value: 300, label: '300秒' }],
},
required: true,
colProps: {
span: 5,
},
},
]

18
src/views/warn/alarm/index.vue

@ -1,13 +1,13 @@
<script lang="ts" setup> <script lang="ts" setup>
import { Switch } from 'ant-design-vue' import { Switch } from 'ant-design-vue'
import { onMounted } from 'vue' import { onMounted,ref } from 'vue'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { columns, searchFormSchema } from './alarm.data' import { columns, searchFormSchema } from './alarm.data'
import UpdateModal from '../../run/instant/warnConfig/UpdateModal.vue' import UpdateModal from '../../run/instant/warnConfig/UpdateModal.vue'
import TrendModal from './TrendModal.vue'
import { BasicTable, TableAction, useTable } from '@/components/Table' import { BasicTable, TableAction, useTable } from '@/components/Table'
import { getWarnPageReal, updateWarn } from '@/api/alert/warn' import {getWarnPageReal, updateWarn, warnTrendReqVO} from '@/api/alert/warn'
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
import { useMessage } from '@/hooks/web/useMessage' import { useMessage } from '@/hooks/web/useMessage'
import { IconEnum } from '@/enums/appEnum' import { IconEnum } from '@/enums/appEnum'
@ -20,6 +20,8 @@ const route = useRoute()
const { createMessage } = useMessage() const { createMessage } = useMessage()
const { t } = useI18n() const { t } = useI18n()
const [registerUpdateModal, { openModal: openUpdateModal }] = useModal() const [registerUpdateModal, { openModal: openUpdateModal }] = useModal()
const [registerTrendModal, { openModal: openTrendModal }] = useModal()
const [registerTable, { getForm, reload, getDataSource, updateTableDataRecord }] = useTable({ const [registerTable, { getForm, reload, getDataSource, updateTableDataRecord }] = useTable({
title: '集中告警列表', title: '集中告警列表',
api: getWarnPageReal, api: getWarnPageReal,
@ -63,6 +65,13 @@ function handleUpdate(record: Recordable) {
openUpdateModal(true, { record, isUpdate: true }) openUpdateModal(true, { record, isUpdate: true })
} }
const warnId=ref<string>();
async function handleTrend(record: Recordable) {
console.log(record)
warnId.value=record.warnId;
openTrendModal(true, { record })
}
onMounted(async () => { onMounted(async () => {
const { setFieldsValue } = getForm() const { setFieldsValue } = getForm()
await setFieldsValue({ system: null }) await setFieldsValue({ system: null })
@ -78,7 +87,7 @@ onMounted(async () => {
:actions="[ :actions="[
{ icon: IconEnum.EDIT, label: t('action.edit'), onClick: handleUpdate.bind(null, record) }, { icon: IconEnum.EDIT, label: t('action.edit'), onClick: handleUpdate.bind(null, record) },
{ icon: IconEnum.TREND, label: t('action.trend'), onClick: handleUpdate.bind(null, record) }, { icon: IconEnum.TREND, label: t('action.trend'), onClick: handleTrend.bind(null, record) },
{ icon: IconEnum.DETAIL, label: t('action.detail'), onClick: handleUpdate.bind(null, record) }, { icon: IconEnum.DETAIL, label: t('action.detail'), onClick: handleUpdate.bind(null, record) },
]" ]"
@ -87,6 +96,7 @@ onMounted(async () => {
</template> </template>
</BasicTable> </BasicTable>
<UpdateModal @register="registerUpdateModal" @success="reload" /> <UpdateModal @register="registerUpdateModal" @success="reload" />
<TrendModal @register="registerTrendModal" :warnId="warnId"/>
</div> </div>
</template> </template>

Loading…
Cancel
Save