This commit is contained in:
ygx
2026-03-29 16:07:17 +08:00
parent 9343c110d3
commit 564eb09b40
5 changed files with 82 additions and 71 deletions

View File

@@ -177,8 +177,11 @@ export const publishDocument = (id: number) => {
};
/** 移入回收站 */
export const moveToTrash = (id: number) => {
return request.post<ApiResponse<string>>("/Kb/v1/trash/move", { id, type: 'document' });
export const moveToTrash = (resourceId: number, resourceType: string) => {
return request.post<ApiResponse<string>>("/Kb/v1/trash/move", {
resource_id: resourceId,
resource_type: resourceType,
});
};
/** 获取我的文档列表(由我创建的所有文档) */

View File

@@ -17,7 +17,7 @@
<!-- 资源类型 -->
<template #resource_type="{ record }">
<a-tag :color="record.resource_type === 'document' ? 'arc-blue' : 'arc-green'">
<a-tag :color="record.resource_type === 'document' ? 'blue' : 'green'">
{{ record.resource_type === 'document' ? '文档' : 'FAQ' }}
</a-tag>
</template>
@@ -69,12 +69,12 @@
>
<div v-if="currentResource" class="detail-content">
<a-descriptions :column="2" bordered>
<a-descriptions-item label="文档编号">
{{ currentResource.doc_no || '-' }}
</a-descriptions-item>
<a-descriptions-item label="标题">
<a-descriptions-item label="资源名称">
{{ currentResource.title || '-' }}
</a-descriptions-item>
<a-descriptions-item label="资源类型">
<a-tag color="blue">文档</a-tag>
</a-descriptions-item>
<a-descriptions-item label="作者">
{{ currentResource.author_name || '-' }}
</a-descriptions-item>
@@ -109,23 +109,20 @@
>
<div v-if="currentFaq" class="detail-content">
<a-descriptions :column="2" bordered>
<a-descriptions-item label="FAQ编号">
{{ currentFaq.faq_no || '-' }}
<a-descriptions-item label="资源名称">
{{ currentFaq.question || '-' }}
</a-descriptions-item>
<a-descriptions-item label="资源类型">
<a-tag color="green">FAQ</a-tag>
</a-descriptions-item>
<a-descriptions-item label="状态">
<a-tag color="green">{{ currentFaq.status || '已发布' }}</a-tag>
</a-descriptions-item>
<a-descriptions-item label="问题" :span="2">
{{ currentFaq.question || '-' }}
</a-descriptions-item>
<a-descriptions-item label="答案" :span="2">
<div class="content-preview" v-html="currentFaq.answer || '-'"></div>
</a-descriptions-item>
<a-descriptions-item label="浏览次数">
{{ currentFaq.view_count || 0 }}
</a-descriptions-item>
<a-descriptions-item label="有用次数">
{{ currentFaq.helpful_count || 0 }}
<a-descriptions-item label="答案" :span="2">
<div class="content-preview" v-html="currentFaq.answer || '-'"></div>
</a-descriptions-item>
</a-descriptions>
</div>
@@ -178,13 +175,6 @@ const columns = computed<TableColumnData[]>(() => [
width: 100,
align: 'center',
},
{
title: '备注',
dataIndex: 'remarks',
ellipsis: true,
tooltip: true,
width: 200,
},
{
title: '收藏时间',
dataIndex: 'created_at',

View File

@@ -330,6 +330,7 @@ const searchKeyword = ref('')
// 文档列表
const documentList = ref<Document[]>([])
const resourceTypeMap = ref<Record<number, string>>({}) // 保存 id -> resource_type 的映射
const loading = ref(false)
const page = ref(1)
const pageSize = ref(20)
@@ -337,6 +338,7 @@ const total = ref(0)
// 当前选中的文档
const currentDocument = ref<Document | null>(null)
const currentResourceType = ref<string>('document') // 外层类型document 或 faq
const isFavorited = ref(false)
// 编辑状态
@@ -433,7 +435,14 @@ const fetchData = async () => {
}
// 处理数据:提取 resource 字段document 和 faq 都作为文档处理)
documentList.value = rawData.map((item: any) => item.resource)
// 同时保存每个文档对应的 resource_type
documentList.value = rawData.map((item: any) => {
// 保存 id -> resource_type 的映射
if (item.resource?.id && item.type) {
resourceTypeMap.value[item.resource.id] = item.type
}
return item.resource
})
} else {
documentList.value = []
total.value = 0
@@ -505,6 +514,14 @@ const handleSelectDocument = async (doc: Document) => {
// 从文档详情中获取收藏状态
isFavorited.value = docData.is_favorited || false
// 获取 resource_type优先从列表映射中获取因为详情接口可能不返回外层 type
if (resourceTypeMap.value[doc.id]) {
currentResourceType.value = resourceTypeMap.value[doc.id]
} else if (res.details.type) {
// 备用:从详情响应中获取(注意:这可能是内层 type如 common/guide
currentResourceType.value = res.details.type
}
}
} catch (error) {
console.error('获取文档详情失败:', error)
@@ -517,6 +534,7 @@ const handleSelectDocument = async (doc: Document) => {
// 新建文档
const handleCreate = () => {
currentDocument.value = null
currentResourceType.value = 'document' // 新建时默认为 document
isFavorited.value = false
editForm.title = ''
editForm.type = 'common'
@@ -671,7 +689,7 @@ const handleConfirmDelete = async () => {
if (!currentDocument.value?.id) return
try {
await moveToTrash(currentDocument.value.id)
await moveToTrash(currentDocument.value.id, currentResourceType.value)
Message.success('删除成功,已移入回收站')
deleteConfirmVisible.value = false
currentDocument.value = null

View File

@@ -1,7 +1,7 @@
<template>
<a-modal
:visible="visible"
:title="isEdit ? '编辑分类' : '新增分类'"
:title="isEdit ? '编辑标签' : '新增标签'"
width="600px"
@ok="handleOk"
@cancel="handleCancel"
@@ -12,42 +12,42 @@
<a-row :gutter="16">
<a-col :span="12">
<a-form-item
label="分类名称"
label="标签名称"
field="name"
:rules="[{ required: true, message: '请输入分类名称' }]"
:rules="[{ required: true, message: '请输入标签名称' }]"
>
<a-input
v-model="form.name"
placeholder="请输入分类名称"
placeholder="请输入标签名称"
:max-length="200"
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="分类类型" field="type">
<a-form-item label="标签类型" field="type">
<a-select
v-model="form.type"
placeholder="请选择分类类型"
placeholder="请选择标签类型"
allow-clear
>
<a-option value="document">文档分类</a-option>
<a-option value="faq">FAQ分类</a-option>
<a-option value="general">通用分类</a-option>
<a-option value="document">文档标签</a-option>
<a-option value="faq">FAQ标签</a-option>
<a-option value="general">通用标签</a-option>
</a-select>
</a-form-item>
</a-col>
</a-row>
<a-form-item label="分类描述" field="description">
<a-form-item label="标签描述" field="description">
<a-textarea
v-model="form.description"
placeholder="请输入分类描述"
placeholder="请输入标签描述"
:auto-size="{ minRows: 2, maxRows: 4 }"
:max-length="500"
/>
</a-form-item>
<a-form-item label="分类颜色" field="color">
<a-form-item label="标签颜色" field="color">
<div class="color-picker-wrapper">
<a-input
v-model="form.color"
@@ -208,11 +208,11 @@ const handleOk = async () => {
let res: any
if (isEdit.value && props.category?.id) {
// 编辑分类
// 编辑标签
data.id = props.category.id
res = await updateCategory(data)
} else {
// 新建分类
// 新建标签
res = await createCategory(data)
}

View File

@@ -7,7 +7,7 @@
:columns="columns"
:loading="loading"
:pagination="pagination"
title="分类管理"
title="标签管理"
search-button-text="查询"
reset-button-text="重置"
@update:form-model="handleFormModelUpdate"
@@ -19,7 +19,7 @@
>
<template #toolbar-left>
<a-button type="primary" @click="handleCreate">
新增分类
新增标签
</a-button>
</template>
@@ -28,7 +28,7 @@
{{ rowIndex + 1 }}
</template>
<!-- 分类类型 -->
<!-- 标签类型 -->
<template #type="{ record }">
<a-tag :color="getTypeColor(record.type)">
{{ getTypeLabel(record.type) }}
@@ -46,7 +46,7 @@
</template>
</search-table>
<!-- 分类表单对话框新增/编辑 -->
<!-- 标签表单对话框新增/编辑 -->
<category-form-dialog
v-model:visible="formVisible"
:category="editingCategory"
@@ -89,17 +89,17 @@ const formItems = computed<FormItem[]>(() => [
field: 'keyword',
label: '关键词',
type: 'input',
placeholder: '请输入分类名称',
placeholder: '请输入标签名称',
},
{
field: 'type',
label: '分类类型',
label: '标签类型',
type: 'select',
placeholder: '请选择分类类型',
placeholder: '请选择标签类型',
options: [
{ label: '文档分类', value: 'document' },
{ label: 'FAQ分类', value: 'faq' },
{ label: '通用分类', value: 'general' },
{ label: '文档标签', value: 'document' },
{ label: 'FAQ标签', value: 'faq' },
{ label: '通用标签', value: 'general' },
],
allowClear: true,
},
@@ -115,19 +115,19 @@ const columns = computed(() => [
align: 'center' as const,
},
{
title: '分类名称',
title: '标签名称',
dataIndex: 'name',
ellipsis: true,
tooltip: true,
},
{
title: '分类描述',
title: '标签描述',
dataIndex: 'description',
ellipsis: true,
tooltip: true,
},
{
title: '分类类型',
title: '标签类型',
dataIndex: 'type',
slotName: 'type',
width: 120,
@@ -153,23 +153,23 @@ const columns = computed(() => [
},
])
// 当前选中的分类
// 当前选中的标签
const editingCategory = ref<Category | null>(null)
// 对话框可见性
const formVisible = ref(false)
// 获取分类类型标签
// 获取标签类型标签
const getTypeLabel = (type: string) => {
const typeMap: Record<string, string> = {
document: '文档分类',
faq: 'FAQ分类',
general: '通用分类',
document: '文档标签',
faq: 'FAQ标签',
general: '通用标签',
}
return typeMap[type] || type
}
// 获取分类类型颜色
// 获取标签类型颜色
const getTypeColor = (type: string) => {
const colorMap: Record<string, string> = {
document: 'blue',
@@ -187,7 +187,7 @@ const updateTableData = () => {
tableData.value = allData.value.slice(start, end)
}
// 获取分类列表
// 获取标签列表
const fetchCategories = async () => {
loading.value = true
@@ -217,14 +217,14 @@ const fetchCategories = async () => {
pagination.value.current = 1
updateTableData()
} else {
Message.error(res.message || '获取分类列表失败')
Message.error(res.message || '获取标签列表失败')
allData.value = []
tableData.value = []
pagination.value.total = 0
}
} catch (error) {
console.error('获取分类列表失败:', error)
Message.error('获取分类列表失败')
console.error('获取标签列表失败:', error)
Message.error('获取标签列表失败')
allData.value = []
tableData.value = []
pagination.value.total = 0
@@ -271,23 +271,23 @@ const handlePageSizeChange = (pageSize: number) => {
updateTableData()
}
// 新增分类
// 新增标签
const handleCreate = () => {
editingCategory.value = null
formVisible.value = true
}
// 编辑分类
// 编辑标签
const handleEdit = (record: Category) => {
editingCategory.value = { ...record }
formVisible.value = true
}
// 删除分类
// 删除标签
const handleDelete = async (record: Category) => {
Modal.confirm({
title: '确认删除',
content: `确认删除分类${record.name}」吗?`,
content: `确认删除标签${record.name}」吗?`,
onOk: async () => {
try {
const res: any = await deleteCategory(record.id)
@@ -298,7 +298,7 @@ const handleDelete = async (record: Category) => {
Message.error(res.message || '删除失败')
}
} catch (error) {
console.error('删除分类失败:', error)
console.error('删除标签失败:', error)
Message.error('删除失败')
}
},