| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <script lang="ts" setup> |
| | | import type { Ref } from 'vue'; |
| | | |
| | | import type { MesCollectApi } from '#/api/mes/collect'; |
| | | |
| | | import { computed, onMounted, onUnmounted, ref } from 'vue'; |
| | | |
| | | import { Page } from '@vben/common-ui'; |
| | | import { formatDateTime } from '@vben/utils'; |
| | | |
| | | import { |
| | | Button, |
| | | Descriptions, |
| | | Drawer, |
| | | Empty, |
| | | message, |
| | | Modal, |
| | | Popconfirm, |
| | | Space, |
| | | Table, |
| | | Tabs, |
| | | Tag, |
| | | } from 'ant-design-vue'; |
| | | |
| | | import { |
| | | ackCollectAlarm, |
| | | getCollectAlarmPage, |
| | | getCollectCyclePage, |
| | | getCollectDeviceList, |
| | | getCollectOperateLogPage, |
| | | getCollectRealtime, |
| | | getCollectRealtimeHistoryPage, |
| | | getCollectTech, |
| | | } from '#/api/mes/collect'; |
| | | |
| | | defineOptions({ name: 'MesCollectMonitor' }); |
| | | |
| | | interface PageData<T> { |
| | | list: T[]; |
| | | total: number; |
| | | } |
| | | |
| | | interface PageQuery { |
| | | current?: number; |
| | | pageSize?: number; |
| | | } |
| | | |
| | | const deviceLoading = ref(false); |
| | | const devices = ref<MesCollectApi.Device[]>([]); |
| | | const lastRefreshAt = ref(''); |
| | | let refreshTimer: ReturnType<typeof setInterval> | undefined; |
| | | |
| | | const drawerOpen = ref(false); |
| | | const currentDevice = ref<MesCollectApi.Device>(); |
| | | const activeTab = ref('realtime'); |
| | | |
| | | const realtime = ref<MesCollectApi.Realtime | null>(null); |
| | | const realtimeLoading = ref(false); |
| | | const tech = ref<MesCollectApi.Tech | null>(null); |
| | | const techLoading = ref(false); |
| | | |
| | | const rawJsonOpen = ref(false); |
| | | const rawJsonTitle = ref(''); |
| | | const rawJsonContent = ref(''); |
| | | |
| | | const drawerTitle = computed(() => { |
| | | const device = currentDevice.value; |
| | | if (!device) { |
| | | return 'æ°é设å¤è¯¦æ
'; |
| | | } |
| | | return `${device.machineryName ?? ''}ï¼${device.collectDeviceCode ?? ''}ï¼`; |
| | | }); |
| | | |
| | | const onlineCount = computed( |
| | | () => devices.value.filter((item) => item.online).length, |
| | | ); |
| | | |
| | | const alarmCount = computed(() => |
| | | devices.value.reduce( |
| | | (total, item) => total + Number(item.activeAlarmCount ?? 0), |
| | | 0, |
| | | ), |
| | | ); |
| | | |
| | | function usePagedTable<T>( |
| | | label: string, |
| | | loader: (pageNo: number, pageSize: number) => Promise<PageData<T>>, |
| | | ) { |
| | | const loading = ref(false); |
| | | const rows = ref([]) as Ref<T[]>; |
| | | const total = ref(0); |
| | | const pageNo = ref(1); |
| | | const pageSize = ref(10); |
| | | |
| | | async function load() { |
| | | loading.value = true; |
| | | try { |
| | | const data = await loader(pageNo.value, pageSize.value); |
| | | rows.value = data.list ?? []; |
| | | total.value = data.total ?? 0; |
| | | } catch { |
| | | rows.value = []; |
| | | total.value = 0; |
| | | message.error(`${label}å 载失败ï¼è¯·ç¨åéè¯`); |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | } |
| | | |
| | | function changePage(page: PageQuery) { |
| | | pageNo.value = page.current ?? 1; |
| | | pageSize.value = page.pageSize ?? 10; |
| | | void load(); |
| | | } |
| | | |
| | | function reset() { |
| | | pageNo.value = 1; |
| | | pageSize.value = 10; |
| | | rows.value = []; |
| | | total.value = 0; |
| | | } |
| | | |
| | | return { changePage, load, loading, pageNo, pageSize, reset, rows, total }; |
| | | } |
| | | |
| | | const realtimeHistory = usePagedTable<MesCollectApi.Realtime>( |
| | | '宿¶ç¶æåå²', |
| | | async (pageNo, pageSize) => |
| | | await getCollectRealtimeHistoryPage({ |
| | | pageNo, |
| | | pageSize, |
| | | deviceCode: currentDevice.value?.collectDeviceCode, |
| | | }), |
| | | ); |
| | | const cyclePage = usePagedTable<MesCollectApi.Cycle>( |
| | | '卿è¿ç¨æ°æ®', |
| | | async (pageNo, pageSize) => |
| | | await getCollectCyclePage({ |
| | | pageNo, |
| | | pageSize, |
| | | deviceCode: currentDevice.value?.collectDeviceCode, |
| | | }), |
| | | ); |
| | | const operateLogPage = usePagedTable<MesCollectApi.OperateLog>( |
| | | 'åæ°åæ´æ¥å¿', |
| | | async (pageNo, pageSize) => |
| | | await getCollectOperateLogPage({ |
| | | pageNo, |
| | | pageSize, |
| | | deviceCode: currentDevice.value?.collectDeviceCode, |
| | | }), |
| | | ); |
| | | const alarmPage = usePagedTable<MesCollectApi.Alarm>( |
| | | 'æ¥è¦è®°å½', |
| | | async (pageNo, pageSize) => |
| | | await getCollectAlarmPage({ |
| | | pageNo, |
| | | pageSize, |
| | | deviceCode: currentDevice.value?.collectDeviceCode, |
| | | }), |
| | | ); |
| | | |
| | | const deviceColumns = [ |
| | | { title: '设å¤', key: 'device', width: 220, fixed: 'left' as const }, |
| | | { title: 'æ°éç¼ç ', dataIndex: 'collectDeviceCode', width: 110 }, |
| | | { title: 'å¨çº¿', key: 'online', width: 90 }, |
| | | { title: 'è¿è¡ç¶æ', key: 'sts', width: 100 }, |
| | | { title: 'è¿è¡æ¨¡å¼', key: 'opm', width: 110 }, |
| | | { title: '油温(â)', dataIndex: 'ot', width: 100 }, |
| | | { title: 'å½åä»»å¡', key: 'task', width: 220 }, |
| | | { title: 'ç产工å', dataIndex: 'workOrderCode', width: 160 }, |
| | | { title: 'æªæ¶é¤æ¥è¦', key: 'alarm', width: 110 }, |
| | | { |
| | | title: 'æè¿ééæ¶é´', |
| | | dataIndex: 'lastCollectTime', |
| | | key: 'lastCollectTime', |
| | | width: 180, |
| | | }, |
| | | { title: 'æä½', key: 'action', width: 110, fixed: 'right' as const }, |
| | | ]; |
| | | |
| | | const realtimeHistoryColumns = [ |
| | | { |
| | | title: 'ééæ¶é´', |
| | | dataIndex: 'collectTime', |
| | | key: 'collectTime', |
| | | width: 180, |
| | | }, |
| | | { title: 'è¿è¡ç¶æ', dataIndex: 'stsName', width: 100 }, |
| | | { title: 'è¿è¡æ¨¡å¼', dataIndex: 'opmName', width: 110 }, |
| | | { title: '油温(â)', dataIndex: 'ot', width: 100 }, |
| | | { title: 'éå ç¶æ', dataIndex: 'asts', width: 100 }, |
| | | { title: '温度', key: 'temps', minWidth: 220 }, |
| | | { title: 'åå§æ°æ®', key: 'raw', width: 100 }, |
| | | ]; |
| | | |
| | | const cycleColumns = [ |
| | | { title: '卿åºå·', dataIndex: 'cycleNo', width: 110 }, |
| | | { |
| | | title: 'ééæ¶é´', |
| | | dataIndex: 'collectTime', |
| | | key: 'collectTime', |
| | | width: 180, |
| | | }, |
| | | { title: '卿æ¶é´', dataIndex: 'ecyct', width: 100 }, |
| | | { title: 'å°åºæ¶é´', dataIndex: 'eipt', width: 100 }, |
| | | { title: 'æå¤§å°é', dataIndex: 'eivm', width: 100 }, |
| | | { title: 'æå¤§å°å', dataIndex: 'eipm', width: 100 }, |
| | | { title: '转ä¿åæ¶é´', dataIndex: 'esipt', width: 110 }, |
| | | { title: '转ä¿ååå', dataIndex: 'esipp', width: 110 }, |
| | | { title: '卿æ¶é´', dataIndex: 'eplst', width: 100 }, |
| | | { title: '温度', key: 'etTemps', minWidth: 220 }, |
| | | { title: 'åå§æ°æ®', key: 'raw', width: 100 }, |
| | | ]; |
| | | |
| | | const operateLogColumns = [ |
| | | { title: 'åéç¼ç ', dataIndex: 'varId', width: 120 }, |
| | | { title: 'ä¿®æ¹å', dataIndex: 'oldValue', width: 150 }, |
| | | { title: 'ä¿®æ¹å', dataIndex: 'newValue', width: 150 }, |
| | | { title: 'ä¿®æ¹æ¶é´', dataIndex: 'modifyTime', key: 'modifyTime', width: 180 }, |
| | | { title: 'ééæ¶é´', dataIndex: 'collectTime', key: 'collectTime', width: 180 }, |
| | | { title: 'åå§æ°æ®', key: 'raw', width: 100 }, |
| | | ]; |
| | | |
| | | const alarmColumns = [ |
| | | { title: 'æ¥è¦æ¶é´', dataIndex: 'wmTime', key: 'wmTime', width: 180 }, |
| | | { title: 'æ¥è¦å
容', dataIndex: 'wmMsg', minWidth: 220 }, |
| | | { title: 'ç¶æ', key: 'status', width: 100 }, |
| | | { title: 'æ¶é¤æ¶é´', dataIndex: 'clearTime', key: 'clearTime', width: 180 }, |
| | | { title: 'ééæ¶é´', dataIndex: 'collectTime', key: 'collectTime', width: 180 }, |
| | | { title: 'æä½', key: 'action', width: 120, fixed: 'right' as const }, |
| | | ]; |
| | | |
| | | async function loadDevices() { |
| | | deviceLoading.value = true; |
| | | try { |
| | | devices.value = await getCollectDeviceList(); |
| | | lastRefreshAt.value = formatDateTime(new Date()); |
| | | } catch { |
| | | message.error('æ°é设å¤ç¶æå 载失败ï¼è¯·ç¹å»âå·æ°âéè¯'); |
| | | } finally { |
| | | deviceLoading.value = false; |
| | | } |
| | | } |
| | | |
| | | function resetDetailData() { |
| | | realtime.value = null; |
| | | tech.value = null; |
| | | realtimeHistory.reset(); |
| | | cyclePage.reset(); |
| | | operateLogPage.reset(); |
| | | alarmPage.reset(); |
| | | } |
| | | |
| | | async function loadRealtime() { |
| | | const deviceCode = currentDevice.value?.collectDeviceCode; |
| | | if (!deviceCode) { |
| | | return; |
| | | } |
| | | realtimeLoading.value = true; |
| | | try { |
| | | realtime.value = await getCollectRealtime(deviceCode); |
| | | } catch { |
| | | realtime.value = null; |
| | | message.error('设å¤å®æ¶ç¶æå 载失败ï¼è¯·å
³é详æ
åéæ°æå¼'); |
| | | } finally { |
| | | realtimeLoading.value = false; |
| | | } |
| | | void realtimeHistory.load(); |
| | | } |
| | | |
| | | async function loadTech() { |
| | | const deviceCode = currentDevice.value?.collectDeviceCode; |
| | | if (!deviceCode) { |
| | | return; |
| | | } |
| | | techLoading.value = true; |
| | | try { |
| | | tech.value = await getCollectTech(deviceCode); |
| | | } catch { |
| | | tech.value = null; |
| | | message.error('å·¥èºåæ°å 载失败ï¼è¯·åæ¢å°å
¶å®é¡µç¾åéè¯'); |
| | | } finally { |
| | | techLoading.value = false; |
| | | } |
| | | } |
| | | |
| | | function openDetail(device: MesCollectApi.Device) { |
| | | currentDevice.value = device; |
| | | activeTab.value = 'realtime'; |
| | | resetDetailData(); |
| | | drawerOpen.value = true; |
| | | void loadRealtime(); |
| | | } |
| | | |
| | | function handleTabChange(key: number | string) { |
| | | const tab = String(key); |
| | | if (tab === 'realtime') { |
| | | void loadRealtime(); |
| | | } else if (tab === 'cycle') { |
| | | void cyclePage.load(); |
| | | } else if (tab === 'tech') { |
| | | void loadTech(); |
| | | } else if (tab === 'oplog') { |
| | | void operateLogPage.load(); |
| | | } else if (tab === 'alarm') { |
| | | void alarmPage.load(); |
| | | } |
| | | } |
| | | |
| | | async function handleAck(row: MesCollectApi.Alarm) { |
| | | if (!row.id) { |
| | | return; |
| | | } |
| | | try { |
| | | await ackCollectAlarm(row.id); |
| | | message.success('æ¥è¦å·²ç¡®è®¤æ¶é¤'); |
| | | void alarmPage.load(); |
| | | void loadDevices(); |
| | | } catch { |
| | | message.error('æ¥è¦ç¡®è®¤å¤±è´¥ï¼è®°å½å¯è½å·²è¢«è®¾å¤èªå¨æ¶é¤ï¼è¯·å·æ°åéè¯'); |
| | | void alarmPage.load(); |
| | | } |
| | | } |
| | | |
| | | function safeParseObject(text?: string): null | Record<string, unknown> { |
| | | if (!text) { |
| | | return null; |
| | | } |
| | | try { |
| | | const value = JSON.parse(text) as unknown; |
| | | return value && typeof value === 'object' |
| | | ? (value as Record<string, unknown>) |
| | | : null; |
| | | } catch { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | function formatNumberedFields(text?: string) { |
| | | const value = safeParseObject(text); |
| | | if (!value) { |
| | | return ''; |
| | | } |
| | | return Object.entries(value) |
| | | .map(([key, item]) => `${key}: ${String(item ?? '')}`) |
| | | .join('ï¼'); |
| | | } |
| | | |
| | | function showRaw(title: string, json?: string) { |
| | | rawJsonTitle.value = title; |
| | | rawJsonContent.value = prettyJson(json); |
| | | rawJsonOpen.value = true; |
| | | } |
| | | |
| | | function prettyJson(json?: string) { |
| | | if (!json) { |
| | | return 'ææ åå§æ°æ®'; |
| | | } |
| | | try { |
| | | return JSON.stringify(JSON.parse(json), null, 2); |
| | | } catch { |
| | | return json; |
| | | } |
| | | } |
| | | |
| | | onMounted(() => { |
| | | void loadDevices(); |
| | | refreshTimer = setInterval(() => { |
| | | if (!drawerOpen.value) { |
| | | void loadDevices(); |
| | | } |
| | | }, 30_000); |
| | | }); |
| | | |
| | | onUnmounted(() => { |
| | | if (refreshTimer) { |
| | | clearInterval(refreshTimer); |
| | | } |
| | | }); |
| | | </script> |
| | | |
| | | <template> |
| | | <Page auto-content-height> |
| | | <div |
| | | class="mb-4 flex flex-wrap items-center justify-between gap-3" |
| | | > |
| | | <div class="flex flex-wrap items-center gap-4"> |
| | | <h2 class="text-lg font-semibold">æ°éçæ§</h2> |
| | | <span class="text-sm text-gray-500"> |
| | | å¨çº¿ {{ onlineCount }} / {{ devices.length }} å° |
| | | </span> |
| | | <span class="text-sm text-gray-500"> |
| | | æªæ¶é¤æ¥è¦ {{ alarmCount }} æ¡ |
| | | </span> |
| | | <span v-if="lastRefreshAt" class="text-sm text-gray-400"> |
| | | å·æ°äº {{ lastRefreshAt }} |
| | | </span> |
| | | </div> |
| | | <Button type="primary" :loading="deviceLoading" @click="loadDevices"> |
| | | å·æ° |
| | | </Button> |
| | | </div> |
| | | |
| | | <Table |
| | | :columns="deviceColumns" |
| | | :data-source="devices" |
| | | :loading="deviceLoading" |
| | | :pagination="false" |
| | | :scroll="{ x: 1600 }" |
| | | row-key="machineryId" |
| | | size="middle" |
| | | > |
| | | <template #bodyCell="{ column, record }"> |
| | | <template v-if="column.key === 'device'"> |
| | | <div class="font-medium"> |
| | | {{ (record as MesCollectApi.Device).machineryName }} |
| | | </div> |
| | | <div class="text-xs text-gray-500"> |
| | | {{ (record as MesCollectApi.Device).machineryCode }} |
| | | <span v-if="(record as MesCollectApi.Device).workstationName"> |
| | | · {{ (record as MesCollectApi.Device).workstationName }} |
| | | </span> |
| | | </div> |
| | | </template> |
| | | <template v-else-if="column.key === 'online'"> |
| | | <Tag |
| | | :color="(record as MesCollectApi.Device).online ? 'success' : 'default'" |
| | | > |
| | | {{ (record as MesCollectApi.Device).online ? 'å¨çº¿' : '离线' }} |
| | | </Tag> |
| | | </template> |
| | | <template v-else-if="column.key === 'sts'"> |
| | | <Tag |
| | | :color=" |
| | | (record as MesCollectApi.Device).sts === 2 ? 'processing' : 'default' |
| | | " |
| | | > |
| | | {{ (record as MesCollectApi.Device).stsName || '-' }} |
| | | </Tag> |
| | | </template> |
| | | <template v-else-if="column.key === 'opm'"> |
| | | {{ (record as MesCollectApi.Device).opmName || '-' }} |
| | | </template> |
| | | <template v-else-if="column.key === 'task'"> |
| | | <div v-if="(record as MesCollectApi.Device).taskId"> |
| | | <div>{{ (record as MesCollectApi.Device).taskName }}</div> |
| | | <div class="text-xs text-gray-500"> |
| | | {{ (record as MesCollectApi.Device).taskCode }} |
| | | </div> |
| | | </div> |
| | | <span v-else class="text-gray-400">æ è¿è¡ä»»å¡</span> |
| | | </template> |
| | | <template v-else-if="column.key === 'alarm'"> |
| | | <Tag |
| | | :color=" |
| | | Number((record as MesCollectApi.Device).activeAlarmCount) > 0 |
| | | ? 'error' |
| | | : 'default' |
| | | " |
| | | > |
| | | {{ (record as MesCollectApi.Device).activeAlarmCount ?? 0 }} |
| | | </Tag> |
| | | </template> |
| | | <template v-else-if="column.key === 'lastCollectTime'"> |
| | | {{ formatDateTime((record as MesCollectApi.Device).lastCollectTime) || '-' }} |
| | | </template> |
| | | <template v-else-if="column.key === 'action'"> |
| | | <Button type="link" @click="openDetail(record as MesCollectApi.Device)"> |
| | | æ¥ç详æ
|
| | | </Button> |
| | | </template> |
| | | </template> |
| | | </Table> |
| | | |
| | | <Drawer |
| | | v-model:open="drawerOpen" |
| | | :title="drawerTitle" |
| | | destroy-on-close |
| | | width="90%" |
| | | > |
| | | <Tabs v-model:active-key="activeTab" @change="handleTabChange"> |
| | | <Tabs.TabPane key="realtime" tab="宿¶ç¶æ"> |
| | | <div v-loading="realtimeLoading" class="mb-4"> |
| | | <Descriptions v-if="realtime" bordered size="small" :column="4"> |
| | | <Descriptions.Item label="ééæ¶é´"> |
| | | {{ formatDateTime(realtime.collectTime) || '-' }} |
| | | </Descriptions.Item> |
| | | <Descriptions.Item label="è¿è¡ç¶æ"> |
| | | {{ realtime.stsName || '-' }} |
| | | </Descriptions.Item> |
| | | <Descriptions.Item label="è¿è¡æ¨¡å¼"> |
| | | {{ realtime.opmName || '-' }} |
| | | </Descriptions.Item> |
| | | <Descriptions.Item label="油温"> |
| | | {{ realtime.ot ?? '-' }} |
| | | </Descriptions.Item> |
| | | <Descriptions.Item label="åæ®µæ¸©åº¦" :span="4"> |
| | | <div class="max-h-24 overflow-auto"> |
| | | {{ formatNumberedFields(realtime.temps) || '-' }} |
| | | </div> |
| | | </Descriptions.Item> |
| | | </Descriptions> |
| | | <Empty v-else description="ææ å®æ¶æ°æ®" /> |
| | | </div> |
| | | <Table |
| | | :columns="realtimeHistoryColumns" |
| | | :data-source="realtimeHistory.rows.value" |
| | | :loading="realtimeHistory.loading.value" |
| | | :pagination="{ |
| | | current: realtimeHistory.pageNo.value, |
| | | pageSize: realtimeHistory.pageSize.value, |
| | | total: realtimeHistory.total.value, |
| | | showSizeChanger: true, |
| | | showTotal: (total: number) => `å
± ${total} æ¡`, |
| | | }" |
| | | :scroll="{ x: 1200 }" |
| | | row-key="id" |
| | | size="small" |
| | | @change="realtimeHistory.changePage" |
| | | > |
| | | <template #bodyCell="{ column, record }"> |
| | | <template v-if="column.key === 'temps'"> |
| | | <div class="max-h-20 overflow-auto text-xs"> |
| | | {{ formatNumberedFields((record as MesCollectApi.Realtime).temps) || '-' }} |
| | | </div> |
| | | </template> |
| | | <template v-else-if="column.key === 'raw'"> |
| | | <Button |
| | | type="link" |
| | | size="small" |
| | | @click=" |
| | | showRaw( |
| | | '宿¶ç¶æåå§æ°æ®', |
| | | (record as MesCollectApi.Realtime).dataJson, |
| | | ) |
| | | " |
| | | > |
| | | æ¥ç |
| | | </Button> |
| | | </template> |
| | | <template v-else-if="column.key === 'collectTime'"> |
| | | {{ formatDateTime((record as MesCollectApi.Realtime).collectTime) || '-' }} |
| | | </template> |
| | | </template> |
| | | </Table> |
| | | </Tabs.TabPane> |
| | | |
| | | <Tabs.TabPane key="cycle" tab="卿è¿ç¨"> |
| | | <Table |
| | | :columns="cycleColumns" |
| | | :data-source="cyclePage.rows.value" |
| | | :loading="cyclePage.loading.value" |
| | | :pagination="{ |
| | | current: cyclePage.pageNo.value, |
| | | pageSize: cyclePage.pageSize.value, |
| | | total: cyclePage.total.value, |
| | | showSizeChanger: true, |
| | | showTotal: (total: number) => `å
± ${total} æ¡`, |
| | | }" |
| | | :scroll="{ x: 1500 }" |
| | | row-key="id" |
| | | size="small" |
| | | @change="cyclePage.changePage" |
| | | > |
| | | <template #bodyCell="{ column, record }"> |
| | | <template v-if="column.key === 'etTemps'"> |
| | | <div class="max-h-20 overflow-auto text-xs"> |
| | | {{ formatNumberedFields((record as MesCollectApi.Cycle).etTemps) || '-' }} |
| | | </div> |
| | | </template> |
| | | <template v-else-if="column.key === 'raw'"> |
| | | <Button |
| | | type="link" |
| | | size="small" |
| | | @click=" |
| | | showRaw( |
| | | '卿è¿ç¨åå§æ°æ®', |
| | | (record as MesCollectApi.Cycle).dataJson, |
| | | ) |
| | | " |
| | | > |
| | | æ¥ç |
| | | </Button> |
| | | </template> |
| | | <template v-else-if="column.key === 'collectTime'"> |
| | | {{ formatDateTime((record as MesCollectApi.Cycle).collectTime) || '-' }} |
| | | </template> |
| | | </template> |
| | | </Table> |
| | | </Tabs.TabPane> |
| | | |
| | | <Tabs.TabPane key="tech" tab="å·¥èºåæ°"> |
| | | <div v-loading="techLoading"> |
| | | <div v-if="tech" class="mb-3 text-sm text-gray-500"> |
| | | ééæ¶é´ï¼{{ formatDateTime(tech.collectTime) || '-' }} |
| | | </div> |
| | | <pre |
| | | v-if="tech" |
| | | class="max-h-[65vh] overflow-auto rounded bg-gray-50 p-4 text-xs" |
| | | >{{ prettyJson(tech.dataJson) }}</pre> |
| | | <Empty v-else description="ææ å·¥èºåæ°" /> |
| | | </div> |
| | | </Tabs.TabPane> |
| | | |
| | | <Tabs.TabPane key="oplog" tab="åæ°åæ´"> |
| | | <Table |
| | | :columns="operateLogColumns" |
| | | :data-source="operateLogPage.rows.value" |
| | | :loading="operateLogPage.loading.value" |
| | | :pagination="{ |
| | | current: operateLogPage.pageNo.value, |
| | | pageSize: operateLogPage.pageSize.value, |
| | | total: operateLogPage.total.value, |
| | | showSizeChanger: true, |
| | | showTotal: (total: number) => `å
± ${total} æ¡`, |
| | | }" |
| | | :scroll="{ x: 1000 }" |
| | | row-key="id" |
| | | size="small" |
| | | @change="operateLogPage.changePage" |
| | | > |
| | | <template #bodyCell="{ column, record }"> |
| | | <template v-if="column.key === 'raw'"> |
| | | <Button |
| | | type="link" |
| | | size="small" |
| | | @click=" |
| | | showRaw( |
| | | 'åæ°åæ´åå§æ°æ®', |
| | | (record as MesCollectApi.OperateLog).dataJson, |
| | | ) |
| | | " |
| | | > |
| | | æ¥ç |
| | | </Button> |
| | | </template> |
| | | <template v-else-if="column.key === 'modifyTime'"> |
| | | {{ formatDateTime((record as MesCollectApi.OperateLog).modifyTime) || '-' }} |
| | | </template> |
| | | <template v-else-if="column.key === 'collectTime'"> |
| | | {{ formatDateTime((record as MesCollectApi.OperateLog).collectTime) || '-' }} |
| | | </template> |
| | | </template> |
| | | </Table> |
| | | </Tabs.TabPane> |
| | | |
| | | <Tabs.TabPane key="alarm" tab="æ¥è¦è®°å½"> |
| | | <Table |
| | | :columns="alarmColumns" |
| | | :data-source="alarmPage.rows.value" |
| | | :loading="alarmPage.loading.value" |
| | | :pagination="{ |
| | | current: alarmPage.pageNo.value, |
| | | pageSize: alarmPage.pageSize.value, |
| | | total: alarmPage.total.value, |
| | | showSizeChanger: true, |
| | | showTotal: (total: number) => `å
± ${total} æ¡`, |
| | | }" |
| | | :scroll="{ x: 1000 }" |
| | | row-key="id" |
| | | size="small" |
| | | @change="alarmPage.changePage" |
| | | > |
| | | <template #bodyCell="{ column, record }"> |
| | | <template v-if="column.key === 'status'"> |
| | | <Tag |
| | | :color=" |
| | | (record as MesCollectApi.Alarm).status === 0 |
| | | ? 'error' |
| | | : 'success' |
| | | " |
| | | > |
| | | {{ (record as MesCollectApi.Alarm).statusName || '-' }} |
| | | </Tag> |
| | | </template> |
| | | <template v-else-if="column.key === 'action'"> |
| | | <Popconfirm |
| | | v-if="(record as MesCollectApi.Alarm).status === 0" |
| | | title="确认已å¤çå¹¶æ¶é¤è¯¥æ¥è¦ï¼" |
| | | @confirm="handleAck(record as MesCollectApi.Alarm)" |
| | | > |
| | | <Button |
| | | v-access:code="['mes:collect-alarm:ack']" |
| | | type="link" |
| | | size="small" |
| | | > |
| | | 确认æ¶é¤ |
| | | </Button> |
| | | </Popconfirm> |
| | | <span v-else class="text-gray-400">å·²æ¶é¤</span> |
| | | </template> |
| | | <template v-else-if="column.key === 'wmTime'"> |
| | | {{ formatDateTime((record as MesCollectApi.Alarm).wmTime) || '-' }} |
| | | </template> |
| | | <template v-else-if="column.key === 'clearTime'"> |
| | | {{ formatDateTime((record as MesCollectApi.Alarm).clearTime) || '-' }} |
| | | </template> |
| | | <template v-else-if="column.key === 'collectTime'"> |
| | | {{ formatDateTime((record as MesCollectApi.Alarm).collectTime) || '-' }} |
| | | </template> |
| | | </template> |
| | | </Table> |
| | | </Tabs.TabPane> |
| | | </Tabs> |
| | | </Drawer> |
| | | |
| | | <Modal |
| | | v-model:open="rawJsonOpen" |
| | | :title="rawJsonTitle" |
| | | :footer="null" |
| | | width="800px" |
| | | > |
| | | <pre class="max-h-[70vh] overflow-auto rounded bg-gray-50 p-4 text-xs">{{ |
| | | rawJsonContent |
| | | }}</pre> |
| | | </Modal> |
| | | </Page> |
| | | </template> |