更新AopLogQueryDto中的时间字段类型为OffsetDateTime,优化AopLogRepository中的时间范围查询逻辑,调整前端模拟数据生成器以支持新的时间格式,修复日期选择器样式,优化日志管理页面的用户体验。

This commit is contained in:
Chuck1sn
2025-07-08 14:36:51 +08:00
parent eecc8bedae
commit deece30554
15 changed files with 3258 additions and 3285 deletions

View File

@@ -1,6 +1,8 @@
package com.zl.mjga.dto.aoplog; package com.zl.mjga.dto.aoplog;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@@ -30,10 +32,10 @@ public class AopLogQueryDto {
private String ipAddress; private String ipAddress;
/** 开始时间 */ /** 开始时间 */
private LocalDateTime startTime; private OffsetDateTime startTime;
/** 结束时间 */ /** 结束时间 */
private LocalDateTime endTime; private OffsetDateTime endTime;
/** 最小执行时间(毫秒) */ /** 最小执行时间(毫秒) */
private Long minExecutionTime; private Long minExecutionTime;

View File

@@ -96,13 +96,11 @@ public class AopLogRepository extends AopLogDao {
// 时间范围查询 // 时间范围查询
if (queryDto.getStartTime() != null) { if (queryDto.getStartTime() != null) {
OffsetDateTime startTime = queryDto.getStartTime().atOffset(OffsetDateTime.now().getOffset()); condition = condition.and(AOP_LOG.CREATE_TIME.ge(queryDto.getStartTime()));
condition = condition.and(AOP_LOG.CREATE_TIME.ge(startTime));
} }
if (queryDto.getEndTime() != null) { if (queryDto.getEndTime() != null) {
OffsetDateTime endTime = queryDto.getEndTime().atOffset(OffsetDateTime.now().getOffset()); condition = condition.and(AOP_LOG.CREATE_TIME.le(queryDto.getEndTime()));
condition = condition.and(AOP_LOG.CREATE_TIME.le(endTime));
} }
// 执行时间范围 // 执行时间范围

View File

@@ -32,7 +32,9 @@ const generateAopLog = () => ({
}), }),
executionTime: faker.number.int({ min: 10, max: 5000 }), executionTime: faker.number.int({ min: 10, max: 5000 }),
success: faker.datatype.boolean(0.9), // 90%成功率 success: faker.datatype.boolean(0.9), // 90%成功率
errorMessage: faker.helpers.maybe(() => faker.lorem.sentence(), { probability: 0.1 }), errorMessage: faker.helpers.maybe(() => faker.lorem.sentence(), {
probability: 0.1,
}),
userId: faker.number.int({ min: 1, max: 100 }), userId: faker.number.int({ min: 1, max: 100 }),
username: faker.internet.userName(), username: faker.internet.userName(),
ipAddress: faker.internet.ip(), ipAddress: faker.internet.ip(),
@@ -76,9 +78,11 @@ export default [
// 删除指定时间前的日志 // 删除指定时间前的日志
http.delete("/aop-log/before", ({ params }) => { http.delete("/aop-log/before", ({ params }) => {
const { beforeTime } = Object.fromEntries( const { beforeTime } = Object.fromEntries(
new URL(params.request.url).searchParams new URL(params.request.url).searchParams,
);
console.log(
`Captured a "DELETE /aop-log/before" request with time: ${beforeTime}`,
); );
console.log(`Captured a "DELETE /aop-log/before" request with time: ${beforeTime}`);
return HttpResponse.json(faker.number.int({ min: 5, max: 50 })); return HttpResponse.json(faker.number.int({ min: 5, max: 50 }));
}), }),
]; ];

View File

