feat(知识库管理): 添加文档和文件列表排序功能并优化表格交互 (#90)
This commit is contained in:
parent
e9efc51179
commit
c787ae7eac
|
@ -100,7 +100,9 @@ def get_knowledgebase_documents(kb_id):
|
||||||
'kb_id': kb_id,
|
'kb_id': kb_id,
|
||||||
'page': int(request.args.get('currentPage', 1)),
|
'page': int(request.args.get('currentPage', 1)),
|
||||||
'size': int(request.args.get('size', 10)),
|
'size': int(request.args.get('size', 10)),
|
||||||
'name': request.args.get('name', '')
|
'name': request.args.get('name', ''),
|
||||||
|
'sort_by': request.args.get("sort_by", "create_time"),
|
||||||
|
'sort_order': request.args.get("sort_order", "desc")
|
||||||
}
|
}
|
||||||
result = KnowledgebaseService.get_knowledgebase_documents(**params)
|
result = KnowledgebaseService.get_knowledgebase_documents(**params)
|
||||||
return success_response(result)
|
return success_response(result)
|
||||||
|
|
|
@ -406,7 +406,7 @@ class KnowledgebaseService:
|
||||||
raise Exception(f"批量删除知识库失败: {str(e)}")
|
raise Exception(f"批量删除知识库失败: {str(e)}")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_knowledgebase_documents(cls, kb_id, page=1, size=10, name=''):
|
def get_knowledgebase_documents(cls, kb_id, page=1, size=10, name='', sort_by="create_time", sort_order="desc"):
|
||||||
"""获取知识库下的文档列表"""
|
"""获取知识库下的文档列表"""
|
||||||
try:
|
try:
|
||||||
conn = cls._get_db_connection()
|
conn = cls._get_db_connection()
|
||||||
|
@ -418,6 +418,14 @@ class KnowledgebaseService:
|
||||||
if not cursor.fetchone():
|
if not cursor.fetchone():
|
||||||
raise Exception("知识库不存在")
|
raise Exception("知识库不存在")
|
||||||
|
|
||||||
|
# 验证排序字段
|
||||||
|
valid_sort_fields = ["name", "size", "create_time", "create_date"]
|
||||||
|
if sort_by not in valid_sort_fields:
|
||||||
|
sort_by = "create_time"
|
||||||
|
|
||||||
|
# 构建排序子句
|
||||||
|
sort_clause = f"ORDER BY d.{sort_by} {sort_order.upper()}"
|
||||||
|
|
||||||
# 查询文档列表
|
# 查询文档列表
|
||||||
query = """
|
query = """
|
||||||
SELECT
|
SELECT
|
||||||
|
@ -439,8 +447,11 @@ class KnowledgebaseService:
|
||||||
if name:
|
if name:
|
||||||
query += " AND d.name LIKE %s"
|
query += " AND d.name LIKE %s"
|
||||||
params.append(f"%{name}%")
|
params.append(f"%{name}%")
|
||||||
|
|
||||||
query += " ORDER BY d.create_date DESC LIMIT %s OFFSET %s"
|
# 添加查询排序条件
|
||||||
|
query += f" {sort_clause}"
|
||||||
|
|
||||||
|
query += " LIMIT %s OFFSET %s"
|
||||||
params.extend([size, (page-1)*size])
|
params.extend([size, (page-1)*size])
|
||||||
|
|
||||||
cursor.execute(query, params)
|
cursor.execute(query, params)
|
||||||
|
|
|
@ -12,6 +12,8 @@ export function getDocumentListApi(params: {
|
||||||
currentPage: number
|
currentPage: number
|
||||||
size: number
|
size: number
|
||||||
name?: string
|
name?: string
|
||||||
|
sort_by: string
|
||||||
|
sort_order: string
|
||||||
}) {
|
}) {
|
||||||
return request({
|
return request({
|
||||||
url: `/api/v1/knowledgebases/${params.kb_id}/documents`,
|
url: `/api/v1/knowledgebases/${params.kb_id}/documents`,
|
||||||
|
@ -19,7 +21,9 @@ export function getDocumentListApi(params: {
|
||||||
params: {
|
params: {
|
||||||
currentPage: params.currentPage,
|
currentPage: params.currentPage,
|
||||||
size: params.size,
|
size: params.size,
|
||||||
name: params.name
|
name: params.name,
|
||||||
|
sort_by: params.sort_by,
|
||||||
|
sort_order: params.sort_order
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -114,10 +118,22 @@ export function getDocumentChunksApi(params: {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取文件列表
|
// 获取文件列表
|
||||||
|
/**
|
||||||
|
* 获取文件列表的 API 请求函数
|
||||||
|
* @param params 请求参数对象
|
||||||
|
* @param params.currentPage 当前页码
|
||||||
|
* @param params.size 每页数量
|
||||||
|
* @param params.name 可选的文件名称过滤
|
||||||
|
* @param params.sort_by 排序字段
|
||||||
|
* @param params.sort_order 排序方式(升序/降序)
|
||||||
|
* @returns Promise 返回文件列表请求的响应
|
||||||
|
*/
|
||||||
export function getFileListApi(params: {
|
export function getFileListApi(params: {
|
||||||
currentPage: number
|
currentPage: number
|
||||||
size: number
|
size: number
|
||||||
name?: string
|
name?: string
|
||||||
|
sort_by: string
|
||||||
|
sort_order: string
|
||||||
}) {
|
}) {
|
||||||
return request({
|
return request({
|
||||||
url: "/api/v1/files",
|
url: "/api/v1/files",
|
||||||
|
|
|
@ -131,7 +131,19 @@ const searchData = reactive({
|
||||||
// 排序状态
|
// 排序状态
|
||||||
const sortData = reactive({
|
const sortData = reactive({
|
||||||
sortBy: "create_date",
|
sortBy: "create_date",
|
||||||
sortOrder: "desc" // 默认排序顺序 (最新创建的在前)
|
sortOrder: "desc" // 默认排序顺序
|
||||||
|
})
|
||||||
|
|
||||||
|
// 文档列表排序状态
|
||||||
|
const docSortData = reactive({
|
||||||
|
sortBy: "create_date",
|
||||||
|
sortOrder: "desc" // 默认排序顺序
|
||||||
|
})
|
||||||
|
|
||||||
|
// 文件列表排序状态
|
||||||
|
const fileSortData = reactive({
|
||||||
|
sortBy: "create_date",
|
||||||
|
sortOrder: "desc" // 默认排序顺序
|
||||||
})
|
})
|
||||||
|
|
||||||
// 存储多选的表格数据
|
// 存储多选的表格数据
|
||||||
|
@ -253,7 +265,9 @@ function getDocumentList() {
|
||||||
kb_id: currentKnowledgeBase.value.id,
|
kb_id: currentKnowledgeBase.value.id,
|
||||||
currentPage: docPaginationData.currentPage,
|
currentPage: docPaginationData.currentPage,
|
||||||
size: docPaginationData.pageSize,
|
size: docPaginationData.pageSize,
|
||||||
name: ""
|
name: "",
|
||||||
|
sort_by: docSortData.sortBy,
|
||||||
|
sort_order: docSortData.sortOrder
|
||||||
}).then((response) => {
|
}).then((response) => {
|
||||||
const result = response as ApiResponse<ListResponse>
|
const result = response as ApiResponse<ListResponse>
|
||||||
documentList.value = result.data.list
|
documentList.value = result.data.list
|
||||||
|
@ -266,6 +280,25 @@ function getDocumentList() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 处理文档表格排序变化事件
|
||||||
|
* @param {object} sortInfo 排序信息对象,包含 prop 和 order
|
||||||
|
* @param {string} sortInfo.prop 排序的字段名
|
||||||
|
* @param {string | null} sortInfo.order 排序的顺序 ('ascending', 'descending', null)
|
||||||
|
*/
|
||||||
|
function handleDocSortChange({ prop }: { prop: string, order: string | null }) {
|
||||||
|
// 如果点击的是同一个字段,则切换排序顺序
|
||||||
|
if (docSortData.sortBy === prop) {
|
||||||
|
// 当前为正序则切换为倒序,否则切换为正序
|
||||||
|
docSortData.sortOrder = docSortData.sortOrder === "asc" ? "desc" : "asc"
|
||||||
|
} else {
|
||||||
|
// 切换字段时,默认正序
|
||||||
|
docSortData.sortBy = prop
|
||||||
|
docSortData.sortOrder = "asc"
|
||||||
|
}
|
||||||
|
getDocumentList()
|
||||||
|
}
|
||||||
|
|
||||||
// 修改handleView方法
|
// 修改handleView方法
|
||||||
function handleView(row: KnowledgeBaseData) {
|
function handleView(row: KnowledgeBaseData) {
|
||||||
currentKnowledgeBase.value = row
|
currentKnowledgeBase.value = row
|
||||||
|
@ -528,7 +561,9 @@ function getFileList() {
|
||||||
getFileListApi({
|
getFileListApi({
|
||||||
currentPage: filePaginationData.currentPage,
|
currentPage: filePaginationData.currentPage,
|
||||||
size: filePaginationData.pageSize,
|
size: filePaginationData.pageSize,
|
||||||
name: ""
|
name: "",
|
||||||
|
sort_by: fileSortData.sortBy,
|
||||||
|
sort_order: fileSortData.sortOrder
|
||||||
}).then((response) => {
|
}).then((response) => {
|
||||||
const typedResponse = response as ApiResponse<FileListResponse>
|
const typedResponse = response as ApiResponse<FileListResponse>
|
||||||
fileList.value = typedResponse.data.list
|
fileList.value = typedResponse.data.list
|
||||||
|
@ -541,6 +576,25 @@ function getFileList() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 处理文件表格排序变化事件
|
||||||
|
* @param {object} sortInfo 排序信息对象,包含 prop 和 order
|
||||||
|
* @param {string} sortInfo.prop 排序的字段名
|
||||||
|
* @param {string | null} sortInfo.order 排序的顺序 ('ascending', 'descending', null)
|
||||||
|
*/
|
||||||
|
function handleFileSortChange({ prop }: { prop: string, order: string | null }) {
|
||||||
|
// 如果点击的是同一个字段,则切换排序顺序
|
||||||
|
if (fileSortData.sortBy === prop) {
|
||||||
|
// 当前为正序则切换为倒序,否则切换为正序
|
||||||
|
fileSortData.sortOrder = fileSortData.sortOrder === "asc" ? "desc" : "asc"
|
||||||
|
} else {
|
||||||
|
// 切换字段时,默认正序
|
||||||
|
fileSortData.sortBy = prop
|
||||||
|
fileSortData.sortOrder = "asc"
|
||||||
|
}
|
||||||
|
getFileList()
|
||||||
|
}
|
||||||
|
|
||||||
// 处理文件选择变化
|
// 处理文件选择变化
|
||||||
function handleFileSelectionChange(selection: any[]) {
|
function handleFileSelectionChange(selection: any[]) {
|
||||||
// 使用Array.from和JSON方法双重确保转换为普通数组
|
// 使用Array.from和JSON方法双重确保转换为普通数组
|
||||||
|
@ -1132,10 +1186,10 @@ function shouldShowProgressCount(status: string) {
|
||||||
<!-- === 结束进度显示 === -->
|
<!-- === 结束进度显示 === -->
|
||||||
|
|
||||||
<div class="document-table-wrapper" v-loading="documentLoading || (isBatchPolling && !batchProgress)">
|
<div class="document-table-wrapper" v-loading="documentLoading || (isBatchPolling && !batchProgress)">
|
||||||
<el-table :data="documentList" style="width: 100%">
|
<el-table :data="documentList" style="width: 100%" @sort-change="handleDocSortChange">
|
||||||
<el-table-column prop="name" label="名称" min-width="180" show-overflow-tooltip />
|
<el-table-column prop="name" label="名称" min-width="180" show-overflow-tooltip sortable="custom" />
|
||||||
<el-table-column prop="chunk_num" label="分块数" width="100" align="center" />
|
<el-table-column prop="chunk_num" label="分块数" width="100" align="center" />
|
||||||
<el-table-column label="上传日期" width="180" align="center">
|
<el-table-column prop="create_date" label="上传日期" width="180" align="center" sortable="custom">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ scope.row.create_date }}
|
{{ scope.row.create_date }}
|
||||||
</template>
|
</template>
|
||||||
|
@ -1235,7 +1289,7 @@ function shouldShowProgressCount(status: string) {
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<!-- 添加文档对话框 -->
|
<!-- 文档对话框 -->
|
||||||
<el-dialog
|
<el-dialog
|
||||||
v-model="addDocumentDialogVisible"
|
v-model="addDocumentDialogVisible"
|
||||||
title="添加文档到知识库"
|
title="添加文档到知识库"
|
||||||
|
@ -1246,10 +1300,11 @@ function shouldShowProgressCount(status: string) {
|
||||||
:data="fileList"
|
:data="fileList"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
@selection-change="handleFileSelectionChange"
|
@selection-change="handleFileSelectionChange"
|
||||||
|
@sort-change="handleFileSortChange"
|
||||||
>
|
>
|
||||||
<el-table-column type="selection" width="55" />
|
<el-table-column type="selection" width="55" />
|
||||||
<el-table-column prop="name" label="文件名" min-width="180" show-overflow-tooltip />
|
<el-table-column prop="name" label="文件名" min-width="180" show-overflow-tooltip sortable="custom" />
|
||||||
<el-table-column prop="size" label="大小" width="100" align="center">
|
<el-table-column prop="size" label="大小" width="100" align="center" sortable="custom">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ formatFileSize(scope.row.size) }}
|
{{ formatFileSize(scope.row.size) }}
|
||||||
</template>
|
</template>
|
||||||
|
@ -1259,7 +1314,11 @@ function shouldShowProgressCount(status: string) {
|
||||||
{{ formatFileType(scope.row.type) }}
|
{{ formatFileType(scope.row.type) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- 移除上传日期列 -->
|
<el-table-column prop="create_date" label="创建时间" align="center" width="180" sortable="custom">
|
||||||
|
<template #default="scope">
|
||||||
|
{{ scope.row.create_date }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<!-- 分页控件 -->
|
<!-- 分页控件 -->
|
||||||
|
@ -1495,4 +1554,4 @@ function shouldShowProgressCount(status: string) {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
animation: rotating 2s linear infinite;
|
animation: rotating 2s linear infinite;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
Loading…
Reference in New Issue