mirror of
https://github.com/ccmjga/zhilu-admin
synced 2026-04-05 03:37:32 +00:00
更新AopLogQueryDto中的时间字段类型为OffsetDateTime,优化AopLogRepository中的时间范围查询逻辑,调整前端模拟数据生成器以支持新的时间格式,修复日期选择器样式,优化日志管理页面的用户体验。
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
@@ -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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 执行时间范围
|
// 执行时间范围
|
||||||
|
|||||||
@@ -3,82 +3,86 @@ import { http, HttpResponse } from "msw";
|
|||||||
|
|
||||||
// 生成AOP日志数据
|
// 生成AOP日志数据
|
||||||
const generateAopLog = () => ({
|
const generateAopLog = () => ({
|
||||||
id: faker.number.int({ min: 1, max: 1000 }),
|
id: faker.number.int({ min: 1, max: 1000 }),
|
||||||
className: faker.helpers.arrayElement([
|
className: faker.helpers.arrayElement([
|
||||||
"com.example.controller.UserController",
|
"com.example.controller.UserController",
|
||||||
"com.example.service.UserService",
|
"com.example.service.UserService",
|
||||||
"com.example.controller.RoleController",
|
"com.example.controller.RoleController",
|
||||||
"com.example.service.RoleService",
|
"com.example.service.RoleService",
|
||||||
"com.example.controller.DepartmentController",
|
"com.example.controller.DepartmentController",
|
||||||
"com.example.service.DepartmentService",
|
"com.example.service.DepartmentService",
|
||||||
]),
|
]),
|
||||||
methodName: faker.helpers.arrayElement([
|
methodName: faker.helpers.arrayElement([
|
||||||
"findById",
|
"findById",
|
||||||
"save",
|
"save",
|
||||||
"update",
|
"update",
|
||||||
"delete",
|
"delete",
|
||||||
"findAll",
|
"findAll",
|
||||||
"findByName",
|
"findByName",
|
||||||
"pageQuery",
|
"pageQuery",
|
||||||
]),
|
]),
|
||||||
methodArgs: JSON.stringify([
|
methodArgs: JSON.stringify([
|
||||||
{ name: "id", value: faker.number.int({ min: 1, max: 100 }) },
|
{ name: "id", value: faker.number.int({ min: 1, max: 100 }) },
|
||||||
{ name: "name", value: faker.person.fullName() },
|
{ name: "name", value: faker.person.fullName() },
|
||||||
]),
|
]),
|
||||||
returnValue: JSON.stringify({
|
returnValue: JSON.stringify({
|
||||||
id: faker.number.int({ min: 1, max: 100 }),
|
id: faker.number.int({ min: 1, max: 100 }),
|
||||||
name: faker.person.fullName(),
|
name: faker.person.fullName(),
|
||||||
success: true,
|
success: true,
|
||||||
}),
|
}),
|
||||||
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(), {
|
||||||
userId: faker.number.int({ min: 1, max: 100 }),
|
probability: 0.1,
|
||||||
username: faker.internet.userName(),
|
}),
|
||||||
ipAddress: faker.internet.ip(),
|
userId: faker.number.int({ min: 1, max: 100 }),
|
||||||
userAgent: faker.internet.userAgent(),
|
username: faker.internet.userName(),
|
||||||
curl: `curl -X GET "${faker.internet.url()}" -H "Authorization: Bearer ${faker.string.alphanumeric(32)}"`,
|
ipAddress: faker.internet.ip(),
|
||||||
createTime: faker.date.recent({ days: 30 }).toISOString(),
|
userAgent: faker.internet.userAgent(),
|
||||||
|
curl: `curl -X GET "${faker.internet.url()}" -H "Authorization: Bearer ${faker.string.alphanumeric(32)}"`,
|
||||||
|
createTime: faker.date.recent({ days: 30 }).toISOString(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
// 分页查询AOP日志
|
// 分页查询AOP日志
|
||||||
http.get("/aop-log/page-query", () => {
|
http.get("/aop-log/page-query", () => {
|
||||||
const mockData = {
|
const mockData = {
|
||||||
data: faker.helpers.multiple(generateAopLog, { count: 10 }),
|
data: faker.helpers.multiple(generateAopLog, { count: 10 }),
|
||||||
total: 100,
|
total: 100,
|
||||||
};
|
};
|
||||||
return HttpResponse.json(mockData);
|
return HttpResponse.json(mockData);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// 查询单条日志详情
|
// 查询单条日志详情
|
||||||
http.get("/aop-log/:id", ({ params }) => {
|
http.get("/aop-log/:id", ({ params }) => {
|
||||||
const id = params.id;
|
const id = params.id;
|
||||||
return HttpResponse.json({
|
return HttpResponse.json({
|
||||||
...generateAopLog(),
|
...generateAopLog(),
|
||||||
id: Number(id),
|
id: Number(id),
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// 删除单条日志
|
// 删除单条日志
|
||||||
http.delete("/aop-log/:id", ({ params }) => {
|
http.delete("/aop-log/:id", ({ params }) => {
|
||||||
console.log(`Captured a "DELETE /aop-log/${params.id}" request`);
|
console.log(`Captured a "DELETE /aop-log/${params.id}" request`);
|
||||||
return HttpResponse.json({ success: true });
|
return HttpResponse.json({ success: true });
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// 批量删除日志
|
// 批量删除日志
|
||||||
http.delete("/aop-log/batch", async ({ request }) => {
|
http.delete("/aop-log/batch", async ({ request }) => {
|
||||||
const ids = await request.json();
|
const ids = await request.json();
|
||||||
console.log(`Captured a "DELETE /aop-log/batch" request with ids: ${ids}`);
|
console.log(`Captured a "DELETE /aop-log/batch" request with ids: ${ids}`);
|
||||||
return HttpResponse.json(ids.length);
|
return HttpResponse.json(ids.length);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// 删除指定时间前的日志
|
// 删除指定时间前的日志
|
||||||
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(
|
||||||
return HttpResponse.json(faker.number.int({ min: 5, max: 50 }));
|
`Captured a "DELETE /aop-log/before" request with time: ${beforeTime}`,
|
||||||
}),
|
);
|
||||||
|
return HttpResponse.json(faker.number.int({ min: 5, max: 50 }));
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -3,90 +3,95 @@ import { http, HttpResponse } from "msw";
|
|||||||
|
|
||||||
// 生成模拟的知识库数据
|
// 生成模拟的知识库数据
|
||||||
const generateLibrary = () => ({
|
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(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// 生成模拟的文档数据
|
// 生成模拟的文档数据
|
||||||
const generateDoc = (libId: number) => ({
|
const generateDoc = (libId: number) => ({
|
||||||
id: faker.number.int({ min: 1, max: 1000 }),
|
id: faker.number.int({ min: 1, max: 1000 }),
|
||||||
libId,
|
libId,
|
||||||
name: faker.system.fileName(),
|
name: faker.system.fileName(),
|
||||||
identify: faker.string.uuid(),
|
identify: faker.string.uuid(),
|
||||||
path: faker.system.filePath(),
|
path: faker.system.filePath(),
|
||||||
meta: {},
|
meta: {},
|
||||||
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(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// 生成模拟的文档段落数据
|
// 生成模拟的文档段落数据
|
||||||
const generateSegment = (docId: number) => ({
|
const generateSegment = (docId: number) => ({
|
||||||
id: faker.number.int({ min: 1, max: 10000 }),
|
id: faker.number.int({ min: 1, max: 10000 }),
|
||||||
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 [
|
||||||
// 获取知识库列表
|
// 获取知识库列表
|
||||||
http.get("/knowledge/libraries", () => {
|
http.get("/knowledge/libraries", () => {
|
||||||
const libraries = faker.helpers.multiple(generateLibrary, { count: 5 });
|
const libraries = faker.helpers.multiple(generateLibrary, { count: 5 });
|
||||||
return HttpResponse.json(libraries);
|
return HttpResponse.json(libraries);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// 获取文档列表
|
// 获取文档列表
|
||||||
http.get("/knowledge/docs", ({ request }) => {
|
http.get("/knowledge/docs", ({ request }) => {
|
||||||
const url = new URL(request.url);
|
const url = new URL(request.url);
|
||||||
const libraryId = Number(url.searchParams.get("libraryId"));
|
const libraryId = Number(url.searchParams.get("libraryId"));
|
||||||
|
|
||||||
if (Number.isNaN(libraryId)) {
|
if (Number.isNaN(libraryId)) {
|
||||||
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), {
|
||||||
return HttpResponse.json(docs);
|
count: 8,
|
||||||
}),
|
});
|
||||||
|
return HttpResponse.json(docs);
|
||||||
|
}),
|
||||||
|
|
||||||
// 获取文档段落
|
// 获取文档段落
|
||||||
http.get("/knowledge/segments", ({ request }) => {
|
http.get("/knowledge/segments", ({ request }) => {
|
||||||
const url = new URL(request.url);
|
const url = new URL(request.url);
|
||||||
const libraryDocId = Number(url.searchParams.get("libraryDocId"));
|
const libraryDocId = Number(url.searchParams.get("libraryDocId"));
|
||||||
|
|
||||||
if (Number.isNaN(libraryDocId)) {
|
if (Number.isNaN(libraryDocId)) {
|
||||||
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(
|
||||||
return HttpResponse.json(segments);
|
() => generateSegment(libraryDocId),
|
||||||
}),
|
{ count: 12 },
|
||||||
|
);
|
||||||
|
return HttpResponse.json(segments);
|
||||||
|
}),
|
||||||
|
|
||||||
// 创建/更新知识库
|
// 创建/更新知识库
|
||||||
http.post("/knowledge/library", async () => {
|
http.post("/knowledge/library", async () => {
|
||||||
return HttpResponse.json({ success: true });
|
return HttpResponse.json({ success: true });
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// 删除知识库
|
// 删除知识库
|
||||||
http.delete("/knowledge/library", () => {
|
http.delete("/knowledge/library", () => {
|
||||||
return HttpResponse.json({ success: true });
|
return HttpResponse.json({ success: true });
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// 更新文档
|
// 更新文档
|
||||||
http.put("/knowledge/doc", async () => {
|
http.put("/knowledge/doc", async () => {
|
||||||
return HttpResponse.json({ success: true });
|
return HttpResponse.json({ success: true });
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// 删除文档
|
// 删除文档
|
||||||
http.delete("/knowledge/doc", () => {
|
http.delete("/knowledge/doc", () => {
|
||||||
return HttpResponse.json({ success: true });
|
return HttpResponse.json({ success: true });
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// 上传文档
|
// 上传文档
|
||||||
http.post("/knowledge/doc/upload", async () => {
|
http.post("/knowledge/doc/upload", async () => {
|
||||||
return HttpResponse.text("upload-success");
|
return HttpResponse.text("upload-success");
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
|
|||||||
5200
frontend/src/api/types/schema.d.ts
vendored
5200
frontend/src/api/types/schema.d.ts
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,70 +1,69 @@
|
|||||||
/* 日期选择器亮色主题 - 与 Flowbite 蓝色主题匹配 */ .dp__theme_light {
|
/* 日期选择器亮色主题 - 与 Flowbite 蓝色主题匹配 */ .dp__theme_light {
|
||||||
/* 基础颜色 */
|
/* 基础颜色 */
|
||||||
--dp-background-color: #fff;
|
--dp-background-color: #fff;
|
||||||
--dp-text-color: #1f2937; /* 对应 Flowbite 的 gray-800 */
|
--dp-text-color: #1f2937; /* 对应 Flowbite 的 gray-800 */
|
||||||
|
|
||||||
/* 主色调 */
|
/* 主色调 */
|
||||||
--dp-primary-color: #2563eb; /* 对应 Flowbite 的 primary-600 */
|
--dp-primary-color: #2563eb; /* 对应 Flowbite 的 primary-600 */
|
||||||
--dp-primary-disabled-color: #93c5fd; /* 对应 Flowbite 的 primary-300 */
|
--dp-primary-disabled-color: #93c5fd; /* 对应 Flowbite 的 primary-300 */
|
||||||
--dp-primary-text-color: #fff;
|
--dp-primary-text-color: #fff;
|
||||||
|
|
||||||
/* 次要颜色 */
|
/* 次要颜色 */
|
||||||
--dp-secondary-color: #9ca3af; /* 对应 Flowbite 的 gray-400 */
|
--dp-secondary-color: #9ca3af; /* 对应 Flowbite 的 gray-400 */
|
||||||
|
|
||||||
/* 背景颜色 */
|
/* 背景颜色 */
|
||||||
--dp-background-color: var(--color-gray-50);
|
--dp-background-color: var(--color-gray-50);
|
||||||
|
|
||||||
/* 边框颜色 */
|
/* 边框颜色 */
|
||||||
--dp-border-color: var(--color-gray-300); /* 对应 Flowbite 的 gray-200 */
|
--dp-border-color: var(--color-gray-300); /* 对应 Flowbite 的 gray-200 */
|
||||||
--dp-menu-border-color: #e5e7eb;
|
--dp-menu-border-color: #e5e7eb;
|
||||||
|
|
||||||
/* 禁用状态 */
|
/* 禁用状态 */
|
||||||
--dp-disabled-color: #f3f4f6; /* 对应 Flowbite 的 gray-100 */
|
--dp-disabled-color: #f3f4f6; /* 对应 Flowbite 的 gray-100 */
|
||||||
--dp-disabled-color-text: #9ca3af; /* 对应 Flowbite 的 gray-400 */
|
--dp-disabled-color-text: #9ca3af; /* 对应 Flowbite 的 gray-400 */
|
||||||
|
|
||||||
/* 滚动条 */
|
/* 滚动条 */
|
||||||
--dp-scroll-bar-background: #f3f4f6; /* 对应 Flowbite 的 gray-100 */
|
--dp-scroll-bar-background: #f3f4f6; /* 对应 Flowbite 的 gray-100 */
|
||||||
--dp-scroll-bar-color: #9ca3af; /* 对应 Flowbite 的 gray-400 */
|
--dp-scroll-bar-color: #9ca3af; /* 对应 Flowbite 的 gray-400 */
|
||||||
|
|
||||||
/* 成功状态 */
|
/* 成功状态 */
|
||||||
--dp-success-color: #10b981; /* 对应 Tailwind 的 emerald-500 */
|
--dp-success-color: #10b981; /* 对应 Tailwind 的 emerald-500 */
|
||||||
--dp-success-color-disabled: #6ee7b7; /* 对应 Tailwind 的 emerald-300 */
|
--dp-success-color-disabled: #6ee7b7; /* 对应 Tailwind 的 emerald-300 */
|
||||||
|
|
||||||
/* 图标颜色 */
|
/* 图标颜色 */
|
||||||
--dp-icon-color: #6b7280; /* 对应 Flowbite 的 gray-500 */
|
--dp-icon-color: #6b7280; /* 对应 Flowbite 的 gray-500 */
|
||||||
|
|
||||||
/* 危险/错误状态 */
|
/* 危险/错误状态 */
|
||||||
--dp-danger-color: #ef4444; /* 对应 Tailwind 的 red-500 */
|
--dp-danger-color: #ef4444; /* 对应 Tailwind 的 red-500 */
|
||||||
--dp-marker-color: #ef4444;
|
--dp-marker-color: #ef4444;
|
||||||
|
|
||||||
/* 提示颜色 */
|
/* 提示颜色 */
|
||||||
--dp-tooltip-color: #f9fafb; /* 对应 Flowbite 的 gray-50 */
|
--dp-tooltip-color: #f9fafb; /* 对应 Flowbite 的 gray-50 */
|
||||||
|
|
||||||
/* 高亮颜色 */
|
/* 高亮颜色 */
|
||||||
--dp-highlight-color: rgb(37 99 235 / 10%); /* 对应 Flowbite 的 primary-600 透明度 */
|
--dp-highlight-color: rgb(37 99 235 / 10%); /* 对应 Flowbite 的 primary-600 透明度 */
|
||||||
|
|
||||||
/* 日期范围相关 */
|
/* 日期范围相关 */
|
||||||
--dp-range-between-dates-background-color: var(--dp-hover-color, #eff6ff);
|
--dp-range-between-dates-background-color: var(--dp-hover-color, #eff6ff);
|
||||||
--dp-range-between-dates-text-color: var(--dp-hover-text-color, #1f2937);
|
--dp-range-between-dates-text-color: var(--dp-hover-text-color, #1f2937);
|
||||||
--dp-range-between-border-color: var(--dp-hover-color, #eff6ff);
|
--dp-range-between-border-color: var(--dp-hover-color, #eff6ff);
|
||||||
|
|
||||||
/* 圆角设置 - 匹配项目中的 rounded-lg */
|
/* 圆角设置 - 匹配项目中的 rounded-lg */
|
||||||
--dp-border-radius: 0.5rem; /* 8px,匹配 Tailwind 的 rounded-lg */
|
--dp-border-radius: 0.5rem; /* 8px,匹配 Tailwind 的 rounded-lg */
|
||||||
--dp-cell-border-radius: 0.375rem; /* 6px,稍微小一点,更美观 */
|
--dp-cell-border-radius: 0.375rem; /* 6px,稍微小一点,更美观 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 修复日期文本与图标重叠的问题 */
|
/* 修复日期文本与图标重叠的问题 */
|
||||||
.dp__input_wrap {
|
.dp__input_wrap {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dp__input {
|
.dp__input {
|
||||||
padding-left: 2rem !important; /* 确保文本不会与图标重叠 */
|
padding-left: 2rem !important; /* 确保文本不会与图标重叠 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.dp__input_icon {
|
|
||||||
position: absolute;
|
|
||||||
/* left: 0.75rem !important; */
|
|
||||||
right: auto !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
.dp__input_icon {
|
||||||
|
position: absolute;
|
||||||
|
/* left: 0.75rem !important; */
|
||||||
|
right: auto !important;
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,6 +19,6 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
defineProps<{
|
defineProps<{
|
||||||
success: boolean;
|
success: boolean;
|
||||||
}>();
|
}>();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -8,94 +8,94 @@ import { ref } from "vue";
|
|||||||
* @returns 日志删除相关的状态和方法
|
* @returns 日志删除相关的状态和方法
|
||||||
*/
|
*/
|
||||||
export function useAopLogDelete() {
|
export function useAopLogDelete() {
|
||||||
const alertStore = useAlertStore();
|
const alertStore = useAlertStore();
|
||||||
const actionExcStore = useActionExcStore();
|
const actionExcStore = useActionExcStore();
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除单条日志
|
* 删除单条日志
|
||||||
* @param id 日志ID
|
* @param id 日志ID
|
||||||
*/
|
*/
|
||||||
const deleteLog = async (id: number) => {
|
const deleteLog = async (id: number) => {
|
||||||
try {
|
try {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
|
||||||
await client.DELETE("/aop-log/{id}", {
|
await client.DELETE("/aop-log/{id}", {
|
||||||
params: {
|
params: {
|
||||||
path: {
|
path: {
|
||||||
id,
|
id,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
alertStore.showAlert({
|
alertStore.showAlert({
|
||||||
level: "success",
|
level: "success",
|
||||||
content: "日志删除成功",
|
content: "日志删除成功",
|
||||||
});
|
});
|
||||||
|
|
||||||
actionExcStore.notify(true);
|
actionExcStore.notify(true);
|
||||||
return true;
|
return true;
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量删除日志
|
* 批量删除日志
|
||||||
* @param ids 日志ID列表
|
* @param ids 日志ID列表
|
||||||
*/
|
*/
|
||||||
const batchDeleteLogs = async (ids: number[]) => {
|
const batchDeleteLogs = async (ids: number[]) => {
|
||||||
try {
|
try {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
|
||||||
const response = await client.DELETE("/aop-log/batch", {
|
const response = await client.DELETE("/aop-log/batch", {
|
||||||
body: ids,
|
body: ids,
|
||||||
});
|
});
|
||||||
|
|
||||||
alertStore.showAlert({
|
alertStore.showAlert({
|
||||||
level: "success",
|
level: "success",
|
||||||
content: `成功删除 ${response.data || 0} 条日志`,
|
content: `成功删除 ${response.data || 0} 条日志`,
|
||||||
});
|
});
|
||||||
|
|
||||||
actionExcStore.notify(true);
|
actionExcStore.notify(true);
|
||||||
return true;
|
return true;
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除指定时间前的日志
|
* 删除指定时间前的日志
|
||||||
* @param beforeTime 时间点
|
* @param beforeTime 时间点
|
||||||
*/
|
*/
|
||||||
const deleteLogsBefore = async (beforeTime: string) => {
|
const deleteLogsBefore = async (beforeTime: string) => {
|
||||||
try {
|
try {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
|
||||||
const response = await client.DELETE("/aop-log/before", {
|
const response = await client.DELETE("/aop-log/before", {
|
||||||
params: {
|
params: {
|
||||||
query: {
|
query: {
|
||||||
beforeTime,
|
beforeTime,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
alertStore.showAlert({
|
alertStore.showAlert({
|
||||||
level: "success",
|
level: "success",
|
||||||
content: `成功删除 ${response.data || 0} 条日志`,
|
content: `成功删除 ${response.data || 0} 条日志`,
|
||||||
});
|
});
|
||||||
|
|
||||||
actionExcStore.notify(true);
|
actionExcStore.notify(true);
|
||||||
return true;
|
return true;
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
loading,
|
loading,
|
||||||
deleteLog,
|
deleteLog,
|
||||||
batchDeleteLogs,
|
batchDeleteLogs,
|
||||||
deleteLogsBefore,
|
deleteLogsBefore,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,120 +12,121 @@ import { ref } from "vue";
|
|||||||
* @returns 日志查询相关的状态和方法
|
* @returns 日志查询相关的状态和方法
|
||||||
*/
|
*/
|
||||||
export function useAopLogQuery() {
|
export function useAopLogQuery() {
|
||||||
const { currentPage, pageSize, total, updatePaginationState } = usePagination();
|
const { currentPage, pageSize, total, updatePaginationState } =
|
||||||
const { sortBy, handleSort, getSortField } = useSorting();
|
usePagination();
|
||||||
|
const { sortBy, handleSort, getSortField } = useSorting();
|
||||||
|
|
||||||
const logs = ref<components["schemas"]["AopLogRespDto"][]>([]);
|
const logs = ref<components["schemas"]["AopLogRespDto"][]>([]);
|
||||||
const currentLog = ref<components["schemas"]["AopLogRespDto"]>();
|
const currentLog = ref<components["schemas"]["AopLogRespDto"]>();
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页查询日志列表
|
* 分页查询日志列表
|
||||||
* @param params 查询参数
|
* @param params 查询参数
|
||||||
*/
|
*/
|
||||||
const fetchLogs = async (params: AopLogQueryParams = {}) => {
|
const fetchLogs = async (params: AopLogQueryParams = {}) => {
|
||||||
try {
|
try {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
|
||||||
// 处理日期范围
|
// 处理日期范围
|
||||||
const queryParams: AopLogQueryParams = { ...params };
|
const queryParams: AopLogQueryParams = { ...params };
|
||||||
|
|
||||||
const response = await client.GET("/aop-log/page-query", {
|
const response = await client.GET("/aop-log/page-query", {
|
||||||
params: {
|
params: {
|
||||||
query: {
|
query: {
|
||||||
pageRequestDto: {
|
pageRequestDto: {
|
||||||
page: currentPage.value,
|
page: currentPage.value,
|
||||||
size: pageSize.value,
|
size: pageSize.value,
|
||||||
sortBy: sortBy.value,
|
sortBy: sortBy.value,
|
||||||
},
|
},
|
||||||
queryDto: queryParams,
|
queryDto: queryParams,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.data) {
|
if (response.data) {
|
||||||
logs.value = response.data.data || [];
|
logs.value = response.data.data || [];
|
||||||
updatePaginationState({ total: response.data.total || 0 });
|
updatePaginationState({ total: response.data.total || 0 });
|
||||||
}
|
}
|
||||||
|
|
||||||
return logs.value;
|
return logs.value;
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取单条日志详情
|
* 获取单条日志详情
|
||||||
* @param id 日志ID
|
* @param id 日志ID
|
||||||
*/
|
*/
|
||||||
const fetchLogDetail = async (id: number) => {
|
const fetchLogDetail = async (id: number) => {
|
||||||
try {
|
try {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
|
||||||
const response = await client.GET("/aop-log/{id}", {
|
const response = await client.GET("/aop-log/{id}", {
|
||||||
params: {
|
params: {
|
||||||
path: {
|
path: {
|
||||||
id,
|
id,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.data) {
|
if (response.data) {
|
||||||
currentLog.value = response.data;
|
currentLog.value = response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
return currentLog.value;
|
return currentLog.value;
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 格式化日期时间
|
* 格式化日期时间
|
||||||
* @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");
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 格式化执行时间
|
* 格式化执行时间
|
||||||
* @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`;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 格式化JSON字符串
|
* 格式化JSON字符串
|
||||||
* @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);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return jsonString;
|
return jsonString;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
logs,
|
logs,
|
||||||
currentLog,
|
currentLog,
|
||||||
loading,
|
loading,
|
||||||
currentPage,
|
currentPage,
|
||||||
pageSize,
|
pageSize,
|
||||||
total,
|
total,
|
||||||
fetchLogs,
|
fetchLogs,
|
||||||
fetchLogDetail,
|
fetchLogDetail,
|
||||||
handleSort,
|
handleSort,
|
||||||
getSortField,
|
getSortField,
|
||||||
formatDateTime,
|
formatDateTime,
|
||||||
formatExecutionTime,
|
formatExecutionTime,
|
||||||
formatJson,
|
formatJson,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ export interface PaginationState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface UsePaginationOptions {
|
export interface UsePaginationOptions {
|
||||||
initialPage?: number;
|
initialPage?: number;
|
||||||
initialPageSize?: number;
|
initialPageSize?: number;
|
||||||
initialTotal?: number;
|
initialTotal?: number;
|
||||||
maxVisiblePages?: number;
|
maxVisiblePages?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页逻辑Composable - 提供分页相关的状态和操作
|
* 分页逻辑Composable - 提供分页相关的状态和操作
|
||||||
|
|||||||
@@ -2,22 +2,22 @@ import type { RouteRecordRaw } from "vue-router";
|
|||||||
import { Routes } from "../constants";
|
import { Routes } from "../constants";
|
||||||
|
|
||||||
const systemRoutes: RouteRecordRaw[] = [
|
const systemRoutes: RouteRecordRaw[] = [
|
||||||
{
|
{
|
||||||
path: Routes.AOPLOGVIEW.path,
|
path: Routes.AOPLOGVIEW.path,
|
||||||
name: Routes.AOPLOGVIEW.name,
|
name: Routes.AOPLOGVIEW.name,
|
||||||
component: () => import("@/views/AopLogManagementPage.vue"),
|
component: () => import("@/views/AopLogManagementPage.vue"),
|
||||||
meta: {
|
meta: {
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: Routes.AOPLOGDETAILVIEW.path,
|
path: Routes.AOPLOGDETAILVIEW.path,
|
||||||
name: Routes.AOPLOGDETAILVIEW.name,
|
name: Routes.AOPLOGDETAILVIEW.name,
|
||||||
component: () => import("@/views/AopLogDetailPage.vue"),
|
component: () => import("@/views/AopLogDetailPage.vue"),
|
||||||
meta: {
|
meta: {
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export default systemRoutes;
|
export default systemRoutes;
|
||||||
|
|||||||
@@ -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,17 +179,14 @@ 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,
|
||||||
loading,
|
loading,
|
||||||
fetchLogDetail,
|
fetchLogDetail,
|
||||||
formatDateTime,
|
formatDateTime,
|
||||||
formatExecutionTime,
|
formatExecutionTime,
|
||||||
formatJson,
|
formatJson,
|
||||||
} = useAopLogQuery();
|
} = useAopLogQuery();
|
||||||
|
|
||||||
const { deleteLog } = useAopLogDelete();
|
const { deleteLog } = useAopLogDelete();
|
||||||
@@ -211,90 +206,83 @@ const isCopied = ref(false);
|
|||||||
const previewLength = 300;
|
const previewLength = 300;
|
||||||
|
|
||||||
const methodArgsPreview = computed(() => {
|
const methodArgsPreview = computed(() => {
|
||||||
const content = formatJson(currentLog.value?.methodArgs);
|
const content = formatJson(currentLog.value?.methodArgs);
|
||||||
return content && content.length > previewLength
|
return content && content.length > previewLength
|
||||||
? `${content.substring(0, previewLength)}...`
|
? `${content.substring(0, previewLength)}...`
|
||||||
: content;
|
: content;
|
||||||
});
|
});
|
||||||
|
|
||||||
const returnValuePreview = computed(() => {
|
const returnValuePreview = computed(() => {
|
||||||
const content = formatJson(currentLog.value?.returnValue);
|
const content = formatJson(currentLog.value?.returnValue);
|
||||||
return content && content.length > previewLength
|
return content && content.length > previewLength
|
||||||
? `${content.substring(0, previewLength)}...`
|
? `${content.substring(0, previewLength)}...`
|
||||||
: content;
|
: content;
|
||||||
});
|
});
|
||||||
|
|
||||||
const errorMessagePreview = computed(() => {
|
const errorMessagePreview = computed(() => {
|
||||||
const content = currentLog.value?.errorMessage;
|
const content = currentLog.value?.errorMessage;
|
||||||
return content && content.length > previewLength
|
return content && content.length > previewLength
|
||||||
? `${content.substring(0, previewLength)}...`
|
? `${content.substring(0, previewLength)}...`
|
||||||
: content;
|
: content;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 判断是否需要折叠
|
// 判断是否需要折叠
|
||||||
const shouldCollapseMethodArgs = computed(() => {
|
const shouldCollapseMethodArgs = computed(() => {
|
||||||
const content = formatJson(currentLog.value?.methodArgs);
|
const content = formatJson(currentLog.value?.methodArgs);
|
||||||
return content && content.length > previewLength;
|
return content && content.length > previewLength;
|
||||||
});
|
});
|
||||||
|
|
||||||
const shouldCollapseReturnValue = computed(() => {
|
const shouldCollapseReturnValue = computed(() => {
|
||||||
const content = formatJson(currentLog.value?.returnValue);
|
const content = formatJson(currentLog.value?.returnValue);
|
||||||
return content && content.length > previewLength;
|
return content && content.length > previewLength;
|
||||||
});
|
});
|
||||||
|
|
||||||
const shouldCollapseErrorMessage = computed(() => {
|
const shouldCollapseErrorMessage = computed(() => {
|
||||||
const content = currentLog.value?.errorMessage;
|
const content = currentLog.value?.errorMessage;
|
||||||
return content && content.length > previewLength;
|
return content && content.length > previewLength;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 复制CURL命令
|
// 复制CURL命令
|
||||||
const copyCurl = () => {
|
const copyCurl = () => {
|
||||||
if (currentLog.value?.curl) {
|
if (currentLog.value?.curl) {
|
||||||
navigator.clipboard.writeText(currentLog.value.curl);
|
navigator.clipboard.writeText(currentLog.value.curl);
|
||||||
isCopied.value = true;
|
isCopied.value = true;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
isCopied.value = false;
|
isCopied.value = false;
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 返回日志列表
|
// 返回日志列表
|
||||||
const navigateBack = () => {
|
const navigateBack = () => {
|
||||||
router.push(Routes.AOPLOGVIEW.fullPath());
|
router.push(Routes.AOPLOGVIEW.fullPath());
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理删除点击
|
// 处理删除点击
|
||||||
const handleDeleteClick = () => {
|
const handleDeleteClick = () => {
|
||||||
deleteLogModal.value?.show();
|
deleteLogModal.value?.show();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 确认删除
|
// 确认删除
|
||||||
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 =
|
||||||
if ($deleteModalElement) {
|
document.querySelector<HTMLElement>("#delete-log-modal");
|
||||||
deleteLogModal.value = new Modal($deleteModalElement);
|
if ($deleteModalElement) {
|
||||||
}
|
deleteLogModal.value = new Modal($deleteModalElement);
|
||||||
|
}
|
||||||
|
|
||||||
// 加载日志详情
|
// 加载日志详情
|
||||||
await fetchLogDetail(logId);
|
await fetchLogDetail(logId);
|
||||||
} catch (error) {
|
|
||||||
handleError(error);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -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();
|
||||||
@@ -223,16 +220,14 @@ const { handleError } = useErrorHandling();
|
|||||||
|
|
||||||
// 获取日志查询和删除的composables
|
// 获取日志查询和删除的composables
|
||||||
const {
|
const {
|
||||||
logs,
|
logs,
|
||||||
currentPage,
|
currentPage,
|
||||||
pageSize,
|
pageSize,
|
||||||
total,
|
total,
|
||||||
loading,
|
loading,
|
||||||
fetchLogs,
|
fetchLogs,
|
||||||
formatDateTime,
|
formatDateTime,
|
||||||
formatExecutionTime,
|
formatExecutionTime,
|
||||||
handleSort,
|
|
||||||
getSortField,
|
|
||||||
} = useAopLogQuery();
|
} = useAopLogQuery();
|
||||||
|
|
||||||
const { deleteLog, batchDeleteLogs, deleteLogsBefore } = useAopLogDelete();
|
const { deleteLog, batchDeleteLogs, deleteLogsBefore } = useAopLogDelete();
|
||||||
@@ -253,230 +248,212 @@ const currentLogToDelete = ref<components["schemas"]["AopLogRespDto"]>();
|
|||||||
|
|
||||||
// 筛选配置
|
// 筛选配置
|
||||||
const filterConfig = [
|
const filterConfig = [
|
||||||
{
|
{
|
||||||
type: "input",
|
type: "input",
|
||||||
name: "className",
|
name: "className",
|
||||||
placeholder: "类名",
|
placeholder: "类名",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "input",
|
type: "input",
|
||||||
name: "methodName",
|
name: "methodName",
|
||||||
placeholder: "方法名",
|
placeholder: "方法名",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "select",
|
type: "select",
|
||||||
name: "success",
|
name: "success",
|
||||||
placeholder: "状态",
|
placeholder: "状态",
|
||||||
options: [
|
options: [
|
||||||
{ value: "", label: "全部" },
|
{ value: "", label: "全部" },
|
||||||
{ value: "true", label: "成功" },
|
{ value: "true", label: "成功" },
|
||||||
{ value: "false", label: "失败" },
|
{ value: "false", label: "失败" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "input",
|
type: "input",
|
||||||
name: "username",
|
name: "username",
|
||||||
placeholder: "用户名",
|
placeholder: "用户名",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "date-range",
|
type: "date-range",
|
||||||
name: "dateRange",
|
name: "dateRange",
|
||||||
},
|
},
|
||||||
] as FilterItem[];
|
] as FilterItem[];
|
||||||
|
|
||||||
// 筛选值
|
// 筛选值
|
||||||
const filterValues = reactive<{
|
const filterValues = reactive<{
|
||||||
className: string;
|
className: string;
|
||||||
methodName: string;
|
methodName: string;
|
||||||
success: string;
|
success: string;
|
||||||
username: string;
|
username: string;
|
||||||
dateRange: Date[];
|
dateRange: Date[];
|
||||||
}>({
|
}>({
|
||||||
className: "",
|
className: "",
|
||||||
methodName: "",
|
methodName: "",
|
||||||
success: "",
|
success: "",
|
||||||
username: "",
|
username: "",
|
||||||
dateRange: [],
|
dateRange: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
// 表格列配置
|
// 表格列配置
|
||||||
const columns = [
|
const columns = [
|
||||||
{ title: "类名", field: "className", sortable: true },
|
{ title: "类名", field: "className", sortable: true },
|
||||||
{ title: "方法名", field: "methodName", sortable: true },
|
{ title: "方法名", field: "methodName", sortable: true },
|
||||||
{ title: "执行时间", field: "executionTime", sortable: true },
|
{ title: "执行时间", field: "executionTime", sortable: true },
|
||||||
{ title: "状态", field: "success" },
|
{ title: "状态", field: "success" },
|
||||||
{ title: "用户", field: "username" },
|
{ title: "用户", field: "username" },
|
||||||
{ title: "创建时间", field: "createTime", sortable: true },
|
{ title: "创建时间", field: "createTime", sortable: true },
|
||||||
{ title: "操作", field: "actions" },
|
{ title: "操作", field: "actions" },
|
||||||
];
|
];
|
||||||
|
|
||||||
// 更新筛选值
|
// 更新筛选值
|
||||||
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;
|
||||||
}
|
}
|
||||||
if (values.methodName !== undefined) {
|
if (values.methodName !== undefined) {
|
||||||
filterValues.methodName = values.methodName as string;
|
filterValues.methodName = values.methodName as string;
|
||||||
}
|
}
|
||||||
if (values.success !== undefined) {
|
if (values.success !== undefined) {
|
||||||
filterValues.success = values.success as string;
|
filterValues.success = values.success as string;
|
||||||
}
|
}
|
||||||
if (values.username !== undefined) {
|
if (values.username !== undefined) {
|
||||||
filterValues.username = values.username as string;
|
filterValues.username = values.username as string;
|
||||||
}
|
}
|
||||||
if (values.dateRange !== undefined) {
|
if (values.dateRange !== undefined) {
|
||||||
filterValues.dateRange = values.dateRange as Date[];
|
filterValues.dateRange = values.dateRange as Date[];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理搜索
|
// 处理搜索
|
||||||
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);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理查看详情
|
// 处理查看详情
|
||||||
const handleViewDetail = (log: components["schemas"]["AopLogRespDto"]) => {
|
const handleViewDetail = (log: components["schemas"]["AopLogRespDto"]) => {
|
||||||
if (log.id) {
|
if (log.id) {
|
||||||
router.push(Routes.AOPLOGDETAILVIEW.withParams({ id: log.id }));
|
router.push(Routes.AOPLOGDETAILVIEW.withParams({ id: log.id }));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理删除点击
|
// 处理删除点击
|
||||||
const handleDeleteClick = (log: components["schemas"]["AopLogRespDto"]) => {
|
const handleDeleteClick = (log: components["schemas"]["AopLogRespDto"]) => {
|
||||||
currentLogToDelete.value = log;
|
currentLogToDelete.value = log;
|
||||||
deleteLogModal.value?.show();
|
deleteLogModal.value?.show();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 确认删除
|
// 确认删除
|
||||||
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);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理批量删除点击
|
// 处理批量删除点击
|
||||||
const handleBatchDeleteClick = () => {
|
const handleBatchDeleteClick = () => {
|
||||||
if (selectedLogs.value.length > 0) {
|
if (selectedLogs.value.length > 0) {
|
||||||
batchDeleteLogsModal.value?.show();
|
batchDeleteLogsModal.value?.show();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 确认批量删除
|
// 确认批量删除
|
||||||
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);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理清理历史日志点击
|
// 处理清理历史日志点击
|
||||||
const handleClearBeforeClick = () => {
|
const handleClearBeforeClick = () => {
|
||||||
clearBeforeModal.value?.show();
|
clearBeforeModal.value?.show();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 关闭清理历史日志对话框
|
// 关闭清理历史日志对话框
|
||||||
const closeClearBeforeModal = () => {
|
const closeClearBeforeModal = () => {
|
||||||
clearBeforeModal.value?.hide();
|
clearBeforeModal.value?.hide();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 确认清理历史日志
|
// 确认清理历史日志
|
||||||
const confirmClearBefore = async () => {
|
const confirmClearBefore = async () => {
|
||||||
try {
|
if (clearBeforeDate.value) {
|
||||||
if (clearBeforeDate.value) {
|
const dateString = formatDate(clearBeforeDate.value);
|
||||||
const dateString = clearBeforeDate.value.toISOString().split("T")[0];
|
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
|
||||||
} else {
|
.map((log) => log.id)
|
||||||
selectedLogs.value = [];
|
.filter((id): id is number => id !== undefined);
|
||||||
}
|
} else {
|
||||||
|
selectedLogs.value = [];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 初始化
|
// 初始化
|
||||||
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);
|
||||||
}
|
}
|
||||||
if ($batchDeleteModalElement) {
|
if ($batchDeleteModalElement) {
|
||||||
batchDeleteLogsModal.value = new Modal($batchDeleteModalElement);
|
batchDeleteLogsModal.value = new Modal($batchDeleteModalElement);
|
||||||
}
|
}
|
||||||
if ($clearBeforeModalElement) {
|
if ($clearBeforeModalElement) {
|
||||||
clearBeforeModal.value = new Modal($clearBeforeModalElement);
|
clearBeforeModal.value = new Modal($clearBeforeModalElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载日志数据
|
// 加载日志数据
|
||||||
await fetchLogs();
|
await fetchLogs();
|
||||||
|
|
||||||
// 设置刷新回调
|
// 设置刷新回调
|
||||||
actionExcStore.setCallback((result) => {
|
actionExcStore.setCallback((result) => {
|
||||||
if (result) {
|
if (result) {
|
||||||
handleSearch();
|
handleSearch();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (error) {
|
|
||||||
handleError(error);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -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";
|
||||||
|
|||||||
Reference in New Issue
Block a user