| ¶Ô±ÈÐÂÎļþ | 
 |  |  | 
 |  |  | <template> | 
 |  |  |   <div class="app-container"> | 
 |  |  |     <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" | 
 |  |  |         /> | 
 |  |  |         <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> | 
 |  |  |         <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> | 
 |  |  |       </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> | 
 |  |  |     </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-row :gutter="20"> | 
 |  |  |           <el-col :span="12"> | 
 |  |  |             <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-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> | 
 |  |  |           </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-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> | 
 |  |  |         <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> | 
 |  |  |         <el-row :gutter="20"> | 
 |  |  |           <el-col :span="12"> | 
 |  |  |             <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> | 
 |  |  |           </el-col> | 
 |  |  |         </el-row> | 
 |  |  |       </el-form> | 
 |  |  |       <template #footer> | 
 |  |  |         <span class="dialog-footer"> | 
 |  |  |           <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" | 
 |  |  |     > | 
 |  |  |       <div class="knowledge-detail"> | 
 |  |  |         <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="ç¥è¯ç±»å"> | 
 |  |  |             <el-tag :type="getTypeTagType(currentKnowledge.type)"> | 
 |  |  |               {{ getTypeLabel(currentKnowledge.type) }} | 
 |  |  |             </el-tag> | 
 |  |  |           </el-descriptions-item> | 
 |  |  |           <el-descriptions-item label="éç¨åºæ¯"> | 
 |  |  |             {{ currentKnowledge.scenario }} | 
 |  |  |           </el-descriptions-item> | 
 |  |  |           <el-descriptions-item label="è§£å³æç"> | 
 |  |  |             <el-tag :type="getEfficiencyTagType(currentKnowledge.efficiency)"> | 
 |  |  |               {{ getEfficiencyLabel(currentKnowledge.efficiency) }} | 
 |  |  |             </el-tag> | 
 |  |  |           </el-descriptions-item> | 
 |  |  |           <el-descriptions-item label="ä½¿ç¨æ¬¡æ°"> | 
 |  |  |             <el-tag type="info">{{ currentKnowledge.usageCount }} æ¬¡</el-tag> | 
 |  |  |           </el-descriptions-item> | 
 |  |  |           <el-descriptions-item label="å建人"> | 
 |  |  |             {{ currentKnowledge.creator }} | 
 |  |  |           </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;" | 
 |  |  |             > | 
 |  |  |               {{ point.trim() }} | 
 |  |  |             </el-tag> | 
 |  |  |           </div> | 
 |  |  |         </div> | 
 |  |  |  | 
 |  |  |         <div class="detail-section"> | 
 |  |  |           <h4>使ç¨ç»è®¡</h4> | 
 |  |  |           <div class="usage-stats"> | 
 |  |  |             <el-row :gutter="20"> | 
 |  |  |               <el-col :span="8"> | 
 |  |  |                 <div class="stat-item"> | 
 |  |  |                   <div class="stat-number">{{ currentKnowledge.usageCount }}</div> | 
 |  |  |                   <div class="stat-label">ä½¿ç¨æ¬¡æ°</div> | 
 |  |  |                 </div> | 
 |  |  |               </el-col> | 
 |  |  |               <el-col :span="8"> | 
 |  |  |                 <div class="stat-item"> | 
 |  |  |                   <div class="stat-number">{{ getEfficiencyScore(currentKnowledge.efficiency) }}%</div> | 
 |  |  |                   <div class="stat-label">æçæå</div> | 
 |  |  |                 </div> | 
 |  |  |               </el-col> | 
 |  |  |               <el-col :span="8"> | 
 |  |  |                 <div class="stat-item"> | 
 |  |  |                   <div class="stat-number">{{ getTimeSaved(currentKnowledge.efficiency) }}</div> | 
 |  |  |                   <div class="stat-label">å¹³åèçæ¶é´</div> | 
 |  |  |                 </div> | 
 |  |  |               </el-col> | 
 |  |  |             </el-row> | 
 |  |  |           </div> | 
 |  |  |         </div> | 
 |  |  |       </div> | 
 |  |  |  | 
 |  |  |       <template #footer> | 
 |  |  |         <span class="dialog-footer"> | 
 |  |  |           <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> | 
 |  |  |     </el-dialog> | 
 |  |  |   </div> | 
 |  |  | </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"; | 
 |  |  |  | 
 |  |  | // è¡¨åéªè¯è§å | 
 |  |  | 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: 100, | 
 |  |  |     total: 0, | 
 |  |  |   }, | 
 |  |  |   tableData: [], | 
 |  |  |   selectedIds: [], | 
 |  |  |   form: { | 
 |  |  |     title: "", | 
 |  |  |     type: "", | 
 |  |  |     scenario: "", | 
 |  |  |     efficiency: "medium", | 
 |  |  |     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() | 
 |  |  |   }; | 
 |  |  |    | 
 |  |  |   // æ·»å å°æ°æ®å¼å¤´ | 
 |  |  |   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; | 
 |  |  |    | 
 |  |  |   setTimeout(() => { | 
 |  |  |     let filteredData = [...mockData]; | 
 |  |  |      | 
 |  |  |     if (searchForm.value.title) { | 
 |  |  |       filteredData = filteredData.filter(item =>  | 
 |  |  |         item.title.toLowerCase().includes(searchForm.value.title.toLowerCase()) | 
 |  |  |       ); | 
 |  |  |     } | 
 |  |  |      | 
 |  |  |     if (searchForm.value.type) { | 
 |  |  |       filteredData = filteredData.filter(item => item.type === searchForm.value.type); | 
 |  |  |     } | 
 |  |  |      | 
 |  |  |     tableData.value = filteredData; | 
 |  |  |     page.value.total = filteredData.length; | 
 |  |  |     tableLoading.value = false; | 
 |  |  |   }, 500); | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | // å页å¤ç | 
 |  |  | 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: "medium", | 
 |  |  |       problem: "", | 
 |  |  |       solution: "", | 
 |  |  |       keyPoints: "", | 
 |  |  |       creator: "", | 
 |  |  |       usageCount: 0 | 
 |  |  |     }); | 
 |  |  |   } else if (type === "edit" && row) { | 
 |  |  |     dialogTitle.value = "ç¼è¾ç¥è¯"; | 
 |  |  |     Object.assign(form.value, { | 
 |  |  |       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") { | 
 |  |  |       // æ°å¢ç¥è¯ | 
 |  |  |       const newKnowledge = { | 
 |  |  |         id: (mockData.length + 1).toString(), | 
 |  |  |         title: form.value.title, | 
 |  |  |         type: form.value.type, | 
 |  |  |         scenario: form.value.scenario, | 
 |  |  |         efficiency: form.value.efficiency, | 
 |  |  |         problem: form.value.problem, | 
 |  |  |         solution: form.value.solution, | 
 |  |  |         keyPoints: form.value.keyPoints, | 
 |  |  |         creator: form.value.creator, | 
 |  |  |         usageCount: form.value.usageCount, | 
 |  |  |         createTime: new Date().toLocaleString() | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |       mockData.unshift(newKnowledge); | 
 |  |  |       ElMessage.success("ç¥è¯å建æå"); | 
 |  |  |     } else { | 
 |  |  |       // ç¼è¾ç¥è¯ | 
 |  |  |       const index = mockData.findIndex(item => item.id === selectedIds.value[0]); | 
 |  |  |       if (index !== -1) { | 
 |  |  |         Object.assign(mockData[index], { | 
 |  |  |           title: form.value.title, | 
 |  |  |           type: form.value.type, | 
 |  |  |           scenario: form.value.scenario, | 
 |  |  |           efficiency: form.value.efficiency, | 
 |  |  |           problem: form.value.problem, | 
 |  |  |           solution: form.value.solution, | 
 |  |  |           keyPoints: form.value.keyPoints, | 
 |  |  |           creator: form.value.creator, | 
 |  |  |           usageCount: form.value.usageCount | 
 |  |  |         }); | 
 |  |  |         ElMessage.success("ç¥è¯æ´æ°æå"); | 
 |  |  |       } | 
 |  |  |     } | 
 |  |  |      | 
 |  |  |     dialogVisible.value = false; | 
 |  |  |     getList(); | 
 |  |  |   } catch (error) { | 
 |  |  |     console.error("表åéªè¯å¤±è´¥:", error); | 
 |  |  |   } | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | // å é¤ç¥è¯ | 
 |  |  | const handleDelete = () => { | 
 |  |  |   if (selectedIds.value.length === 0) { | 
 |  |  |     ElMessage.warning("è¯·éæ©è¦å é¤çç¥è¯"); | 
 |  |  |     return; | 
 |  |  |   } | 
 |  |  |    | 
 |  |  |   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 = []; | 
 |  |  |     getList(); | 
 |  |  |   }).catch(() => { | 
 |  |  |     // ç¨æ·åæ¶ | 
 |  |  |   }); | 
 |  |  | }; | 
 |  |  | </script> | 
 |  |  |  | 
 |  |  | <style scoped> | 
 |  |  | .auto-refresh-info { | 
 |  |  |   margin-bottom: 15px; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .auto-refresh-info .el-alert { | 
 |  |  |   border-radius: 8px; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .dialog-footer { | 
 |  |  |   text-align: right; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .knowledge-detail { | 
 |  |  |   padding: 20px 0; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .detail-title { | 
 |  |  |   font-size: 18px; | 
 |  |  |   font-weight: bold; | 
 |  |  |   color: #303133; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .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-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; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .usage-stats { | 
 |  |  |   margin-top: 16px; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .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-label { | 
 |  |  |   font-size: 14px; | 
 |  |  |   color: #909399; | 
 |  |  | } | 
 |  |  | </style> |