| | |
| | | </el-select> |
| | | </div> |
| | | <div> |
| | | <el-button size="small" type="primary" @click="loadPlan">刷新</el-button> |
| | | <el-button size="small" type="primary" @click="loadYearOptions(true)">刷新</el-button> |
| | | <el-button size="small" type="primary" :loading="outLoading" @click="handleDownOne">导出</el-button> |
| | | </div> |
| | | </div> |
| | |
| | | :row-class-name="tableRowClassName" :height="'calc(100vh - 29em)'" style="width: 100%;"> |
| | | <el-table-column align="center" header-align="center" label="序号" prop="prop" type="index" |
| | | width="70"></el-table-column> |
| | | <el-table-column label="设备名称及型号" min-width="180" show-overflow-tooltip> |
| | | <el-table-column label="设备名称" min-width="150" prop="deviceName" show-overflow-tooltip></el-table-column> |
| | | <el-table-column label="设备型号" min-width="130" prop="specificationModel" show-overflow-tooltip></el-table-column> |
| | | <el-table-column label="设备编号" min-width="140" prop="deviceNumber"></el-table-column> |
| | | <el-table-column label="存放点" min-width="120" prop="storagePoint"></el-table-column> |
| | | <el-table-column align="center" header-align="center" label="审核日期" min-width="110"> |
| | | <template #default="scope">{{ formatReviewDate(scope.row) }}</template> |
| | | </el-table-column> |
| | | <el-table-column align="center" header-align="center" label="维护保养内容"> |
| | | <el-table-column v-for="item in checkColumns" :key="item.prop" align="center" header-align="center" |
| | | :label="item.label" width="110"> |
| | | <template #default="scope">{{ scope.row[item.prop] || '—' }}</template> |
| | | </el-table-column> |
| | | </el-table-column> |
| | | <el-table-column align="center" header-align="center" label="维护人" min-width="100"> |
| | | <template #default="scope">{{ scope.row.maintenanceUserName || '—' }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="审核状态" min-width="100"> |
| | | <template #default="scope"> |
| | | {{ scope.row.deviceName }}{{ scope.row.specificationModel ? ' ' + scope.row.specificationModel : '' }} |
| | | <el-tag v-if="!scope.row.recordStatus" type="info" disable-transitions>未开始</el-tag> |
| | | <el-tag v-else-if="scope.row.recordStatus === 1" type="warning" disable-transitions>待审核</el-tag> |
| | | <el-tag v-else-if="scope.row.recordStatus === 2" type="success" disable-transitions>通过</el-tag> |
| | | <el-tag v-else-if="scope.row.recordStatus === 3" type="danger" disable-transitions>不通过</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="设备编号" min-width="140" prop="deviceNumber"></el-table-column> |
| | | <el-table-column label="归属实验室" min-width="120" prop="storagePoint"></el-table-column> |
| | | <el-table-column label="保养关键部位" min-width="150" prop="maintenanceSite" show-overflow-tooltip></el-table-column> |
| | | <el-table-column label="保养内容" min-width="180" prop="maintenanceContent" show-overflow-tooltip></el-table-column> |
| | | <el-table-column label="保养周期" min-width="100" prop="maintenanceIntervals"></el-table-column> |
| | | <el-table-column label="计划保养时间" min-width="130" prop="maintenanceDate" |
| | | :formatter="formatDateCell"></el-table-column> |
| | | <el-table-column align="center" fixed="right" label="操作" min-width="160"> |
| | | <el-table-column label="备注" min-width="140" show-overflow-tooltip> |
| | | <template #default="scope">{{ scope.row.recordRemark || '—' }}</template> |
| | | </el-table-column> |
| | | <el-table-column align="center" fixed="right" label="操作" min-width="300"> |
| | | <template #default="scope"> |
| | | <el-button size="small" link type="primary" |
| | | :disabled="scope.row.recordStatus === 2 || scope.row.recordStatus === 3" |
| | | @click="handleForm('edit', scope.row)">编辑</el-button> |
| | | <el-button size="small" link type="primary" @click="handleForm('view', scope.row)">查看</el-button> |
| | | <el-button size="small" link type="danger" |
| | | @click="deleteRow(scope.row)">删除</el-button> |
| | | <el-button size="small" link type="primary" :disabled="!scope.row.recordId" |
| | | @click="handleForm('view', scope.row)">查看</el-button> |
| | | <el-button v-if="scope.row.recordStatus === 0 || scope.row.recordStatus === 1" |
| | | size="small" link type="primary" :disabled="!scope.row.maintenanceUserName" |
| | | @click="handleReview(scope.row)">审核</el-button> |
| | | <el-button v-if="scope.row.recordStatus !== 2" |
| | | size="small" link type="danger" @click="deleteRow(scope.row)">删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | </el-pagination> |
| | | </div> |
| | | <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" v-model="dialogVisible" |
| | | title="设备保养计划明细" width="60%" @close="resetForm"> |
| | | <el-form ref="modelForm" :model="form" :rules="rules" label-width="130px"> |
| | | :title="dialogTitle" width="880px" @close="resetForm"> |
| | | <el-form ref="modelForm" :model="form" :rules="rules" label-width="150px" size="small"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设备名称:"> |
| | | <el-input v-model="form.deviceName" disabled size="small"></el-input> |
| | | <el-input v-model="form.deviceName" disabled></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设备型号:"> |
| | | <el-input v-model="form.specificationModel" disabled></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设备编号:"> |
| | | <el-input v-model="form.deviceNumber" disabled size="small"></el-input> |
| | | <el-input v-model="form.deviceNumber" disabled></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="归属实验室:"> |
| | | <el-input v-model="form.storagePoint" disabled size="small"></el-input> |
| | | <el-form-item label="存放点:"> |
| | | <el-input v-model="form.storagePoint" disabled></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="保养周期:"> |
| | | <el-input v-model="form.maintenanceIntervals" :disabled="operationType === 'view'" clearable |
| | | size="small"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="保养关键部位:"> |
| | | <el-input v-model="form.maintenanceSite" :disabled="operationType === 'view'" clearable size="small" |
| | | type="textarea"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="保养内容:"> |
| | | <el-input v-model="form.maintenanceContent" :disabled="operationType === 'view'" clearable size="small" |
| | | type="textarea"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="计划保养时间:" prop="maintenanceDate"> |
| | | <el-date-picker v-model="form.maintenanceDate" :disabled="operationType === 'view'" clearable |
| | | format="YYYY-MM-DD" placeholder="选择日期" size="small" style="width:100%" type="date" |
| | | <el-form-item label="维护日期:" prop="maintenanceDate"> |
| | | <el-date-picker v-model="form.maintenanceDate" :disabled="!isEdit" clearable |
| | | format="YYYY-MM-DD" placeholder="选择日期" style="width: 100%" type="date" |
| | | value-format="YYYY-MM-DD"></el-date-picker> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="维护人:" prop="maintenanceUserId"> |
| | | <el-select v-model="form.maintenanceUserId" :disabled="!isEdit" clearable filterable |
| | | placeholder="请选择" style="width: 100%"> |
| | | <el-option v-for="item in maintainerOptions" :key="item.id" :label="item.name" |
| | | :value="item.id"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <div class="form-section-title">维护保养内容</div> |
| | | <el-row> |
| | | <el-col v-for="item in checkColumns" :key="item.prop" :span="12"> |
| | | <el-form-item :label="item.label + ':'" :prop="item.prop"> |
| | | <el-radio-group v-model="form[item.prop]" :disabled="!isEdit"> |
| | | <el-radio value="√">√</el-radio> |
| | | <el-radio value="×">×</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="保养备注:"> |
| | | <el-input v-model="form.remark" :disabled="!isEdit" :rows="2" placeholder="可填写保养备注" |
| | | type="textarea"></el-input> |
| | | </el-form-item> |
| | | <el-form-item v-if="operationType === 'review'" label="审核备注:"> |
| | | <el-input v-model="form.reviewRemark" :rows="2" placeholder="可填写审核意见" |
| | | type="textarea"></el-input> |
| | | </el-form-item> |
| | | <div class="check-note">备注:正常、良好打“√”,不正常及否打“×”。</div> |
| | | <div v-if="cycleNote" class="check-note">{{ cycleNote }}</div> |
| | | </el-form> |
| | | <template #footer><span class="dialog-footer"> |
| | | <el-button @click="resetForm">取 消</el-button> |
| | | <el-button :loading="submitFormLoading" type="primary" @click="submitForm" |
| | | v-if="operationType !== 'view'">确 认</el-button> |
| | | <template v-if="operationType === 'review'"> |
| | | <el-button :loading="reviewLoading" @click="submitReview(0)">不通过</el-button> |
| | | <el-button :loading="reviewLoading" type="primary" @click="submitReview(1)">通 过</el-button> |
| | | </template> |
| | | <el-button v-else-if="operationType === 'edit'" :loading="submitFormLoading" type="primary" |
| | | @click="submitForm">确 认</el-button> |
| | | </span></template> |
| | | </el-dialog> |
| | | </div> |
| | |
| | | |
| | | <script> |
| | | import { |
| | | selectDeviceMaintenancePlanByPage, |
| | | getMaintenancePlanYears, |
| | | getMaintenancePlanByYear, |
| | | pageMaintenancePlanDetail, |
| | | updateMaintenancePlanDetail, |
| | | deleteMaintenancePlanDetail, |
| | | exportDeviceMaintenancePlan, |
| | | addDeviceMaintenance, |
| | | reviewDeviceMaintenance, |
| | | } from '@/api/cnas/resourceDemand/device.js' |
| | | import { selectUserCondition } from '@/api/system/user' |
| | | import dayjs from 'dayjs' |
| | | import { formatDateOnly } from './dateFormat' |
| | | import { saveBlobOrShowError } from '@/utils/saveBlob' |
| | | |
| | | // 维护保养检查项,与仪器设备维护保养记录表一致 |
| | | const CHECK_ITEMS = [ |
| | | { label: '外观是否良好', prop: 'appearanceGood' }, |
| | | { label: '是否可以正常使用', prop: 'normalUse' }, |
| | | { label: '是否清洁仪器表面', prop: 'surfaceClean' }, |
| | | { label: '标识是否完好', prop: 'labelIntact' }, |
| | | { label: '显示器灯是否正常', prop: 'displayLightNormal' }, |
| | | { label: '仪器是否生锈', prop: 'noRust' }, |
| | | { label: '校准是否正常', prop: 'calibrationNormal' }, |
| | | { label: '配件是否需要更换', prop: 'partsReplace' }, |
| | | { label: '维护结果是否正常', prop: 'resultNormal' }, |
| | | ] |
| | | |
| | | export default { |
| | | name: "equipment-maintenance-plan", |
| | | props: { |
| | |
| | | } |
| | | }, |
| | | data() { |
| | | const rules = { |
| | | maintenanceDate: [{ required: true, message: '请选择维护日期', trigger: 'change' }], |
| | | maintenanceUserId: [{ required: true, message: '请选择维护人', trigger: 'change' }], |
| | | } |
| | | return { |
| | | planYear: '', |
| | | yearOptions: [], |
| | |
| | | current: 1, |
| | | total: 0, |
| | | }, |
| | | checkColumns: CHECK_ITEMS.map(item => ({ ...item })), |
| | | dialogVisible: false, |
| | | operationType: '', |
| | | form: {}, |
| | | rules: { |
| | | maintenanceDate: [{ required: true, message: '请选择计划保养时间', trigger: 'change' }], |
| | | }, |
| | | rules, |
| | | submitFormLoading: false, |
| | | outLoading: false, |
| | | reviewLoading: false, |
| | | userOptions: [], |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.loadYearOptions() |
| | | this.getUserList() |
| | | }, |
| | | methods: { |
| | | // 年份下拉选项:已有计划年份 + 当前年份 |
| | | loadYearOptions() { |
| | | // 年份下拉:只列出有明细的年份(空年份计划由后端删除),默认显示本年度(本年度无计划时退回最新年份) |
| | | loadYearOptions(preserveYear = false) { |
| | | const currentYear = String(new Date().getFullYear()) |
| | | const finish = (years) => { |
| | | if (years.indexOf(currentYear) === -1) { |
| | | years.push(currentYear) |
| | | let list = [...new Set(years.map(y => String(y)).filter(Boolean))] |
| | | list.sort((a, b) => b.localeCompare(a)) |
| | | if (!list.length) { |
| | | list = [currentYear] |
| | | } |
| | | this.yearOptions = [...new Set(years)].sort((a, b) => b.localeCompare(a)) |
| | | this.planYear = currentYear |
| | | this.yearOptions = list |
| | | const keep = preserveYear && this.planYear && list.includes(String(this.planYear)) |
| | | this.planYear = keep ? String(this.planYear) : (list.includes(currentYear) ? currentYear : list[0]) |
| | | this.loadPlan() |
| | | } |
| | | selectDeviceMaintenancePlanByPage({ |
| | | current: 1, |
| | | size: 99, |
| | | }).then(res => { |
| | | let years = [] |
| | | if (res.code == 200) { |
| | | years = (res.data.records || []).map(r => r.planYear).filter(Boolean) |
| | | } |
| | | finish(years) |
| | | getMaintenancePlanYears().then(res => { |
| | | finish(res.code == 200 ? (res.data || []) : []) |
| | | }).catch(() => { |
| | | finish([]) |
| | | }) |
| | |
| | | this.tableLoading = false |
| | | }) |
| | | }, |
| | | // 到点需保养的行标红 |
| | | formatDateCell(row, column, cellValue) { |
| | | return formatDateOnly(cellValue) |
| | | // 未审核显示计划保养时间;审核通过后显示审核当天(与核查计划一致) |
| | | formatReviewDate(row) { |
| | | const date = row.reviewStatus === 1 ? row.reviewTime : row.maintenanceDate |
| | | return formatDateOnly(date) || '—' |
| | | }, |
| | | tableRowClassName({ row }) { |
| | | return row.redFlag === 1 ? 'red-row' : '' |
| | |
| | | this.pagination1.current = val |
| | | this.getTableList() |
| | | }, |
| | | // 打开明细弹框 |
| | | // 打开明细弹框:edit 填写/修改保养记录,view 查看,review 审核 |
| | | handleForm(type, row) { |
| | | this.operationType = type |
| | | this.form = this.HaveJson(row) |
| | | this.form = this.buildForm(row) |
| | | this.dialogVisible = true |
| | | this.$nextTick(() => { |
| | | if (this.$refs.modelForm) { |
| | |
| | | } |
| | | }) |
| | | }, |
| | | // 提交表单(只回传明细表字段) |
| | | buildForm(row) { |
| | | const form = { |
| | | id: row.recordId || null, |
| | | maintenancePlanDetailId: row.maintenancePlanDetailId, |
| | | deviceId: row.deviceId, |
| | | deviceName: row.deviceName, |
| | | specificationModel: row.specificationModel, |
| | | deviceNumber: row.deviceNumber, |
| | | storagePoint: row.storagePoint, |
| | | // 已有记录用记录日期;还没记录时默认今天,避免把计划日期当成实际保养日期 |
| | | maintenanceDate: row.recordId |
| | | ? formatDateOnly(row.recordMaintenanceDate) |
| | | : dayjs().format('YYYY-MM-DD'), |
| | | maintenanceCycle: row.maintenanceCycle || row.maintenanceIntervals || '', |
| | | maintenanceUserId: row.maintenanceUserId || '', |
| | | maintenanceUserName: row.maintenanceUserName || '', |
| | | remark: row.recordRemark || '', |
| | | reviewRemark: '', |
| | | } |
| | | this.checkColumns.forEach(item => { |
| | | form[item.prop] = row[item.prop] || '' |
| | | }) |
| | | return form |
| | | }, |
| | | // 保存保养记录(新增或修改后进入待审核) |
| | | submitForm() { |
| | | this.$refs.modelForm.validate(valid => { |
| | | if (valid) { |
| | | this.submitFormLoading = true |
| | | const payload = { |
| | | maintenancePlanDetailId: this.form.maintenancePlanDetailId, |
| | | maintenancePlanId: this.form.maintenancePlanId, |
| | | deviceId: this.form.deviceId, |
| | | maintenanceSite: this.form.maintenanceSite, |
| | | maintenanceContent: this.form.maintenanceContent, |
| | | maintenanceIntervals: this.form.maintenanceIntervals, |
| | | maintenanceDate: this.form.maintenanceDate, |
| | | } |
| | | updateMaintenancePlanDetail(payload).then(res => { |
| | | if (res.code == 200) { |
| | | this.$message.success('修改成功') |
| | | this.dialogVisible = false |
| | | this.getTableList() |
| | | } |
| | | this.submitFormLoading = false |
| | | }).catch(() => { |
| | | this.submitFormLoading = false |
| | | }) |
| | | if (!valid) { |
| | | return |
| | | } |
| | | this.submitFormLoading = true |
| | | const payload = { |
| | | maintenancePlanDetailId: this.form.maintenancePlanDetailId, |
| | | deviceId: this.form.deviceId, |
| | | maintenanceDate: this.form.maintenanceDate, |
| | | maintenanceUserId: this.form.maintenanceUserId, |
| | | remark: this.form.remark, |
| | | } |
| | | if (this.form.id) { |
| | | payload.id = this.form.id |
| | | } |
| | | this.checkColumns.forEach(item => { |
| | | payload[item.prop] = this.form[item.prop] |
| | | }) |
| | | addDeviceMaintenance(payload).then(res => { |
| | | this.submitFormLoading = false |
| | | if (res.code == 200) { |
| | | this.$message.success(this.form.id ? '修改成功' : '保存成功') |
| | | this.dialogVisible = false |
| | | this.loadPlan() |
| | | } |
| | | }).catch(() => { |
| | | this.submitFormLoading = false |
| | | }) |
| | | }) |
| | | }, |
| | | resetForm() { |
| | |
| | | }, |
| | | // 明细-删除 |
| | | deleteRow(row) { |
| | | this.$confirm('此操作将永久删除该条明细, 是否继续?', '提示', { |
| | | this.$confirm('删除后,该行的保养记录(未审核或审核不通过)会一并删除,是否继续?', '提示', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | deleteMaintenancePlanDetail({ maintenancePlanDetailId: row.maintenancePlanDetailId }).then(() => { |
| | | this.$message.success('删除成功!'); |
| | | this.getTableList() |
| | | // 删完可能是该年份最后一条,重新取年份,空年份会一并清掉 |
| | | this.loadYearOptions(true) |
| | | }); |
| | | }).catch(() => { |
| | | this.$message({ |
| | |
| | | }).catch(() => { |
| | | this.outLoading = false |
| | | }) |
| | | } |
| | | }, |
| | | // 打开保养记录审核弹框 |
| | | handleReview(row) { |
| | | this.handleForm('review', row) |
| | | }, |
| | | // 提交审核结果:1 通过,0 不通过 |
| | | submitReview(status) { |
| | | this.reviewLoading = true |
| | | reviewDeviceMaintenance({ |
| | | maintenancePlanDetailId: this.form.maintenancePlanDetailId, |
| | | reviewStatus: status, |
| | | reviewRemark: this.form.reviewRemark, |
| | | }).then(res => { |
| | | this.reviewLoading = false |
| | | if (res.code == 200) { |
| | | this.$message.success(status === 1 ? '审核通过' : '审核不通过') |
| | | this.dialogVisible = false |
| | | // 审核通过后明细会归到审核年份的计划,重新取年份避免停在不存在的年份 |
| | | this.loadYearOptions(true) |
| | | } |
| | | }).catch(() => { |
| | | this.reviewLoading = false |
| | | }) |
| | | }, |
| | | // 维护人下拉 |
| | | getUserList() { |
| | | selectUserCondition({ type: 2 }).then(res => { |
| | | if (res.code == 200) { |
| | | this.userOptions = res.data || [] |
| | | } |
| | | }) |
| | | }, |
| | | }, |
| | | computed: { |
| | | // 是否已完成审核(通过/不通过) |
| | | isAudited() { |
| | | return this.planInfo.status === 0 || this.planInfo.status === 1; |
| | | }, |
| | | // 仅编辑状态可填写表单 |
| | | isEdit() { |
| | | return this.operationType === 'edit' |
| | | }, |
| | | // 按设备档案的保养周期(月)生成底部说明 |
| | | cycleNote() { |
| | | const months = parseInt((this.form && this.form.maintenanceCycle) || '', 10) |
| | | if (!months || months <= 0) { |
| | | return '' |
| | | } |
| | | if (months === 1) { |
| | | return '此设备维护保养每月 1 次。' |
| | | } |
| | | if (months === 3) { |
| | | return '此设备维护保养每季度 1 次。' |
| | | } |
| | | if (months === 6) { |
| | | return '此设备维护保养每半年 1 次。' |
| | | } |
| | | if (months === 12) { |
| | | return '此设备维护保养每年 1 次。' |
| | | } |
| | | if (months % 12 === 0) { |
| | | return `此设备维护保养每 ${months / 12} 年 1 次。` |
| | | } |
| | | return `此设备维护保养每 ${months} 个月 1 次。` |
| | | }, |
| | | dialogTitle() { |
| | | if (this.operationType === 'view') { |
| | | return '查看保养记录' |
| | | } |
| | | if (this.operationType === 'review') { |
| | | return '保养记录审核' |
| | | } |
| | | return '编辑保养记录' |
| | | }, |
| | | // 已选维护人不在当前人员列表时补一条,保证下拉能显示姓名 |
| | | maintainerOptions() { |
| | | const list = this.userOptions.slice() |
| | | const form = this.form || {} |
| | | if (form.maintenanceUserId && !list.some(item => item.id === form.maintenanceUserId)) { |
| | | list.unshift({ |
| | | id: form.maintenanceUserId, |
| | | name: form.maintenanceUserName || String(form.maintenanceUserId), |
| | | }) |
| | | } |
| | | return list |
| | | }, |
| | | }, |
| | | } |
| | |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .form-section-title { |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | color: var(--lims-text); |
| | | margin: 4px 0 16px; |
| | | padding-left: 8px; |
| | | border-left: 4px solid var(--el-color-primary); |
| | | } |
| | | |
| | | .check-note { |
| | | font-size: 13px; |
| | | color: #909399; |
| | | line-height: 22px; |
| | | padding-left: 150px; |
| | | } |
| | | |
| | | :deep(.red-row td) { |
| | | background: #ffcccc !important; |
| | | } |