Files
ndm-web-client/src/pages/vimp-log-page.vue
2025-08-25 11:08:14 +08:00

202 lines
6.4 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 setup lang="ts">
import type { NdmVimpLogResultVO } from '@/apis/models/device';
import { ndmVimpLogDefaultExportByTemplate, postNdmVimpLogPage } from '@/apis/requests';
import { useStationListQuery } from '@/composables/query/use-station-list-query';
import { JAVA_INTEGER_MAX_VALUE } from '@/constants';
import { useStationStore } from '@/stores/station';
import { downloadByData } from '@/utils/download';
import { useMutation } from '@tanstack/vue-query';
import dayjs from 'dayjs';
import {
NButton,
NDataTable,
NDatePicker,
NForm,
NFormItemGi,
NGrid,
NGridItem,
NSelect,
NSpace,
NTag,
type DataTableColumns,
type DataTableRowData,
type PaginationProps,
type SelectOption,
} from 'naive-ui';
import { storeToRefs } from 'pinia';
import { computed, h, onBeforeMount, reactive, ref } from 'vue';
useStationListQuery();
const stationStore = useStationStore();
const { stationList } = storeToRefs(stationStore);
const stationSelectOptions = computed(() => {
return stationList.value.map<SelectOption>((station) => ({
label: station.name,
value: station.deviceIdPrefix,
disabled: !station.online,
}));
});
const searchFields = reactive({
stationCode: stationList.value.find((s) => s.online)?.code,
createdTime: [dayjs().startOf('date').subtract(7, 'day').format('YYYY-MM-DD HH:mm:ss'), dayjs().endOf('date').format('YYYY-MM-DD HH:mm:ss')] as [string, string],
});
const resetSearchFields = () => {
searchFields.stationCode = undefined;
};
const tableColumns: DataTableColumns<NdmVimpLogResultVO> = [
{ title: '时间', key: 'createdTime' },
{ title: '操作内容', key: 'description' },
{ title: '请求IP', key: 'requestIp' },
{ title: '操作参数', key: 'params' },
{ title: '操作结果', key: 'result' },
];
const tableData = ref<DataTableRowData[]>([]);
const tablePagination = reactive<PaginationProps>({
showSizePicker: true,
page: 1,
pageSize: 10,
pageSizes: [5, 10, 20, 50, 80, 100],
pageCount: 1,
itemCount: 0,
prefix: ({ itemCount }) => {
return h('div', {}, { default: () => `${itemCount}` });
},
onUpdatePage: (page: number) => {
tablePagination.page = page;
getVimpLogList();
},
onUpdatePageSize: (pageSize: number) => {
tablePagination.pageSize = pageSize;
tablePagination.page = 1;
getVimpLogList();
},
});
const { mutate: getVimpLogList, isPending: isTableLoading } = useMutation({
mutationFn: async () => {
if (!searchFields.stationCode) return [];
const res = await postNdmVimpLogPage(searchFields.stationCode, {
model: {},
extra: {
createdTime_precisest: searchFields.createdTime[0],
createdTime_preciseed: searchFields.createdTime[1],
},
size: tablePagination.pageSize!,
current: tablePagination.page!,
sort: 'id',
order: 'descending',
});
const { records, pages, size, total } = res;
tablePagination.pageSize = parseInt(size);
tablePagination.pageCount = parseInt(pages);
tablePagination.itemCount = parseInt(total);
return records;
},
onSuccess: (records) => {
tableData.value = records;
},
onError: (error) => {
window.$message.error(error.message);
},
});
const onClickReset = () => {
resetSearchFields();
tablePagination.page = 1;
tablePagination.pageSize = 10;
tablePagination.pageCount = 1;
tablePagination.itemCount = 0;
getVimpLogList();
};
const onClickQuery = () => getVimpLogList();
const { mutate: downloadTableData, isPending: isDownloading } = useMutation({
mutationFn: async () => {
if (!searchFields.stationCode) throw Error('请选择车站');
const data = await ndmVimpLogDefaultExportByTemplate(searchFields.stationCode, {
model: {},
extra: {
createdTime_precisest: searchFields.createdTime[0],
createdTime_preciseed: searchFields.createdTime[1],
},
current: 1,
size: JAVA_INTEGER_MAX_VALUE,
sort: 'id',
order: 'descending',
});
return data;
},
onSuccess: (data) => {
downloadByData(data, `设备告警记录.xlsx`);
},
onError: (error) => {
window.$message.error(error.message);
},
});
const exportTableData = () => downloadTableData();
onBeforeMount(() => getVimpLogList());
</script>
<template>
<!-- 容器上下布局表格自适应剩余高度 -->
<div style="height: 100%; display: flex; flex-direction: column">
<!-- 查询面板 -->
<div style="flex: 0 0 auto; padding: 8px">
<NForm>
<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">
<NDatePicker v-model:formatted-value="searchFields.createdTime" type="datetimerange" />
</NFormItemGi>
</NGrid>
<!-- 按钮 -->
<NGrid :cols="1">
<NGridItem>
<NSpace>
<NButton @click="onClickReset">重置</NButton>
<NButton type="primary" :loading="isTableLoading" @click="onClickQuery">查询</NButton>
</NSpace>
</NGridItem>
</NGrid>
</NForm>
</div>
<!-- 工具栏:横向、右对齐按钮) -->
<div style="flex: 0 0 auto; display: flex; align-items: center; padding: 8px">
<div style="font-size: medium">视频平台日志</div>
<NSpace style="margin-left: auto">
<NButton type="primary" :loading="isDownloading" @click="exportTableData">导出</NButton>
</NSpace>
</div>
<!-- 表格区域:填满剩余空间 -->
<div style="flex: 1 1 auto; min-height: 0; padding: 8px">
<NDataTable remote :columns="tableColumns" :data="tableData" :pagination="tablePagination" :loading="isTableLoading" :single-line="false" flex-height style="height: 100%" />
</div>
</div>
</template>
<style scoped lang="scss"></style>