refactor: 重构项目结构
- 优化 `车站-设备-告警` 轮询机制 - 改进设备卡片的布局 - 支持修改设备 - 告警轮询中获取完整告警数据 - 车站告警详情支持导出完整的 `今日告警列表` - 支持将状态持久化到 `IndexedDB` - 新增轮询控制 (调试模式) - 新增离线开发模式 (调试模式) - 新增 `IndexedDB` 数据控制 (调试模式)
This commit is contained in:
2
src/composables/alarm/index.ts
Normal file
2
src/composables/alarm/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './use-alarm-action-column';
|
||||
export * from './use-camera-snap-column';
|
||||
149
src/composables/alarm/use-alarm-action-column.ts
Normal file
149
src/composables/alarm/use-alarm-action-column.ts
Normal file
@@ -0,0 +1,149 @@
|
||||
import { deleteCameraIgnoreApi, pageCameraIgnoreApi, saveCameraIgnoreApi, updateDeviceAlarmLogApi, type NdmDeviceAlarmLogResultVO } from '@/apis';
|
||||
import { DEVICE_TYPE_LITERALS, tryGetDeviceType } from '@/enums';
|
||||
import { parseErrorFeedback } from '@/utils';
|
||||
import { useMutation } from '@tanstack/vue-query';
|
||||
import { NButton, NFlex, NPopconfirm, type DataTableColumn, type DataTableRowData } from 'naive-ui';
|
||||
import { h, type Ref } from 'vue';
|
||||
|
||||
export const useAlarmActionColumn = (tableData: Ref<DataTableRowData[]>) => {
|
||||
const { mutate: confirmAlarm } = useMutation({
|
||||
mutationFn: async (params: { id: string | null }) => {
|
||||
const { id } = params;
|
||||
if (!id) return;
|
||||
const alarmLog = tableData.value.find((item) => item.id === id);
|
||||
if (alarmLog) {
|
||||
alarmLog['alarmConfirm'] = '1';
|
||||
}
|
||||
await updateDeviceAlarmLogApi({ id, alarmConfirm: '1' });
|
||||
},
|
||||
onError: (error, variables) => {
|
||||
console.error(error);
|
||||
const errorFeedback = parseErrorFeedback(error);
|
||||
window.$message.error(errorFeedback);
|
||||
const { id } = variables;
|
||||
if (id) {
|
||||
const alarmLog = tableData.value.find((item) => item.id === id);
|
||||
if (alarmLog) {
|
||||
alarmLog['alarmConfirm'] = '2';
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const { mutate: ignoreCamera } = useMutation({
|
||||
mutationFn: async (params: { id: string | null }) => {
|
||||
const { id } = params;
|
||||
if (!id) return;
|
||||
const alarmLog = tableData.value.find((item) => item.id === id);
|
||||
if (!alarmLog) return;
|
||||
const { records } = await pageCameraIgnoreApi({
|
||||
model: { deviceId: alarmLog.deviceId },
|
||||
extra: {},
|
||||
current: 1,
|
||||
size: 10,
|
||||
sort: 'id',
|
||||
order: 'descending',
|
||||
});
|
||||
const ignoredCamera = records.at(0);
|
||||
if (ignoredCamera) {
|
||||
window.$message.info('设备已被忽略');
|
||||
return;
|
||||
}
|
||||
await saveCameraIgnoreApi({ deviceId: alarmLog.deviceId });
|
||||
window.$message.success('忽略设备成功');
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error(error);
|
||||
const errorFeedback = parseErrorFeedback(error);
|
||||
window.$message.error(errorFeedback);
|
||||
},
|
||||
});
|
||||
|
||||
// const { mutate: noticeCamera } = useMutation({
|
||||
// mutationFn: async (params: { id: string | null }) => {
|
||||
// const { id } = params;
|
||||
// if (!id) return;
|
||||
// const alarmLog = tableData.value.find((item) => item.id === id);
|
||||
// if (!alarmLog) return;
|
||||
// const { records } = await pageCameraIgnoreApi({
|
||||
// model: { deviceId: alarmLog.deviceId },
|
||||
// extra: {},
|
||||
// current: 1,
|
||||
// size: 10,
|
||||
// sort: 'id',
|
||||
// order: 'descending',
|
||||
// });
|
||||
// if (records.length === 0) {
|
||||
// window.$message.info('设备未被忽略');
|
||||
// return;
|
||||
// }
|
||||
// await deleteCameraIgnoreApi([...records.map((record) => record.id ?? '')]);
|
||||
// window.$message.success('取消忽略设备成功');
|
||||
// },
|
||||
// onError: (error) => {
|
||||
// console.error(error);
|
||||
// const errorFeedback = parseErrorFeedback(error);
|
||||
// window.$message.error(errorFeedback);
|
||||
// },
|
||||
// });
|
||||
|
||||
const alarmActionColumn: DataTableColumn<NdmDeviceAlarmLogResultVO> = {
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
render: (rowData) => {
|
||||
const { id } = rowData;
|
||||
return h(
|
||||
NFlex,
|
||||
{
|
||||
size: 'small',
|
||||
justify: 'center',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
default: () => [
|
||||
rowData.alarmConfirm === '1'
|
||||
? h(NButton, { disabled: true, secondary: true, type: 'info', size: 'tiny' }, { default: () => '确认' })
|
||||
: h(
|
||||
NPopconfirm,
|
||||
{
|
||||
onPositiveClick: () => confirmAlarm({ id }),
|
||||
},
|
||||
{
|
||||
trigger: () => h(NButton, { secondary: true, type: 'info', size: 'tiny' }, { default: () => '确认' }),
|
||||
default: () => '确认告警?',
|
||||
},
|
||||
),
|
||||
tryGetDeviceType(rowData.deviceType) === DEVICE_TYPE_LITERALS.ndmCamera && [
|
||||
h(
|
||||
NPopconfirm,
|
||||
{
|
||||
onPositiveClick: () => ignoreCamera({ id }),
|
||||
},
|
||||
{
|
||||
trigger: () => h(NButton, { tertiary: true, type: 'info', size: 'tiny' }, { default: () => '忽略' }),
|
||||
default: () => '忽略设备?',
|
||||
},
|
||||
),
|
||||
// h(
|
||||
// NPopconfirm,
|
||||
// {
|
||||
// onPositiveClick: () => noticeCamera({ id }),
|
||||
// },
|
||||
// {
|
||||
// trigger: () => h(NButton, { text: true, type: 'info', size: 'small' }, { icon: () => h(EyeOutlined) }),
|
||||
// default: () => '取消忽略设备?',
|
||||
// },
|
||||
// ),
|
||||
],
|
||||
],
|
||||
},
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
alarmActionColumn,
|
||||
};
|
||||
};
|
||||
66
src/composables/alarm/use-camera-snap-column.ts
Normal file
66
src/composables/alarm/use-camera-snap-column.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import { getCameraSnapApi, type NdmDeviceAlarmLogResultVO } from '@/apis';
|
||||
import { tryGetDeviceType, DEVICE_TYPE_LITERALS } from '@/enums';
|
||||
import { parseErrorFeedback } from '@/utils';
|
||||
import { useMutation } from '@tanstack/vue-query';
|
||||
import { NButton, NImage, type DataTableColumn, type DataTableRowData } from 'naive-ui';
|
||||
import { h, ref, watch, type Ref } from 'vue';
|
||||
|
||||
export const useCameraSnapColumn = (tableData: Ref<DataTableRowData[]>) => {
|
||||
const { mutateAsync: getSnapByDeviceId } = useMutation({
|
||||
mutationFn: async (params: { deviceAlarmLog: NdmDeviceAlarmLogResultVO }) => {
|
||||
const { deviceAlarmLog } = params;
|
||||
const { deviceId } = deviceAlarmLog;
|
||||
if (!deviceId) throw new Error('设备ID不能为空');
|
||||
const snap = await getCameraSnapApi(deviceId);
|
||||
return snap;
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error(error);
|
||||
const errorFeedback = parseErrorFeedback(error);
|
||||
window.$message.error(errorFeedback);
|
||||
},
|
||||
});
|
||||
|
||||
// 控制每一行的查看按钮loading状态
|
||||
const loadingMap = ref<Record<string, boolean>>({});
|
||||
watch(tableData, () => {
|
||||
loadingMap.value = {};
|
||||
});
|
||||
|
||||
const cameraSnapColumn: DataTableColumn<NdmDeviceAlarmLogResultVO & { snapUrl?: string }> = {
|
||||
title: '实时画面截图',
|
||||
key: 'snapUrl',
|
||||
align: 'center',
|
||||
render: (rowData) => {
|
||||
const { deviceType: deviceTypeCode, snapUrl } = rowData;
|
||||
const deviceType = tryGetDeviceType(deviceTypeCode);
|
||||
if (deviceType !== DEVICE_TYPE_LITERALS.ndmCamera) return null;
|
||||
if (!snapUrl) {
|
||||
const id = rowData.id ?? '';
|
||||
return h(
|
||||
NButton,
|
||||
{
|
||||
type: 'info',
|
||||
size: 'small',
|
||||
loading: !!loadingMap.value[id],
|
||||
onClick: async () => {
|
||||
loadingMap.value[id] = true;
|
||||
try {
|
||||
const snap = await getSnapByDeviceId({ deviceAlarmLog: rowData });
|
||||
rowData.snapUrl = snap.url;
|
||||
} finally {
|
||||
loadingMap.value[id] = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
{ default: () => '查看' },
|
||||
);
|
||||
} else {
|
||||
return h(NImage, { src: snapUrl, previewDisabled: false, showToolbar: false });
|
||||
}
|
||||
},
|
||||
};
|
||||
return {
|
||||
cameraSnapColumn,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user