| | |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">知识标题:</span> |
| | | <el-input |
| | | v-model="searchForm.title" |
| | | style="width: 240px" |
| | | placeholder="请输入知识标题搜索" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | <el-input v-model="searchForm.title" |
| | | style="width: 240px" |
| | | placeholder="请输入知识标题搜索" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" /> |
| | | <span class="search_title ml10">知识类型:</span> |
| | | <el-select v-model="searchForm.type" clearable @change="handleQuery" style="width: 240px"> |
| | | <el-option label="合同特批" :value="'contract'" /> |
| | | <el-option label="审批案例" :value="'approval'" /> |
| | | <el-option label="解决方案" :value="'solution'" /> |
| | | <el-option label="经验总结" :value="'experience'" /> |
| | | <el-option label="操作指南" :value="'guide'" /> |
| | | <el-select v-model="searchForm.type" |
| | | clearable |
| | | @change="handleQuery" |
| | | style="width: 240px"> |
| | | <el-option label="合同特批" |
| | | :value="'contract'" /> |
| | | <el-option label="审批案例" |
| | | :value="'approval'" /> |
| | | <el-option label="解决方案" |
| | | :value="'solution'" /> |
| | | <el-option label="经验总结" |
| | | :value="'experience'" /> |
| | | <el-option label="操作指南" |
| | | :value="'guide'" /> |
| | | </el-select> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px"> |
| | | <el-button type="primary" |
| | | @click="handleQuery" |
| | | style="margin-left: 10px"> |
| | | 搜索 |
| | | </el-button> |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" @click="openForm('add')">新增知识</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">删除</el-button> |
| | | <el-button @click="handleExport" |
| | | style="margin-right: 10px">导出</el-button> |
| | | <el-button type="primary" |
| | | @click="openForm('add')">新增知识</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleDelete">删除</el-button> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="table_list"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total" |
| | | ></PIMTable> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total"></PIMTable> |
| | | </div> |
| | | |
| | | <!-- 新增/编辑知识弹窗 --> |
| | | <el-dialog |
| | | v-model="dialogVisible" |
| | | :title="dialogTitle" |
| | | width="800px" |
| | | :close-on-click-modal="false" |
| | | > |
| | | <el-form ref="formRef" :model="form" :rules="rules" label-width="120px"> |
| | | <el-dialog v-model="dialogVisible" |
| | | :title="dialogTitle" |
| | | width="800px" |
| | | :close-on-click-modal="false"> |
| | | <el-form ref="formRef" |
| | | :model="form" |
| | | :rules="rules" |
| | | label-width="120px"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="知识标题" prop="title"> |
| | | <el-input v-model="form.title" placeholder="请输入知识标题" /> |
| | | <el-form-item label="知识标题" |
| | | prop="title"> |
| | | <el-input v-model="form.title" |
| | | placeholder="请输入知识标题" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="知识类型" prop="type"> |
| | | <el-select v-model="form.type" placeholder="请选择知识类型" style="width: 100%"> |
| | | <el-option label="合同特批" value="contract" /> |
| | | <el-option label="审批案例" value="approval" /> |
| | | <el-option label="解决方案" value="solution" /> |
| | | <el-option label="经验总结" value="experience" /> |
| | | <el-option label="操作指南" value="guide" /> |
| | | <el-form-item label="知识类型" |
| | | prop="type"> |
| | | <el-select v-model="form.type" |
| | | placeholder="请选择知识类型" |
| | | style="width: 100%"> |
| | | <el-option label="合同特批" |
| | | value="contract" /> |
| | | <el-option label="审批案例" |
| | | value="approval" /> |
| | | <el-option label="解决方案" |
| | | value="solution" /> |
| | | <el-option label="经验总结" |
| | | value="experience" /> |
| | | <el-option label="操作指南" |
| | | value="guide" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="适用场景" prop="scenario"> |
| | | <el-input v-model="form.scenario" placeholder="请输入适用场景" /> |
| | | <el-form-item label="适用场景" |
| | | prop="scenario"> |
| | | <el-input v-model="form.scenario" |
| | | placeholder="请输入适用场景" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="解决效率" prop="efficiency"> |
| | | <el-select v-model="form.efficiency" placeholder="请选择解决效率" style="width: 100%"> |
| | | <el-option label="显著提升" value="high" /> |
| | | <el-option label="一般提升" value="medium" /> |
| | | <el-option label="轻微提升" value="low" /> |
| | | <el-form-item label="解决效率" |
| | | prop="efficiency"> |
| | | <el-select v-model="form.efficiency" |
| | | placeholder="请选择解决效率" |
| | | style="width: 100%"> |
| | | <el-option label="显著提升" |
| | | value="high" /> |
| | | <el-option label="一般提升" |
| | | value="medium" /> |
| | | <el-option label="轻微提升" |
| | | value="low" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="问题描述" prop="problem"> |
| | | <el-input |
| | | v-model="form.problem" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请描述遇到的问题" |
| | | /> |
| | | <el-form-item label="问题描述" |
| | | prop="problem"> |
| | | <el-input v-model="form.problem" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请描述遇到的问题" /> |
| | | </el-form-item> |
| | | <el-form-item label="解决方案" prop="solution"> |
| | | <el-input |
| | | v-model="form.solution" |
| | | type="textarea" |
| | | :rows="4" |
| | | placeholder="请详细描述解决方案" |
| | | /> |
| | | <el-form-item label="解决方案" |
| | | prop="solution"> |
| | | <el-input v-model="form.solution" |
| | | type="textarea" |
| | | :rows="4" |
| | | placeholder="请详细描述解决方案" /> |
| | | </el-form-item> |
| | | <el-form-item label="关键要点" prop="keyPoints"> |
| | | <el-input |
| | | v-model="form.keyPoints" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请输入关键要点,用逗号分隔" |
| | | /> |
| | | <el-form-item label="关键要点" |
| | | prop="keyPoints"> |
| | | <el-input v-model="form.keyPoints" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请输入关键要点,用逗号分隔" /> |
| | | </el-form-item> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="创建人" prop="creator"> |
| | | <el-input v-model="form.creator" placeholder="请输入创建人" /> |
| | | <el-form-item label="创建人" |
| | | prop="creator"> |
| | | <el-input v-model="form.creator" |
| | | placeholder="请输入创建人" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="使用次数" prop="usageCount"> |
| | | <el-input-number v-model="form.usageCount" :min="0" style="width: 100%" /> |
| | | <el-form-item label="使用次数" |
| | | prop="usageCount"> |
| | | <el-input-number v-model="form.usageCount" |
| | | :min="0" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitForm">确定</el-button> |
| | | <el-button @click="dialogVisible = false">取消</el-button> |
| | | <el-button type="primary" @click="submitForm">确定</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 查看知识详情弹窗 --> |
| | | <el-dialog |
| | | v-model="viewDialogVisible" |
| | | title="知识详情" |
| | | width="900px" |
| | | :close-on-click-modal="false" |
| | | > |
| | | <el-dialog v-model="viewDialogVisible" |
| | | title="知识详情" |
| | | width="900px" |
| | | :close-on-click-modal="false"> |
| | | <div class="knowledge-detail"> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions-item label="知识标题" :span="2"> |
| | | <el-descriptions :column="2" |
| | | border> |
| | | <el-descriptions-item label="知识标题" |
| | | :span="2"> |
| | | <span class="detail-title">{{ currentKnowledge.title }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="知识类型"> |
| | |
| | | {{ currentKnowledge.createTime }} |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | |
| | | <div class="detail-section"> |
| | | <h4>问题描述</h4> |
| | | <div class="detail-content">{{ currentKnowledge.problem }}</div> |
| | | </div> |
| | | |
| | | <div class="detail-section"> |
| | | <h4>解决方案</h4> |
| | | <div class="detail-content">{{ currentKnowledge.solution }}</div> |
| | | </div> |
| | | |
| | | <div class="detail-section"> |
| | | <h4>关键要点</h4> |
| | | <div class="key-points"> |
| | | <el-tag |
| | | v-for="(point, index) in currentKnowledge.keyPoints.split(',')" |
| | | :key="index" |
| | | type="success" |
| | | style="margin-right: 8px; margin-bottom: 8px;" |
| | | > |
| | | <el-tag v-for="(point, index) in currentKnowledge.keyPoints.split(',')" |
| | | :key="index" |
| | | type="success" |
| | | style="margin-right: 8px; margin-bottom: 8px;"> |
| | | {{ point.trim() }} |
| | | </el-tag> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="detail-section"> |
| | | <h4>使用统计</h4> |
| | | <div class="usage-stats"> |
| | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="copyKnowledge">复制知识</el-button> |
| | | <el-button @click="viewDialogVisible = false">关闭</el-button> |
| | | <el-button type="primary" @click="copyKnowledge">复制知识</el-button> |
| | | <!-- <el-button type="success" @click="markAsFavorite">收藏@</el-button> --> |
| | | </span> |
| | | </template> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { onMounted, ref, reactive, toRefs } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | | import { listKnowledgeBase, delKnowledgeBaseBatch,addKnowledgeBase,updateKnowledgeBase } from "@/api/collaborativeApproval/knowledgeBase.js"; |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { onMounted, ref, reactive, toRefs, getCurrentInstance } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | | import { |
| | | listKnowledgeBase, |
| | | delKnowledgeBase, |
| | | addKnowledgeBase, |
| | | updateKnowledgeBase, |
| | | } from "@/api/collaborativeApproval/knowledgeBase.js"; |
| | | |
| | | // 表单验证规则 |
| | | const rules = { |
| | | title: [ |
| | | { required: true, message: "请输入知识标题", trigger: "blur" } |
| | | ], |
| | | type: [ |
| | | { required: true, message: "请选择知识类型", trigger: "change" } |
| | | ], |
| | | problem: [ |
| | | { required: true, message: "请描述遇到的问题", trigger: "blur" } |
| | | ], |
| | | solution: [ |
| | | { required: true, message: "请详细描述解决方案", trigger: "blur" } |
| | | ] |
| | | }; |
| | | |
| | | // 响应式数据 |
| | | const data = reactive({ |
| | | searchForm: { |
| | | title: "", |
| | | type: "", |
| | | }, |
| | | tableLoading: false, |
| | | page: { |
| | | current: 1, |
| | | size: 20, |
| | | total: 0, |
| | | }, |
| | | tableData: [], |
| | | selectedIds: [], |
| | | form: { |
| | | title: "", |
| | | type: "", |
| | | scenario: "", |
| | | efficiency: "", |
| | | problem: "", |
| | | solution: "", |
| | | keyPoints: "", |
| | | creator: "", |
| | | usageCount: 0 |
| | | }, |
| | | dialogVisible: false, |
| | | dialogTitle: "", |
| | | dialogType: "add", |
| | | viewDialogVisible: false, |
| | | currentKnowledge: {} |
| | | }); |
| | | |
| | | const { |
| | | searchForm, |
| | | tableLoading, |
| | | page, |
| | | tableData, |
| | | selectedIds, |
| | | form, |
| | | dialogVisible, |
| | | dialogTitle, |
| | | dialogType, |
| | | viewDialogVisible, |
| | | currentKnowledge |
| | | } = toRefs(data); |
| | | |
| | | // 表单引用 |
| | | const formRef = ref(); |
| | | |
| | | // 表格列配置 |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "知识标题", |
| | | prop: "title", |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "知识类型", |
| | | prop: "type", |
| | | dataType: "tag", |
| | | formatData: (params) => { |
| | | const typeMap = { |
| | | contract: "合同特批", |
| | | approval: "审批案例", |
| | | solution: "解决方案", |
| | | experience: "经验总结", |
| | | guide: "操作指南" |
| | | }; |
| | | return typeMap[params] || params; |
| | | }, |
| | | formatType: (params) => { |
| | | const typeMap = { |
| | | contract: "success", |
| | | approval: "warning", |
| | | solution: "primary", |
| | | experience: "info", |
| | | guide: "danger" |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | } |
| | | }, |
| | | { |
| | | label: "适用场景", |
| | | prop: "scenario", |
| | | width: 150, |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "解决效率", |
| | | prop: "efficiency", |
| | | dataType: "tag", |
| | | formatData: (params) => { |
| | | const efficiencyMap = { |
| | | high: "显著提升", |
| | | medium: "一般提升", |
| | | low: "轻微提升" |
| | | }; |
| | | return efficiencyMap[params] || params; |
| | | }, |
| | | formatType: (params) => { |
| | | const typeMap = { |
| | | high: "success", |
| | | medium: "warning", |
| | | low: "info" |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | } |
| | | }, |
| | | { |
| | | label: "使用次数", |
| | | prop: "usageCount", |
| | | width: 100, |
| | | align: "center" |
| | | }, |
| | | { |
| | | label: "创建人", |
| | | prop: "creator", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "创建时间", |
| | | prop: "createTime", |
| | | width: 180, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "操作", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 200, |
| | | operation: [ |
| | | { |
| | | name: "编辑", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openForm("edit", row); |
| | | } |
| | | }, |
| | | { |
| | | name: "查看", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | viewKnowledge(row); |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | ]); |
| | | |
| | | // 模拟数据 |
| | | // let mockData = [ |
| | | // { |
| | | // id: "1", |
| | | // title: "特殊合同审批流程优化方案", |
| | | // type: "contract", |
| | | // scenario: "大额合同快速审批", |
| | | // efficiency: "high", |
| | | // problem: "大额合同审批流程复杂,审批时间长,影响业务进展", |
| | | // solution: "建立绿色通道,对符合条件的合同采用简化审批流程,由部门负责人直接审批,平均审批时间从3天缩短至1天", |
| | | // keyPoints: "绿色通道条件,简化流程,审批权限,时间控制", |
| | | // creator: "张经理", |
| | | // usageCount: 15, |
| | | // createTime: "2024-01-15 10:30:00" |
| | | // }, |
| | | // { |
| | | // id: "2", |
| | | // title: "跨部门协作审批经验总结", |
| | | // type: "experience", |
| | | // scenario: "多部门协作项目", |
| | | // efficiency: "medium", |
| | | // problem: "跨部门项目审批时,各部门意见不统一,审批进度缓慢", |
| | | // solution: "建立项目协调机制,指定项目负责人,定期召开协调会议,统一各方意见后再进行审批", |
| | | // keyPoints: "项目协调,定期会议,统一意见,负责人制度", |
| | | // creator: "李主管", |
| | | // usageCount: 8, |
| | | // createTime: "2024-01-14 15:20:00" |
| | | // }, |
| | | // { |
| | | // id: "3", |
| | | // title: "紧急采购审批操作指南", |
| | | // type: "guide", |
| | | // scenario: "紧急采购需求", |
| | | // efficiency: "high", |
| | | // problem: "紧急采购时审批流程复杂,无法满足紧急需求", |
| | | // solution: "制定紧急采购审批标准,明确紧急程度分级,不同级别采用不同审批流程,确保紧急需求得到及时处理", |
| | | // keyPoints: "紧急分级,标准制定,流程简化,及时处理", |
| | | // creator: "王专员", |
| | | // usageCount: 12, |
| | | // createTime: "2024-01-13 09:15:00" |
| | | // } |
| | | // ]; |
| | | |
| | | // 知识标题模板 |
| | | const titleTemplates = [ |
| | | "{type}审批流程优化方案", |
| | | "{scenario}处理经验总结", |
| | | "{type}特殊情况处理指南", |
| | | "{scenario}快速审批方案", |
| | | "{type}标准化操作流程", |
| | | "{scenario}问题解决方案", |
| | | "{type}最佳实践总结", |
| | | "{scenario}效率提升方案" |
| | | ]; |
| | | |
| | | // 知识类型配置 |
| | | const knowledgeTypes = [ |
| | | { type: "contract", label: "合同特批", efficiency: "high" }, |
| | | { type: "approval", label: "审批案例", efficiency: "medium" }, |
| | | { type: "solution", label: "解决方案", efficiency: "high" }, |
| | | { type: "experience", label: "经验总结", efficiency: "medium" }, |
| | | { type: "guide", label: "操作指南", efficiency: "low" } |
| | | ]; |
| | | |
| | | // 场景列表 |
| | | const scenarios = ["大额合同审批", "跨部门协作", "紧急采购", "特殊申请", "流程优化", "问题处理", "标准化建设", "效率提升"]; |
| | | |
| | | // 自动生成新数据 |
| | | const generateNewData = () => { |
| | | const newId = (mockData.length + 1).toString(); |
| | | const now = new Date(); |
| | | const randomType = knowledgeTypes[Math.floor(Math.random() * knowledgeTypes.length)]; |
| | | const randomScenario = scenarios[Math.floor(Math.random() * scenarios.length)]; |
| | | |
| | | // 生成随机标题 |
| | | let title = titleTemplates[Math.floor(Math.random() * titleTemplates.length)]; |
| | | title = title |
| | | .replace('{type}', randomType.label) |
| | | .replace('{scenario}', randomScenario); |
| | | |
| | | const newKnowledge = { |
| | | id: newId, |
| | | title: title, |
| | | type: randomType.type, |
| | | scenario: randomScenario, |
| | | efficiency: randomType.efficiency, |
| | | problem: `在${randomScenario}过程中遇到的问题描述...`, |
| | | solution: `针对${randomScenario}的解决方案和操作步骤...`, |
| | | keyPoints: "关键要点1,关键要点2,关键要点3,关键要点4", |
| | | creator: ["张经理", "李主管", "王专员", "刘总监"][Math.floor(Math.random() * 4)], |
| | | usageCount: Math.floor(Math.random() * 20) + 1, |
| | | createTime: now.toLocaleString() |
| | | // 表单验证规则 |
| | | const rules = { |
| | | title: [{ required: true, message: "请输入知识标题", trigger: "blur" }], |
| | | type: [{ required: true, message: "请选择知识类型", trigger: "change" }], |
| | | problem: [{ required: true, message: "请描述遇到的问题", trigger: "blur" }], |
| | | solution: [ |
| | | { required: true, message: "请详细描述解决方案", trigger: "blur" }, |
| | | ], |
| | | }; |
| | | |
| | | // 添加到数据开头 |
| | | mockData.unshift(newKnowledge); |
| | | |
| | | // 保持数据量在合理范围内(最多保留30条) |
| | | if (mockData.length > 30) { |
| | | mockData = mockData.slice(0, 30); |
| | | } |
| | | |
| | | console.log(`[${new Date().toLocaleString()}] 自动生成新知识: ${title}`); |
| | | }; |
| | | |
| | | // 生命周期 |
| | | onMounted(() => { |
| | | getList(); |
| | | startAutoRefresh(); |
| | | }); |
| | | |
| | | // 开始自动刷新 |
| | | const startAutoRefresh = () => { |
| | | setInterval(() => { |
| | | generateNewData(); |
| | | getList(); |
| | | }, 600000); // 10分钟刷新一次 (10 * 60 * 1000 = 600000ms) |
| | | }; |
| | | |
| | | // 查询数据 |
| | | const handleQuery = () => { |
| | | page.value.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | listKnowledgeBase({...page.value, ...searchForm.value}) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | }; |
| | | |
| | | // 分页处理 |
| | | const pagination = (obj) => { |
| | | page.value.current = obj.page; |
| | | page.value.size = obj.limit; |
| | | handleQuery(); |
| | | }; |
| | | |
| | | // 选择变化处理 |
| | | const handleSelectionChange = (selection) => { |
| | | selectedIds.value = selection.map(item => item.id); |
| | | }; |
| | | |
| | | // 打开表单 |
| | | const openForm = (type, row = null) => { |
| | | dialogType.value = type; |
| | | if (type === "add") { |
| | | dialogTitle.value = "新增知识"; |
| | | // 重置表单 |
| | | Object.assign(form.value, { |
| | | // 响应式数据 |
| | | const data = reactive({ |
| | | searchForm: { |
| | | title: "", |
| | | type: "", |
| | | }, |
| | | tableLoading: false, |
| | | page: { |
| | | current: 1, |
| | | size: 20, |
| | | total: 0, |
| | | }, |
| | | tableData: [], |
| | | selectedIds: [], |
| | | form: { |
| | | title: "", |
| | | type: "", |
| | | scenario: "", |
| | |
| | | solution: "", |
| | | keyPoints: "", |
| | | creator: "", |
| | | usageCount: 0 |
| | | }); |
| | | } else if (type === "edit" && row) { |
| | | dialogTitle.value = "编辑知识"; |
| | | Object.assign(form.value, { |
| | | id: row.id, |
| | | title: row.title, |
| | | type: row.type, |
| | | scenario: row.scenario, |
| | | efficiency: row.efficiency, |
| | | problem: row.problem, |
| | | solution: row.solution, |
| | | keyPoints: row.keyPoints, |
| | | creator: row.creator, |
| | | usageCount: row.usageCount |
| | | }); |
| | | } |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | // 查看知识详情 |
| | | const viewKnowledge = (row) => { |
| | | currentKnowledge.value = { ...row }; |
| | | viewDialogVisible.value = true; |
| | | }; |
| | | |
| | | // 获取类型标签类型 |
| | | const getTypeTagType = (type) => { |
| | | const typeMap = { |
| | | contract: "success", |
| | | approval: "warning", |
| | | solution: "primary", |
| | | experience: "info", |
| | | guide: "danger" |
| | | }; |
| | | return typeMap[type] || "info"; |
| | | }; |
| | | |
| | | // 获取类型标签文本 |
| | | const getTypeLabel = (type) => { |
| | | const typeMap = { |
| | | contract: "合同特批", |
| | | approval: "审批案例", |
| | | solution: "解决方案", |
| | | experience: "经验总结", |
| | | guide: "操作指南" |
| | | }; |
| | | return typeMap[type] || type; |
| | | }; |
| | | |
| | | // 获取效率标签类型 |
| | | const getEfficiencyTagType = (efficiency) => { |
| | | const typeMap = { |
| | | high: "success", |
| | | medium: "warning", |
| | | low: "info" |
| | | }; |
| | | return typeMap[efficiency] || "info"; |
| | | }; |
| | | |
| | | // 获取效率标签文本 |
| | | const getEfficiencyLabel = (efficiency) => { |
| | | const efficiencyMap = { |
| | | high: "显著提升", |
| | | medium: "一般提升", |
| | | low: "轻微提升" |
| | | }; |
| | | return efficiencyMap[efficiency] || efficiency; |
| | | }; |
| | | |
| | | // 获取效率提升百分比 |
| | | const getEfficiencyScore = (efficiency) => { |
| | | const scoreMap = { |
| | | high: 40, |
| | | medium: 25, |
| | | low: 15 |
| | | }; |
| | | return scoreMap[efficiency] || 0; |
| | | }; |
| | | |
| | | // 获取平均节省时间 |
| | | const getTimeSaved = (efficiency) => { |
| | | const timeMap = { |
| | | high: "2-3天", |
| | | medium: "1-2天", |
| | | low: "0.5-1天" |
| | | }; |
| | | return timeMap[efficiency] || "未知"; |
| | | }; |
| | | |
| | | // 复制知识 |
| | | const copyKnowledge = () => { |
| | | const knowledgeText = ` |
| | | 知识标题:${currentKnowledge.value.title} |
| | | 知识类型:${getTypeLabel(currentKnowledge.value.type)} |
| | | 适用场景:${currentKnowledge.value.scenario} |
| | | 问题描述:${currentKnowledge.value.problem} |
| | | 解决方案:${currentKnowledge.value.solution} |
| | | 关键要点:${currentKnowledge.value.keyPoints} |
| | | 创建人:${currentKnowledge.value.creator} |
| | | `.trim(); |
| | | |
| | | // 复制到剪贴板 |
| | | navigator.clipboard.writeText(knowledgeText).then(() => { |
| | | ElMessage.success("知识内容已复制到剪贴板"); |
| | | }).catch(() => { |
| | | ElMessage.error("复制失败,请手动复制"); |
| | | usageCount: 0, |
| | | }, |
| | | dialogVisible: false, |
| | | dialogTitle: "", |
| | | dialogType: "add", |
| | | viewDialogVisible: false, |
| | | currentKnowledge: {}, |
| | | }); |
| | | }; |
| | | |
| | | // 收藏知识 |
| | | const markAsFavorite = () => { |
| | | // 增加使用次数 |
| | | const index = mockData.findIndex(item => item.id === currentKnowledge.value.id); |
| | | if (index !== -1) { |
| | | mockData[index].usageCount += 1; |
| | | currentKnowledge.value.usageCount += 1; |
| | | } |
| | | const { |
| | | searchForm, |
| | | tableLoading, |
| | | page, |
| | | tableData, |
| | | selectedIds, |
| | | form, |
| | | dialogVisible, |
| | | dialogTitle, |
| | | dialogType, |
| | | viewDialogVisible, |
| | | currentKnowledge, |
| | | } = toRefs(data); |
| | | |
| | | ElMessage.success("已收藏,使用次数+1"); |
| | | }; |
| | | // 表单引用 |
| | | const formRef = ref(); |
| | | |
| | | // 提交知识表单 |
| | | const submitForm = async () => { |
| | | try { |
| | | await formRef.value.validate(); |
| | | if (dialogType.value === "add") { |
| | | // 新增知识 |
| | | addKnowledgeBase({...form.value}).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("添加成功"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | } else { |
| | | updateKnowledgeBase({...form.value}).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("更新成功"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | // 表格列配置 |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "知识标题", |
| | | prop: "title", |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "知识类型", |
| | | prop: "type", |
| | | dataType: "tag", |
| | | formatData: params => { |
| | | const typeMap = { |
| | | contract: "合同特批", |
| | | approval: "审批案例", |
| | | solution: "解决方案", |
| | | experience: "经验总结", |
| | | guide: "操作指南", |
| | | }; |
| | | return typeMap[params] || params; |
| | | }, |
| | | formatType: params => { |
| | | const typeMap = { |
| | | contract: "success", |
| | | approval: "warning", |
| | | solution: "primary", |
| | | experience: "info", |
| | | guide: "danger", |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | }, |
| | | }, |
| | | { |
| | | label: "适用场景", |
| | | prop: "scenario", |
| | | width: 150, |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "解决效率", |
| | | prop: "efficiency", |
| | | dataType: "tag", |
| | | formatData: params => { |
| | | const efficiencyMap = { |
| | | high: "显著提升", |
| | | medium: "一般提升", |
| | | low: "轻微提升", |
| | | }; |
| | | return efficiencyMap[params] || params; |
| | | }, |
| | | formatType: params => { |
| | | const typeMap = { |
| | | high: "success", |
| | | medium: "warning", |
| | | low: "info", |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | }, |
| | | }, |
| | | { |
| | | label: "使用次数", |
| | | prop: "usageCount", |
| | | width: 100, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "创建人", |
| | | prop: "creator", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "创建时间", |
| | | prop: "createTime", |
| | | width: 180, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "操作", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 200, |
| | | operation: [ |
| | | { |
| | | name: "编辑", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openForm("edit", row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "查看", |
| | | type: "text", |
| | | clickFun: row => { |
| | | viewKnowledge(row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | |
| | | // 模拟数据 |
| | | // let mockData = [ |
| | | // { |
| | | // id: "1", |
| | | // title: "特殊合同审批流程优化方案", |
| | | // type: "contract", |
| | | // scenario: "大额合同快速审批", |
| | | // efficiency: "high", |
| | | // problem: "大额合同审批流程复杂,审批时间长,影响业务进展", |
| | | // solution: "建立绿色通道,对符合条件的合同采用简化审批流程,由部门负责人直接审批,平均审批时间从3天缩短至1天", |
| | | // keyPoints: "绿色通道条件,简化流程,审批权限,时间控制", |
| | | // creator: "张经理", |
| | | // usageCount: 15, |
| | | // createTime: "2024-01-15 10:30:00" |
| | | // }, |
| | | // { |
| | | // id: "2", |
| | | // title: "跨部门协作审批经验总结", |
| | | // type: "experience", |
| | | // scenario: "多部门协作项目", |
| | | // efficiency: "medium", |
| | | // problem: "跨部门项目审批时,各部门意见不统一,审批进度缓慢", |
| | | // solution: "建立项目协调机制,指定项目负责人,定期召开协调会议,统一各方意见后再进行审批", |
| | | // keyPoints: "项目协调,定期会议,统一意见,负责人制度", |
| | | // creator: "李主管", |
| | | // usageCount: 8, |
| | | // createTime: "2024-01-14 15:20:00" |
| | | // }, |
| | | // { |
| | | // id: "3", |
| | | // title: "紧急采购审批操作指南", |
| | | // type: "guide", |
| | | // scenario: "紧急采购需求", |
| | | // efficiency: "high", |
| | | // problem: "紧急采购时审批流程复杂,无法满足紧急需求", |
| | | // solution: "制定紧急采购审批标准,明确紧急程度分级,不同级别采用不同审批流程,确保紧急需求得到及时处理", |
| | | // keyPoints: "紧急分级,标准制定,流程简化,及时处理", |
| | | // creator: "王专员", |
| | | // usageCount: 12, |
| | | // createTime: "2024-01-13 09:15:00" |
| | | // } |
| | | // ]; |
| | | |
| | | // 知识标题模板 |
| | | const titleTemplates = [ |
| | | "{type}审批流程优化方案", |
| | | "{scenario}处理经验总结", |
| | | "{type}特殊情况处理指南", |
| | | "{scenario}快速审批方案", |
| | | "{type}标准化操作流程", |
| | | "{scenario}问题解决方案", |
| | | "{type}最佳实践总结", |
| | | "{scenario}效率提升方案", |
| | | ]; |
| | | |
| | | // 知识类型配置 |
| | | const knowledgeTypes = [ |
| | | { type: "contract", label: "合同特批", efficiency: "high" }, |
| | | { type: "approval", label: "审批案例", efficiency: "medium" }, |
| | | { type: "solution", label: "解决方案", efficiency: "high" }, |
| | | { type: "experience", label: "经验总结", efficiency: "medium" }, |
| | | { type: "guide", label: "操作指南", efficiency: "low" }, |
| | | ]; |
| | | |
| | | // 场景列表 |
| | | const scenarios = [ |
| | | "大额合同审批", |
| | | "跨部门协作", |
| | | "紧急采购", |
| | | "特殊申请", |
| | | "流程优化", |
| | | "问题处理", |
| | | "标准化建设", |
| | | "效率提升", |
| | | ]; |
| | | |
| | | // 自动生成新数据 |
| | | const generateNewData = () => { |
| | | const newId = (mockData.length + 1).toString(); |
| | | const now = new Date(); |
| | | const randomType = |
| | | knowledgeTypes[Math.floor(Math.random() * knowledgeTypes.length)]; |
| | | const randomScenario = |
| | | scenarios[Math.floor(Math.random() * scenarios.length)]; |
| | | |
| | | // 生成随机标题 |
| | | let title = titleTemplates[Math.floor(Math.random() * titleTemplates.length)]; |
| | | title = title |
| | | .replace("{type}", randomType.label) |
| | | .replace("{scenario}", randomScenario); |
| | | |
| | | const newKnowledge = { |
| | | id: newId, |
| | | title: title, |
| | | type: randomType.type, |
| | | scenario: randomScenario, |
| | | efficiency: randomType.efficiency, |
| | | problem: `在${randomScenario}过程中遇到的问题描述...`, |
| | | solution: `针对${randomScenario}的解决方案和操作步骤...`, |
| | | keyPoints: "关键要点1,关键要点2,关键要点3,关键要点4", |
| | | creator: ["张经理", "李主管", "王专员", "刘总监"][ |
| | | Math.floor(Math.random() * 4) |
| | | ], |
| | | usageCount: Math.floor(Math.random() * 20) + 1, |
| | | createTime: now.toLocaleString(), |
| | | }; |
| | | |
| | | // 添加到数据开头 |
| | | mockData.unshift(newKnowledge); |
| | | |
| | | // 保持数据量在合理范围内(最多保留30条) |
| | | if (mockData.length > 30) { |
| | | mockData = mockData.slice(0, 30); |
| | | } |
| | | } catch (error) { |
| | | console.error("表单验证失败:", error); |
| | | } |
| | | }; |
| | | |
| | | // 删除知识 |
| | | const handleDelete = () => { |
| | | if (selectedIds.value.length === 0) { |
| | | ElMessage.warning("请选择要删除的知识"); |
| | | return; |
| | | } |
| | | console.log(`[${new Date().toLocaleString()}] 自动生成新知识: ${title}`); |
| | | }; |
| | | |
| | | ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "删除", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }).then(() => { |
| | | // 从mockData中删除选中的项 |
| | | selectedIds.value.forEach(id => { |
| | | const index = mockData.findIndex(item => item.id === id); |
| | | if (index !== -1) { |
| | | mockData.splice(index, 1); |
| | | } |
| | | }); |
| | | |
| | | ElMessage.success("删除成功"); |
| | | selectedIds.value = []; |
| | | // 生命周期 |
| | | onMounted(() => { |
| | | getList(); |
| | | }).catch(() => { |
| | | // 用户取消 |
| | | startAutoRefresh(); |
| | | }); |
| | | }; |
| | | |
| | | // 开始自动刷新 |
| | | const startAutoRefresh = () => { |
| | | setInterval(() => { |
| | | generateNewData(); |
| | | getList(); |
| | | }, 600000); // 10分钟刷新一次 (10 * 60 * 1000 = 600000ms) |
| | | }; |
| | | |
| | | // 查询数据 |
| | | const handleQuery = () => { |
| | | page.value.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | listKnowledgeBase({ ...page.value, ...searchForm.value }) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // 分页处理 |
| | | const pagination = obj => { |
| | | page.value.current = obj.page; |
| | | page.value.size = obj.limit; |
| | | handleQuery(); |
| | | }; |
| | | |
| | | // 选择变化处理 |
| | | const handleSelectionChange = selection => { |
| | | selectedIds.value = selection.map(item => item.id); |
| | | }; |
| | | |
| | | // 打开表单 |
| | | const openForm = (type, row = null) => { |
| | | dialogType.value = type; |
| | | if (type === "add") { |
| | | dialogTitle.value = "新增知识"; |
| | | // 重置表单 |
| | | Object.assign(form.value, { |
| | | title: "", |
| | | type: "", |
| | | scenario: "", |
| | | efficiency: "", |
| | | problem: "", |
| | | solution: "", |
| | | keyPoints: "", |
| | | creator: "", |
| | | usageCount: 0, |
| | | }); |
| | | } else if (type === "edit" && row) { |
| | | dialogTitle.value = "编辑知识"; |
| | | Object.assign(form.value, { |
| | | id: row.id, |
| | | title: row.title, |
| | | type: row.type, |
| | | scenario: row.scenario, |
| | | efficiency: row.efficiency, |
| | | problem: row.problem, |
| | | solution: row.solution, |
| | | keyPoints: row.keyPoints, |
| | | creator: row.creator, |
| | | usageCount: row.usageCount, |
| | | }); |
| | | } |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | // 查看知识详情 |
| | | const viewKnowledge = row => { |
| | | currentKnowledge.value = { ...row }; |
| | | viewDialogVisible.value = true; |
| | | }; |
| | | |
| | | // 获取类型标签类型 |
| | | const getTypeTagType = type => { |
| | | const typeMap = { |
| | | contract: "success", |
| | | approval: "warning", |
| | | solution: "primary", |
| | | experience: "info", |
| | | guide: "danger", |
| | | }; |
| | | return typeMap[type] || "info"; |
| | | }; |
| | | |
| | | // 获取类型标签文本 |
| | | const getTypeLabel = type => { |
| | | const typeMap = { |
| | | contract: "合同特批", |
| | | approval: "审批案例", |
| | | solution: "解决方案", |
| | | experience: "经验总结", |
| | | guide: "操作指南", |
| | | }; |
| | | return typeMap[type] || type; |
| | | }; |
| | | |
| | | // 获取效率标签类型 |
| | | const getEfficiencyTagType = efficiency => { |
| | | const typeMap = { |
| | | high: "success", |
| | | medium: "warning", |
| | | low: "info", |
| | | }; |
| | | return typeMap[efficiency] || "info"; |
| | | }; |
| | | |
| | | // 获取效率标签文本 |
| | | const getEfficiencyLabel = efficiency => { |
| | | const efficiencyMap = { |
| | | high: "显著提升", |
| | | medium: "一般提升", |
| | | low: "轻微提升", |
| | | }; |
| | | return efficiencyMap[efficiency] || efficiency; |
| | | }; |
| | | |
| | | // 获取效率提升百分比 |
| | | const getEfficiencyScore = efficiency => { |
| | | const scoreMap = { |
| | | high: 40, |
| | | medium: 25, |
| | | low: 15, |
| | | }; |
| | | return scoreMap[efficiency] || 0; |
| | | }; |
| | | |
| | | // 获取平均节省时间 |
| | | const getTimeSaved = efficiency => { |
| | | const timeMap = { |
| | | high: "2-3天", |
| | | medium: "1-2天", |
| | | low: "0.5-1天", |
| | | }; |
| | | return timeMap[efficiency] || "未知"; |
| | | }; |
| | | |
| | | // 复制知识 |
| | | const copyKnowledge = () => { |
| | | const knowledgeText = ` |
| | | 知识标题:${currentKnowledge.value.title} |
| | | 知识类型:${getTypeLabel(currentKnowledge.value.type)} |
| | | 适用场景:${currentKnowledge.value.scenario} |
| | | 问题描述:${currentKnowledge.value.problem} |
| | | 解决方案:${currentKnowledge.value.solution} |
| | | 关键要点:${currentKnowledge.value.keyPoints} |
| | | 创建人:${currentKnowledge.value.creator} |
| | | `.trim(); |
| | | |
| | | // 复制到剪贴板 |
| | | navigator.clipboard |
| | | .writeText(knowledgeText) |
| | | .then(() => { |
| | | ElMessage.success("知识内容已复制到剪贴板"); |
| | | }) |
| | | .catch(() => { |
| | | ElMessage.error("复制失败,请手动复制"); |
| | | }); |
| | | }; |
| | | |
| | | // 收藏知识 |
| | | const markAsFavorite = () => { |
| | | // 增加使用次数 |
| | | const index = mockData.findIndex( |
| | | item => item.id === currentKnowledge.value.id |
| | | ); |
| | | if (index !== -1) { |
| | | mockData[index].usageCount += 1; |
| | | currentKnowledge.value.usageCount += 1; |
| | | } |
| | | |
| | | ElMessage.success("已收藏,使用次数+1"); |
| | | }; |
| | | |
| | | // 提交知识表单 |
| | | const submitForm = async () => { |
| | | try { |
| | | await formRef.value.validate(); |
| | | if (dialogType.value === "add") { |
| | | // 新增知识 |
| | | addKnowledgeBase({ ...form.value }) |
| | | .then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("添加成功"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } else { |
| | | updateKnowledgeBase({ ...form.value }) |
| | | .then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("更新成功"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } |
| | | } catch (error) { |
| | | console.error("表单验证失败:", error); |
| | | } |
| | | }; |
| | | |
| | | // 删除知识 |
| | | const handleDelete = () => { |
| | | if (selectedIds.value.length === 0) { |
| | | ElMessage.warning("请选择要删除的知识"); |
| | | return; |
| | | } |
| | | |
| | | ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "删除", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | // console.log(selectedIds.value); |
| | | delKnowledgeBase(selectedIds.value).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("删除成功"); |
| | | selectedIds.value = []; |
| | | getList(); |
| | | } |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | // 用户取消 |
| | | }); |
| | | }; |
| | | |
| | | // 导出 |
| | | const { proxy } = getCurrentInstance(); |
| | | const handleExport = () => { |
| | | proxy.download( |
| | | "/knowledgeBase/export", |
| | | { ...searchForm.value }, |
| | | "知识库.xlsx" |
| | | ); |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .auto-refresh-info { |
| | | margin-bottom: 15px; |
| | | } |
| | | .auto-refresh-info { |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .auto-refresh-info .el-alert { |
| | | border-radius: 8px; |
| | | } |
| | | .auto-refresh-info .el-alert { |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | text-align: right; |
| | | } |
| | | .dialog-footer { |
| | | text-align: right; |
| | | } |
| | | |
| | | .knowledge-detail { |
| | | padding: 20px 0; |
| | | } |
| | | .knowledge-detail { |
| | | padding: 20px 0; |
| | | } |
| | | |
| | | .detail-title { |
| | | font-size: 18px; |
| | | font-weight: bold; |
| | | color: #303133; |
| | | } |
| | | .detail-title { |
| | | font-size: 18px; |
| | | font-weight: bold; |
| | | color: #303133; |
| | | } |
| | | |
| | | .detail-section { |
| | | margin-top: 24px; |
| | | } |
| | | .detail-section { |
| | | margin-top: 24px; |
| | | } |
| | | |
| | | .detail-section h4 { |
| | | margin: 0 0 12px 0; |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | border-left: 4px solid #409eff; |
| | | padding-left: 12px; |
| | | } |
| | | .detail-section h4 { |
| | | margin: 0 0 12px 0; |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | border-left: 4px solid #409eff; |
| | | padding-left: 12px; |
| | | } |
| | | |
| | | .detail-content { |
| | | background: #f8f9fa; |
| | | padding: 16px; |
| | | border-radius: 6px; |
| | | line-height: 1.6; |
| | | color: #606266; |
| | | white-space: pre-wrap; |
| | | } |
| | | .detail-content { |
| | | background: #f8f9fa; |
| | | padding: 16px; |
| | | border-radius: 6px; |
| | | line-height: 1.6; |
| | | color: #606266; |
| | | white-space: pre-wrap; |
| | | } |
| | | |
| | | .key-points { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 8px; |
| | | } |
| | | .key-points { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .usage-stats { |
| | | margin-top: 16px; |
| | | } |
| | | .usage-stats { |
| | | margin-top: 16px; |
| | | } |
| | | |
| | | .stat-item { |
| | | text-align: center; |
| | | padding: 20px; |
| | | background: #f8f9fa; |
| | | border-radius: 8px; |
| | | } |
| | | .stat-item { |
| | | text-align: center; |
| | | padding: 20px; |
| | | background: #f8f9fa; |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | .stat-number { |
| | | font-size: 24px; |
| | | font-weight: bold; |
| | | color: #409eff; |
| | | margin-bottom: 8px; |
| | | } |
| | | .stat-number { |
| | | font-size: 24px; |
| | | font-weight: bold; |
| | | color: #409eff; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .stat-label { |
| | | font-size: 14px; |
| | | color: #909399; |
| | | } |
| | | .stat-label { |
| | | font-size: 14px; |
| | | color: #909399; |
| | | } |
| | | </style> |