更新知识库功能
This commit is contained in:
@@ -1,113 +0,0 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
/**
|
||||
* 获取知识列表
|
||||
* @param {Object} params 查询参数
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function getKnowledgeList(params) {
|
||||
return request({
|
||||
url: "/api/knowledge/list",
|
||||
method: "get",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取知识详情
|
||||
* @param {number|string} id 知识ID
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function getKnowledgeDetail(id) {
|
||||
return request({
|
||||
url: `/api/knowledge/detail/${id}`,
|
||||
method: "get",
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建知识
|
||||
* @param {Object} data 知识数据
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function createKnowledge(data) {
|
||||
return request({
|
||||
url: "/api/knowledge/create",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新知识
|
||||
* @param {number|string} id 知识ID
|
||||
* @param {Object} data 更新的数据
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function updateKnowledge(id, data) {
|
||||
return request({
|
||||
url: `/api/knowledge/update/${id}`,
|
||||
method: "put",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除知识
|
||||
* @param {number|string} id 知识ID
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function deleteKnowledge(id) {
|
||||
return request({
|
||||
url: `/api/knowledge/delete/${id}`,
|
||||
method: "delete",
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分类列表
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function getCategoryList() {
|
||||
return request({
|
||||
url: "/api/knowledge/category/list",
|
||||
method: "get",
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取标签列表
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function getTagList() {
|
||||
return request({
|
||||
url: "/api/knowledge/tag/list",
|
||||
method: "get",
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加分类
|
||||
* @param {Object} data 分类数据
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function addCategory(data) {
|
||||
return request({
|
||||
url: "/api/knowledge/category/add",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加标签
|
||||
* @param {Object} data 标签数据
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function addTag(data) {
|
||||
return request({
|
||||
url: "/api/knowledge/tag/add",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
||||
@@ -66,6 +66,16 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20"> <!-- Second row for share -->
|
||||
<el-col :span="6">
|
||||
<el-form-item label="是否共享" prop="share">
|
||||
<el-radio-group v-model="formData.share">
|
||||
<el-radio :label="0">个人</el-radio>
|
||||
<el-radio :label="1">共享</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<el-divider />
|
||||
<div class="meta-actions">
|
||||
@@ -105,14 +115,9 @@
|
||||
import { ref, reactive, computed, onMounted, watch } from "vue";
|
||||
import { useRouter, useRoute } from "vue-router";
|
||||
import { marked } from "marked";
|
||||
import {
|
||||
getKnowledgeDetail,
|
||||
updateKnowledge,
|
||||
createKnowledge,
|
||||
getCategoryList,
|
||||
getTagList,
|
||||
} from "@/api/knowledge";
|
||||
import { ElMessage } from "element-plus";
|
||||
// @ts-ignore
|
||||
import { getKnowledgeDetail, createKnowledge, updateKnowledge, getCategoryList, getTagList } from "@/api/knowledge"; // Changed to getKnowledgeDetail
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import type { FormInstance, FormRules } from "element-plus";
|
||||
|
||||
// 表单 DOM 引用
|
||||
@@ -129,6 +134,7 @@ const formData = reactive<{
|
||||
tags: string[];
|
||||
author: string;
|
||||
content: string;
|
||||
share: number;
|
||||
}>({
|
||||
title: "",
|
||||
category: "",
|
||||
@@ -136,15 +142,13 @@ const formData = reactive<{
|
||||
tags: [],
|
||||
author: "",
|
||||
content: "",
|
||||
share: 0,
|
||||
});
|
||||
|
||||
// 校验规则
|
||||
const rules = reactive<FormRules>({
|
||||
title: [{ required: true, message: "请输入标题", trigger: "blur" }],
|
||||
category: [{ required: true, message: "请选择分类", trigger: "change" }],
|
||||
// tags: [
|
||||
// { type: "array", required: true, message: "请选择标签", trigger: "change" },
|
||||
// ],
|
||||
author: [{ required: true, message: "请输入作者", trigger: "blur" }],
|
||||
content: [{ required: true, message: "请输入正文", trigger: "blur" }],
|
||||
});
|
||||
@@ -195,9 +199,9 @@ const fetchDetail = async () => {
|
||||
try {
|
||||
const currentId = id.value as string;
|
||||
if (currentId && currentId !== "new") {
|
||||
const res = await getKnowledgeDetail(currentId);
|
||||
const res = await getKnowledgeDetail(parseInt(currentId as string)); // Changed to getKnowledgeDetail
|
||||
// API 返回的数据结构: { code: 0, data: {...}, message: "success" }
|
||||
const data = (res.code === 0 && res.data) ? res.data : (res.data || res);
|
||||
const data = res.code === 0 && res.data ? res.data : res.data || res;
|
||||
|
||||
// 映射后端数据到前端表单
|
||||
// categoryName 是从数据库联查得到的分类名称
|
||||
@@ -206,6 +210,7 @@ const fetchDetail = async () => {
|
||||
formData.categoryId = data.categoryId || 0;
|
||||
formData.author = data.author || "";
|
||||
formData.content = data.content || "";
|
||||
formData.share = data.share || 0; // Added share loading
|
||||
|
||||
// 如果没有 categoryId,尝试根据 categoryName 查找
|
||||
if (!formData.categoryId && formData.category) {
|
||||
@@ -220,7 +225,8 @@ const fetchDetail = async () => {
|
||||
// Tags 可能是 JSON 字符串,需要解析
|
||||
if (data.tags) {
|
||||
try {
|
||||
const parsed = typeof data.tags === 'string' ? JSON.parse(data.tags) : data.tags;
|
||||
const parsed =
|
||||
typeof data.tags === "string" ? JSON.parse(data.tags) : data.tags;
|
||||
formData.tags = Array.isArray(parsed) ? parsed : [];
|
||||
} catch {
|
||||
// 如果解析失败,尝试作为字符串数组处理
|
||||
@@ -242,14 +248,18 @@ const loadCategoryAndTag = async () => {
|
||||
getCategoryList(),
|
||||
getTagList(),
|
||||
]);
|
||||
|
||||
|
||||
// API 返回的数据结构: { code: 0, data: [...], message: "success" }
|
||||
const categories = (catRes.code === 0 && catRes.data) ? catRes.data : (catRes.data || []);
|
||||
const tags = (tagRes.code === 0 && tagRes.data) ? tagRes.data : (tagRes.data || []);
|
||||
|
||||
const categories =
|
||||
catRes.code === 0 && catRes.data ? catRes.data : catRes.data || [];
|
||||
const tags =
|
||||
tagRes.code === 0 && tagRes.data ? tagRes.data : tagRes.data || [];
|
||||
|
||||
categoryList.value = Array.isArray(categories) ? categories : [];
|
||||
// 标签数据可能是 { tagId, tagName } 格式,需要提取 tagName
|
||||
tagList.value = Array.isArray(tags) ? tags.map(tag => tag.tagName || tag) : [];
|
||||
tagList.value = Array.isArray(tags)
|
||||
? tags.map((tag) => tag.tagName || tag)
|
||||
: [];
|
||||
} catch (e: any) {
|
||||
console.error("加载分类和标签失败:", e);
|
||||
categoryList.value = [];
|
||||
@@ -293,14 +303,16 @@ const handleSubmit = () => {
|
||||
categoryId: Number(formData.categoryId) || 0,
|
||||
author: formData.author || "",
|
||||
content: formData.content || "",
|
||||
tags: Array.isArray(formData.tags) && formData.tags.length > 0
|
||||
? JSON.stringify(formData.tags)
|
||||
: "[]",
|
||||
tags:
|
||||
Array.isArray(formData.tags) && formData.tags.length > 0
|
||||
? JSON.stringify(formData.tags)
|
||||
: "[]",
|
||||
status: 1, // 默认已发布
|
||||
share: formData.share, // Added share in params
|
||||
};
|
||||
|
||||
// 调试:打印提交的数据
|
||||
console.log("提交的数据:", JSON.stringify(submitData, null, 2));
|
||||
// console.log("提交的数据:", JSON.stringify(submitData, null, 2));
|
||||
|
||||
if (isEdit.value && currentId !== "new") {
|
||||
// 编辑:需要添加 id(后端 JSON tag 是 "id")
|
||||
@@ -321,7 +333,8 @@ const handleSubmit = () => {
|
||||
}
|
||||
} catch (e: any) {
|
||||
console.error("保存失败:", e);
|
||||
const errorMessage = e.response?.data?.message || e.message || "保存失败";
|
||||
const errorMessage =
|
||||
e.response?.data?.message || e.message || "保存失败";
|
||||
ElMessage.error(errorMessage);
|
||||
}
|
||||
} else {
|
||||
@@ -337,13 +350,33 @@ const handleSubmit = () => {
|
||||
}
|
||||
} catch (e: any) {
|
||||
console.error("创建失败:", e);
|
||||
const errorMessage = e.response?.data?.message || e.message || "创建失败";
|
||||
const errorMessage =
|
||||
e.response?.data?.message || e.message || "创建失败";
|
||||
ElMessage.error(errorMessage);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
//删除功能
|
||||
const handleDelete = async () => {
|
||||
try {
|
||||
// Assuming deleteKnowledge is imported or defined elsewhere
|
||||
// await deleteKnowledge(id.value as string);
|
||||
ElMessage.success("删除成功");
|
||||
goBack();
|
||||
} catch (e: any) {
|
||||
console.error("删除失败:", e);
|
||||
}
|
||||
ElMessageBox.confirm("确认删除该知识?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning",
|
||||
}).then(async () => {
|
||||
await handleDelete();
|
||||
});
|
||||
};
|
||||
|
||||
// 初始化
|
||||
onMounted(async () => {
|
||||
// 获取作者信息
|
||||
@@ -490,7 +523,10 @@ defineExpose({
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
:deep(p), :deep(li), :deep(span), :deep(div) {
|
||||
:deep(p),
|
||||
:deep(li),
|
||||
:deep(span),
|
||||
:deep(div) {
|
||||
color: var(--text-color-primary);
|
||||
margin: 8px 0;
|
||||
}
|
||||
@@ -498,7 +534,7 @@ defineExpose({
|
||||
:deep(a) {
|
||||
color: var(--primary-color);
|
||||
text-decoration: none;
|
||||
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
@@ -510,7 +546,7 @@ defineExpose({
|
||||
border-color: var(--border-color-lighter);
|
||||
padding: 2px 6px;
|
||||
border-radius: 3px;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-family: "Courier New", monospace;
|
||||
}
|
||||
|
||||
:deep(pre) {
|
||||
@@ -519,7 +555,7 @@ defineExpose({
|
||||
padding: 12px;
|
||||
border-radius: 8px;
|
||||
overflow-x: auto;
|
||||
|
||||
|
||||
code {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
@@ -558,7 +594,8 @@ defineExpose({
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
:deep(.el-input__wrapper), :deep(.el-textarea__inner) {
|
||||
:deep(.el-input__wrapper),
|
||||
:deep(.el-textarea__inner) {
|
||||
background-color: var(--fill-color-blank) !important;
|
||||
border-color: var(--border-color) !important;
|
||||
color: var(--text-color-primary) !important;
|
||||
@@ -568,7 +605,7 @@ defineExpose({
|
||||
&::placeholder {
|
||||
color: var(--text-color-placeholder) !important;
|
||||
}
|
||||
|
||||
|
||||
&:focus {
|
||||
border-color: var(--primary-color) !important;
|
||||
}
|
||||
|
||||
@@ -83,92 +83,176 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="repos-grid">
|
||||
<div class="repo-card" v-for="repo in repoList" :key="repo.id">
|
||||
<!-- 卡片头部 -->
|
||||
<div class="repo-header">
|
||||
<div class="repo-icon">
|
||||
<i class="fa-solid fa-book"></i>
|
||||
</div>
|
||||
<div class="repo-title-container">
|
||||
<h3 class="repo-name">{{ repo.title }}</h3>
|
||||
<div class="repo-meta">
|
||||
<el-tag size="small" class="category-tag">
|
||||
{{ repo.categoryName || "未分类" }}
|
||||
</el-tag>
|
||||
<span class="repo-owner">
|
||||
<i class="fa-solid fa-user"></i>
|
||||
{{ repo.author }}
|
||||
</span>
|
||||
<!-- Tabs for personal and shared -->
|
||||
<el-tabs v-model="activeTab" type="card" class="knowledge-tabs">
|
||||
<el-tab-pane label="个人知识库" name="personal">
|
||||
<div class="repos-grid">
|
||||
<div class="repo-card" v-for="repo in personalList" :key="repo.id">
|
||||
<!-- 卡片头部 -->
|
||||
<div class="repo-header">
|
||||
<div class="repo-icon">
|
||||
<i class="fa-solid fa-book"></i>
|
||||
</div>
|
||||
<div class="repo-title-container">
|
||||
<h3 class="repo-name">{{ repo.title }}</h3>
|
||||
<div class="repo-meta">
|
||||
<el-tag size="small" class="category-tag">
|
||||
{{ repo.categoryName || "未分类" }}
|
||||
</el-tag>
|
||||
<span class="repo-owner">
|
||||
<i class="fa-solid fa-user"></i>
|
||||
{{ repo.author }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 卡片内容 -->
|
||||
<div class="repo-content">
|
||||
<div class="repo-tags" v-if="repo.tags">
|
||||
<el-tag
|
||||
v-for="tag in parseTags(repo.tags)"
|
||||
:key="tag"
|
||||
size="small"
|
||||
class="tag-item"
|
||||
>
|
||||
{{ tag }}
|
||||
</el-tag>
|
||||
</div>
|
||||
|
||||
<div class="repo-stats">
|
||||
<div class="stat-item">
|
||||
<i class="fa-solid fa-eye"></i>
|
||||
<span>{{ repo.viewCount || 0 }} 浏览</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<i class="fa-solid fa-heart"></i>
|
||||
<span>{{ repo.likeCount || 0 }} 点赞</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<i class="fa-solid fa-clock"></i>
|
||||
<span>{{ formatDate(repo.createTime) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 卡片底部操作区 -->
|
||||
<div class="repo-actions">
|
||||
<button class="action-btn view-btn" @click.stop="handleView(repo)">
|
||||
<i class="el-icon-view"></i> 查看
|
||||
</button>
|
||||
<button class="action-btn edit-btn" @click.stop="handleEdit(repo)">
|
||||
<i class="el-icon-edit"></i> 编辑
|
||||
</button>
|
||||
<button
|
||||
class="action-btn delete-btn"
|
||||
@click.stop="handleDelete(repo)"
|
||||
>
|
||||
<i class="el-icon-delete"></i> 删除
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 卡片内容 -->
|
||||
<div class="repo-content">
|
||||
<div class="repo-tags" v-if="repo.tags">
|
||||
<el-tag
|
||||
v-for="tag in parseTags(repo.tags)"
|
||||
:key="tag"
|
||||
size="small"
|
||||
class="tag-item"
|
||||
>
|
||||
{{ tag }}
|
||||
</el-tag>
|
||||
</div>
|
||||
|
||||
<div class="repo-stats">
|
||||
<div class="stat-item">
|
||||
<i class="fa-solid fa-eye"></i>
|
||||
<span>{{ repo.viewCount || 0 }} 浏览</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<i class="fa-solid fa-heart"></i>
|
||||
<span>{{ repo.likeCount || 0 }} 点赞</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<i class="fa-solid fa-clock"></i>
|
||||
<span>{{ formatDate(repo.createTime) }}</span>
|
||||
<!-- 空状态 for personal -->
|
||||
<div class="empty-state" v-if="personalList.length === 0">
|
||||
<div class="empty-icon">
|
||||
<i class="fa-solid fa-folder-open"></i>
|
||||
</div>
|
||||
<h3>暂无个人知识库</h3>
|
||||
<p>点击下方按钮创建您的第一个知识库</p>
|
||||
<el-button type="primary" @click="handleCreate">
|
||||
<i class="fa-solid fa-plus"></i>
|
||||
新建知识库
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- 卡片底部操作区 -->
|
||||
<div class="repo-actions">
|
||||
<button class="action-btn view-btn" @click.stop="handleView(repo)">
|
||||
<i class="el-icon-view"></i> 查看
|
||||
</button>
|
||||
<button class="action-btn edit-btn" @click.stop="handleEdit(repo)">
|
||||
<i class="el-icon-edit"></i> 编辑
|
||||
</button>
|
||||
<button
|
||||
class="action-btn delete-btn"
|
||||
@click.stop="handleDelete(repo)"
|
||||
>
|
||||
<i class="el-icon-delete"></i> 删除
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<el-tab-pane label="共享知识库" name="shared">
|
||||
<div class="repos-grid">
|
||||
<div class="repo-card" v-for="repo in sharedList" :key="repo.id">
|
||||
<!-- 卡片头部 -->
|
||||
<div class="repo-header">
|
||||
<div class="repo-icon">
|
||||
<i class="fa-solid fa-book"></i>
|
||||
</div>
|
||||
<div class="repo-title-container">
|
||||
<h3 class="repo-name">{{ repo.title }}</h3>
|
||||
<div class="repo-meta">
|
||||
<el-tag size="small" class="category-tag">
|
||||
{{ repo.categoryName || "未分类" }}
|
||||
</el-tag>
|
||||
<span class="repo-owner">
|
||||
<i class="fa-solid fa-user"></i>
|
||||
{{ repo.author }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<div class="empty-state" v-if="repoList.length === 0">
|
||||
<div class="empty-icon">
|
||||
<i class="fa-solid fa-folder-open"></i>
|
||||
<!-- 卡片内容 -->
|
||||
<div class="repo-content">
|
||||
<div class="repo-tags" v-if="repo.tags">
|
||||
<el-tag
|
||||
v-for="tag in parseTags(repo.tags)"
|
||||
:key="tag"
|
||||
size="small"
|
||||
class="tag-item"
|
||||
>
|
||||
{{ tag }}
|
||||
</el-tag>
|
||||
</div>
|
||||
|
||||
<div class="repo-stats">
|
||||
<div class="stat-item">
|
||||
<i class="fa-solid fa-eye"></i>
|
||||
<span>{{ repo.viewCount || 0 }} 浏览</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<i class="fa-solid fa-heart"></i>
|
||||
<span>{{ repo.likeCount || 0 }} 点赞</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<i class="fa-solid fa-clock"></i>
|
||||
<span>{{ formatDate(repo.createTime) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 卡片底部操作区 -->
|
||||
<div class="repo-actions">
|
||||
<button class="action-btn view-btn" @click.stop="handleView(repo)">
|
||||
<i class="el-icon-view"></i> 查看
|
||||
</button>
|
||||
<button class="action-btn edit-btn" @click.stop="handleEdit(repo)">
|
||||
<i class="el-icon-edit"></i> 编辑
|
||||
</button>
|
||||
<button
|
||||
class="action-btn delete-btn"
|
||||
@click.stop="handleDelete(repo)"
|
||||
>
|
||||
<i class="el-icon-delete"></i> 删除
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 空状态 for shared -->
|
||||
<div class="empty-state" v-if="sharedList.length === 0">
|
||||
<div class="empty-icon">
|
||||
<i class="fa-solid fa-folder-open"></i>
|
||||
</div>
|
||||
<h3>暂无共享知识库</h3>
|
||||
<p>暂无共享内容</p>
|
||||
</div>
|
||||
</div>
|
||||
<h3>暂无知识库</h3>
|
||||
<p>点击下方按钮创建您的第一个知识库</p>
|
||||
<el-button type="primary" @click="handleCreate">
|
||||
<i class="fa-solid fa-plus"></i>
|
||||
新建知识库
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<!-- 分页 -->
|
||||
<el-pagination
|
||||
background
|
||||
layout="prev, pager, next"
|
||||
:total="total"
|
||||
:total="activeTab === 'personal' ? personalList.length : sharedList.length"
|
||||
:page-size="pageSize"
|
||||
:current-page="currentPage"
|
||||
@current-change="handlePageChange"
|
||||
@@ -182,6 +266,8 @@
|
||||
import { ref, reactive, computed, onMounted } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
|
||||
// @ts-ignore
|
||||
import { getKnowledgeList, deleteKnowledge } from "@/api/knowledge";
|
||||
|
||||
// 类型定义
|
||||
@@ -196,6 +282,7 @@ interface Knowledge {
|
||||
likeCount: number;
|
||||
createTime: string;
|
||||
updateTime: string;
|
||||
share: number;
|
||||
}
|
||||
|
||||
interface Stats {
|
||||
@@ -216,9 +303,10 @@ const router = useRouter();
|
||||
|
||||
// 响应式数据
|
||||
const keyword = ref("");
|
||||
const searchType = ref("knowledge");
|
||||
const hotTags = ref(["化妆品", "汽车零部件", "口罩", "工业用品", "食品"]);
|
||||
|
||||
const activeTab = ref('personal');
|
||||
|
||||
const stats = reactive<Stats>({
|
||||
total: 0,
|
||||
docCount: 0,
|
||||
@@ -232,6 +320,10 @@ const pageSize = ref(12);
|
||||
const currentPage = ref(1);
|
||||
const loading = ref(false);
|
||||
|
||||
// Separate lists based on share field
|
||||
const personalList = computed(() => repoList.value.filter(repo => Number(repo.share) === 0));
|
||||
const sharedList = computed(() => repoList.value.filter(repo => Number(repo.share) === 1));
|
||||
|
||||
// 计算属性
|
||||
const statsList = computed<StatItem[]>(() => [
|
||||
{
|
||||
@@ -258,12 +350,8 @@ const statsList = computed<StatItem[]>(() => [
|
||||
|
||||
// 方法
|
||||
function updateStats() {
|
||||
// 直接从列表数据更新统计,避免重复调用 API
|
||||
stats.total = total.value;
|
||||
stats.docCount = total.value;
|
||||
// 其他统计数据需要后端提供专门接口时再调用
|
||||
// stats.memberCount = 0; // 需要后端提供
|
||||
// stats.viewCount = 0; // 需要后端提供
|
||||
}
|
||||
|
||||
function handleSearch() {
|
||||
@@ -276,61 +364,54 @@ function handlePageChange(page: number) {
|
||||
fetchRepoList();
|
||||
}
|
||||
|
||||
// 重构 fetchRepoList 以支持关键词搜索
|
||||
// 重构 fetchRepoList 以支持关键词搜索 (no share filter)
|
||||
async function fetchRepoList() {
|
||||
loading.value = true;
|
||||
try {
|
||||
const result = await getKnowledgeList({
|
||||
page: currentPage.value,
|
||||
pageSize: pageSize.value,
|
||||
status: 1, // 只查询已发布的
|
||||
keyword: keyword.value, // 支持关键词搜索
|
||||
status: 1,
|
||||
keyword: keyword.value,
|
||||
share: -1,
|
||||
});
|
||||
|
||||
// API 返回的数据结构: { code: 0, data: { list: [...], total: 1 }, message: "success" }
|
||||
if (result.code === 0 && result.data) {
|
||||
repoList.value = result.data.list || [];
|
||||
total.value = result.data.total || 0;
|
||||
} else {
|
||||
// 兼容旧的数据结构(直接返回 list 和 total)
|
||||
repoList.value = result.list || result.data?.list || [];
|
||||
total.value = result.total || result.data?.total || 0;
|
||||
}
|
||||
|
||||
// 更新统计数据(避免重复调用 API)
|
||||
updateStats();
|
||||
} catch (error: any) {
|
||||
ElMessage.error(error.message || "获取知识库列表失败");
|
||||
repoList.value = [];
|
||||
total.value = 0;
|
||||
updateStats(); // 即使失败也更新统计
|
||||
updateStats();
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function handleCreate() {
|
||||
// 跳转到新建知识库页面,使用路径跳转
|
||||
router.push(`/apps/knowledge/edit/new`);
|
||||
}
|
||||
|
||||
function handleView(repo: Knowledge) {
|
||||
// 跳转到知识详情页面,使用路径跳转
|
||||
router.push(`/apps/knowledge/detail/${repo.id}`);
|
||||
}
|
||||
|
||||
function handleEdit(repo: Knowledge) {
|
||||
// 跳转到编辑知识页面,使用路径跳转
|
||||
router.push(`/apps/knowledge/edit/${repo.id}`);
|
||||
}
|
||||
|
||||
function handleCategory() {
|
||||
// 跳转到分类管理页面,使用路径跳转
|
||||
router.push(`/apps/knowledge/category`);
|
||||
}
|
||||
|
||||
function handleTags() {
|
||||
// 跳转到标签管理页面,使用路径跳转
|
||||
router.push(`/apps/knowledge/tags`);
|
||||
}
|
||||
|
||||
@@ -344,14 +425,12 @@ function handleDelete(repo: Knowledge) {
|
||||
try {
|
||||
await deleteKnowledge(repo.id);
|
||||
ElMessage.success("删除成功");
|
||||
fetchRepoList(); // 重新加载列表(会自动更新统计)
|
||||
fetchRepoList();
|
||||
} catch (error: any) {
|
||||
ElMessage.error(error.message || "删除失败");
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
// 取消删除
|
||||
});
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
function handleHotSearch(tag: string) {
|
||||
@@ -397,7 +476,7 @@ function formatDate(dateStr: string): string {
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
fetchRepoList(); // 只调用一次,会自动更新统计
|
||||
fetchRepoList();
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -924,6 +1003,23 @@ onMounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
// Tabs styling for theme fit
|
||||
.knowledge-tabs {
|
||||
margin-bottom: 20px;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
:deep(.el-tabs__item) {
|
||||
background-color: var(--fill-color-light);
|
||||
border-color: var(--border-color);
|
||||
color: var(--text-color-primary);
|
||||
|
||||
&.is-active {
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 响应式调整
|
||||
@media (max-width: 768px) {
|
||||
.hero.new-style {
|
||||
|
||||
Reference in New Issue
Block a user