| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">å±é©æºåç§°ï¼</span> |
| | | <el-input v-model="searchForm.name" |
| | | 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 v-for="item in knowledgeTypeOptions" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" /> |
| | | </el-select> |
| | | <el-button type="primary" |
| | | @click="handleQuery" |
| | | style="margin-left: 10px"> |
| | | æç´¢ |
| | | </el-button> |
| | | </div> |
| | | <div> |
| | | <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" |
| | | :rowClassName="getRowClass"></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="code"> |
| | | <el-input v-model="form.code" |
| | | placeholder="请è¾å
¥å±é©æºç¼ç " /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å±é©æºåç§°" |
| | | prop="name"> |
| | | <el-input v-model="form.name" |
| | | placeholder="请è¾å
¥å±é©æºåç§°" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æå¨ä½ç½®" |
| | | prop="location"> |
| | | <el-input v-model="form.location" |
| | | placeholder="请è¾å
¥æå¨ä½ç½®" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç®¡æ§æªæ½" |
| | | prop="controlMeasures"> |
| | | <el-input v-model="form.controlMeasures" |
| | | placeholder="请è¾å
¥ç®¡æ§æªæ½" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å±é©æºç±»å" |
| | | prop="type"> |
| | | <el-select v-model="form.type" |
| | | placeholder="è¯·éæ©å±é©æºç±»å" |
| | | style="width: 100%"> |
| | | <el-option v-for="item in knowledgeTypeOptions" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="åºåæ°é" |
| | | prop="stockQty"> |
| | | <el-input v-model="form.stockQty" |
| | | type="number" |
| | | min="0" |
| | | placeholder="请è¾å
¥åºåæ°é" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="管æ§è´£ä»»äºº" |
| | | prop="principalUserId"> |
| | | <el-select v-model="form.principalUserId" |
| | | placeholder="è¯·éæ©ç®¡æ§è´£ä»»äºº" |
| | | @change="handleUserChange" |
| | | clearable> |
| | | <el-option v-for="item in userList" |
| | | :key="item.userId" |
| | | :label="item.nickName" |
| | | :value="item.userId" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="责任人èç³»çµè¯" |
| | | prop="principalMobile"> |
| | | <el-input v-model="form.principalMobile" |
| | | readonly |
| | | placeholder="èªå¨å¸¦åº" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é£é©ç级" |
| | | prop="riskLevel"> |
| | | <el-select v-model="form.riskLevel" |
| | | placeholder="è¯·éæ©é£é©ç级" |
| | | clearable> |
| | | <el-option v-for="item in riskLevelOptions" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="è§æ ¼ / é£é©æè¿°" |
| | | prop="specInfo"> |
| | | <el-input v-model="form.specInfo" |
| | | type="textarea" |
| | | :rows="4" |
| | | placeholder="请è¾å
¥è§æ ¼ / é£é©æè¿°" /> |
| | | </el-form-item> |
| | | </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.name }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="å±é©æºç¼ç "> |
| | | {{ currentKnowledge.code }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="å±é©æºç±»å"> |
| | | {{ getTypeLabel(currentKnowledge.type) }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="æå¨ä½ç½®"> |
| | | {{ currentKnowledge.location }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="ç®¡æ§æªæ½"> |
| | | {{ currentKnowledge.controlMeasures }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="åºåæ°é"> |
| | | {{ currentKnowledge.stockQty }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="管æ§è´£ä»»äºº"> |
| | | {{ currentKnowledge.principalUserId }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="责任人èç³»çµè¯"> |
| | | {{ currentKnowledge.principalMobile }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="é£é©ç级"> |
| | | <el-tag :type="getTypeTagType(currentKnowledge.riskLevel)"> |
| | | {{ currentKnowledge.riskLevel }} |
| | | </el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="è§æ ¼ / é£é©æè¿°"> |
| | | {{ currentKnowledge.specInfo }} |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | </div> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="viewDialogVisible = false">å
³é</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { |
| | | onMounted, |
| | | ref, |
| | | reactive, |
| | | toRefs, |
| | | getCurrentInstance, |
| | | computed, |
| | | } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | import { |
| | | listKnowledgeBase, |
| | | delKnowledgeBase, |
| | | addKnowledgeBase, |
| | | updateKnowledgeBase, |
| | | } from "@/api/collaborativeApproval/knowledgeBase.js"; |
| | | import { |
| | | safeHazardListPage, |
| | | safeHazardAdd, |
| | | safeHazardUpdate, |
| | | safeHazardDel, |
| | | } from "@/api/safeProduction/hazardSourceLedger.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: { |
| | | name: "", |
| | | type: "", |
| | | }, |
| | | tableLoading: false, |
| | | page: { |
| | | current: 1, |
| | | size: 20, |
| | | total: 0, |
| | | }, |
| | | tableData: [], |
| | | selectedIds: [], |
| | | form: { |
| | | code: "", |
| | | name: "", |
| | | location: "", |
| | | controlMeasures: "", |
| | | riskLevel: "", |
| | | principalUser: "", |
| | | principalMobile: "", |
| | | specInfo: "", |
| | | principalUserId: "", |
| | | controlMeasures: "", |
| | | stockQty: "", |
| | | type: "", |
| | | }, |
| | | 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 riskLevelOptions = ref([ |
| | | { value: "ä½é£é©", label: "ä½é£é©" }, |
| | | { value: "ä¸è¬é£é©", label: "ä¸è¬é£é©" }, |
| | | { value: "è¾å¤§é£é©", label: "è¾å¤§é£é©" }, |
| | | { value: "é大é£é©", label: "é大é£é©" }, |
| | | ]); |
| | | |
| | | // è¡¨æ ¼åé
ç½® |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "å±é©æºç¼ç ", |
| | | prop: "code", |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "å±é©æºåç§°", |
| | | prop: "name", |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "å±é©æºç±»å", |
| | | prop: "type", |
| | | showOverflowTooltip: true, |
| | | formatData: params => { |
| | | return getTypeLabel(params); |
| | | }, |
| | | }, |
| | | { |
| | | label: "é£é©ç级", |
| | | prop: "riskLevel", |
| | | showOverflowTooltip: true, |
| | | dataType: "tag", |
| | | formatType: params => { |
| | | const typeMap = { |
| | | ä½é£é©: "info", |
| | | ä¸è¬é£é©: "info", |
| | | è¾å¤§é£é©: "warning", |
| | | é大é£é©: "danger", |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | }, |
| | | }, |
| | | { |
| | | label: "æå¨ä½ç½®", |
| | | prop: "location", |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "ç®¡æ§æªæ½", |
| | | prop: "controlMeasures", |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "åºåæ°é", |
| | | prop: "stockQty", |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "管æ§è´£ä»»äºº", |
| | | prop: "principalUser", |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "责任人èç³»çµè¯", |
| | | prop: "principalMobile", |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "è§æ ¼ / é£é©æè¿°", |
| | | prop: "specInfo", |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | 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); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const userList = ref([]); |
| | | // çå½å¨æ |
| | | onMounted(() => { |
| | | getList(); |
| | | startAutoRefresh(); |
| | | userListNoPage().then(res => { |
| | | userList.value = res.data; |
| | | }); |
| | | }); |
| | | |
| | | // å¤çç¨æ·éæ©åå |
| | | const handleUserChange = userId => { |
| | | const selectedUser = userList.value.find(user => user.userId === userId); |
| | | if (selectedUser) { |
| | | form.value.principalUser = selectedUser.nickName; |
| | | form.value.principalMobile = selectedUser.phonenumber; |
| | | } |
| | | }; |
| | | |
| | | // å¼å§èªå¨å·æ° |
| | | const startAutoRefresh = () => { |
| | | setInterval(() => { |
| | | getList(); |
| | | }, 600000); // 10åéå·æ°ä¸æ¬¡ (10 * 60 * 1000 = 600000ms) |
| | | }; |
| | | |
| | | // æ¥è¯¢æ°æ® |
| | | const handleQuery = () => { |
| | | page.value.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | safeHazardListPage({ ...page.value, ...searchForm.value }) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.value.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, { |
| | | code: "", |
| | | name: "", |
| | | location: "", |
| | | controlMeasures: "", |
| | | riskLevel: "", |
| | | principalUser: "", |
| | | principalMobile: "", |
| | | specInfo: "", |
| | | principalUserId: "", |
| | | controlMeasures: "", |
| | | stockQty: "", |
| | | type: "", |
| | | }); |
| | | } else if (type === "edit" && row) { |
| | | dialogTitle.value = "ç¼è¾ç¥è¯"; |
| | | Object.assign(form.value, { |
| | | id: row.id, |
| | | code: row.code, |
| | | name: row.name, |
| | | location: row.location, |
| | | controlMeasures: row.controlMeasures, |
| | | riskLevel: row.riskLevel, |
| | | principalUser: row.principalUser, |
| | | principalMobile: row.principalMobile, |
| | | specInfo: row.specInfo, |
| | | principalUserId: row.principalUserId, |
| | | controlMeasures: row.controlMeasures, |
| | | stockQty: row.stockQty, |
| | | type: row.type, |
| | | }); |
| | | } |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | // æ¥çç¥è¯è¯¦æ
|
| | | const viewKnowledge = row => { |
| | | currentKnowledge.value = { ...row }; |
| | | viewDialogVisible.value = true; |
| | | }; |
| | | |
| | | // è·åç±»åæ ç¾ç±»å |
| | | const getTypeTagType = type => { |
| | | const typeMap = { |
| | | è¾å¤§é£é©: "warning", |
| | | ä½é£é©: "info", |
| | | ä¸è¬é£é©: "info", |
| | | é大é£é©: "danger", |
| | | }; |
| | | return typeMap[type] || "info"; |
| | | }; |
| | | |
| | | // è·åç±»åæ ç¾ææ¬ |
| | | const getTypeLabel = type => { |
| | | return getKnowledgeTypeLabel(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] || "æªç¥"; |
| | | }; |
| | | |
| | | /** |
| | | * è·åè¡ç±»åï¼ç¨äºå¤æé£é©ç级æ¯å¦ä¸ºé大é£é© |
| | | * @param row è¡æ°æ® |
| | | * @returns ç±»å |
| | | */ |
| | | const getRowClass = ({ row }) => { |
| | | if (row.riskLevel === "é大é£é©") { |
| | | return "danger-row"; |
| | | } |
| | | return ""; |
| | | }; |
| | | |
| | | // æäº¤ç¥è¯è¡¨å |
| | | const submitForm = async () => { |
| | | try { |
| | | await formRef.value.validate(); |
| | | if (dialogType.value === "add") { |
| | | // æ°å¢å±é©æºå°è´¦ |
| | | safeHazardAdd({ ...form.value }) |
| | | .then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("æ·»å æå"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } else { |
| | | // æ´æ°å±é©æºå°è´¦ |
| | | safeHazardUpdate({ ...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); |
| | | safeHazardDel(selectedIds.value).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("å 餿å"); |
| | | selectedIds.value = []; |
| | | getList(); |
| | | } |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | // ç¨æ·åæ¶ |
| | | }); |
| | | }; |
| | | |
| | | // å¯¼åº |
| | | const { proxy } = getCurrentInstance(); |
| | | const { hazard_source_type } = proxy.useDict("hazard_source_type"); |
| | | |
| | | // åå
¸å·¥å
· |
| | | const knowledgeTypeOptions = computed(() => hazard_source_type?.value || []); |
| | | const getKnowledgeTypeLabel = val => { |
| | | const item = knowledgeTypeOptions.value.find( |
| | | i => String(i.value) === String(val) |
| | | ); |
| | | return item ? item.label : val; |
| | | }; |
| | | const getKnowledgeTypeTagType = val => { |
| | | const item = knowledgeTypeOptions.value.find( |
| | | i => String(i.value) === String(val) |
| | | ); |
| | | return item?.elTagType || "info"; |
| | | }; |
| | | const handleExport = () => { |
| | | proxy.download( |
| | | "/knowledgeBase/export", |
| | | { ...searchForm.value }, |
| | | "ç¥è¯åº.xlsx" |
| | | ); |
| | | }; |
| | | </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; |
| | | } |
| | | |
| | | :deep(.danger-row td) { |
| | | color: #e95a66 !important; |
| | | } |
| | | </style> |