@@ -6,7 +6,7 @@ const generateLibrary = () => ({
id: faker.number.int({ min: 1, max: 100 }), id: faker.number.int({ min: 1, max: 100 }),
name: faker.lorem.words(2), name: faker.lorem.words(2),
description: faker.lorem.sentence(), description: faker.lorem.sentence(),
createTime: faker.date.recent().toISOString() createTime: faker.date.recent().toISOString(),
}); });
// 生成模拟的文档数据 // 生成模拟的文档数据
@@ -20,7 +20,7 @@ const generateDoc = (libId: number) => ({
enable: faker.datatype.boolean(), enable: faker.datatype.boolean(),
status: faker.helpers.arrayElement(["SUCCESS", "INDEXING"]), status: faker.helpers.arrayElement(["SUCCESS", "INDEXING"]),
createTime: faker.date.recent().toISOString(), createTime: faker.date.recent().toISOString(),
updateTime: faker.date.recent().toISOString() updateTime: faker.date.recent().toISOString(),
}); });
// 生成模拟的文档段落数据 // 生成模拟的文档段落数据
@@ -29,7 +29,7 @@ const generateSegment = (docId: number) => ({
docId, docId,
embeddingId: faker.string.uuid(), embeddingId: faker.string.uuid(),
content: faker.lorem.paragraphs(), content: faker.lorem.paragraphs(),
tokenUsage: faker.number.int({ min: 10, max: 1000 }) tokenUsage: faker.number.int({ min: 10, max: 1000 }),
}); });
export default [ export default [
@@ -48,7 +48,9 @@ export default [
return new HttpResponse(null, { status: 400 }); return new HttpResponse(null, { status: 400 });
} }
const docs = faker.helpers.multiple(() => generateDoc(libraryId), { count: 8 }); const docs = faker.helpers.multiple(() => generateDoc(libraryId), {
count: 8,
});
return HttpResponse.json(docs); return HttpResponse.json(docs);
}), }),
@@ -61,7 +63,10 @@ export default [
return new HttpResponse(null, { status: 400 }); return new HttpResponse(null, { status: 400 });
} }
const segments = faker.helpers.multiple(() => generateSegment(libraryDocId), { count: 12 }); const segments = faker.helpers.multiple(
() => generateSegment(libraryDocId),
{ count: 12 },
);
return HttpResponse.json(segments); return HttpResponse.json(segments);
}), }),

View File

@@ -67,4 +67,3 @@
/* left: 0.75rem !important; */ /* left: 0.75rem !important; */
right: auto !important; right: auto !important;
} }

View File

@@ -55,7 +55,7 @@ const props = defineProps<{
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
'change-page': [page: number]; "change-page": [page: number];
}>(); }>();
// 创建一个本地的totalPages引用 // 创建一个本地的totalPages引用
@@ -74,7 +74,7 @@ const {
} = usePagination({ } = usePagination({
initialPage: props.currentPage, initialPage: props.currentPage,
initialTotal: props.total, initialTotal: props.total,
maxVisiblePages: props.maxVisiblePages || 7 // 默认显示7个页码 maxVisiblePages: props.maxVisiblePages || 7, // 默认显示7个页码
}); });
const handlePageChangeClick = async (page: number) => { const handlePageChangeClick = async (page: number) => {
@@ -85,7 +85,7 @@ const handlePageChangeClick = async (page: number) => {
await props.pageChange(page, pageSize.value); await props.pageChange(page, pageSize.value);
} else { } else {
// 否则触发change-page事件 // 否则触发change-page事件
emit('change-page', page); emit("change-page", page);
} }
updatePaginationState({ updatePaginationState({
@@ -116,7 +116,7 @@ watch(
total: props.total, total: props.total,
}); });
} }
} },
); );
watch( watch(
@@ -125,6 +125,6 @@ watch(
if (newVal !== undefined) { if (newVal !== undefined) {
localTotalPages.value = newVal; localTotalPages.value = newVal;
} }
} },
); );
</script> </script>

View File

