| | |
| | | }); |
| | | } |
| | | |
| | | export function specialEquipmentRectificationUpdate(data) { |
| | | return request({ |
| | | url: "/safe/specialEquipment/rectification/update", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | } |
| | | |
| | | export function specialEquipmentRectificationClose(data) { |
| | | return request({ |
| | | url: "/safe/specialEquipment/rectification/close", |
| | |
| | | <template v-for="(o, key) in item.operation" |
| | | :key="key"> |
| | | <el-button v-show="o.type != 'upload'" |
| | | v-if="o.showHide ? o.showHide(scope.row) : true" |
| | | v-if="isOperationVisible(o, scope.row)" |
| | | :disabled="isOperationDisabled(o, scope.row)" |
| | | :loading="isOperationLoading(o, scope.row)" |
| | | :plain="o.plain" |
| | |
| | | " |
| | | v-if="o.type == 'upload'" |
| | | style="display: inline-block; width: 50px" |
| | | v-show="o.showHide ? o.showHide(scope.row) : true" |
| | | v-show="isOperationVisible(o, scope.row)" |
| | | :headers="uploadHeader" |
| | | :before-upload="(file) => beforeUpload(file, scope.$index)" |
| | | :on-change=" |
| | |
| | | }; |
| | | |
| | | const formatters = (val, format) => { |
| | | return typeof format === "function" ? format(val) : val; |
| | | if (typeof format === "function") return format(val); |
| | | if (format && typeof format === "object") return format[val] ?? val; |
| | | return val; |
| | | }; |
| | | |
| | | // Props(使用 defineProps 的非 TS 形式) |
| | |
| | | : !!operation.disabled; |
| | | }; |
| | | |
| | | const isOperationVisible = (operation, row) => { |
| | | const visibleHandler = operation?.showHide ?? operation?.show; |
| | | if (visibleHandler === undefined) return true; |
| | | return typeof visibleHandler === "function" ? !!visibleHandler(row) : !!visibleHandler; |
| | | }; |
| | | |
| | | const isOperationLoading = (operation, row) => { |
| | | if (!operation?.loading) return false; |
| | | return typeof operation.loading === "function" |
| | |
| | | // 文件上传前校验 |
| | | const beforeUpload = (rawFile, index) => { |
| | | currentFiles.value[index] = {}; |
| | | if (rawfile.size > 1024 * 1024 * 10 * 10) { |
| | | if (rawFile.size > 1024 * 1024 * 10 * 10) { |
| | | ElMessage.error("上传文件不超过10M"); |
| | | return false; |
| | | } |
| | |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="checkDesc" label="检查说明" width="200" show-overflow-tooltip /> |
| | | <el-table-column label="现场照片" width="100"> |
| | | <template #default="{ row }"> |
| | | <el-tag :type="hasAttachments(row.storageBlobVOs) ? 'success' : 'info'"> |
| | | {{ hasAttachments(row.storageBlobVOs) ? '已上传' : '未上传' }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="checkTime" label="检查时间" width="180" /> |
| | | <el-table-column label="操作" width="120" fixed="right"> |
| | | <template #default="{ row }"> |
| | |
| | | type="textarea" |
| | | :rows="2" |
| | | placeholder="请输入检查说明" /> |
| | | </el-form-item> |
| | | <el-form-item v-if="recordForm.checkResult === '异常'" label="现场照片"> |
| | | <ImageUpload v-model:file-list="recordForm.storageBlobDTOs" |
| | | :limit="6" |
| | | button-text="上传照片" /> |
| | | </el-form-item> |
| | | <el-form-item label="检查时间"> |
| | | <el-date-picker v-model="recordForm.checkTime" |
| | |
| | | |
| | | <script setup> |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { nextTick, onMounted, ref, reactive, toRefs } from "vue"; |
| | | import { onMounted, ref, reactive, toRefs } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | | import ImageUpload from "@/components/AttachmentUpload/image/index.vue"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | import { |
| | | getLineInspectionList, |
| | |
| | | checkContent: "", |
| | | checkResult: "正常", |
| | | checkDesc: "", |
| | | checkTime: "" |
| | | checkTime: "", |
| | | storageBlobDTOs: [] |
| | | }, |
| | | // 隐患管理 |
| | | hazardDialogVisible: false, |
| | |
| | | return map[status] || "info"; |
| | | }; |
| | | |
| | | const getAttachments = row => row?.storageBlobDTOs || row?.storageBlobVOs || []; |
| | | const hasAttachments = attachments => Array.isArray(attachments) && attachments.length > 0; |
| | | |
| | | // 打开表单 |
| | | const openForm = (type, row = null) => { |
| | | dialogType.value = type; |
| | |
| | | checkContent: "", |
| | | checkResult: "正常", |
| | | checkDesc: "", |
| | | checkTime: "" |
| | | checkTime: "", |
| | | storageBlobDTOs: [] |
| | | }); |
| | | recordFormVisible.value = true; |
| | | }; |
| | |
| | | checkContent: row.checkContent, |
| | | checkResult: row.checkResult, |
| | | checkDesc: row.checkDesc, |
| | | checkTime: row.checkTime |
| | | checkTime: row.checkTime, |
| | | storageBlobDTOs: getAttachments(row) |
| | | }); |
| | | recordFormVisible.value = true; |
| | | }; |
| | |
| | | const submitRecordForm = async () => { |
| | | try { |
| | | await recordFormRef.value.validate(); |
| | | if (recordForm.value.checkResult === "异常" && !hasAttachments(recordForm.value.storageBlobDTOs)) { |
| | | ElMessage.warning("巡检结果异常时请上传现场照片"); |
| | | return; |
| | | } |
| | | const api = recordForm.value.id ? updateInspectionRecord : addInspectionRecord; |
| | | const res = await api({ ...recordForm.value }); |
| | | if (res.code === 200) { |
| | |
| | | <el-form-item label="巡检编号" |
| | | prop="inspectionCode"> |
| | | <el-input v-model="inspectionForm.inspectionCode" |
| | | placeholder="请输入巡检编号" /> |
| | | placeholder="请输入巡检编号" |
| | | :disabled="isInspectionView" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | |
| | | prop="inspectionType"> |
| | | <el-select v-model="inspectionForm.inspectionType" |
| | | placeholder="请选择巡检类型" |
| | | style="width: 100%"> |
| | | style="width: 100%" |
| | | :disabled="isInspectionView"> |
| | | <el-option label="定期巡检" value="定期巡检" /> |
| | | <el-option label="临时巡检" value="临时巡检" /> |
| | | </el-select> |
| | |
| | | placeholder="请选择计划巡检时间" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | style="width: 100%" /> |
| | | style="width: 100%" |
| | | :disabled="isInspectionView" /> |
| | | </el-form-item> |
| | | <template v-if="inspectionDialogTitle === '巡检'"> |
| | | <template v-if="inspectionDialogType !== 'add'"> |
| | | <el-form-item label="检查结果" |
| | | prop="checkResult"> |
| | | <el-radio-group v-model="inspectionForm.checkResult"> |
| | | <el-radio-group v-model="inspectionForm.checkResult" :disabled="isInspectionView"> |
| | | <el-radio label="正常">正常</el-radio> |
| | | <el-radio label="异常">异常</el-radio> |
| | | </el-radio-group> |
| | |
| | | <el-input v-model="inspectionForm.checkDesc" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请输入检查说明" /> |
| | | placeholder="请输入检查说明" |
| | | :disabled="isInspectionView" /> |
| | | </el-form-item> |
| | | <el-form-item v-if="inspectionForm.checkResult === '异常'" label="现场照片"> |
| | | <ImageUpload v-model:file-list="inspectionForm.storageBlobDTOs" |
| | | :limit="6" |
| | | button-text="上传照片" |
| | | :disabled="isInspectionView" /> |
| | | </el-form-item> |
| | | </template> |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" |
| | | <el-button v-if="!isInspectionView" |
| | | type="primary" |
| | | @click="submitInspectionForm">确定</el-button> |
| | | <el-button @click="inspectionDialogVisible = false">取消</el-button> |
| | | <el-button @click="inspectionDialogVisible = false">{{ isInspectionView ? '关闭' : '取消' }}</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | <el-input v-model="rectificationForm.problemDesc" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请输入问题描述" /> |
| | | placeholder="请输入问题描述" |
| | | :disabled="isRectificationView" /> |
| | | </el-form-item> |
| | | <el-form-item label="问题等级"> |
| | | <el-select v-model="rectificationForm.problemLevel" |
| | | placeholder="请选择问题等级" |
| | | style="width: 100%"> |
| | | style="width: 100%" |
| | | :disabled="isRectificationView"> |
| | | <el-option label="一般" value="一般" /> |
| | | <el-option label="重大" value="重大" /> |
| | | </el-select> |
| | |
| | | placeholder="请选择计划整改时间" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | style="width: 100%" /> |
| | | style="width: 100%" |
| | | :disabled="isRectificationView" /> |
| | | </el-form-item> |
| | | </template> |
| | | <el-form-item label="整改说明" v-if="rectificationDialogTitle === '整改'"> |
| | | <el-input v-model="rectificationForm.rectifyDesc" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请输入整改说明" /> |
| | | placeholder="请输入整改说明" |
| | | :disabled="isRectificationView" /> |
| | | </el-form-item> |
| | | <el-form-item label="验收说明" v-if="rectificationDialogTitle === '验收'"> |
| | | <el-input v-model="rectificationForm.verifyDesc" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请输入验收说明" /> |
| | | placeholder="请输入验收说明" |
| | | :disabled="isRectificationView" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" |
| | | <el-button v-if="!isRectificationView" |
| | | type="primary" |
| | | @click="submitRectificationForm">确定</el-button> |
| | | <el-button @click="rectificationDialogVisible = false">取消</el-button> |
| | | <el-button @click="rectificationDialogVisible = false">{{ isRectificationView ? '关闭' : '取消' }}</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | import { onMounted, ref, reactive, toRefs, computed } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | | import ImageUpload from "@/components/AttachmentUpload/image/index.vue"; |
| | | import { |
| | | getFacilityLedgerList, |
| | | addFacilityLedger, |
| | |
| | | inspectionTableData: [], |
| | | inspectionForm: { |
| | | id: null, facilityId: null, inspectionCode: "", inspectionType: "定期巡检", |
| | | planTime: "", checkResult: "", checkDesc: "" |
| | | planTime: "", checkResult: "", checkDesc: "", storageBlobDTOs: [] |
| | | }, |
| | | inspectionDialogVisible: false, |
| | | inspectionDialogTitle: "", |
| | |
| | | const ledgerFormRef = ref(); |
| | | const inspectionFormRef = ref(); |
| | | const rectificationFormRef = ref(); |
| | | const isInspectionView = computed(() => inspectionDialogType.value === "view"); |
| | | const isRectificationView = computed(() => rectificationDialogType.value === "view"); |
| | | |
| | | // 自动计算下次检查时间 |
| | | const computedNextCheckTime = computed(() => { |
| | |
| | | inspectionDialogTitle.value = "发起巡检"; |
| | | Object.assign(inspectionForm.value, { |
| | | id: null, facilityId: row.id, inspectionCode: "", inspectionType: "定期巡检", |
| | | planTime: "", checkResult: "", checkDesc: "" |
| | | planTime: "", checkResult: "", checkDesc: "", storageBlobDTOs: [] |
| | | }); |
| | | } else if (type === "do") { |
| | | inspectionDialogTitle.value = "巡检"; |
| | | Object.assign(inspectionForm.value, { |
| | | id: row.id, facilityId: row.facilityId, inspectionCode: row.inspectionCode, |
| | | inspectionType: row.inspectionType, planTime: row.planTime, checkResult: "", checkDesc: "" |
| | | inspectionType: row.inspectionType, planTime: row.planTime, checkResult: "", checkDesc: "", storageBlobDTOs: [] |
| | | }); |
| | | } else { |
| | | inspectionDialogTitle.value = "查看巡检"; |
| | | Object.assign(inspectionForm.value, { ...row }); |
| | | Object.assign(inspectionForm.value, { ...row, storageBlobDTOs: row.storageBlobVOs || row.storageBlobDTOs || [] }); |
| | | } |
| | | inspectionDialogVisible.value = true; |
| | | }; |
| | |
| | | try { |
| | | await inspectionFormRef.value.validate(); |
| | | if (inspectionDialogTitle.value === "巡检") { |
| | | if (inspectionForm.value.checkResult === "异常" && !hasAttachments(inspectionForm.value.storageBlobDTOs)) { |
| | | ElMessage.warning("检查结果异常时请上传现场照片"); |
| | | return; |
| | | } |
| | | inspectionForm.value.status = "已巡检"; |
| | | inspectionForm.value.actualTime = new Date().toISOString().replace("T", " ").substring(0, 19); |
| | | } |
| | |
| | | } |
| | | }; |
| | | |
| | | const hasAttachments = attachments => Array.isArray(attachments) && attachments.length > 0; |
| | | |
| | | const handleDeleteInspection = row => { |
| | | ElMessageBox.confirm("确认删除该巡检记录吗?", "删除", { |
| | | confirmButtonText: "确认", cancelButtonText: "取消", type: "warning" |
| | |
| | | <el-form-item label="问题描述" prop="problemDescription"><el-input v-model="recordForm.problemDescription" type="textarea" :rows="3" /></el-form-item> |
| | | <el-form-item label="处理措施" prop="disposeMeasure"><el-input v-model="recordForm.disposeMeasure" type="textarea" :rows="3" /></el-form-item> |
| | | <el-form-item label="附件说明" prop="attachmentRemark"><el-input v-model="recordForm.attachmentRemark" type="textarea" :rows="2" /></el-form-item> |
| | | <el-form-item label="附件上传"> |
| | | <FileUpload v-model:file-list="recordForm.storageBlobDTOs" :limit="6" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button type="primary" @click="submitRecordForm">确定</el-button> |
| | |
| | | <el-form-item label="隐患描述" prop="hazardDescription"><el-input v-model="rectForm.hazardDescription" type="textarea" :rows="3" /></el-form-item> |
| | | <el-form-item label="整改措施" prop="rectificationMeasures"><el-input v-model="rectForm.rectificationMeasures" type="textarea" :rows="3" /></el-form-item> |
| | | <el-form-item label="整改结果" prop="rectificationResult"><el-input v-model="rectForm.rectificationResult" type="textarea" :rows="3" /></el-form-item> |
| | | <el-form-item label="整改附件"> |
| | | <FileUpload v-model:file-list="rectForm.storageBlobDTOs" :limit="6" /> |
| | | </el-form-item> |
| | | <el-form-item label="备注" prop="remarks"><el-input v-model="rectForm.remarks" type="textarea" :rows="2" /></el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | |
| | | |
| | | <script setup> |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { computed, reactive, ref, onMounted, getCurrentInstance } from "vue"; |
| | | import { computed, reactive, ref, onMounted } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | | import { |
| | |
| | | specialEquipmentRecordDel, |
| | | specialEquipmentRectificationListPage, |
| | | specialEquipmentRectificationAdd, |
| | | specialEquipmentRectificationClose, |
| | | specialEquipmentRectificationUpdate, |
| | | specialEquipmentRectificationDel, |
| | | } from "@/api/safeProduction/specialEquipmentManagement.js"; |
| | | import { userListNoPageByTenantId } from "@/api/system/user.js"; |
| | | import FileUpload from "@/components/AttachmentUpload/file/index.vue"; |
| | | |
| | | const { proxy } = getCurrentInstance(); |
| | | const activeTab = ref("ledger"); |
| | | const userOptions = ref([]); |
| | | |
| | |
| | | executorName: "", |
| | | nextDueDate: "", |
| | | attachmentRemark: "", |
| | | storageBlobDTOs: [], |
| | | }); |
| | | const recordRules = { |
| | | equipmentId: [{ required: true, message: "请选择关联设备", trigger: "change" }], |
| | |
| | | rectificationStatus: 1, |
| | | rectificationMeasures: "", |
| | | rectificationResult: "", |
| | | storageBlobDTOs: [], |
| | | remarks: "", |
| | | }); |
| | | const rectRules = { |
| | |
| | | const ledgerOptions = ref([]); |
| | | const activeLedgerOptions = computed(() => ledgerOptions.value); |
| | | const activeUserOptions = computed(() => userOptions.value || []); |
| | | const getAttachments = row => row?.storageBlobDTOs || row?.storageBlobVOs || []; |
| | | |
| | | const getDueDays = (dateValue) => { |
| | | if (!dateValue) return null; |
| | | const today = new Date(); |
| | | today.setHours(0, 0, 0, 0); |
| | | const dueDate = new Date(`${dateValue}T00:00:00`); |
| | | if (Number.isNaN(dueDate.getTime())) return null; |
| | | return Math.ceil((dueDate.getTime() - today.getTime()) / 86400000); |
| | | }; |
| | | |
| | | const formatDueStatus = (dateValue) => { |
| | | const days = getDueDays(dateValue); |
| | | if (days === null) return "未设置"; |
| | | if (days < 0) return "已逾期"; |
| | | if (days === 0) return "今日到期"; |
| | | if (days <= 30) return `${days}天后到期`; |
| | | return "未到期"; |
| | | }; |
| | | |
| | | const getDueStatusType = (dateValue) => { |
| | | const days = getDueDays(dateValue); |
| | | if (days === null) return "info"; |
| | | if (days < 0) return "danger"; |
| | | if (days <= 7) return "danger"; |
| | | if (days <= 30) return "warning"; |
| | | return "success"; |
| | | }; |
| | | |
| | | const getRectStatusType = status => { |
| | | const map = { 1: "danger", 2: "warning", 3: "primary", 4: "success" }; |
| | | return map[status] || "info"; |
| | | }; |
| | | |
| | | const ledgerColumns = [ |
| | | { label: "设备编号", prop: "equipmentNo" }, |
| | |
| | | { label: "执行人", prop: "executorName" }, |
| | | { label: "执行结果", prop: "executeResult" }, |
| | | { label: "下次到期日期", prop: "nextDueDate" }, |
| | | { label: "到期提醒", prop: "nextDueDate", dataType: "tag", formatData: formatDueStatus, formatType: getDueStatusType }, |
| | | { |
| | | label: "操作", |
| | | dataType: "action", |
| | |
| | | { label: "发现日期", prop: "discoveredDate" }, |
| | | { label: "责任人", prop: "responsibleUserName" }, |
| | | { label: "整改期限", prop: "rectificationDeadline" }, |
| | | { label: "整改状态", prop: "rectificationStatus", formatData: { 1: "待整改", 2: "整改中", 3: "待复核", 4: "已闭环" } }, |
| | | { label: "整改状态", prop: "rectificationStatus", dataType: "tag", formatData: { 1: "待整改", 2: "整改中", 3: "待复核", 4: "已闭环" }, formatType: getRectStatusType }, |
| | | { |
| | | label: "操作", |
| | | dataType: "action", |
| | | width: "220", |
| | | operation: [ |
| | | { name: "编辑", clickFun: (row) => openRectForm(row) }, |
| | | { name: "删除", clickFun: (row) => deleteRect(row.id) }, |
| | | ], |
| | | }, |
| | |
| | | executorName: "", |
| | | nextDueDate: "", |
| | | attachmentRemark: "", |
| | | storageBlobDTOs: [], |
| | | }); |
| | | Object.assign(recordForm, row); |
| | | recordForm.storageBlobDTOs = getAttachments(row); |
| | | if (!recordForm.executorId && recordForm.executorName) { |
| | | const matched = userOptions.value.find((item) => (item.nickName || item.userName) === recordForm.executorName); |
| | | recordForm.executorId = matched?.userId || ""; |
| | |
| | | rectificationStatus: 1, |
| | | rectificationMeasures: "", |
| | | rectificationResult: "", |
| | | storageBlobDTOs: [], |
| | | remarks: "", |
| | | }); |
| | | Object.assign(rectForm, row); |
| | | rectForm.storageBlobDTOs = getAttachments(row); |
| | | if (!rectForm.responsibleUserId && rectForm.responsibleUserName) { |
| | | const matched = userOptions.value.find((item) => (item.nickName || item.userName) === rectForm.responsibleUserName); |
| | | rectForm.responsibleUserId = matched?.userId || ""; |
| | | } |
| | | rectDialogTitle.value = "新增整改"; |
| | | rectDialogTitle.value = row.id ? "编辑整改" : "新增整改"; |
| | | rectDialogVisible.value = true; |
| | | }; |
| | | |
| | | const submitRectForm = async () => { |
| | | await rectFormRef.value.validate(); |
| | | await specialEquipmentRectificationAdd(rectForm); |
| | | const api = rectForm.id ? specialEquipmentRectificationUpdate : specialEquipmentRectificationAdd; |
| | | await api(rectForm); |
| | | ElMessage.success("保存成功"); |
| | | rectDialogVisible.value = false; |
| | | rectQuery(); |