mirror of
https://github.com/ccmjga/zhilu-admin
synced 2026-04-16 15:46:04 +00:00
更新AopLogQueryDto中的时间字段类型为OffsetDateTime,优化AopLogRepository中的时间范围查询逻辑,调整前端模拟数据生成器以支持新的时间格式,修复日期选择器样式,优化日志管理页面的用户体验。
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
package com.zl.mjga.dto.aoplog;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
@@ -30,10 +32,10 @@ public class AopLogQueryDto {
|
||||
private String ipAddress;
|
||||
|
||||
/** 开始时间 */
|
||||
private LocalDateTime startTime;
|
||||
private OffsetDateTime startTime;
|
||||
|
||||
/** 结束时间 */
|
||||
private LocalDateTime endTime;
|
||||
private OffsetDateTime endTime;
|
||||
|
||||
/** 最小执行时间(毫秒) */
|
||||
private Long minExecutionTime;
|
||||
|
||||
@@ -96,13 +96,11 @@ public class AopLogRepository extends AopLogDao {
|
||||
|
||||
// 时间范围查询
|
||||
if (queryDto.getStartTime() != null) {
|
||||
OffsetDateTime startTime = queryDto.getStartTime().atOffset(OffsetDateTime.now().getOffset());
|
||||
condition = condition.and(AOP_LOG.CREATE_TIME.ge(startTime));
|
||||
condition = condition.and(AOP_LOG.CREATE_TIME.ge(queryDto.getStartTime()));
|
||||
}
|
||||
|
||||
if (queryDto.getEndTime() != null) {
|
||||
OffsetDateTime endTime = queryDto.getEndTime().atOffset(OffsetDateTime.now().getOffset());
|
||||
condition = condition.and(AOP_LOG.CREATE_TIME.le(endTime));
|
||||
condition = condition.and(AOP_LOG.CREATE_TIME.le(queryDto.getEndTime()));
|
||||
}
|
||||
|
||||
// 执行时间范围
|
||||
|
||||
@@ -32,7 +32,9 @@ const generateAopLog = () => ({
|
||||
}),
|
||||
executionTime: faker.number.int({ min: 10, max: 5000 }),
|
||||
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 }),
|
||||
username: faker.internet.userName(),
|
||||
ipAddress: faker.internet.ip(),
|
||||
@@ -76,9 +78,11 @@ export default [
|
||||
// 删除指定时间前的日志
|
||||
http.delete("/aop-log/before", ({ params }) => {
|
||||
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 }));
|
||||
}),
|
||||
];
|
||||
|
||||
@@ -6,7 +6,7 @@ const generateLibrary = () => ({
|
||||
id: faker.number.int({ min: 1, max: 100 }),
|
||||
name: faker.lorem.words(2),
|
||||
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(),
|
||||
status: faker.helpers.arrayElement(["SUCCESS", "INDEXING"]),
|
||||
createTime: faker.date.recent().toISOString(),
|
||||
updateTime: faker.date.recent().toISOString()
|
||||
updateTime: faker.date.recent().toISOString(),
|
||||
});
|
||||
|
||||
// 生成模拟的文档段落数据
|
||||
@@ -29,7 +29,7 @@ const generateSegment = (docId: number) => ({
|
||||
docId,
|
||||
embeddingId: faker.string.uuid(),
|
||||
content: faker.lorem.paragraphs(),
|
||||
tokenUsage: faker.number.int({ min: 10, max: 1000 })
|
||||
tokenUsage: faker.number.int({ min: 10, max: 1000 }),
|
||||
});
|
||||
|
||||
export default [
|
||||
@@ -48,7 +48,9 @@ export default [
|
||||
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);
|
||||
}),
|
||||
|
||||
@@ -61,7 +63,10 @@ export default [
|
||||
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);
|
||||
}),
|
||||
|
||||
|
||||
@@ -51,20 +51,19 @@
|
||||
/* 圆角设置 - 匹配项目中的 rounded-lg */
|
||||
--dp-border-radius: 0.5rem; /* 8px,匹配 Tailwind 的 rounded-lg */
|
||||
--dp-cell-border-radius: 0.375rem; /* 6px,稍微小一点,更美观 */
|
||||
}
|
||||
}
|
||||
|
||||
/* 修复日期文本与图标重叠的问题 */
|
||||
.dp__input_wrap {
|
||||
/* 修复日期文本与图标重叠的问题 */
|
||||
.dp__input_wrap {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.dp__input {
|
||||
.dp__input {
|
||||
padding-left: 2rem !important; /* 确保文本不会与图标重叠 */
|
||||
}
|
||||
}
|
||||
|
||||
.dp__input_icon {
|
||||
.dp__input_icon {
|
||||
position: absolute;
|
||||
/* left: 0.75rem !important; */
|
||||
right: auto !important;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ const props = defineProps<{
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
'change-page': [page: number];
|
||||
"change-page": [page: number];
|
||||
}>();
|
||||
|
||||
// 创建一个本地的totalPages引用
|
||||
@@ -74,7 +74,7 @@ const {
|
||||
} = usePagination({
|
||||
initialPage: props.currentPage,
|
||||
initialTotal: props.total,
|
||||
maxVisiblePages: props.maxVisiblePages || 7 // 默认显示7个页码
|
||||
maxVisiblePages: props.maxVisiblePages || 7, // 默认显示7个页码
|
||||
});
|
||||
|
||||
const handlePageChangeClick = async (page: number) => {
|
||||
@@ -85,7 +85,7 @@ const handlePageChangeClick = async (page: number) => {
|
||||
await props.pageChange(page, pageSize.value);
|
||||
} else {
|
||||
// 否则触发change-page事件
|
||||
emit('change-page', page);
|
||||
emit("change-page", page);
|
||||
}
|
||||
|
||||
updatePaginationState({
|
||||
@@ -116,7 +116,7 @@ watch(
|
||||
total: props.total,
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
watch(
|
||||
@@ -125,6 +125,6 @@ watch(
|
||||
if (newVal !== undefined) {
|
||||
localTotalPages.value = newVal;
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
</script>
|
||||
|
||||
@@ -12,7 +12,8 @@ import { ref } from "vue";
|
||||
* @returns 日志查询相关的状态和方法
|
||||
*/
|
||||
export function useAopLogQuery() {
|
||||
const { currentPage, pageSize, total, updatePaginationState } = usePagination();
|
||||
const { currentPage, pageSize, total, updatePaginationState } =
|
||||
usePagination();
|
||||
const { sortBy, handleSort, getSortField } = useSorting();
|
||||
|
||||
const logs = ref<components["schemas"]["AopLogRespDto"][]>([]);
|
||||
@@ -85,8 +86,8 @@ export function useAopLogQuery() {
|
||||
* @param dateTime 日期时间字符串
|
||||
*/
|
||||
const formatDateTime = (dateTime?: string) => {
|
||||
if (!dateTime) return '';
|
||||
return dayjs(dateTime).format('YYYY-MM-DD HH:mm:ss');
|
||||
if (!dateTime) return "";
|
||||
return dayjs(dateTime).format("YYYY-MM-DD HH:mm:ss");
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -94,7 +95,7 @@ export function useAopLogQuery() {
|
||||
* @param time 执行时间(毫秒)
|
||||
*/
|
||||
const formatExecutionTime = (time?: number) => {
|
||||
if (!time) return '';
|
||||
if (!time) return "";
|
||||
if (time < 1000) return `${time}ms`;
|
||||
return `${(time / 1000).toFixed(2)}s`;
|
||||
};
|
||||
@@ -104,7 +105,7 @@ export function useAopLogQuery() {
|
||||
* @param jsonString JSON字符串
|
||||
*/
|
||||
const formatJson = (jsonString?: string) => {
|
||||
if (!jsonString) return '';
|
||||
if (!jsonString) return "";
|
||||
try {
|
||||
const obj = JSON.parse(jsonString);
|
||||
return JSON.stringify(obj, null, 2);
|
||||
|
||||
@@ -11,7 +11,7 @@ export interface UsePaginationOptions {
|
||||
initialPageSize?: number;
|
||||
initialTotal?: number;
|
||||
maxVisiblePages?: number;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页逻辑Composable - 提供分页相关的状态和操作
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
<div class="mt-2 sm:mt-0">
|
||||
<Button variant="secondary" size="sm" @click="navigateBack">
|
||||
<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>
|
||||
</svg>
|
||||
@@ -27,12 +28,12 @@
|
||||
<div v-if="currentLog.curl" class="p-4 border-b border-gray-200">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h2 class="text-lg font-medium text-gray-900">CURL</h2>
|
||||
<button
|
||||
@click="copyCurl"
|
||||
class="text-sm font-medium text-blue-600 hover:text-blue-800 flex items-center"
|
||||
>
|
||||
<svg class="w-4 h-4 mr-1" 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="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>
|
||||
<button @click="copyCurl" class="text-sm font-medium text-blue-600 hover:text-blue-800 flex items-center">
|
||||
<svg class="w-4 h-4 mr-1" 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="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>
|
||||
</svg>
|
||||
{{ isCopied ? '已复制' : '复制' }}
|
||||
</button>
|
||||
@@ -90,12 +91,11 @@
|
||||
<div class="p-4 border-b border-gray-200">
|
||||
<h2 class="text-lg font-medium text-gray-900 mb-4">方法参数</h2>
|
||||
<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">
|
||||
<button
|
||||
@click="isMethodArgsExpanded = !isMethodArgsExpanded"
|
||||
class="text-blue-600 hover:text-blue-800 text-sm font-medium"
|
||||
>
|
||||
<button @click="isMethodArgsExpanded = !isMethodArgsExpanded"
|
||||
class="text-blue-600 hover:text-blue-800 text-sm font-medium">
|
||||
{{ isMethodArgsExpanded ? '折叠' : '展开' }}
|
||||
</button>
|
||||
</div>
|
||||
@@ -106,12 +106,11 @@
|
||||
<div class="p-4 border-b border-gray-200">
|
||||
<h2 class="text-lg font-medium text-gray-900 mb-4">返回值</h2>
|
||||
<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">
|
||||
<button
|
||||
@click="isReturnValueExpanded = !isReturnValueExpanded"
|
||||
class="text-blue-600 hover:text-blue-800 text-sm font-medium"
|
||||
>
|
||||
<button @click="isReturnValueExpanded = !isReturnValueExpanded"
|
||||
class="text-blue-600 hover:text-blue-800 text-sm font-medium">
|
||||
{{ isReturnValueExpanded ? '折叠' : '展开' }}
|
||||
</button>
|
||||
</div>
|
||||
@@ -122,12 +121,11 @@
|
||||
<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>
|
||||
<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">
|
||||
<button
|
||||
@click="isErrorMessageExpanded = !isErrorMessageExpanded"
|
||||
class="text-blue-600 hover:text-blue-800 text-sm font-medium"
|
||||
>
|
||||
<button @click="isErrorMessageExpanded = !isErrorMessageExpanded"
|
||||
class="text-blue-600 hover:text-blue-800 text-sm font-medium">
|
||||
{{ isErrorMessageExpanded ? '折叠' : '展开' }}
|
||||
</button>
|
||||
</div>
|
||||
@@ -138,7 +136,8 @@
|
||||
<div class="p-4 bg-gray-50 rounded-b-lg flex justify-end">
|
||||
<Button variant="danger" @click="handleDeleteClick">
|
||||
<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="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>
|
||||
@@ -173,7 +172,6 @@ import { Button } from "@/components/ui";
|
||||
|
||||
import { useAopLogDelete } from "@/composables/aop/useAopLogDelete";
|
||||
import { useAopLogQuery } from "@/composables/aop/useAopLogQuery";
|
||||
import { useErrorHandling } from "@/composables/common/useErrorHandling";
|
||||
import { Routes } from "@/router/constants";
|
||||
|
||||
// 路由
|
||||
@@ -181,9 +179,6 @@ const route = useRoute();
|
||||
const router = useRouter();
|
||||
const logId = Number(route.params.id);
|
||||
|
||||
// 获取错误处理
|
||||
const { handleError } = useErrorHandling();
|
||||
|
||||
// 获取日志查询和删除的composables
|
||||
const {
|
||||
currentLog,
|
||||
@@ -270,31 +265,24 @@ const handleDeleteClick = () => {
|
||||
|
||||
// 确认删除
|
||||
const confirmDelete = async () => {
|
||||
try {
|
||||
if (currentLog.value?.id) {
|
||||
await deleteLog(currentLog.value.id);
|
||||
navigateBack();
|
||||
}
|
||||
} catch (error) {
|
||||
handleError(error);
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
// 初始化Flowbite
|
||||
initFlowbite();
|
||||
|
||||
// 初始化模态框
|
||||
const $deleteModalElement = document.querySelector<HTMLElement>("#delete-log-modal");
|
||||
const $deleteModalElement =
|
||||
document.querySelector<HTMLElement>("#delete-log-modal");
|
||||
if ($deleteModalElement) {
|
||||
deleteLogModal.value = new Modal($deleteModalElement);
|
||||
}
|
||||
|
||||
// 加载日志详情
|
||||
await fetchLogDetail(logId);
|
||||
} catch (error) {
|
||||
handleError(error);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
<!-- 移动端卡片列表 -->
|
||||
<div class="md:hidden mt-4">
|
||||
<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 justify-between items-start">
|
||||
<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>{{ formatExecutionTime(item.executionTime) }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-gray-500">用户</div>
|
||||
<div>{{ item.username || '-' }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-gray-500">创建时间</div>
|
||||
<div>{{ formatDateTime(item.createTime) }}</div>
|
||||
@@ -172,8 +168,8 @@
|
||||
删除此日期之前的所有日志
|
||||
</label>
|
||||
<div class="datepicker-container">
|
||||
<VueDatePicker v-model="clearBeforeDate" locale="zh-CN" format="yyyy-MM-dd" :enable-time-picker="false"
|
||||
:auto-apply="true" class="filter-datepicker" teleport="body" />
|
||||
<VueDatePicker v-model="clearBeforeDate" locale="zh-CN" format="yyyy/MM/dd HH:mm:ss"
|
||||
:enable-time-picker="false" :auto-apply="true" class="filter-datepicker" teleport="body" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end gap-2">
|
||||
@@ -214,6 +210,7 @@ import { useErrorHandling } from "@/composables/common/useErrorHandling";
|
||||
import { useActionExcStore } from "@/composables/store/useActionExcStore";
|
||||
import { Routes } from "@/router/constants";
|
||||
import type { AopLogQueryParams } from "@/types/AlertTypes";
|
||||
import { formatDate } from "@/utils";
|
||||
|
||||
// 路由
|
||||
const router = useRouter();
|
||||
@@ -231,8 +228,6 @@ const {
|
||||
fetchLogs,
|
||||
formatDateTime,
|
||||
formatExecutionTime,
|
||||
handleSort,
|
||||
getSortField,
|
||||
} = useAopLogQuery();
|
||||
|
||||
const { deleteLog, batchDeleteLogs, deleteLogsBefore } = useAopLogDelete();
|
||||
@@ -312,7 +307,7 @@ const columns = [
|
||||
|
||||
// 更新筛选值
|
||||
const updateFilterValues = (
|
||||
values: Record<string, string | number | boolean | Date[] | undefined>
|
||||
values: Record<string, string | number | boolean | Date[] | undefined>,
|
||||
) => {
|
||||
if (values.className !== undefined) {
|
||||
filterValues.className = values.className as string;
|
||||
@@ -333,35 +328,26 @@ const updateFilterValues = (
|
||||
|
||||
// 处理搜索
|
||||
const handleSearch = async () => {
|
||||
try {
|
||||
const params: AopLogQueryParams = {
|
||||
className: filterValues.className || undefined,
|
||||
methodName: filterValues.methodName || undefined,
|
||||
success: filterValues.success ? filterValues.success === "true" : undefined,
|
||||
username: filterValues.username || undefined,
|
||||
};
|
||||
|
||||
// 处理日期范围
|
||||
if (filterValues.dateRange && filterValues.dateRange.length === 2) {
|
||||
params.startTime = filterValues.dateRange[0].toISOString();
|
||||
params.endTime = filterValues.dateRange[1].toISOString();
|
||||
params.startTime = formatDate(filterValues.dateRange[0]);
|
||||
params.endTime = formatDate(filterValues.dateRange[1]);
|
||||
}
|
||||
|
||||
await fetchLogs(params);
|
||||
selectedLogs.value = [];
|
||||
} catch (error) {
|
||||
handleError(error);
|
||||
}
|
||||
};
|
||||
|
||||
// 处理页码变化
|
||||
const handlePageChange = async (page: number) => {
|
||||
try {
|
||||
currentPage.value = page;
|
||||
await handleSearch();
|
||||
} catch (error) {
|
||||
handleError(error);
|
||||
}
|
||||
};
|
||||
|
||||
// 处理查看详情
|
||||
@@ -379,15 +365,11 @@ const handleDeleteClick = (log: components["schemas"]["AopLogRespDto"]) => {
|
||||
|
||||
// 确认删除
|
||||
const confirmDelete = async () => {
|
||||
try {
|
||||
if (currentLogToDelete.value?.id) {
|
||||
await deleteLog(currentLogToDelete.value.id);
|
||||
await handleSearch();
|
||||
deleteLogModal.value?.hide();
|
||||
}
|
||||
} catch (error) {
|
||||
handleError(error);
|
||||
}
|
||||
};
|
||||
|
||||
// 处理批量删除点击
|
||||
@@ -399,15 +381,11 @@ const handleBatchDeleteClick = () => {
|
||||
|
||||
// 确认批量删除
|
||||
const confirmBatchDelete = async () => {
|
||||
try {
|
||||
if (selectedLogs.value.length > 0) {
|
||||
await batchDeleteLogs(selectedLogs.value);
|
||||
await handleSearch();
|
||||
batchDeleteLogsModal.value?.hide();
|
||||
}
|
||||
} catch (error) {
|
||||
handleError(error);
|
||||
}
|
||||
};
|
||||
|
||||
// 处理清理历史日志点击
|
||||
@@ -422,22 +400,20 @@ const closeClearBeforeModal = () => {
|
||||
|
||||
// 确认清理历史日志
|
||||
const confirmClearBefore = async () => {
|
||||
try {
|
||||
if (clearBeforeDate.value) {
|
||||
const dateString = clearBeforeDate.value.toISOString().split("T")[0];
|
||||
await deleteLogsBefore(dateString);
|
||||
const dateString = formatDate(clearBeforeDate.value);
|
||||
await deleteLogsBefore(dateString!);
|
||||
await handleSearch();
|
||||
clearBeforeModal.value?.hide();
|
||||
}
|
||||
} catch (error) {
|
||||
handleError(error);
|
||||
}
|
||||
};
|
||||
|
||||
// 处理全选
|
||||
const handleSelectAll = (selected: boolean) => {
|
||||
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 {
|
||||
selectedLogs.value = [];
|
||||
}
|
||||
@@ -447,14 +423,18 @@ const handleSelectAll = (selected: boolean) => {
|
||||
const actionExcStore = useActionExcStore();
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
// 初始化Flowbite
|
||||
initFlowbite();
|
||||
|
||||
// 初始化模态框
|
||||
const $deleteModalElement = document.querySelector<HTMLElement>("#delete-log-modal");
|
||||
const $batchDeleteModalElement = document.querySelector<HTMLElement>("#batch-delete-logs-modal");
|
||||
const $clearBeforeModalElement = document.querySelector<HTMLElement>("#clear-before-modal");
|
||||
const $deleteModalElement =
|
||||
document.querySelector<HTMLElement>("#delete-log-modal");
|
||||
const $batchDeleteModalElement = document.querySelector<HTMLElement>(
|
||||
"#batch-delete-logs-modal",
|
||||
);
|
||||
const $clearBeforeModalElement = document.querySelector<HTMLElement>(
|
||||
"#clear-before-modal",
|
||||
);
|
||||
|
||||
if ($deleteModalElement) {
|
||||
deleteLogModal.value = new Modal($deleteModalElement);
|
||||
@@ -475,8 +455,5 @@ onMounted(async () => {
|
||||
handleSearch();
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
handleError(error);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -164,7 +164,6 @@ import type { components } from "@/api/types/schema";
|
||||
import PromotionBanner from "@/components/common/PromotionBanner.vue";
|
||||
import { PlusIcon } from "@/components/icons";
|
||||
import Breadcrumbs from "@/components/layout/Breadcrumbs.vue";
|
||||
import ConfirmationDialog from "@/components/modals/ConfirmationDialog.vue";
|
||||
import UserDeleteModal from "@/components/modals/ConfirmationDialog.vue";
|
||||
import UserFormDialog from "@/components/modals/UserFormDialog.vue";
|
||||
import TableButton from "@/components/tables/TableButton.vue";
|
||||
|
||||
Reference in New Issue
Block a user