Files
ndm-web-platform/src/pages/vimp-log-page.vue

333 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script lang="ts">
const vimpOperationTypeOptions: SelectOption[] = [
{ label: '视频点播', value: 10001 },
{ label: '视频回放', value: 10002 },
// { label: '停止视频回放', value: 10003 },
// { label: '回放暂停', value: 10004 },
// { label: '回放恢复', value: 10005 },
// { label: '回放倍速播放', value: 10006 },
// { label: '回放拖动播放', value: 10007 },
{ label: '云台指令', value: 10008 },
{ label: '根据国标码查录像', value: 10009 },
{ label: '下载录像', value: 10010 },
{ label: '停止下载录像', value: 10011 },
{ label: '获取预置位列表', value: 10012 },
{ label: '设置本平台分屏数量', value: 20001 },
{ label: '设置本平台monitor播放的摄像机rtsp流', value: 20002 },
{ label: '停止本平台monitor播放的摄像机rtsp流', value: 20003 },
{ label: '启动非报警时序', value: 30001 },
{ label: '停止非报警时序', value: 30002 },
{ label: '暂停非报警时序', value: 30003 },
{ label: '调用组切', value: 30004 },
{ label: '启动报警时序', value: 40001 },
{ label: '停止报警时序', value: 40002 },
{ label: '分页查询报警', value: 50001 },
{ label: '确认报警', value: 50002 },
{ label: '删除报警', value: 50004 },
];
</script>
<script setup lang="ts">
import { exportVimpLogApi, pageVimpLogApi, type NdmVimpLog, type NdmVimpLogResultVO, type PageQueryExtra, type Station } from '@/apis';
import { useStationStore } from '@/stores';
import { downloadByData, parseErrorFeedback } from '@/utils';
import { useMutation } from '@tanstack/vue-query';
import dayjs from 'dayjs';
import destr from 'destr';
import {
NButton,
NDataTable,
NDatePicker,
NFlex,
NForm,
NFormItemGi,
NGrid,
NGridItem,
NPopover,
NScrollbar,
NSelect,
NTag,
type DataTableColumns,
type DataTableRowData,
type PaginationProps,
type SelectOption,
} from 'naive-ui';
import { storeToRefs } from 'pinia';
import { computed, h, reactive, ref, watch, watchEffect } from 'vue';
interface SearchFields extends PageQueryExtra<NdmVimpLog> {
stationCode?: Station['code'];
logType_in: number[];
createdTime: [string, string];
}
const stationStore = useStationStore();
const { stations, onlineStations } = storeToRefs(stationStore);
const stationSelectOptions = computed(() => {
return stations.value.map<SelectOption>((station) => ({
label: station.name,
value: station.code,
disabled: !station.online,
}));
});
const searchFields = ref<SearchFields>({
logType_in: [],
createdTime: [dayjs().startOf('date').subtract(1, 'week').format('YYYY-MM-DD HH:mm:ss'), dayjs().endOf('date').format('YYYY-MM-DD HH:mm:ss')] as [string, string],
});
const resetSearchFields = () => {
searchFields.value = {
stationCode: onlineStations.value.at(0)?.code,
logType_in: [],
createdTime: [dayjs().startOf('date').subtract(1, 'week').format('YYYY-MM-DD HH:mm:ss'), dayjs().endOf('date').format('YYYY-MM-DD HH:mm:ss')] as [string, string],
};
};
const getExtraFields = (): PageQueryExtra<NdmVimpLog> => {
const createdTime_precisest = searchFields.value.createdTime[0];
const createdTime_preciseed = searchFields.value.createdTime[1];
const logType_in = (searchFields.value.logType_in ?? []).length > 0 ? [...searchFields.value.logType_in] : undefined;
return {
createdTime_precisest,
createdTime_preciseed,
logType_in,
};
};
const searchFieldsChanged = ref(false);
watch(searchFields, () => {
searchFieldsChanged.value = true;
});
const tableColumns: DataTableColumns<NdmVimpLogResultVO> = [
{ title: '时间', key: 'createdTime' },
{ title: '操作类型', key: 'description' },
{ title: '请求IP', key: 'requestIp' },
{ title: '耗时(ms)', key: 'consumedTime' },
{ title: '被调用设备', key: 'targetCode' },
{
title: '操作参数',
key: 'params',
width: 100,
render(rowData) {
const result = JSON.stringify(destr(rowData.params), null, 2);
return h(
NPopover,
{ trigger: 'click' },
{
trigger: () => h(NButton, { size: 'tiny', text: true, type: 'primary' }, { default: () => '查看' }),
default: () =>
h(
NScrollbar,
{ style: { maxHeight: '40vh' } },
{
default: () => h('pre', {}, { default: () => result }),
},
),
},
);
},
},
{
title: '操作结果',
key: 'result',
width: 100,
render: (rowData) => {
const result = JSON.stringify(destr(rowData.result), null, 2);
return h(
NPopover,
{ trigger: 'click' },
{
trigger: () => h(NButton, { size: 'tiny', text: true, type: 'primary' }, { default: () => '查看' }),
default: () =>
h(
NScrollbar,
{ style: { maxHeight: '40vh' } },
{
default: () => h('pre', {}, { default: () => result }),
},
),
},
);
},
},
];
const tableData = ref<DataTableRowData[]>([]);
const DEFAULT_PAGE_SIZE = 10;
const pagination = reactive<PaginationProps>({
showSizePicker: true,
page: 1,
pageSize: DEFAULT_PAGE_SIZE,
pageSizes: [5, 10, 20, 50, 80, 100],
itemCount: 0,
prefix: ({ itemCount }) => {
return h('div', {}, { default: () => `${itemCount}` });
},
onUpdatePage: (page: number) => {
pagination.page = page;
getTableData();
},
onUpdatePageSize: (pageSize: number) => {
pagination.pageSize = pageSize;
pagination.page = 1;
getTableData();
},
});
const { mutate: getTableData, isPending: tableLoading } = useMutation({
mutationFn: async () => {
if (!searchFields.value.stationCode) throw Error('请选择车站');
const res = await pageVimpLogApi(
{
model: {},
extra: getExtraFields(),
current: pagination.page ?? 1,
size: pagination.pageSize ?? DEFAULT_PAGE_SIZE,
order: 'descending',
sort: 'id',
},
{
stationCode: searchFields.value.stationCode,
},
);
return res;
},
onSuccess: (res) => {
const { records, size, total } = res;
pagination.pageSize = parseInt(size);
pagination.itemCount = parseInt(total);
tableData.value = records;
},
onError: (error) => {
console.error(error);
const errorFeedback = parseErrorFeedback(error);
window.$message.error(errorFeedback);
},
});
const onClickReset = () => {
resetSearchFields();
pagination.page = 1;
pagination.pageSize = DEFAULT_PAGE_SIZE;
pagination.itemCount = 0;
getTableData();
};
const onClickQuery = () => {
if (searchFieldsChanged.value) {
pagination.page = 1;
pagination.pageSize = DEFAULT_PAGE_SIZE;
searchFieldsChanged.value = false;
}
getTableData();
};
const { mutate: exportTableData, isPending: exporting } = useMutation({
mutationFn: async () => {
if (!searchFields.value.stationCode) throw Error('请选择车站');
const data = await exportVimpLogApi(
{
model: {},
extra: getExtraFields(),
current: pagination.page ?? 1,
size: pagination.pageSize ?? 10,
order: 'descending',
sort: 'id',
},
{
stationCode: searchFields.value.stationCode,
},
);
return data;
},
onSuccess: (data) => {
const time = dayjs().format('YYYY-MM-DD_HH-mm-ss');
downloadByData(data, `视频操作日志_${time}.xlsx`);
},
onError: (error) => {
console.error(error);
const errorFeedback = parseErrorFeedback(error);
window.$message.error(errorFeedback);
},
});
// 进入页面时选择首个在线的车站
// 当页面刷新时车站列表还没有加载完成defaultStation不存在if条件为false
// 等待车站列表加载完成后defaultStation会更新if条件为true会更新选择的车站并加载日志记录。
// 当从其他页面跳转过来时车站列表已经存在defaultStation存在if条件为true会更新选择的车站并加载日志记录。
// 由于if条件是and逻辑所以即使defaultStation因车站状态变化而更新由于已经选择了车站所以if条件为false。
const defaultStation = computed(() => onlineStations.value.at(0));
watchEffect(() => {
if (defaultStation.value?.code && !searchFields.value.stationCode) {
searchFields.value.stationCode = defaultStation.value.code;
}
});
// 当选中的车站第一次有值时,主动获取数据
watch(
() => searchFields.value.stationCode,
(newCode, oldCode) => {
if (oldCode === undefined && !!newCode) {
getTableData();
}
},
{
immediate: true,
},
);
</script>
<template>
<NFlex vertical :size="0" style="height: 100%">
<!-- 查询面板 -->
<NForm style="flex: 0 0 auto; padding: 8px">
<NGrid cols="3" :x-gap="24">
<NFormItemGi span="1" label="车站" label-placement="left">
<NSelect
v-model:value="searchFields.stationCode"
:options="stationSelectOptions"
:render-label="
(option: SelectOption) => {
return [
h(NTag, { type: option.disabled ? 'error' : 'success', size: 'tiny' }, { default: () => (option.disabled ? '离线' : '在线') }),
h('span', {}, { default: () => `${option.label}` }),
];
}
"
:multiple="false"
clearable
/>
</NFormItemGi>
<NFormItemGi :span="1" label="操作类型" label-placement="left">
<NSelect v-model:value="searchFields.logType_in" :options="vimpOperationTypeOptions" multiple clearable />
</NFormItemGi>
<NFormItemGi span="1" label="时间" label-placement="left">
<NDatePicker v-model:formatted-value="searchFields.createdTime" type="datetimerange" />
</NFormItemGi>
</NGrid>
<!-- 操作按钮 -->
<NGrid :cols="1">
<NGridItem>
<NFlex>
<NButton @click="onClickReset">重置</NButton>
<NButton type="primary" :loading="tableLoading" @click="onClickQuery">查询</NButton>
</NFlex>
</NGridItem>
</NGrid>
</NForm>
<!-- 数据表格工具栏 -->
<NFlex align="center" style="padding: 8px; flex: 0 0 auto">
<div style="font-size: medium">视频平台日志</div>
<NFlex style="margin-left: auto">
<NButton type="primary" :loading="exporting" @click="() => exportTableData()">导出</NButton>
</NFlex>
</NFlex>
<!-- 数据表格 -->
<NDataTable remote :columns="tableColumns" :data="tableData" :pagination="pagination" :loading="tableLoading" :single-line="false" flex-height style="height: 100%; padding: 8px; flex: 1 1 auto" />
</NFlex>
</template>
<style scoped lang="scss"></style>