@@ -12,7 +12,8 @@ import { ref } from "vue";
* @returns 日志查询相关的状态和方法 * @returns 日志查询相关的状态和方法
*/ */
export function useAopLogQuery() { export function useAopLogQuery() {
const { currentPage, pageSize, total, updatePaginationState } = usePagination(); const { currentPage, pageSize, total, updatePaginationState } =
usePagination();
const { sortBy, handleSort, getSortField } = useSorting(); const { sortBy, handleSort, getSortField } = useSorting();
const logs = ref<components["schemas"]["AopLogRespDto"][]>([]); const logs = ref<components["schemas"]["AopLogRespDto"][]>([]);
@@ -85,8 +86,8 @@ export function useAopLogQuery() {
* @param dateTime 日期时间字符串 * @param dateTime 日期时间字符串
*/ */
const formatDateTime = (dateTime?: string) => { const formatDateTime = (dateTime?: string) => {
if (!dateTime) return ''; if (!dateTime) return "";
return dayjs(dateTime).format('YYYY-MM-DD HH:mm:ss'); return dayjs(dateTime).format("YYYY-MM-DD HH:mm:ss");
}; };
/** /**
@@ -94,7 +95,7 @@ export function useAopLogQuery() {
* @param time 执行时间(毫秒) * @param time 执行时间(毫秒)
*/ */
const formatExecutionTime = (time?: number) => { const formatExecutionTime = (time?: number) => {
if (!time) return ''; if (!time) return "";
if (time < 1000) return `${time}ms`; if (time < 1000) return `${time}ms`;
return `${(time / 1000).toFixed(2)}s`; return `${(time / 1000).toFixed(2)}s`;
}; };
@@ -104,7 +105,7 @@ export function useAopLogQuery() {
* @param jsonString JSON字符串 * @param jsonString JSON字符串
*/ */
const formatJson = (jsonString?: string) => { const formatJson = (jsonString?: string) => {
if (!jsonString) return ''; if (!jsonString) return "";
try { try {
const obj = JSON.parse(jsonString); const obj = JSON.parse(jsonString);
return JSON.stringify(obj, null, 2); return JSON.stringify(obj, null, 2);

View File

@@ -6,7 +6,8 @@
<div class="mt-2 sm:mt-0"> <div class="mt-2 sm:mt-0">
<Button variant="secondary" size="sm" @click="navigateBack"> <Button variant="secondary" size="sm" @click="navigateBack">
<template #icon> <template #icon>
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18">
</path> </path>
</svg> </svg>
@@ -27,12 +28,12 @@
<div v-if="currentLog.curl" class="p-4 border-b border-gray-200"> <div v-if="currentLog.curl" class="p-4 border-b border-gray-200">
<div class="flex justify-between items-center mb-4"> <div class="flex justify-between items-center mb-4">
<h2 class="text-lg font-medium text-gray-900">CURL</h2> <h2 class="text-lg font-medium text-gray-900">CURL</h2>
<button <button @click="copyCurl" class="text-sm font-medium text-blue-600 hover:text-blue-800 flex items-center">
@click="copyCurl" <svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24"
class="text-sm font-medium text-blue-600 hover:text-blue-800 flex items-center" xmlns="http://www.w3.org/2000/svg">
> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"></path> </path>
</svg> </svg>
{{ isCopied ? '已复制' : '复制' }} {{ isCopied ? '已复制' : '复制' }}
</button> </button>
@@ -90,12 +91,11 @@
<div class="p-4 border-b border-gray-200"> <div class="p-4 border-b border-gray-200">
<h2 class="text-lg font-medium text-gray-900 mb-4">方法参数</h2> <h2 class="text-lg font-medium text-gray-900 mb-4">方法参数</h2>
<div class="bg-gray-50 p-4 rounded-lg"> <div class="bg-gray-50 p-4 rounded-lg">
<pre class="text-sm text-gray-800 overflow-x-auto whitespace-pre-wrap">{{ isMethodArgsExpanded ? formatJson(currentLog.methodArgs) : methodArgsPreview }}</pre> <pre class="text-sm text-gray-800 overflow-x-auto whitespace-pre-wrap">{{ isMethodArgsExpanded ?
formatJson(currentLog.methodArgs) : methodArgsPreview }}</pre>
<div v-if="shouldCollapseMethodArgs" class="mt-2 flex justify-end"> <div v-if="shouldCollapseMethodArgs" class="mt-2 flex justify-end">
<button <button @click="isMethodArgsExpanded = !isMethodArgsExpanded"
@click="isMethodArgsExpanded = !isMethodArgsExpanded" class="text-blue-600 hover:text-blue-800 text-sm font-medium">
class="text-blue-600 hover:text-blue-800 text-sm font-medium"
>
{{ isMethodArgsExpanded ? '折叠' : '展开' }} {{ isMethodArgsExpanded ? '折叠' : '展开' }}
</button> </button>
</div> </div>
@@ -106,12 +106,11 @@
<div class="p-4 border-b border-gray-200"> <div class="p-4 border-b border-gray-200">
<h2 class="text-lg font-medium text-gray-900 mb-4">返回值</h2> <h2 class="text-lg font-medium text-gray-900 mb-4">返回值</h2>
<div class="bg-gray-50 p-4 rounded-lg"> <div class="bg-gray-50 p-4 rounded-lg">
<pre class="text-sm text-gray-800 overflow-x-auto whitespace-pre-wrap">{{ isReturnValueExpanded ? formatJson(currentLog.returnValue) : returnValuePreview }}</pre> <pre class="text-sm text-gray-800 overflow-x-auto whitespace-pre-wrap">{{ isReturnValueExpanded ?
formatJson(currentLog.returnValue) : returnValuePreview }}</pre>
<div v-if="shouldCollapseReturnValue" class="mt-2 flex justify-end"> <div v-if="shouldCollapseReturnValue" class="mt-2 flex justify-end">
<button <button @click="isReturnValueExpanded = !isReturnValueExpanded"
@click="isReturnValueExpanded = !isReturnValueExpanded" class="text-blue-600 hover:text-blue-800 text-sm font-medium">
class="text-blue-600 hover:text-blue-800 text-sm font-medium"
>
{{ isReturnValueExpanded ? '折叠' : '展开' }} {{ isReturnValueExpanded ? '折叠' : '展开' }}
</button> </button>
</div> </div>
@@ -122,12 +121,11 @@
<div v-if="currentLog.errorMessage" class="p-4 border-b border-gray-200"> <div v-if="currentLog.errorMessage" class="p-4 border-b border-gray-200">
<h2 class="text-lg font-medium text-gray-900 mb-4">错误信息</h2> <h2 class="text-lg font-medium text-gray-900 mb-4">错误信息</h2>
<div class="bg-red-50 p-4 rounded-lg"> <div class="bg-red-50 p-4 rounded-lg">
<pre class="text-sm text-red-800 overflow-x-auto whitespace-pre-wrap">{{ isErrorMessageExpanded ? currentLog.errorMessage : errorMessagePreview }}</pre> <pre class="text-sm text-red-800 overflow-x-auto whitespace-pre-wrap">{{ isErrorMessageExpanded ?
currentLog.errorMessage : errorMessagePreview }}</pre>
<div v-if="shouldCollapseErrorMessage" class="mt-2 flex justify-end"> <div v-if="shouldCollapseErrorMessage" class="mt-2 flex justify-end">
<button <button @click="isErrorMessageExpanded = !isErrorMessageExpanded"
@click="isErrorMessageExpanded = !isErrorMessageExpanded" class="text-blue-600 hover:text-blue-800 text-sm font-medium">
class="text-blue-600 hover:text-blue-800 text-sm font-medium"
>
{{ isErrorMessageExpanded ? '折叠' : '展开' }} {{ isErrorMessageExpanded ? '折叠' : '展开' }}
</button> </button>
</div> </div>
@@ -138,7 +136,8 @@
<div class="p-4 bg-gray-50 rounded-b-lg flex justify-end"> <div class="p-4 bg-gray-50 rounded-b-lg flex justify-end">
<Button variant="danger" @click="handleDeleteClick"> <Button variant="danger" @click="handleDeleteClick">
<template #icon> <template #icon>
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"> d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16">
</path> </path>
@@ -173,7 +172,6 @@ import { Button } from "@/components/ui";
import { useAopLogDelete } from "@/composables/aop/useAopLogDelete"; import { useAopLogDelete } from "@/composables/aop/useAopLogDelete";
import { useAopLogQuery } from "@/composables/aop/useAopLogQuery"; import { useAopLogQuery } from "@/composables/aop/useAopLogQuery";
import { useErrorHandling } from "@/composables/common/useErrorHandling";
import { Routes } from "@/router/constants"; import { Routes } from "@/router/constants";
// 路由 // 路由
@@ -181,9 +179,6 @@ const route = useRoute();
const router = useRouter(); const router = useRouter();
const logId = Number(route.params.id); const logId = Number(route.params.id);
// 获取错误处理
const { handleError } = useErrorHandling();
// 获取日志查询和删除的composables // 获取日志查询和删除的composables
const { const {
currentLog, currentLog,
@@ -270,31 +265,24 @@ const handleDeleteClick = () => {
// 确认删除 // 确认删除
const confirmDelete = async () => { const confirmDelete = async () => {
try {
if (currentLog.value?.id) { if (currentLog.value?.id) {
await deleteLog(currentLog.value.id); await deleteLog(currentLog.value.id);
navigateBack(); navigateBack();
} }
} catch (error) {
handleError(error);
}
}; };
onMounted(async () => { onMounted(async () => {
try {
// 初始化Flowbite // 初始化Flowbite
initFlowbite(); initFlowbite();
// 初始化模态框 // 初始化模态框
const $deleteModalElement = document.querySelector<HTMLElement>("#delete-log-modal"); const $deleteModalElement =
document.querySelector<HTMLElement>("#delete-log-modal");
if ($deleteModalElement) { if ($deleteModalElement) {
deleteLogModal.value = new Modal($deleteModalElement); deleteLogModal.value = new Modal($deleteModalElement);
} }
// 加载日志详情 // 加载日志详情
await fetchLogDetail(logId); await fetchLogDetail(logId);
} catch (error) {
handleError(error);
}
}); });
</script> </script>

View File

@@ -92,7 +92,7 @@
<!-- 移动端卡片列表 --> <!-- 移动端卡片列表 -->
<div class="md:hidden mt-4"> <div class="md:hidden mt-4">
<MobileCardListWithCheckbox :items="logs" v-model="selectedLogs" idField="id"> <MobileCardListWithCheckbox :items="logs" v-model="selectedLogs" idField="id">
<template #item="{ item }"> <template v-for="item in logs" :key="item.id">
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<div class="flex justify-between items-start"> <div class="flex justify-between items-start">
<div class="font-medium text-gray-900 truncate max-w-[200px]" :title="item.className"> <div class="font-medium text-gray-900 truncate max-w-[200px]" :title="item.className">
@@ -109,10 +109,6 @@
<div class="text-gray-500">执行时间</div> <div class="text-gray-500">执行时间</div>
<div>{{ formatExecutionTime(item.executionTime) }}</div> <div>{{ formatExecutionTime(item.executionTime) }}</div>
</div> </div>
<div>
<div class="text-gray-500">用户</div>
<div>{{ item.username || '-' }}</div>
</div>
<div> <div>
<div class="text-gray-500">创建时间</div> <div class="text-gray-500">创建时间</div>
<div>{{ formatDateTime(item.createTime) }}</div> <div>{{ formatDateTime(item.createTime) }}</div>
@@ -172,8 +168,8 @@
删除此日期之前的所有日志 删除此日期之前的所有日志
</label> </label>
<div class="datepicker-container"> <div class="datepicker-container">
<VueDatePicker v-model="clearBeforeDate" locale="zh-CN" format="yyyy-MM-dd" :enable-time-picker="false" <VueDatePicker v-model="clearBeforeDate" locale="zh-CN" format="yyyy/MM/dd HH:mm:ss"
:auto-apply="true" class="filter-datepicker" teleport="body" /> :enable-time-picker="false" :auto-apply="true" class="filter-datepicker" teleport="body" />
</div> </div>
</div> </div>
<div class="flex justify-end gap-2"> <div class="flex justify-end gap-2">
@@ -214,6 +210,7 @@ import { useErrorHandling } from "@/composables/common/useErrorHandling";
import { useActionExcStore } from "@/composables/store/useActionExcStore"; import { useActionExcStore } from "@/composables/store/useActionExcStore";
import { Routes } from "@/router/constants"; import { Routes } from "@/router/constants";
import type { AopLogQueryParams } from "@/types/AlertTypes"; import type { AopLogQueryParams } from "@/types/AlertTypes";
import { formatDate } from "@/utils";
// 路由 // 路由
const router = useRouter(); const router = useRouter();
@@ -231,8 +228,6 @@ const {
fetchLogs, fetchLogs,
formatDateTime, formatDateTime,
formatExecutionTime, formatExecutionTime,
handleSort,
getSortField,
} = useAopLogQuery(); } = useAopLogQuery();
const { deleteLog, batchDeleteLogs, deleteLogsBefore } = useAopLogDelete(); const { deleteLog, batchDeleteLogs, deleteLogsBefore } = useAopLogDelete();
@@ -312,7 +307,7 @@ const columns = [
// 更新筛选值 // 更新筛选值
const updateFilterValues = ( const updateFilterValues = (
values: Record<string, string | number | boolean | Date[] | undefined> values: Record<string, string | number | boolean | Date[] | undefined>,
) => { ) => {
if (values.className !== undefined) { if (values.className !== undefined) {
filterValues.className = values.className as string; filterValues.className = values.className as string;
@@ -333,35 +328,26 @@ const updateFilterValues = (
// 处理搜索 // 处理搜索
const handleSearch = async () => { const handleSearch = async () => {
try {
const params: AopLogQueryParams = { const params: AopLogQueryParams = {
className: filterValues.className || undefined, className: filterValues.className || undefined,
methodName: filterValues.methodName || undefined, methodName: filterValues.methodName || undefined,
success: filterValues.success ? filterValues.success === "true" : undefined, success: filterValues.success ? filterValues.success === "true" : undefined,
username: filterValues.username || undefined,
}; };
// 处理日期范围 // 处理日期范围
if (filterValues.dateRange && filterValues.dateRange.length === 2) { if (filterValues.dateRange && filterValues.dateRange.length === 2) {
params.startTime = filterValues.dateRange[0].toISOString(); params.startTime = formatDate(filterValues.dateRange[0]);
params.endTime = filterValues.dateRange[1].toISOString(); params.endTime = formatDate(filterValues.dateRange[1]);
} }
await fetchLogs(params); await fetchLogs(params);
selectedLogs.value = []; selectedLogs.value = [];
} catch (error) {
handleError(error);
}
}; };
// 处理页码变化 // 处理页码变化
const handlePageChange = async (page: number) => { const handlePageChange = async (page: number) => {
try {
currentPage.value = page; currentPage.value = page;
await handleSearch(); await handleSearch();
} catch (error) {
handleError(error);
}
}; };
// 处理查看详情 // 处理查看详情
@@ -379,15 +365,11 @@ const handleDeleteClick = (log: components["schemas"]["AopLogRespDto"]) => {
// 确认删除 // 确认删除
const confirmDelete = async () => { const confirmDelete = async () => {
try {
if (currentLogToDelete.value?.id) { if (currentLogToDelete.value?.id) {
await deleteLog(currentLogToDelete.value.id); await deleteLog(currentLogToDelete.value.id);
await handleSearch(); await handleSearch();
deleteLogModal.value?.hide(); deleteLogModal.value?.hide();
} }
} catch (error) {
handleError(error);
}
}; };
// 处理批量删除点击 // 处理批量删除点击
@@ -399,15 +381,11 @@ const handleBatchDeleteClick = () => {
// 确认批量删除 // 确认批量删除
const confirmBatchDelete = async () => { const confirmBatchDelete = async () => {
try {
if (selectedLogs.value.length > 0) { if (selectedLogs.value.length > 0) {
await batchDeleteLogs(selectedLogs.value); await batchDeleteLogs(selectedLogs.value);
await handleSearch(); await handleSearch();
batchDeleteLogsModal.value?.hide(); batchDeleteLogsModal.value?.hide();
} }
} catch (error) {
handleError(error);
}
}; };
// 处理清理历史日志点击 // 处理清理历史日志点击
@@ -422,22 +400,20 @@ const closeClearBeforeModal = () => {
// 确认清理历史日志 // 确认清理历史日志
const confirmClearBefore = async () => { const confirmClearBefore = async () => {
try {
if (clearBeforeDate.value) { if (clearBeforeDate.value) {
const dateString = clearBeforeDate.value.toISOString().split("T")[0]; const dateString = formatDate(clearBeforeDate.value);
await deleteLogsBefore(dateString); await deleteLogsBefore(dateString!);
await handleSearch(); await handleSearch();
clearBeforeModal.value?.hide(); clearBeforeModal.value?.hide();
} }
} catch (error) {
handleError(error);
}
}; };
// 处理全选 // 处理全选
const handleSelectAll = (selected: boolean) => { const handleSelectAll = (selected: boolean) => {
if (selected) { if (selected) {
selectedLogs.value = logs.value.map(log => log.id).filter((id): id is number => id !== undefined); selectedLogs.value = logs.value
.map((log) => log.id)
.filter((id): id is number => id !== undefined);
} else { } else {
selectedLogs.value = []; selectedLogs.value = [];
} }
@@ -447,14 +423,18 @@ const handleSelectAll = (selected: boolean) => {
const actionExcStore = useActionExcStore(); const actionExcStore = useActionExcStore();
onMounted(async () => { onMounted(async () => {
try {
// 初始化Flowbite // 初始化Flowbite
initFlowbite(); initFlowbite();
// 初始化模态框 // 初始化模态框
const $deleteModalElement = document.querySelector<HTMLElement>("#delete-log-modal"); const $deleteModalElement =
const $batchDeleteModalElement = document.querySelector<HTMLElement>("#batch-delete-logs-modal"); document.querySelector<HTMLElement>("#delete-log-modal");
const $clearBeforeModalElement = document.querySelector<HTMLElement>("#clear-before-modal"); const $batchDeleteModalElement = document.querySelector<HTMLElement>(
"#batch-delete-logs-modal",
);
const $clearBeforeModalElement = document.querySelector<HTMLElement>(
"#clear-before-modal",
);
if ($deleteModalElement) { if ($deleteModalElement) {
deleteLogModal.value = new Modal($deleteModalElement); deleteLogModal.value = new Modal($deleteModalElement);
@@ -475,8 +455,5 @@ onMounted(async () => {
handleSearch(); handleSearch();
} }
}); });
} catch (error) {
handleError(error);
}
}); });
</script> </script>

View File

@@ -164,7 +164,6 @@ import type { components } from "@/api/types/schema";
import PromotionBanner from "@/components/common/PromotionBanner.vue"; import PromotionBanner from "@/components/common/PromotionBanner.vue";
import { PlusIcon } from "@/components/icons"; import { PlusIcon } from "@/components/icons";
import Breadcrumbs from "@/components/layout/Breadcrumbs.vue"; import Breadcrumbs from "@/components/layout/Breadcrumbs.vue";
import ConfirmationDialog from "@/components/modals/ConfirmationDialog.vue";
import UserDeleteModal from "@/components/modals/ConfirmationDialog.vue"; import UserDeleteModal from "@/components/modals/ConfirmationDialog.vue";
import UserFormDialog from "@/components/modals/UserFormDialog.vue"; import UserFormDialog from "@/components/modals/UserFormDialog.vue";
import TableButton from "@/components/tables/TableButton.vue"; import TableButton from "@/components/tables/TableButton.vue";