<template>
|
<!-- 设备保养计划-->
|
<div>
|
<div style="margin: 10px 0 14px;">
|
<div class="plan-top">
|
<div class="plan-top-left">
|
<span class="title" style="margin-bottom: 0;">{{ planInfo.planName || (planYear + '年度设备保养计划') }}</span>
|
<el-select v-model="planYear" size="small" style="width: 110px; margin-left: 16px;" @change="handleYearChange">
|
<el-option v-for="y in yearOptions" :key="y" :label="y" :value="y"></el-option>
|
</el-select>
|
</div>
|
<div>
|
<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>
|
<div class="plan-info-bar">
|
<span>编制人:{{ planInfo.compiler || '—' }}</span>
|
<span>编制日期:{{ planInfo.datePreparationStr || '—' }}</span>
|
<span v-if="planInfo.status === 1">审核状态:<el-tag type="success">通 过</el-tag></span>
|
<span v-else-if="planInfo.status === 0">审核状态:<el-tag type="danger">不通过</el-tag></span>
|
<span v-if="planInfo.auditRemark">审核信息:{{ planInfo.auditRemark }}</span>
|
<span v-if="isAudited && planInfo.audit">审核人:{{ planInfo.audit }}</span>
|
<span v-if="isAudited && planInfo.auditDateStr">审核时间:{{ planInfo.auditDateStr }}</span>
|
</div>
|
</div>
|
<div class="search">
|
<div>
|
<el-form :model="searchForm" ref="searchForm" size="small" :inline="true">
|
<el-form-item label="设备名称" prop="deviceName">
|
<el-input v-model="searchForm.deviceName" clearable @keyup.enter="handleQuery"
|
size="small"></el-input>
|
</el-form-item>
|
<el-form-item label="设备编号" prop="deviceNumber">
|
<el-input v-model="searchForm.deviceNumber" @keyup.enter="handleQuery" clearable
|
size="small"></el-input>
|
</el-form-item>
|
<el-form-item>
|
<el-button type="primary" size="small" @click="handleQuery">查询</el-button>
|
<el-button size="small" @click="reset">重置</el-button>
|
</el-form-item>
|
</el-form>
|
</div>
|
</div>
|
<div>
|
<el-table ref="yearTable" v-loading="tableLoading" :data="tableData" border
|
: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="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">
|
<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" 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" :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 :current-page="pagination1.current" :page-size="pagination1.size"
|
:page-sizes="[10, 20, 30, 50, 100]" background :total="pagination1.total"
|
layout="->,total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange1"
|
@current-change="handleCurrentChange1">
|
</el-pagination>
|
</div>
|
<el-dialog :close-on-click-modal="false" :close-on-press-escape="false" v-model="dialogVisible"
|
: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></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></el-input>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<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="维护日期:" 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>
|
<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>
|
</template>
|
|
<script>
|
import {
|
getMaintenancePlanYears,
|
getMaintenancePlanByYear,
|
pageMaintenancePlanDetail,
|
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: {
|
clickNodeVal: {
|
type: Object,
|
default: () => {
|
return {};
|
}
|
}
|
},
|
data() {
|
const rules = {
|
maintenanceDate: [{ required: true, message: '请选择维护日期', trigger: 'change' }],
|
maintenanceUserId: [{ required: true, message: '请选择维护人', trigger: 'change' }],
|
}
|
return {
|
planYear: '',
|
yearOptions: [],
|
planInfo: {},
|
searchForm: {
|
deviceName: '',
|
deviceNumber: '',
|
},
|
tableData: [],
|
tableLoading: false,
|
pagination1: {
|
size: 10,
|
current: 1,
|
total: 0,
|
},
|
checkColumns: CHECK_ITEMS.map(item => ({ ...item })),
|
dialogVisible: false,
|
operationType: '',
|
form: {},
|
rules,
|
submitFormLoading: false,
|
outLoading: false,
|
reviewLoading: false,
|
userOptions: [],
|
}
|
},
|
mounted() {
|
this.loadYearOptions()
|
this.getUserList()
|
},
|
methods: {
|
// 年份下拉:只列出有明细的年份(空年份计划由后端删除),默认显示本年度(本年度无计划时退回最新年份)
|
loadYearOptions(preserveYear = false) {
|
const currentYear = String(new Date().getFullYear())
|
const finish = (years) => {
|
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 = 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()
|
}
|
getMaintenancePlanYears().then(res => {
|
finish(res.code == 200 ? (res.data || []) : [])
|
}).catch(() => {
|
finish([])
|
})
|
},
|
// 切换年份
|
handleYearChange() {
|
this.pagination1.current = 1
|
this.loadPlan()
|
},
|
// 查询年份计划(不存在自动创建并补全到点明细),随后刷新明细
|
loadPlan() {
|
getMaintenancePlanByYear({ planYear: this.planYear }).then(res => {
|
if (res.code == 200) {
|
this.planInfo = res.data || {}
|
}
|
this.getTableList()
|
}).catch(() => {
|
this.planInfo = {}
|
this.tableData = []
|
this.pagination1.total = 0
|
this.tableLoading = false
|
})
|
},
|
// 查询条件变化后从第一页开始查
|
handleQuery() {
|
this.pagination1.current = 1
|
this.getTableList()
|
},
|
// 明细-查询
|
getTableList() {
|
if (!this.planInfo.maintenancePlanId) {
|
return
|
}
|
this.tableLoading = true
|
pageMaintenancePlanDetail({
|
current: this.pagination1.current,
|
size: this.pagination1.size,
|
planId: this.planInfo.maintenancePlanId,
|
deviceName: this.searchForm.deviceName,
|
deviceNumber: this.searchForm.deviceNumber,
|
}).then(res => {
|
if (res.code == 200) {
|
this.tableData = res.data.records
|
this.pagination1.total = res.data.total
|
}
|
this.tableLoading = false
|
}).catch(() => {
|
this.tableLoading = false
|
})
|
},
|
// 未审核显示计划保养时间;审核通过后显示审核当天(与核查计划一致)
|
formatReviewDate(row) {
|
const date = row.reviewStatus === 1 ? row.reviewTime : row.maintenanceDate
|
return formatDateOnly(date) || '—'
|
},
|
tableRowClassName({ row }) {
|
return row.redFlag === 1 ? 'red-row' : ''
|
},
|
reset() {
|
this.searchForm = {
|
deviceName: '',
|
deviceNumber: '',
|
}
|
this.pagination1.current = 1
|
this.getTableList()
|
},
|
// 分页
|
handleSizeChange1(val) {
|
this.pagination1.size = val
|
this.getTableList()
|
},
|
// 分页
|
handleCurrentChange1(val) {
|
this.pagination1.current = val
|
this.getTableList()
|
},
|
// 打开明细弹框:edit 填写/修改保养记录,view 查看,review 审核
|
handleForm(type, row) {
|
this.operationType = type
|
this.form = this.buildForm(row)
|
this.dialogVisible = true
|
this.$nextTick(() => {
|
if (this.$refs.modelForm) {
|
this.$refs.modelForm.clearValidate()
|
}
|
})
|
},
|
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) {
|
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() {
|
this.dialogVisible = false
|
},
|
// 明细-删除
|
deleteRow(row) {
|
this.$confirm('删除后,该行的保养记录(未审核或审核不通过)会一并删除,是否继续?', '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning'
|
}).then(() => {
|
deleteMaintenancePlanDetail({ maintenancePlanDetailId: row.maintenancePlanDetailId }).then(() => {
|
this.$message.success('删除成功!');
|
// 删完可能是该年份最后一条,重新取年份,空年份会一并清掉
|
this.loadYearOptions(true)
|
});
|
}).catch(() => {
|
this.$message({
|
type: 'info',
|
message: '已取消删除'
|
});
|
});
|
},
|
// 导出
|
handleDownOne() {
|
this.outLoading = true
|
exportDeviceMaintenancePlan({ maintenancePlanId: this.planInfo.maintenancePlanId }).then(res => {
|
this.outLoading = false
|
saveBlobOrShowError(res, '设备保养计划表.docx', 'application/msword')
|
}).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
|
},
|
},
|
}
|
</script>
|
|
<style scoped>
|
.title {
|
position: relative;
|
font-size: 16px;
|
color: var(--lims-text);
|
font-weight: 400;
|
padding-left: 10px;
|
margin-bottom: 10px;
|
}
|
|
.title::before {
|
position: absolute;
|
left: 0;
|
top: 4px;
|
content: '';
|
width: 4px;
|
height: 16px;
|
background-color: var(--el-color-primary);
|
border-radius: 2px;
|
}
|
|
.plan-top {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
flex-wrap: wrap;
|
}
|
|
.plan-top-left {
|
display: flex;
|
align-items: center;
|
}
|
|
.plan-info-bar {
|
display: flex;
|
align-items: center;
|
flex-wrap: wrap;
|
gap: 32px;
|
background: #f5f7fa;
|
border-radius: 4px;
|
padding: 10px 16px;
|
margin-top: 14px;
|
font-size: 14px;
|
color: #606266;
|
}
|
|
.search {
|
display: flex;
|
justify-content: space-between;
|
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;
|
}
|
</style>
|