|
@@ -1,3 +1,378 @@
|
|
|
|
+<script setup lang="ts">
|
|
|
|
+import { ref, useTemplateRef } from 'vue';
|
|
|
|
+import dayjs from 'dayjs';
|
|
|
|
+
|
|
|
|
+import ConfirmModal from '@/components/ConfirmModal.vue';
|
|
|
|
+import SvgIcon from '@/components/SvgIcon.vue';
|
|
|
|
+import { t } from '@/i18n';
|
|
|
|
+
|
|
|
|
+import AlarmConditions from './AlarmConditions.vue';
|
|
|
|
+
|
|
|
|
+import type { Rule } from 'ant-design-vue/es/form';
|
|
|
|
+import type { AlarmForm } from '@/types';
|
|
|
|
+
|
|
|
|
+const modalComponentRef = useTemplateRef('modalComponent');
|
|
|
|
+const historyOpen = ref<boolean>(false);
|
|
|
|
+const alarmOpen = ref<boolean>(false);
|
|
|
|
+// 日期时间格式
|
|
|
|
+const dateFormat = 'HH:mm';
|
|
|
|
+const alarmForm = ref<AlarmForm>({
|
|
|
|
+ name: '',
|
|
|
|
+ time: [dayjs(), dayjs()],
|
|
|
|
+});
|
|
|
|
+const historyData = ref([
|
|
|
|
+ {
|
|
|
|
+ alarm: '启动命令执行失败',
|
|
|
|
+ state: '智控预警提醒',
|
|
|
|
+ state1: '2023-12-31 23:12:00',
|
|
|
|
+ state2: '2024-01-31 23:12:10',
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ alarm: '启动命令执行失败1',
|
|
|
|
+ state: '智控预警提醒',
|
|
|
|
+ state1: '2024-12-31 23:12:00',
|
|
|
|
+ state2: '2025-01-31 23:12:10',
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ alarm: '启动命令执行失败2',
|
|
|
|
+ state: '智控预警提醒',
|
|
|
|
+ state1: '2023-10-31 23:12:00',
|
|
|
|
+ state2: '2024-02-31 23:12:10',
|
|
|
|
+ },
|
|
|
|
+]);
|
|
|
|
+const alarmData = ref([
|
|
|
|
+ {
|
|
|
|
+ alarm: '2025年4月7日09:24:59产生报警内容',
|
|
|
|
+ state1: '群控柜设备',
|
|
|
|
+ state2: 10,
|
|
|
|
+ state3: '2024-12-31 23:12:00',
|
|
|
|
+ state4: '2024-12-31 23:12:10',
|
|
|
|
+ state: true,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ alarm: '2025年4月7日15:04:56产生报警内容',
|
|
|
|
+ state1: '群控柜设备',
|
|
|
|
+ state2: 10,
|
|
|
|
+ state3: '2024-12-31 23:12:00',
|
|
|
|
+ state4: '2024-11-31 23:11:10',
|
|
|
|
+ state: false,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ alarm: '2025年4月7日15:04:56产生报警内容',
|
|
|
|
+ state1: '群控柜设备',
|
|
|
|
+ state2: 10,
|
|
|
|
+ state3: '2024-12-31 23:12:00',
|
|
|
|
+ state4: '2024-12-31 23:11:10',
|
|
|
|
+ state: true,
|
|
|
|
+ },
|
|
|
|
+]);
|
|
|
|
+const historyQuery = ref({
|
|
|
|
+ pageIndex: 1,
|
|
|
|
+ pageSize: 10,
|
|
|
|
+ total: 0,
|
|
|
|
+});
|
|
|
|
+const alarmQuery = ref({
|
|
|
|
+ pageIndex: 1,
|
|
|
|
+ pageSize: 10,
|
|
|
|
+ searchContent: '',
|
|
|
|
+ total: 0,
|
|
|
|
+});
|
|
|
|
+
|
|
|
|
+const rules: Record<string, Rule[]> = {
|
|
|
|
+ name: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
|
|
|
|
+ time: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
|
|
|
|
+};
|
|
|
|
+const historyColumns = [
|
|
|
|
+ {
|
|
|
|
+ title: '',
|
|
|
|
+ dataIndex: 'index',
|
|
|
|
+ key: 'index',
|
|
|
|
+ width: 40,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ title: '故障信息',
|
|
|
|
+ dataIndex: 'alarm',
|
|
|
|
+ key: 'alarm',
|
|
|
|
+ ellipsis: true,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ title: '类型',
|
|
|
|
+ dataIndex: 'state',
|
|
|
|
+ key: 'state',
|
|
|
|
+ ellipsis: true,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ title: '发生日期',
|
|
|
|
+ dataIndex: 'state1',
|
|
|
|
+ key: 'state1',
|
|
|
|
+ ellipsis: true,
|
|
|
|
+ sorter: (a: { state1: string | number | Date }, b: { state1: string | number | Date }) => {
|
|
|
|
+ const timeA = new Date(a.state1).getTime();
|
|
|
|
+ const timeB = new Date(b.state1).getTime();
|
|
|
|
+ return timeA - timeB;
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ title: '解决日期',
|
|
|
|
+ dataIndex: 'state2',
|
|
|
|
+ key: 'state2',
|
|
|
|
+ ellipsis: true,
|
|
|
|
+ },
|
|
|
|
+];
|
|
|
|
+const alarmColumns = [
|
|
|
|
+ {
|
|
|
|
+ title: '报警内容',
|
|
|
|
+ dataIndex: 'alarm',
|
|
|
|
+ key: 'alarm',
|
|
|
|
+ ellipsis: true,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ title: '设备',
|
|
|
|
+ dataIndex: 'state1',
|
|
|
|
+ key: 'state1',
|
|
|
|
+ ellipsis: true,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ title: '触发次数',
|
|
|
|
+ dataIndex: 'state2',
|
|
|
|
+ key: 'state2',
|
|
|
|
+ ellipsis: true,
|
|
|
|
+ width: 100,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ title: '最近触发',
|
|
|
|
+ dataIndex: 'state3',
|
|
|
|
+ key: 'state3',
|
|
|
|
+ ellipsis: true,
|
|
|
|
+ width: 220,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ title: '更新时间',
|
|
|
|
+ dataIndex: 'state4',
|
|
|
|
+ key: 'state4',
|
|
|
|
+ ellipsis: true,
|
|
|
|
+ width: 220,
|
|
|
|
+ sorter: (a: { state4: string | number | Date }, b: { state4: string | number | Date }) => {
|
|
|
|
+ const timeA = new Date(a.state4).getTime();
|
|
|
|
+ const timeB = new Date(b.state4).getTime();
|
|
|
|
+ return timeA - timeB;
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ title: '启用',
|
|
|
|
+ dataIndex: 'state',
|
|
|
|
+ key: 'state',
|
|
|
|
+ ellipsis: true,
|
|
|
|
+ width: 80,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ title: '操作',
|
|
|
|
+ dataIndex: 'action',
|
|
|
|
+ key: 'action',
|
|
|
|
+ width: 152,
|
|
|
|
+ },
|
|
|
|
+];
|
|
|
|
+
|
|
|
|
+const addAlarm = () => {
|
|
|
|
+ alarmOpen.value = true;
|
|
|
|
+};
|
|
|
|
+const alarmSearch = () => {};
|
|
|
|
+const alarmReset = () => {};
|
|
|
|
+const alarmEditor = (id: number) => {
|
|
|
|
+ console.log(id);
|
|
|
|
+};
|
|
|
|
+const alarmHistory = (id: number) => {
|
|
|
|
+ console.log(id);
|
|
|
|
+ historyOpen.value = true;
|
|
|
|
+};
|
|
|
|
+const alarmDelete = (id: number) => {
|
|
|
|
+ console.log(id);
|
|
|
|
+ modalComponentRef.value?.showView();
|
|
|
|
+};
|
|
|
|
+const confirm = () => {
|
|
|
|
+ modalComponentRef.value?.hideView();
|
|
|
|
+};
|
|
|
|
+const switchPages = () => {};
|
|
|
|
+const switchHistoryPages = () => {};
|
|
|
|
+const addTriggerConditions = () => {};
|
|
|
|
+</script>
|
|
|
|
+
|
|
<template>
|
|
<template>
|
|
- <div>报警管理</div>
|
|
|
|
|
|
+ <div>
|
|
|
|
+ <AFlex justify="space-between">
|
|
|
|
+ <div class="text-top">报警管理</div>
|
|
|
|
+ <div>
|
|
|
|
+ <AButton type="primary" class="icon-button" @click="addAlarm">
|
|
|
|
+ <AFlex align="center">
|
|
|
|
+ <SvgIcon name="plus" />
|
|
|
|
+ <span> 新增 </span>
|
|
|
|
+ </AFlex>
|
|
|
|
+ </AButton>
|
|
|
|
+ </div>
|
|
|
|
+ </AFlex>
|
|
|
|
+ <div class="content">
|
|
|
|
+ <AFlex justify="space-between" class="content-header">
|
|
|
|
+ <div>
|
|
|
|
+ <span class="query-text">搜索</span>
|
|
|
|
+ <AInput
|
|
|
|
+ v-model:value="alarmQuery.searchContent"
|
|
|
|
+ placeholder="请输入报警内容、设备"
|
|
|
|
+ class="query-input button-margin"
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+ <div>
|
|
|
|
+ <AButton type="primary" @click="alarmSearch"> 查询 </AButton>
|
|
|
|
+ <AButton class="button-margin" @click="alarmReset">重置</AButton>
|
|
|
|
+ </div>
|
|
|
|
+ </AFlex>
|
|
|
|
+
|
|
|
|
+ <ATable :columns="alarmColumns" :data-source="alarmData" :pagination="false">
|
|
|
|
+ <template #bodyCell="{ column, record }">
|
|
|
|
+ <template v-if="column.key === 'state'">
|
|
|
|
+ <ASwitch v-model:checked="record.state" />
|
|
|
|
+ </template>
|
|
|
|
+ <template v-else-if="column.key === 'action'">
|
|
|
|
+ <SvgIcon @click="alarmEditor(record.id)" class="icon-style" name="edit-o" />
|
|
|
|
+ <SvgIcon @click="alarmHistory(record.id)" class="icon-style" name="clock-circle-o" />
|
|
|
|
+ <SvgIcon @click="alarmDelete(record.id)" class="icon-style" name="delete" />
|
|
|
|
+ </template>
|
|
|
|
+ </template>
|
|
|
|
+ </ATable>
|
|
|
|
+ <br />
|
|
|
|
+ <br />
|
|
|
|
+ <AFlex justify="flex-end" class="gateway-left-footer">
|
|
|
|
+ <APagination
|
|
|
|
+ v-model:current="alarmQuery.pageIndex"
|
|
|
|
+ v-model:page-size="alarmQuery.pageSize"
|
|
|
|
+ :total="alarmQuery.total"
|
|
|
|
+ :show-size-changer="true"
|
|
|
|
+ @change="switchPages"
|
|
|
|
+ show-quick-jumper
|
|
|
|
+ :show-total="(total) => $t('common.pageTotal', { total })"
|
|
|
|
+ />
|
|
|
|
+ </AFlex>
|
|
|
|
+ </div>
|
|
|
|
+ <AModal v-model:open="alarmOpen" title="预警条件添加" width="920px" :mask-closable="false">
|
|
|
|
+ <AForm ref="formRef" class="alarm-modal" :model="alarmForm" label-align="left" layout="vertical" :rules="rules">
|
|
|
|
+ <AFormItem label="事件名称" name="name">
|
|
|
|
+ <AInput v-model:value="alarmForm.name" placeholder="请输入" class="query-input query-bottom" />
|
|
|
|
+ </AFormItem>
|
|
|
|
+ <AFormItem label="生效时间段" name="time">
|
|
|
|
+ <ATimeRangePicker
|
|
|
|
+ :format="dateFormat"
|
|
|
|
+ v-model:value="alarmForm.time"
|
|
|
|
+ :separator="$t('common.to')"
|
|
|
|
+ show-time
|
|
|
|
+ />
|
|
|
|
+ </AFormItem>
|
|
|
|
+ <div class="alarm-text">当任一情况发生</div>
|
|
|
|
+ <AlarmConditions :alarm-form="alarmForm" />
|
|
|
|
+
|
|
|
|
+ <AButton type="primary" ghost class="icon-button button-top" @click="addTriggerConditions">
|
|
|
|
+ <AFlex align="center">
|
|
|
|
+ <SvgIcon name="plus" />
|
|
|
|
+ <span> 添加触发条件 </span>
|
|
|
|
+ </AFlex></AButton
|
|
|
|
+ >
|
|
|
|
+ </AForm>
|
|
|
|
+ </AModal>
|
|
|
|
+ <AModal v-model:open="historyOpen" title="历史报警" width="920px" :footer="null">
|
|
|
|
+ <ATable :columns="historyColumns" :data-source="historyData" :pagination="false">
|
|
|
|
+ <template #bodyCell="{ column, index }">
|
|
|
|
+ <template v-if="column.key === 'index'">
|
|
|
|
+ {{ index + 1 }}
|
|
|
|
+ </template>
|
|
|
|
+ </template>
|
|
|
|
+ </ATable>
|
|
|
|
+ <br />
|
|
|
|
+ <br />
|
|
|
|
+ <AFlex justify="flex-end" class="gateway-left-footer">
|
|
|
|
+ <APagination
|
|
|
|
+ v-model:current="historyQuery.pageIndex"
|
|
|
|
+ v-model:page-size="historyQuery.pageSize"
|
|
|
|
+ :total="historyQuery.total"
|
|
|
|
+ :show-size-changer="true"
|
|
|
|
+ @change="switchHistoryPages"
|
|
|
|
+ show-quick-jumper
|
|
|
|
+ :show-total="(total) => $t('common.pageTotal', { total })"
|
|
|
|
+ />
|
|
|
|
+ </AFlex>
|
|
|
|
+ </AModal>
|
|
|
|
+ <ConfirmModal
|
|
|
|
+ ref="modalComponent"
|
|
|
|
+ :title="'删除确定'"
|
|
|
|
+ :description-text="'是否确认删除?'"
|
|
|
|
+ :icon="{ name: 'delete' }"
|
|
|
|
+ :icon-bg-color="'#F56C6C'"
|
|
|
|
+ @confirm="confirm"
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
</template>
|
|
</template>
|
|
|
|
+
|
|
|
|
+<style lang="scss" scoped>
|
|
|
|
+.query-bottom {
|
|
|
|
+ margin-bottom: 8px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.alarm-modal :deep(.ant-form-item-label > label) {
|
|
|
|
+ font-size: 14px;
|
|
|
|
+ font-style: normal;
|
|
|
|
+ font-weight: 400;
|
|
|
|
+ line-height: 22px;
|
|
|
|
+ color: #666;
|
|
|
|
+ text-align: left;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.alarm-modal :deep(.ant-form-item) {
|
|
|
|
+ margin-bottom: 16px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.button-top {
|
|
|
|
+ margin-top: 16px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.alarm-text {
|
|
|
|
+ margin-top: 8px;
|
|
|
|
+ font-size: 16px;
|
|
|
|
+ font-style: normal;
|
|
|
|
+ font-weight: 500;
|
|
|
|
+ line-height: 24px;
|
|
|
|
+ color: #333;
|
|
|
|
+ text-align: left;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.content-header {
|
|
|
|
+ margin-bottom: 16px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.icon-style {
|
|
|
|
+ margin-right: 16px;
|
|
|
|
+ font-size: 24px;
|
|
|
|
+ color: var(--antd-color-primary-hover);
|
|
|
|
+ cursor: pointer;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.button-margin {
|
|
|
|
+ margin-left: 12px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.query-input {
|
|
|
|
+ width: 256px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.content {
|
|
|
|
+ padding: 24px;
|
|
|
|
+ margin-top: 16px;
|
|
|
|
+ background: #fff;
|
|
|
|
+ border-radius: 16px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.text-top {
|
|
|
|
+ font-size: 20px;
|
|
|
|
+ font-style: normal;
|
|
|
|
+ font-weight: 500;
|
|
|
|
+ line-height: 28px;
|
|
|
|
+ color: rgb(0 0 0 / 85%);
|
|
|
|
+ text-align: left;
|
|
|
|
+}
|
|
|
|
+</style>
|