<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 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="trainingDate">
|
<el-date-picker style="width: 100%"
|
v-model="form.trainingDate"
|
value-format="YYYY-MM-DD"
|
format="YYYY-MM-DD"
|
type="date"
|
placeholder="请选择"
|
clearable />
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="课程编号"
|
prop="courseCode">
|
<el-input v-model="form.courseCode"
|
disabled
|
placeholder="自动生成" />
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="开始时间"
|
prop="openingTime">
|
<el-time-picker v-model="form.openingTime"
|
placeholder="请选择"
|
value-format="HH:mm:ss"
|
format="HH:mm:ss"
|
clearable />
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="结束时间"
|
prop="endTime">
|
<el-time-picker v-model="form.endTime"
|
placeholder="请选择"
|
value-format="HH:mm:ss"
|
format="HH:mm:ss"
|
clearable />
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="培训目标"
|
prop="trainingObjectives">
|
<el-input v-model="form.trainingObjectives"
|
placeholder="请输入培训目标" />
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="参加对象"
|
prop="participants">
|
<el-input v-model="form.participants"
|
placeholder="请输入参加对象" />
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="培训内容"
|
prop="trainingContent">
|
<el-input v-model="form.trainingContent"
|
placeholder="请输入培训内容" />
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="培训讲师"
|
prop="trainingLecturer">
|
<el-input v-model="form.trainingLecturer"
|
placeholder="请输入培训讲师" />
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="课程学分"
|
prop="projectCredits">
|
<el-input v-model="form.projectCredits"
|
placeholder="请输入课程学分" />
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="培训方式"
|
prop="trainingMode">
|
<el-select v-model="form.trainingMode"
|
placeholder="请选择培训方式"
|
clearable>
|
<el-option v-for="item in trainingModeOptions"
|
:key="item.value"
|
:label="item.label"
|
:value="item.value" />
|
</el-select>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="培训地点"
|
prop="placeTraining">
|
<el-input v-model="form.placeTraining"
|
placeholder="请输入培训地点" />
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="课时"
|
prop="classHour">
|
<el-input v-model="form.classHour"
|
type="number"
|
min="0"
|
placeholder="请输入课时" />
|
</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.name }}</span>
|
</el-descriptions-item>
|
<el-descriptions-item label="培训编码">
|
{{ currentKnowledge.code }}
|
</el-descriptions-item>
|
<el-descriptions-item label="培训类型">
|
<el-tag type="info">
|
<!-- {{ getTypeLabel(currentKnowledge.type) }} -->
|
</el-tag>
|
</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>
|
<!-- 附件列表弹窗 -->
|
<FileListDialog ref="fileListRef"
|
v-model="fileListDialogVisible"
|
:show-upload-button="true"
|
:show-delete-button="true"
|
:upload-method="handleUpload"
|
:delete-method="handleFileDelete"
|
title="附件列表" />
|
</div>
|
</template>
|
|
<script setup>
|
import { Search } from "@element-plus/icons-vue";
|
import FileListDialog from "@/components/Dialog/FileListDialog.vue";
|
import {
|
onMounted,
|
ref,
|
reactive,
|
toRefs,
|
getCurrentInstance,
|
computed,
|
} from "vue";
|
import request from "@/utils/request";
|
import { getToken } from "@/utils/auth";
|
import { ElMessage, ElMessageBox } from "element-plus";
|
import PIMTable from "@/components/PIMTable/PIMTable.vue";
|
import { userListNoPage } from "@/api/system/user.js";
|
import {
|
safeTrainingListPage,
|
safeTrainingAdd,
|
safeTrainingExport,
|
safeTrainingDel,
|
safeTrainingFileListPage,
|
safeTrainingFileAdd,
|
safeTrainingFileDel,
|
} from "@/api/safeProduction/safetyTrainingAssessment.js";
|
|
// 表单验证规则
|
const rules = {
|
trainingDate: [
|
{ required: true, message: "请选择培训日期", trigger: "change" },
|
],
|
openingTime: [
|
{ required: true, message: "请选择开始时间", trigger: "change" },
|
],
|
endTime: [{ required: true, message: "请选择结束时间", trigger: "change" }],
|
trainingContent: [
|
{ required: true, message: "请输入培训内容", trigger: "blur" },
|
],
|
trainingLecturer: [
|
{ required: true, message: "请输入培训讲师", trigger: "blur" },
|
],
|
classHour: [{ required: true, message: "请输入课时", trigger: "blur" }],
|
};
|
|
// 响应式数据
|
const data = reactive({
|
searchForm: {
|
name: "",
|
type: "",
|
},
|
tableLoading: false,
|
page: {
|
current: 1,
|
size: 20,
|
total: 0,
|
},
|
tableData: [],
|
selectedIds: [],
|
form: {
|
courseCode: "", // 课程编号
|
trainingDate: "", // 培训日期
|
openingTime: "", // 开始时间
|
endTime: "", // 结束时间
|
trainingObjectives: "", // 培训目标
|
participants: "", // 参加对象
|
trainingContent: "", // 培训内容
|
trainingLecturer: "", // 培训讲师
|
projectCredits: "", // 项目学分
|
trainingMode: "", // 培训方式
|
placeTraining: "", // 培训地点
|
classHour: "", // 课时
|
},
|
dialogVisible: false,
|
dialogTitle: "",
|
dialogType: "add",
|
viewDialogVisible: false,
|
currentKnowledge: {},
|
});
|
|
const {
|
searchForm,
|
tableLoading,
|
page,
|
tableData,
|
selectedIds,
|
form,
|
dialogVisible,
|
dialogTitle,
|
dialogType,
|
viewDialogVisible,
|
currentKnowledge,
|
} = toRefs(data);
|
const { proxy } = getCurrentInstance();
|
const { safe_training_methods } = proxy.useDict("safe_training_methods");
|
const trainingModeOptions = computed(() => safe_training_methods?.value || []);
|
const getTrainingModeLabel = val => {
|
const item = trainingModeOptions.value.find(
|
i => String(i.value) === String(val)
|
);
|
return item ? item.label : val;
|
};
|
// 表单引用
|
const formRef = ref();
|
const riskLevelOptions = ref([
|
{ value: "低风险", label: "低风险" },
|
{ value: "一般风险", label: "一般风险" },
|
{ value: "较大风险", label: "较大风险" },
|
{ value: "重大风险", label: "重大风险" },
|
]);
|
|
// 表格列配置
|
const tableColumn = ref([
|
{
|
label: "课程编号",
|
prop: "courseCode",
|
showOverflowTooltip: true,
|
},
|
{
|
label: "培训日期",
|
prop: "trainingDate",
|
showOverflowTooltip: true,
|
},
|
{
|
label: "开始时间",
|
prop: "openingTime",
|
showOverflowTooltip: true,
|
},
|
{
|
label: "结束时间",
|
prop: "endTime",
|
showOverflowTooltip: true,
|
},
|
{
|
label: "培训目标",
|
prop: "trainingObjectives",
|
showOverflowTooltip: true,
|
},
|
{
|
label: "参加对象",
|
prop: "participants",
|
showOverflowTooltip: true,
|
},
|
{
|
label: "培训内容",
|
prop: "trainingContent",
|
showOverflowTooltip: true,
|
},
|
{
|
label: "培训讲师",
|
prop: "trainingLecturer",
|
showOverflowTooltip: true,
|
},
|
{
|
label: "项目学分",
|
prop: "projectCredits",
|
showOverflowTooltip: true,
|
},
|
{
|
label: "培训方式",
|
prop: "trainingMode",
|
showOverflowTooltip: true,
|
formatData: params => {
|
return getTrainingModeLabel(params);
|
},
|
},
|
{
|
label: "培训地点",
|
prop: "placeTraining",
|
showOverflowTooltip: true,
|
},
|
{
|
label: "课时",
|
prop: "classHour",
|
showOverflowTooltip: true,
|
},
|
{
|
dataType: "action",
|
label: "操作",
|
align: "center",
|
fixed: "right",
|
width: 200,
|
operation: [
|
{
|
name: "编辑",
|
type: "text",
|
clickFun: row => {
|
openForm("edit", row);
|
},
|
},
|
{
|
name: "导出",
|
type: "danger",
|
clickFun: row => {
|
exportKnowledge(row);
|
},
|
},
|
{
|
name: "附件",
|
type: "danger",
|
clickFun: row => {
|
downLoadFile(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;
|
}
|
};
|
/**
|
* 下载文件
|
*
|
* @param row 下载文件的相关信息对象
|
*/
|
const fileListRef = ref(null);
|
const fileListDialogVisible = ref(false);
|
const currentFileRow = ref(null);
|
const downLoadFile = row => {
|
currentFileRow.value = row;
|
safeTrainingFileListPage({ safeTrainingId: row.id }).then(res => {
|
if (fileListRef.value) {
|
fileListRef.value.open(res.data.records);
|
}
|
});
|
};
|
// 上传附件
|
const handleUpload = async () => {
|
if (!currentFileRow.value) {
|
proxy.$modal.msgWarning("请先选择数据");
|
return null;
|
}
|
|
return new Promise(resolve => {
|
// 创建一个隐藏的文件输入元素
|
const input = document.createElement("input");
|
input.type = "file";
|
input.style.display = "none";
|
input.onchange = async e => {
|
const file = e.target.files[0];
|
if (!file) {
|
resolve(null);
|
return;
|
}
|
|
try {
|
// 使用 FormData 上传文件
|
const formData = new FormData();
|
formData.append("file", file);
|
|
const uploadRes = await request({
|
url: "/file/upload",
|
method: "post",
|
data: formData,
|
headers: {
|
"Content-Type": "multipart/form-data",
|
Authorization: `Bearer ${getToken()}`,
|
},
|
});
|
|
if (uploadRes.code === 200) {
|
// 保存附件信息
|
const fileData = {
|
safeTrainingId: currentFileRow.value.id,
|
name: uploadRes.data.originalName || file.name,
|
url: uploadRes.data.tempPath || uploadRes.data.url,
|
};
|
|
const saveRes = await safeTrainingFileAdd(fileData);
|
if (saveRes.code === 200) {
|
proxy.$modal.msgSuccess("文件上传成功");
|
// 重新加载文件列表
|
const listRes = await safeTrainingFileListPage({
|
safeTrainingId: currentFileRow.value.id,
|
});
|
if (listRes.code === 200 && fileListRef.value) {
|
const fileList = (listRes.data?.records || []).map(item => ({
|
name: item.name,
|
url: item.url,
|
id: item.id,
|
...item,
|
}));
|
fileListRef.value.setList(fileList);
|
}
|
// 返回新文件信息
|
resolve({
|
name: fileData.name,
|
url: fileData.url,
|
id: saveRes.data?.id,
|
});
|
} else {
|
proxy.$modal.msgError(saveRes.msg || "文件保存失败");
|
resolve(null);
|
}
|
} else {
|
proxy.$modal.msgError(uploadRes.msg || "文件上传失败");
|
resolve(null);
|
}
|
} catch (error) {
|
proxy.$modal.msgError("文件上传失败");
|
resolve(null);
|
} finally {
|
document.body.removeChild(input);
|
}
|
};
|
|
document.body.appendChild(input);
|
input.click();
|
});
|
};
|
// 删除附件
|
const handleFileDelete = async row => {
|
try {
|
const res = await safeTrainingFileDel([row.id]);
|
if (res.code === 200) {
|
proxy.$modal.msgSuccess("删除成功");
|
// 重新加载文件列表
|
if (currentFileRow.value && fileListRef.value) {
|
const listRes = await safeTrainingFileListPage({
|
safeTrainingId: currentFileRow.value.id,
|
});
|
if (listRes.code === 200) {
|
const fileList = (listRes.data?.records || []).map(item => ({
|
name: item.name,
|
url: item.url,
|
id: item.id,
|
...item,
|
}));
|
fileListRef.value.setList(fileList);
|
}
|
}
|
return true; // 返回 true 表示删除成功,组件会更新列表
|
} else {
|
proxy.$modal.msgError(res.msg || "删除失败");
|
return false;
|
}
|
} catch (error) {
|
proxy.$modal.msgError("删除失败");
|
return false;
|
}
|
};
|
|
// 开始自动刷新
|
const startAutoRefresh = () => {
|
setInterval(() => {
|
getList();
|
}, 600000); // 10分钟刷新一次 (10 * 60 * 1000 = 600000ms)
|
};
|
|
// 查询数据
|
const handleQuery = () => {
|
page.value.current = 1;
|
getList();
|
};
|
const exportKnowledge = row => {
|
safeTrainingExport(row)
|
.then(res => {
|
// 创建Blob对象
|
const blob = new Blob([res], {
|
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
});
|
// 创建下载链接
|
const url = window.URL.createObjectURL(blob);
|
const link = document.createElement("a");
|
link.href = url;
|
link.download = `培训记录_${row.courseCode}.xlsx`;
|
|
// 模拟点击下载
|
document.body.appendChild(link);
|
link.click();
|
|
// 清理临时对象
|
setTimeout(() => {
|
document.body.removeChild(link);
|
window.URL.revokeObjectURL(url);
|
}, 100);
|
|
ElMessage.success("导出成功");
|
})
|
.catch(err => {
|
console.error("导出失败:", err);
|
ElMessage.error("导出失败,请重试");
|
});
|
};
|
const getList = () => {
|
tableLoading.value = true;
|
safeTrainingListPage({ ...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, {
|
courseCode: "", // 课程编号
|
trainingDate: "", // 培训日期
|
openingTime: "", // 开始时间
|
endTime: "", // 结束时间
|
trainingObjectives: "", // 培训目标
|
participants: "", // 参加对象
|
trainingContent: "", // 培训内容
|
trainingLecturer: "", // 培训讲师
|
projectCredits: "", // 项目学分
|
trainingMode: "", // 培训方式
|
placeTraining: "", // 培训地点
|
classHour: "", // 课时
|
});
|
} else if (type === "edit" && row) {
|
dialogTitle.value = "编辑培训";
|
Object.assign(form.value, {
|
id: row.id,
|
courseCode: row.courseCode, // 课程编号
|
trainingDate: row.trainingDate, // 培训日期
|
openingTime: row.openingTime, // 开始时间
|
endTime: row.endTime, // 结束时间
|
trainingObjectives: row.trainingObjectives, // 培训目标
|
participants: row.participants, // 参加对象
|
trainingContent: row.trainingContent, // 培训内容
|
trainingLecturer: row.trainingLecturer, // 培训讲师
|
projectCredits: row.projectCredits, // 项目学分
|
trainingMode: row.trainingMode, // 培训方式
|
placeTraining: row.placeTraining, // 培训地点
|
classHour: row.classHour, // 课时
|
});
|
}
|
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 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") {
|
// 新增培训台账
|
safeTrainingAdd({ ...form.value })
|
.then(res => {
|
if (res.code == 200) {
|
ElMessage.success("添加成功");
|
dialogVisible.value = false;
|
getList();
|
}
|
})
|
.catch(err => {
|
ElMessage.error(err.msg);
|
});
|
} else {
|
// 更新培训台账
|
safeTrainingAdd({ ...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);
|
safeTrainingDel(selectedIds.value).then(res => {
|
if (res.code == 200) {
|
ElMessage.success("删除成功");
|
selectedIds.value = [];
|
getList();
|
}
|
});
|
})
|
.catch(() => {
|
// 用户取消
|
});
|
};
|
|
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>
|