feat
This commit is contained in:
@@ -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,
|
||||
});
|
||||
};
|
||||
|
||||
/** 获取我的文档列表(由我创建的所有文档) */
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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('删除失败')
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user