mirror of
https://github.com/ccmjga/zhilu-admin
synced 2026-04-01 09:03:43 +08:00
init aop log
This commit is contained in:
@@ -45,4 +45,30 @@ export default [
|
||||
message: "Llm updated successfully",
|
||||
});
|
||||
}),
|
||||
http.post("/ai/chat/refresh", () => {
|
||||
return HttpResponse.json({
|
||||
success: true,
|
||||
message: "Conversation cleared successfully",
|
||||
});
|
||||
}),
|
||||
http.post("/ai/action/execute", () => {
|
||||
const response = new HttpResponse(`data: ${faker.lorem.paragraph()}\n\n`, {
|
||||
headers: {
|
||||
"Content-Type": "text/event-stream",
|
||||
},
|
||||
});
|
||||
return response;
|
||||
}),
|
||||
http.delete("/ai/action/department", () => {
|
||||
return HttpResponse.json({ success: true });
|
||||
}),
|
||||
http.delete("/ai/action/position", () => {
|
||||
return HttpResponse.json({ success: true });
|
||||
}),
|
||||
http.delete("/ai/action/role", () => {
|
||||
return HttpResponse.json({ success: true });
|
||||
}),
|
||||
http.delete("/ai/action/permission", () => {
|
||||
return HttpResponse.json({ success: true });
|
||||
}),
|
||||
];
|
||||
|
||||
92
frontend/src/api/mocks/knowledgeHandlers.ts
Normal file
92
frontend/src/api/mocks/knowledgeHandlers.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import { faker } from "@faker-js/faker";
|
||||
import { http, HttpResponse } from "msw";
|
||||
|
||||
// 生成模拟的知识库数据
|
||||
const generateLibrary = () => ({
|
||||
id: faker.number.int({ min: 1, max: 100 }),
|
||||
name: faker.lorem.words(2),
|
||||
description: faker.lorem.sentence(),
|
||||
createTime: faker.date.recent().toISOString()
|
||||
});
|
||||
|
||||
// 生成模拟的文档数据
|
||||
const generateDoc = (libId: number) => ({
|
||||
id: faker.number.int({ min: 1, max: 1000 }),
|
||||
libId,
|
||||
name: faker.system.fileName(),
|
||||
identify: faker.string.uuid(),
|
||||
path: faker.system.filePath(),
|
||||
meta: {},
|
||||
enable: faker.datatype.boolean(),
|
||||
status: faker.helpers.arrayElement(["SUCCESS", "INDEXING"]),
|
||||
createTime: faker.date.recent().toISOString(),
|
||||
updateTime: faker.date.recent().toISOString()
|
||||
});
|
||||
|
||||
// 生成模拟的文档段落数据
|
||||
const generateSegment = (docId: number) => ({
|
||||
id: faker.number.int({ min: 1, max: 10000 }),
|
||||
docId,
|
||||
embeddingId: faker.string.uuid(),
|
||||
content: faker.lorem.paragraphs(),
|
||||
tokenUsage: faker.number.int({ min: 10, max: 1000 })
|
||||
});
|
||||
|
||||
export default [
|
||||
// 获取知识库列表
|
||||
http.get("/knowledge/libraries", () => {
|
||||
const libraries = faker.helpers.multiple(generateLibrary, { count: 5 });
|
||||
return HttpResponse.json(libraries);
|
||||
}),
|
||||
|
||||
// 获取文档列表
|
||||
http.get("/knowledge/docs", ({ request }) => {
|
||||
const url = new URL(request.url);
|
||||
const libraryId = Number(url.searchParams.get("libraryId"));
|
||||
|
||||
if (Number.isNaN(libraryId)) {
|
||||
return new HttpResponse(null, { status: 400 });
|
||||
}
|
||||
|
||||
const docs = faker.helpers.multiple(() => generateDoc(libraryId), { count: 8 });
|
||||
return HttpResponse.json(docs);
|
||||
}),
|
||||
|
||||
// 获取文档段落
|
||||
http.get("/knowledge/segments", ({ request }) => {
|
||||
const url = new URL(request.url);
|
||||
const libraryDocId = Number(url.searchParams.get("libraryDocId"));
|
||||
|
||||
if (Number.isNaN(libraryDocId)) {
|
||||
return new HttpResponse(null, { status: 400 });
|
||||
}
|
||||
|
||||
const segments = faker.helpers.multiple(() => generateSegment(libraryDocId), { count: 12 });
|
||||
return HttpResponse.json(segments);
|
||||
}),
|
||||
|
||||
// 创建/更新知识库
|
||||
http.post("/knowledge/library", async () => {
|
||||
return HttpResponse.json({ success: true });
|
||||
}),
|
||||
|
||||
// 删除知识库
|
||||
http.delete("/knowledge/library", () => {
|
||||
return HttpResponse.json({ success: true });
|
||||
}),
|
||||
|
||||
// 更新文档
|
||||
http.put("/knowledge/doc", async () => {
|
||||
return HttpResponse.json({ success: true });
|
||||
}),
|
||||
|
||||
// 删除文档
|
||||
http.delete("/knowledge/doc", () => {
|
||||
return HttpResponse.json({ success: true });
|
||||
}),
|
||||
|
||||
// 上传文档
|
||||
http.post("/knowledge/doc/upload", async () => {
|
||||
return HttpResponse.text("upload-success");
|
||||
}),
|
||||
];
|
||||
@@ -7,6 +7,8 @@ import userHandlers from "./iamHandlers";
|
||||
import departmentHandlers from "./departmentHandlers";
|
||||
import positionHandlers from "./positionHandlers";
|
||||
import aiHandlers from "./aiHandlers";
|
||||
import knowledgeHandlers from "./knowledgeHandlers";
|
||||
|
||||
export const worker = setupWorker(
|
||||
...userHandlers,
|
||||
...authHandlers,
|
||||
@@ -16,4 +18,5 @@ export const worker = setupWorker(
|
||||
...departmentHandlers,
|
||||
...positionHandlers,
|
||||
...aiHandlers,
|
||||
...knowledgeHandlers,
|
||||
);
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
<Avatar :src="user.avatar" size="sm" />
|
||||
</button>
|
||||
</div>
|
||||
<div class="z-50 hidden my-4 text-base list-none bg-white divide-y divide-gray-100 rounded-sm shadow-sm "
|
||||
<div class="z-50 hidden my-4 text-base list-none bg-white divide-y divide-gray-100 rounded-sm shadow-sm"
|
||||
id="dropdown-user">
|
||||
<div class="px-4 py-3" role="none">
|
||||
<p class="text-sm font-medium text-gray-900 truncate " role="none">
|
||||
|
||||
@@ -1,53 +1,53 @@
|
||||
<template>
|
||||
<div class="relative overflow-x-auto shadow-md sm:rounded-lg">
|
||||
<table class="w-full text-sm text-left rtl:text-right text-gray-500">
|
||||
<thead class="text-xs text-gray-700 uppercase bg-gray-50">
|
||||
<tr>
|
||||
<th v-if="hasCheckbox" scope="col" class="p-4 w-4">
|
||||
<div class="flex items-center">
|
||||
<input id="checkbox-all-search" type="checkbox" v-model="allChecked" @change="handleAllCheckedChange"
|
||||
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded-sm focus:ring-blue-500 focus:ring-2">
|
||||
<label for="checkbox-all-search" class="sr-only">checkbox</label>
|
||||
</div>
|
||||
</th>
|
||||
<th v-for="(column, index) in columns" :key="index" scope="col" :class="[
|
||||
<div class="relative overflow-x-auto shadow-md sm:rounded-lg">
|
||||
<table class="w-full text-sm text-left rtl:text-right text-gray-500 whitespace-nowrap">
|
||||
<thead class="text-xs text-gray-700 uppercase bg-gray-50">
|
||||
<tr>
|
||||
<th v-if="hasCheckbox" scope="col" class="p-4 w-4">
|
||||
<div class="flex items-center">
|
||||
<input id="checkbox-all-search" type="checkbox" v-model="allChecked" @change="handleAllCheckedChange"
|
||||
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded-sm focus:ring-blue-500 focus:ring-2">
|
||||
<label for="checkbox-all-search" class="sr-only">checkbox</label>
|
||||
</div>
|
||||
</th>
|
||||
<th v-for="(column, index) in columns" :key="index" scope="col" :class="[
|
||||
'px-6 py-3',
|
||||
column.sortable ? 'cursor-pointer' : '',
|
||||
column.class || ''
|
||||
]" @click="column.sortable ? handleSortClick(column.field) : null">
|
||||
<div class="flex items-center">
|
||||
<span>{{ column.title }}</span>
|
||||
<slot v-if="column.sortable" name="sort-icon" :field="column.field"></slot>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(item, rowIndex) in items" :key="getItemKey(item, rowIndex)"
|
||||
class="bg-white border-b border-gray-200 hover:bg-gray-50">
|
||||
<td v-if="hasCheckbox" class="w-4 p-4">
|
||||
<div class="flex items-center">
|
||||
<input :id="`checkbox-table-search-${rowIndex}`" :value="getItemId(item)" type="checkbox"
|
||||
v-model="checkedItems"
|
||||
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded-sm focus:ring-blue-500 focus:ring-2">
|
||||
<label :for="`checkbox-table-search-${rowIndex}`" class="sr-only">checkbox</label>
|
||||
</div>
|
||||
</td>
|
||||
<td v-for="(column, colIndex) in columns" :key="colIndex" :class="[
|
||||
<div class="flex items-center">
|
||||
<span>{{ column.title }}</span>
|
||||
<slot v-if="column.sortable" name="sort-icon" :field="column.field"></slot>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(item, rowIndex) in items" :key="getItemKey(item, rowIndex)"
|
||||
class="bg-white border-b border-gray-200 hover:bg-gray-50">
|
||||
<td v-if="hasCheckbox" class="w-4 p-4">
|
||||
<div class="flex items-center">
|
||||
<input :id="`checkbox-table-search-${rowIndex}`" :value="getItemId(item)" type="checkbox"
|
||||
v-model="checkedItems"
|
||||
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded-sm focus:ring-blue-500 focus:ring-2">
|
||||
<label :for="`checkbox-table-search-${rowIndex}`" class="sr-only">checkbox</label>
|
||||
</div>
|
||||
</td>
|
||||
<td v-for="(column, colIndex) in columns" :key="colIndex" :class="[
|
||||
'px-6 py-4',
|
||||
column.class || '',
|
||||
colIndex === 0 ? 'font-medium text-gray-900' : ''
|
||||
]">
|
||||
<slot :name="column.field" :item="item" :index="rowIndex">
|
||||
<div class="max-w-sm whitespace-nowrap overflow-hidden text-ellipsis">
|
||||
{{ getItemValue(item, column.field) }}
|
||||
</div>
|
||||
</slot>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<slot :name="column.field" :item="item" :index="rowIndex">
|
||||
<div class="max-w-sm whitespace-nowrap overflow-hidden text-ellipsis">
|
||||
{{ getItemValue(item, column.field) }}
|
||||
</div>
|
||||
</slot>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup generic="T" lang="ts">
|
||||
|
||||
Reference in New Issue
Block a user