| | |
| | | <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> |
| | | <span class="search_title">培训日期:</span> |
| | | <el-date-picker v-model="searchForm.trainingDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | @change="handleQuery" |
| | | type="date" |
| | | placeholder="请选择" |
| | | clearable /> |
| | | <el-button type="primary" |
| | | @click="handleQuery" |
| | | style="margin-left: 10px"> |
| | |
| | | <div> |
| | | <el-button type="primary" |
| | | @click="openForm('add')">新增培训</el-button> |
| | | <el-button type="primary" |
| | | @click="opendetail">培训记录</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleDelete">删除</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <el-tabs v-model="searchForm.state" |
| | | @tab-click="tabhandleQuery"> |
| | | <el-tab-pane label="未开始" |
| | | :name="0"></el-tab-pane> |
| | | <el-tab-pane label="进行中" |
| | | :name="1"></el-tab-pane> |
| | | <el-tab-pane label="已结束" |
| | | :name="2"></el-tab-pane> |
| | | </el-tabs> |
| | | <!-- state 状态(0:未开始1:进行中;2:已结束) --> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | |
| | | <el-form-item label="课程学分" |
| | | prop="projectCredits"> |
| | | <el-input v-model="form.projectCredits" |
| | | type="number" |
| | | min="0" |
| | | placeholder="请输入课程学分" /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | </el-dialog> |
| | | <!-- 查看知识详情弹窗 --> |
| | | <el-dialog v-model="viewDialogVisible" |
| | | title="培训详情" |
| | | 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-descriptions size="mini" |
| | | style="margin-left: 60px;" |
| | | :column="3"> |
| | | <el-descriptions-item label="课程编号:">{{ currentKnowledge.courseCode }}</el-descriptions-item> |
| | | <el-descriptions-item label="培训内容:">{{ currentKnowledge.trainingContent }}</el-descriptions-item> |
| | | <el-descriptions-item label="状态:"> |
| | | <el-tag :type="currentKnowledge.status === 0 ? 'success' : (currentKnowledge.status === 1 ? 'success' : 'info')"> |
| | | {{ currentKnowledge.status === 0 ? '未开始' : (currentKnowledge.status === 1 ? '进行中' : '已结束') }} |
| | | </el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="所在位置"> |
| | | {{ currentKnowledge.location }} |
| | | <el-descriptions-item label="培训讲师:"> |
| | | {{ currentKnowledge.trainingLecturer }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="管控措施"> |
| | | {{ currentKnowledge.controlMeasures }} |
| | | <el-descriptions-item label="培训开始时间:"> |
| | | {{ currentKnowledge.trainingDate + ' ' + currentKnowledge.openingTime }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="库存数量"> |
| | | {{ currentKnowledge.stockQty }} |
| | | <el-descriptions-item label="培训结束时间:"> |
| | | {{ currentKnowledge.trainingDate + ' ' + currentKnowledge.endTime }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="管控责任人"> |
| | | {{ currentKnowledge.principalUserId }} |
| | | <el-descriptions-item label="培训目标:"> |
| | | {{ currentKnowledge.trainingObjectives }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="责任人联系电话"> |
| | | {{ currentKnowledge.principalMobile }} |
| | | <el-descriptions-item label="参加对象:"> |
| | | {{ currentKnowledge.participants }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="风险等级"> |
| | | <el-tag :type="getTypeTagType(currentKnowledge.riskLevel)"> |
| | | {{ currentKnowledge.riskLevel }} |
| | | <el-descriptions-item label="培训方式:"> |
| | | <el-tag type="primary"> |
| | | {{ getTrainingModeLabel(currentKnowledge.trainingMode) }} |
| | | </el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="规格 / 风险描述"> |
| | | {{ currentKnowledge.specInfo }} |
| | | <el-descriptions-item label="培训地点:"> |
| | | {{ currentKnowledge.placeTraining }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="课时:"> |
| | | {{ currentKnowledge.classHour }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="课程学分:"> |
| | | {{ currentKnowledge.projectCredits }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="报名人数:"> |
| | | {{ currentKnowledge.nums }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="附件列表:"> |
| | | <el-button type="primary" |
| | | size="small" |
| | | @click="downLoadFile(endform)">附件列表</el-button> |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | <el-divider style="margin: 20px 0;" /> |
| | | <el-form ref="formRef" |
| | | :model="form" |
| | | :rules="rules" |
| | | label-width="130px"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="评价人:" |
| | | prop="courseCode"> |
| | | <el-input v-model="endform.assessmentUserName" |
| | | disabled |
| | | placeholder="请选择评价人" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="评价时间:" |
| | | prop="trainingDate"> |
| | | <el-date-picker style="width: 100%" |
| | | disabled |
| | | v-model="endform.assessmentDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="请选择" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="考核方式:" |
| | | prop="assessmentMethod"> |
| | | <el-input v-model="endform.assessmentMethod" |
| | | placeholder="请选择考核方式" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="本次课程综合评价:" |
| | | prop="comprehensiveAssessment"> |
| | | <el-input v-model="endform.comprehensiveAssessment" |
| | | placeholder="请输入本次课程综合评价" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="培训摘要:" |
| | | prop="trainingAbstract"> |
| | | <el-input v-model="endform.trainingAbstract" |
| | | type="textarea" |
| | | :rows="2" |
| | | placeholder="请输入培训摘要" /> |
| | | </el-form-item> |
| | | <!-- <el-row :gutter="30"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="附件材料:" |
| | | prop="remark"> |
| | | <el-upload v-model:file-list="fileList" |
| | | :action="upload.url" |
| | | multiple |
| | | ref="fileUpload" |
| | | auto-upload |
| | | :headers="upload.headers" |
| | | :before-upload="handleBeforeUpload" |
| | | :on-error="handleUploadError" |
| | | :on-success="handleUploadSuccess" |
| | | :on-remove="handleRemove"> |
| | | <el-button type="primary" |
| | | v-if="operationType !== 'view'">上传</el-button> |
| | | <template #tip |
| | | v-if="operationType !== 'view'"> |
| | | <div class="el-upload__tip"> |
| | | 文件格式支持 |
| | | doc,docx,xls,xlsx,ppt,pptx,pdf,txt,xml,jpg,jpeg,png,gif,bmp,rar,zip,7z |
| | | </div> |
| | | </template> |
| | | </el-upload> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> --> |
| | | </el-form> |
| | | <el-table style="margin-top: 20px;" |
| | | :data="endform.safeTrainingDetailsDtoList" |
| | | border |
| | | fit |
| | | highlight-current-row> |
| | | <el-table-column prop="nickName" |
| | | label="姓名" /> |
| | | <el-table-column prop="phonenumber" |
| | | label="电话号码" /> |
| | | <el-table-column prop="examinationResults" |
| | | label="考核结果"> |
| | | <template #default="scope"> |
| | | <el-select v-model="scope.row.examinationResults" |
| | | placeholder="请选择考核结果"> |
| | | <el-option label="合格" |
| | | value="合格" /> |
| | | <el-option label="不合格" |
| | | value="不合格" /> |
| | | </el-select> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitForm2">提交</el-button> |
| | | <el-button @click="viewDialogVisible = false">关闭</el-button> |
| | | </span> |
| | | </template> |
| | |
| | | safeTrainingFileListPage, |
| | | safeTrainingFileAdd, |
| | | safeTrainingFileDel, |
| | | safeTrainingSign, |
| | | safeTrainingGet, |
| | | safeTrainingSave, |
| | | } from "@/api/safeProduction/safetyTrainingAssessment.js"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import dayjs from "dayjs"; |
| | | const userStore = useUserStore(); |
| | | |
| | | // 表单验证规则 |
| | | const rules = { |
| | |
| | | ], |
| | | classHour: [{ required: true, message: "请输入课时", trigger: "blur" }], |
| | | }; |
| | | |
| | | const upload = reactive({ |
| | | // 上传的地址 |
| | | url: import.meta.env.VITE_APP_BASE_API + "/file/upload", |
| | | // 设置上传的请求头部 |
| | | headers: { Authorization: "Bearer " + getToken() }, |
| | | }); |
| | | // 响应式数据 |
| | | const data = reactive({ |
| | | searchForm: { |
| | | name: "", |
| | | type: "", |
| | | trainingDate: "", |
| | | state: 0, |
| | | }, |
| | | tableLoading: false, |
| | | page: { |
| | |
| | | ); |
| | | return item ? item.label : val; |
| | | }; |
| | | // 切换tab查询 |
| | | const tabhandleQuery = val => { |
| | | searchForm.value.state = val.paneName; |
| | | console.log(searchForm.value.state, "searchForm.value.state"); |
| | | |
| | | handleQuery(); |
| | | }; |
| | | // 表单引用 |
| | | const formRef = ref(); |
| | | const riskLevelOptions = ref([ |
| | |
| | | { value: "重大风险", label: "重大风险" }, |
| | | ]); |
| | | |
| | | const fileList = ref([]); |
| | | |
| | | // 表格列配置 |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "课程编号", |
| | | prop: "courseCode", |
| | | width: 150, |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "培训日期", |
| | | prop: "trainingDate", |
| | | width: 120, |
| | | |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "开始时间", |
| | | prop: "openingTime", |
| | | width: 120, |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "结束时间", |
| | | prop: "endTime", |
| | | width: 120, |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "培训目标", |
| | | prop: "trainingObjectives", |
| | | width: 200, |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "参加对象", |
| | | prop: "participants", |
| | | width: 200, |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "培训内容", |
| | | prop: "trainingContent", |
| | | width: 200, |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "培训讲师", |
| | | prop: "trainingLecturer", |
| | | width: 200, |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "项目学分", |
| | | prop: "projectCredits", |
| | | width: 120, |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "培训方式", |
| | | prop: "trainingMode", |
| | | width: 120, |
| | | showOverflowTooltip: true, |
| | | formatData: params => { |
| | | return getTrainingModeLabel(params); |
| | |
| | | { |
| | | label: "培训地点", |
| | | prop: "placeTraining", |
| | | width: 200, |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "课时", |
| | | prop: "classHour", |
| | | width: 120, |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "报名人数", |
| | | prop: "nums", |
| | | width: 120, |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | |
| | | label: "操作", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 200, |
| | | width: 300, |
| | | operation: [ |
| | | { |
| | | name: "签到", |
| | | type: "text", |
| | | disabled: row => row.state !== 1, |
| | | clickFun: row => { |
| | | signIn(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "编辑", |
| | | type: "text", |
| | | disabled: row => row.state !== 0, |
| | | clickFun: row => { |
| | | openForm("edit", row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "导出", |
| | | type: "danger", |
| | | type: "text", |
| | | clickFun: row => { |
| | | exportKnowledge(row); |
| | | }, |
| | | color: "#C49000", |
| | | }, |
| | | { |
| | | name: "附件", |
| | | type: "danger", |
| | | type: "text", |
| | | clickFun: row => { |
| | | downLoadFile(row); |
| | | }, |
| | | color: "#007AFF", |
| | | }, |
| | | |
| | | { |
| | | name: "结果明细", |
| | | type: "text", |
| | | // disabled: row => row.state !== 2, |
| | | clickFun: row => { |
| | | viewResultDetail(row); |
| | | }, |
| | | }, |
| | | // { |
| | |
| | | const userList = ref([]); |
| | | // 生命周期 |
| | | onMounted(() => { |
| | | getCurrentFactoryName(); |
| | | getList(); |
| | | startAutoRefresh(); |
| | | userListNoPage().then(res => { |
| | | userList.value = res.data; |
| | | }); |
| | | }); |
| | | const endform = ref({ |
| | | assessmentUserId: "", //评价人 |
| | | assessmentUserName: "", //评价人姓名 |
| | | assessmentMethod: "", //考核方式 |
| | | assessmentDate: "", //评价时间 |
| | | comprehensiveAssessment: "", //综合评价 |
| | | trainingAbstract: "", //培训摘要 |
| | | safeTrainingFileList: [], //培训附件 |
| | | safeTrainingDetailsDtoList: [], //考核结果详情 |
| | | }); |
| | | const operationType = ref("edit"); |
| | | const viewResultDetail = row => { |
| | | // fileList.value = []; |
| | | operationType.value = "edit"; |
| | | safeTrainingGet({ id: row.id }).then(res => { |
| | | if (res.code === 200) { |
| | | console.log(res.data, "res.data"); |
| | | currentKnowledge.value = JSON.parse(JSON.stringify(res.data)); |
| | | currentKnowledge.value.nums = row.nums; |
| | | viewDialogVisible.value = true; |
| | | endform.value = { ...res.data }; |
| | | endform.value.assessmentUserName = endform.value.assessmentUserName |
| | | ? endform.value.assessmentUserName |
| | | : currentUserName.value; |
| | | endform.value.assessmentUserId = endform.value.assessmentUserId |
| | | ? endform.value.assessmentUserId |
| | | : currentUserId.value; |
| | | endform.value.assessmentDate = dayjs().format("YYYY-MM-DD"); |
| | | } else { |
| | | proxy.$modal.msgError(res.msg || "查询详情失败"); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // 上传前校检 |
| | | function handleBeforeUpload(file) { |
| | | proxy.$modal.loading("正在上传文件,请稍候..."); |
| | | return true; |
| | | } |
| | | // 上传失败 |
| | | function handleUploadError(err) { |
| | | proxy.$modal.msgError("上传文件失败"); |
| | | proxy.$modal.closeLoading(); |
| | | } |
| | | // 上传成功回调 |
| | | function handleUploadSuccess(res, file, uploadFiles) { |
| | | proxy.$modal.closeLoading(); |
| | | if (res.code === 200) { |
| | | // 确保 tempFileIds 存在且为数组 |
| | | if (!endform.value.safeTrainingFileList) { |
| | | endform.value.safeTrainingFileList = []; |
| | | } |
| | | endform.value.safeTrainingFileList.push({ |
| | | id: res.data.tempId, |
| | | fileName: res.data.originalName, |
| | | url: res.data.tempPath, |
| | | safeTrainingId: currentKnowledge.value.id, |
| | | }); |
| | | proxy.$modal.msgSuccess("上传成功"); |
| | | } else { |
| | | proxy.$modal.msgError(res.msg); |
| | | proxy.$refs.fileUpload.handleRemove(file); |
| | | } |
| | | } |
| | | // 移除文件 |
| | | function handleRemove(file) { |
| | | if (operationType.value === "edit") { |
| | | let index = endform.value.safeTrainingFileList.findIndex( |
| | | item => item.fileName === file.name |
| | | ); |
| | | if (index !== -1) { |
| | | endform.value.safeTrainingFileList.splice(index, 1); |
| | | } |
| | | } |
| | | } |
| | | const submitForm2 = () => { |
| | | endform.value.safeTrainingDetailsDtoList.forEach((item, index) => { |
| | | if (!item.examinationResults) { |
| | | proxy.$modal.msgError(`请选择${item.nickName}的考核结果`); |
| | | return; |
| | | } |
| | | }); |
| | | console.log(endform.value, "endform.value"); |
| | | proxy.$modal.loading("正在提交,请稍候..."); |
| | | safeTrainingSave(endform.value).then(res => { |
| | | proxy.$modal.closeLoading(); |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess("提交成功"); |
| | | getList(); |
| | | viewDialogVisible.value = false; |
| | | } else { |
| | | proxy.$modal.msgError(res.msg || "提交失败"); |
| | | } |
| | | }); |
| | | }; |
| | | const opendetail = row => { |
| | | proxy.$router.push({ |
| | | path: "/safeProduction/safetyTrainingAssessmentDetail", |
| | | }); |
| | | }; |
| | | |
| | | const signIn = row => { |
| | | ElMessageBox.confirm("确认签到吗?", "提示", { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }).then(() => { |
| | | safeTrainingSign({ |
| | | safeTrainingId: row.id, |
| | | userId: currentUserId.value, |
| | | }).then(res => { |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess("签到成功"); |
| | | getList(); |
| | | } else { |
| | | proxy.$modal.msgError(res.msg || "签到失败"); |
| | | } |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | | // 处理用户选择变化 |
| | | const handleUserChange = userId => { |
| | |
| | | const url = window.URL.createObjectURL(blob); |
| | | const link = document.createElement("a"); |
| | | link.href = url; |
| | | link.download = `培训记录_${row.courseCode}.xlsx`; |
| | | link.download = `培训记录_${row.courseCode}.docx`; |
| | | |
| | | // 模拟点击下载 |
| | | document.body.appendChild(link); |
| | |
| | | const handleSelectionChange = selection => { |
| | | selectedIds.value = selection.map(item => item.id); |
| | | }; |
| | | const currentUserId = ref(""); |
| | | const currentUserName = ref(""); |
| | | const getCurrentFactoryName = async () => { |
| | | let res = await userStore.getInfo(); |
| | | currentUserId.value = res.user.userId; |
| | | currentUserName.value = res.user.nickName; |
| | | }; |
| | | |
| | | // 打开表单 |
| | | const openForm = (type, row = null) => { |
| | |
| | | }); |
| | | } |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | // 查看培训详情 |
| | | const viewKnowledge = row => { |
| | | currentKnowledge.value = { ...row }; |
| | | viewDialogVisible.value = true; |
| | | }; |
| | | |
| | | // 获取类型标签类型 |