feat(device): 设备核查计划附件上传与运行记录导出调整
- 核查计划表单接入附件上传组件
- 附件组件支持只读、内联展示与延迟上传
- 仪器设备运行记录导出支持按月份筛选并校验无记录情况
| | |
| | | }); |
| | | } |
| | | |
| | | // 查找可复用的核查计划明细(只查询,不新增) |
| | | export function findExaminePlanDetail(query) { |
| | | return request({ |
| | | url: "/deviceExaminePlan/findExaminePlanDetail", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // 新增设备核查计划详情 |
| | | export function addDeviceExaminePlanDetail(data) { |
| | | return request({ |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog :title="dialogTitle" v-model="visible" width="760px"> |
| | | <div class="lims-attachment"> |
| | | <div v-if="inline" class="attachment-inline"> |
| | | <div class="attachment-header"> |
| | | <div class="el-upload__tip">{{ tip }}</div> |
| | | <el-upload :action="uploadAction" :headers="uploadHeader" multiple :show-file-list="false" |
| | | :on-success="handleUploadSuccess" :on-error="handleUploadError"> |
| | | <div class="el-upload__tip"> |
| | | {{ readonly ? '仅可预览、下载附件' : ((currentId || deferUpload) ? tip : emptyTip) }} |
| | | </div> |
| | | <el-upload v-if="!readonly" :action="uploadAction" :headers="uploadHeader" multiple |
| | | :show-file-list="false" :disabled="!canUpload" :auto-upload="!deferUpload" |
| | | :on-change="handleFileChange" :on-success="handleUploadSuccess" |
| | | :on-error="handleUploadError"> |
| | | <el-button size="small" type="primary" :disabled="!canUpload">上传附件</el-button> |
| | | </el-upload> |
| | | </div> |
| | | <el-table :data="displayList" border size="small" max-height="180" style="margin-top:8px"> |
| | | <el-table-column label="文件名称" prop="fileName" min-width="220" show-overflow-tooltip /> |
| | | <el-table-column label="上传时间" prop="createTime" width="160" /> |
| | | <el-table-column label="操作" width="170"> |
| | | <template #default="scope"> |
| | | <template v-if="scope.row.pending"> |
| | | <el-button link type="danger" @click="removePending(scope.row)">删除</el-button> |
| | | </template> |
| | | <template v-else> |
| | | <el-button link type="primary" @click="previewFile(scope.row)">预览</el-button> |
| | | <el-button link type="primary" @click="downloadFile(scope.row)">下载</el-button> |
| | | <el-button v-if="!readonly" link type="danger" @click="removeFile(scope.row)">删除</el-button> |
| | | </template> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | <el-dialog v-else :title="dialogTitle" v-model="visible" width="760px" append-to-body @close="$emit('closed')"> |
| | | <div class="attachment-header"> |
| | | <div class="el-upload__tip">{{ readonly ? '仅可预览、下载附件' : tip }}</div> |
| | | <el-upload v-if="!readonly" :action="uploadAction" :headers="uploadHeader" multiple |
| | | :show-file-list="false" :on-success="handleUploadSuccess" :on-error="handleUploadError"> |
| | | <el-button size="small" type="primary">上传附件</el-button> |
| | | </el-upload> |
| | | </div> |
| | |
| | | <template #default="scope"> |
| | | <el-button link type="primary" @click="previewFile(scope.row)">预览</el-button> |
| | | <el-button link type="primary" @click="downloadFile(scope.row)">下载</el-button> |
| | | <el-button link type="danger" @click="removeFile(scope.row)">删除</el-button> |
| | | <el-button v-if="!readonly" link type="danger" @click="removeFile(scope.row)">删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | components: { |
| | | filePreview |
| | | }, |
| | | emits: ['closed'], |
| | | props: { |
| | | // 上传接口地址,如 /supplierManagement/uploadAttachment |
| | | uploadUrl: { |
| | |
| | | tip: { |
| | | type: String, |
| | | default: '支持任意格式文件,单个文件不超过200MB' |
| | | }, |
| | | // 只读模式:仅预览/下载,不显示上传和删除 |
| | | readonly: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // 内嵌模式:直接渲染上传区和附件列表,不弹管理弹窗 |
| | | inline: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // 内嵌模式关联主表ID,变化时自动加载附件 |
| | | mainId: { |
| | | type: [String, Number], |
| | | default: '' |
| | | }, |
| | | // 内嵌模式未关联主表ID时的提示 |
| | | emptyTip: { |
| | | type: String, |
| | | default: '请先选择数据后再上传附件' |
| | | }, |
| | | // 内嵌模式:没有主表ID时也允许选择文件,先暂存在页面,提交时再统一上传 |
| | | deferUpload: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | watch: { |
| | | mainId: { |
| | | immediate: true, |
| | | handler(val) { |
| | | if (!this.inline) { |
| | | return |
| | | } |
| | | const field = this.idField || this.idParam |
| | | this.currentRow = { [field]: val } |
| | | this.attachmentList = [] |
| | | if (val !== null && val !== undefined && val !== '') { |
| | | this.loadList() |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | visible: false, |
| | | attachmentList: [], |
| | | pendingFiles: [], |
| | | currentRow: {}, |
| | | previewVisible: false, |
| | | previewRow: {}, |
| | |
| | | currentId() { |
| | | const field = this.idField || this.idParam |
| | | return this.currentRow ? this.currentRow[field] : undefined |
| | | }, |
| | | canUpload() { |
| | | return !this.readonly && (!!this.currentId || this.deferUpload) |
| | | }, |
| | | displayList() { |
| | | const pending = this.pendingFiles.map(item => ({ |
| | | id: 'pending_' + item.uid, |
| | | uid: item.uid, |
| | | fileName: item.fileName, |
| | | createTime: '待上传', |
| | | pending: true |
| | | })) |
| | | return pending.concat(this.attachmentList) |
| | | }, |
| | | dialogTitle() { |
| | | const name = this.nameField && this.currentRow ? this.currentRow[this.nameField] : '' |
| | |
| | | handleUploadError() { |
| | | this.$message.error('上传失败,文件可能超过200MB') |
| | | }, |
| | | // 延迟上传模式:文件先暂存在页面,提交保存时再统一上传 |
| | | handleFileChange(file) { |
| | | if (!this.deferUpload || !file || !file.raw) { |
| | | return |
| | | } |
| | | this.pendingFiles.push({ uid: file.uid, fileName: file.name, raw: file.raw }) |
| | | }, |
| | | removePending(row) { |
| | | this.pendingFiles = this.pendingFiles.filter(item => item.uid !== row.uid) |
| | | }, |
| | | // 提交时调用:把暂存的附件上传到指定主表ID,全部成功才算完成 |
| | | flushPending(planDetailsId) { |
| | | if (!this.pendingFiles.length) { |
| | | return Promise.resolve() |
| | | } |
| | | const field = this.idField || this.idParam |
| | | this.currentRow = { [field]: planDetailsId } |
| | | return Promise.all(this.pendingFiles.slice().map(item => { |
| | | const formData = new FormData() |
| | | formData.append('file', item.raw) |
| | | return request({ |
| | | url: this.uploadUrl, |
| | | method: 'post', |
| | | params: { [this.idParam]: planDetailsId }, |
| | | data: formData, |
| | | headers: { 'Content-Type': 'multipart/form-data', repeatSubmit: false } |
| | | }).then(res => { |
| | | if (!res || res.code !== 200) { |
| | | throw new Error((res && res.msg) || ('附件“' + item.fileName + '”上传失败')) |
| | | } |
| | | this.pendingFiles = this.pendingFiles.filter(pending => pending.uid !== item.uid) |
| | | }) |
| | | })).then(() => { |
| | | this.loadList() |
| | | }) |
| | | }, |
| | | previewFile(row) { |
| | | this.previewRow = row |
| | | this.previewUrl = this.fullUrl(row.fileUrl) |
| | |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .lims-attachment { |
| | | width: 100%; |
| | | } |
| | | |
| | | .attachment-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | |
| | | .attachment-inline { |
| | | width: 100%; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" v-model="dialogVisible" |
| | | :title="currentStep === 0 ? '新增核查记录' : '设备核查记录'" width="50%" @close="resetForm"> |
| | | <el-steps v-if="currentStep === 1" :active="1" align-center finish-status="success"> |
| | | :title="currentStep === 0 ? '新增核查记录' : '设备核查记录'" top="5vh" width="960px" @close="resetForm"> |
| | | <el-steps v-if="currentStep === 1" class="record-steps" :active="1" align-center finish-status="success"> |
| | | <el-step title="填写核查记录"></el-step> |
| | | <el-step title="审核"></el-step> |
| | | </el-steps> |
| | | <el-form ref="recordForm" :model="form" :rules="rules" label-width="110px"> |
| | | <el-form-item label="设备编号:" prop="deviceNumber"> |
| | | <el-input v-model="form.deviceNumber" disabled size="small"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="设备名称:" prop="deviceName"> |
| | | <el-select v-if="currentStep === 0" v-model="selectedDeviceId" clearable filterable |
| | | placeholder="请选择设备" size="small" style="width: 100%" @change="changeMachineName"> |
| | | <el-option v-for="item in equipOptions" :key="item.id" :label="item.label + '-' + item.value" |
| | | :value="item.id"></el-option> |
| | | </el-select> |
| | | <el-input v-else v-model="form.deviceName" disabled size="small"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="核查时间:" prop="checkTime"> |
| | | <el-date-picker v-model="form.checkTime" :disabled="currentStep !== 0" clearable format="YYYY-MM" |
| | | placeholder="选择日期" size="small" style="width: 100%" type="month" value-format="YYYY-MM"> |
| | | </el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item label="核查指标:" prop="checkIndex"> |
| | | <el-input v-model="form.checkIndex" :disabled="currentStep !== 0" clearable size="small"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="核查方法:" prop="checkMethod"> |
| | | <el-input v-model="form.checkMethod" :disabled="currentStep !== 0" clearable size="small" |
| | | type="textarea"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="结果如何判定:" prop="howResults"> |
| | | <el-input v-model="form.howResults" :disabled="currentStep !== 0" clearable size="small" |
| | | type="textarea"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="核查责任人:" prop="checkChargerUserId"> |
| | | <el-select v-if="currentStep === 0" v-model="form.checkChargerUserId" clearable filterable |
| | | placeholder="请选择" size="small" style="width: 100%" @change="setCheckChargerUser"> |
| | | <el-option v-for="item in chargerOptions" :key="item.id" :label="item.name" |
| | | :value="item.id"></el-option> |
| | | </el-select> |
| | | <el-input v-else v-model="form.checkChargerUser" disabled size="small"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="备注:" prop="remark"> |
| | | <el-input v-model="form.remark" :disabled="currentStep !== 0" clearable size="small"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="附件:"> |
| | | <el-upload v-if="currentStep === 0" :action="javaApi + '/deviceScope/uploadFile'" :headers="uploadHeader" |
| | | :limit="1" :on-exceed="handleUploadExceed" :before-upload="beforeAttachmentUpload" |
| | | :on-success="handleAttachmentSuccess" :on-remove="handleAttachmentRemove"> |
| | | <el-button size="small" type="primary">选择附件</el-button> |
| | | </el-upload> |
| | | <el-link v-if="form.fileUrl" type="primary" @click="openAttachment"> |
| | | {{ form.fileName || '查看附件' }} |
| | | </el-link> |
| | | <span v-else-if="currentStep !== 0">—</span> |
| | | </el-form-item> |
| | | <el-form ref="recordForm" :model="form" :rules="rules" label-width="104px"> |
| | | <div class="form-section"> |
| | | <div class="form-section-title">基本信息</div> |
| | | <el-row :gutter="12"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="仪器名称:" prop="deviceName"> |
| | | <el-select v-if="currentStep === 0" v-model="selectedDeviceId" clearable filterable |
| | | placeholder="请选择设备" size="small" style="width: 100%" @change="changeMachineName"> |
| | | <el-option v-for="item in equipOptions" :key="item.id" :label="item.label + '-' + item.value" |
| | | :value="item.id"></el-option> |
| | | </el-select> |
| | | <el-input v-else v-model="form.deviceName" disabled size="small"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="检查日期:" prop="checkTime"> |
| | | <el-date-picker v-if="currentStep === 0" v-model="form.checkTime" clearable format="YYYY-MM-DD" |
| | | placeholder="选择检查日期" size="small" style="width: 100%" type="date" value-format="YYYY-MM-DD" |
| | | @change="resolveAttachmentPlan"> |
| | | </el-date-picker> |
| | | <el-input v-else v-model="form.checkTime" disabled size="small"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="管理编号:" prop="deviceNumber"> |
| | | <el-input v-model="form.deviceNumber" disabled size="small"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="设备型号:" prop="deviceModel"> |
| | | <el-input v-model="form.deviceModel" disabled size="small"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="核查人:" prop="checkChargerUserId"> |
| | | <el-select v-if="currentStep === 0" v-model="form.checkChargerUserId" clearable filterable |
| | | placeholder="请选择" size="small" style="width: 100%" @change="setCheckChargerUser"> |
| | | <el-option v-for="item in chargerOptions" :key="item.id" :label="item.name" |
| | | :value="item.id"></el-option> |
| | | </el-select> |
| | | <el-input v-else v-model="form.checkChargerUser" disabled size="small"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <div class="form-section"> |
| | | <div class="form-section-title">核查内容</div> |
| | | <el-row :gutter="12"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="环境温湿度:" prop="environment"> |
| | | <el-input v-model="form.environment" :disabled="currentStep !== 0" clearable size="small" |
| | | placeholder="如:25℃ / 50%RH"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="核查依据:" prop="checkBasis"> |
| | | <el-input v-model="form.checkBasis" :disabled="currentStep !== 0" clearable size="small"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="核查指标:" prop="checkIndex"> |
| | | <el-input v-model="form.checkIndex" :disabled="currentStep !== 0" clearable size="small"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="核查方式:" prop="checkMethod"> |
| | | <el-input v-model="form.checkMethod" :disabled="currentStep !== 0" clearable :rows="2" size="small" |
| | | type="textarea"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="结果如何判定:" prop="howResults"> |
| | | <el-input v-model="form.howResults" :disabled="currentStep !== 0" clearable :rows="2" size="small" |
| | | type="textarea"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="外观情况:"> |
| | | <el-radio-group v-model="form.appearanceStatus" :disabled="currentStep !== 0"> |
| | | <el-radio value="良好">良好</el-radio> |
| | | <el-radio value="一般">一般</el-radio> |
| | | <el-radio value="损坏">损坏</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="运行状态:"> |
| | | <el-radio-group v-model="form.runningStatus" :disabled="currentStep !== 0"> |
| | | <el-radio value="正常">正常</el-radio> |
| | | <el-radio value="异常">异常</el-radio> |
| | | <el-radio value="停机">停机</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="备注:" prop="remark"> |
| | | <el-input v-model="form.remark" :disabled="currentStep !== 0" clearable size="small"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <div class="form-section"> |
| | | <div class="form-section-title">附件资料</div> |
| | | <el-form-item label-width="0"> |
| | | <lims-attachment ref="recordAttachment" inline upload-url="/deviceExaminePlan/uploadAttachment" |
| | | select-url="/deviceExaminePlan/selectAttachments" delete-url="/deviceExaminePlan/deleteAttachment" |
| | | id-param="planDetailsId" name-field="deviceName" title="核查记录附件" |
| | | :main-id="form.planDetailsId" :readonly="currentStep === 1" |
| | | :defer-upload="currentStep === 0" :tip="attachmentTip"></lims-attachment> |
| | | <el-link v-if="form.fileUrl" type="primary" @click="openAttachment"> |
| | | {{ form.fileName || '查看原附件' }} |
| | | </el-link> |
| | | </el-form-item> |
| | | </div> |
| | | </el-form> |
| | | <template #footer><span class="dialog-footer"> |
| | | <el-button @click="resetForm">取 消</el-button> |
| | |
| | | addExamineRecord, |
| | | reviewExamineRecord, |
| | | deviceScopeSearch, |
| | | findExaminePlanDetail, |
| | | resolveExaminePlanDetail, |
| | | updateDeviceExaminePlanDetail, |
| | | } from '@/api/cnas/resourceDemand/device.js' |
| | | import { selectUserCondition } from "@/api/performance/class"; |
| | | import draftSave from '@/mixins/draftSave' |
| | | import LimsAttachment from '@/components/Attachment/lims-attachment.vue' |
| | | |
| | | const createEmptyForm = () => ({ |
| | | deviceId: '', |
| | | deviceName: '', |
| | | deviceNumber: '', |
| | | deviceModel: '', |
| | | checkTime: '', |
| | | checkIndex: '', |
| | | checkMethod: '', |
| | | howResults: '', |
| | | checkChargerUserId: '', |
| | | checkChargerUser: '', |
| | | environment: '', |
| | | checkBasis: '', |
| | | appearanceStatus: '', |
| | | runningStatus: '', |
| | | remark: '', |
| | | fileName: '', |
| | | fileUrl: '', |
| | |
| | | }) |
| | | export default { |
| | | name: "check-record", |
| | | mixins: [draftSave], |
| | | components: { LimsAttachment }, |
| | | data() { |
| | | // 这里存放数据 |
| | | return { |
| | |
| | | submitFormLoading: false, |
| | | userList: [], |
| | | rules: { |
| | | checkMethod: [{ required: true, message: '请填写核查方法', trigger: 'blur' }], |
| | | checkMethod: [{ required: true, message: '请填写核查方式', trigger: 'blur' }], |
| | | }, |
| | | } |
| | | }, |
| | |
| | | deviceId: row.deviceId || '', |
| | | deviceName: row.deviceName || '', |
| | | deviceNumber: row.deviceNumber || '', |
| | | checkTime: (row.checkTime || '').substring(0, 7), |
| | | deviceModel: row.deviceModel || '', |
| | | checkTime: row.checkTime || '', |
| | | checkIndex: row.checkIndex || '', |
| | | checkMethod: row.checkMethod || '', |
| | | howResults: row.howResults || '', |
| | | checkChargerUserId: row.checkChargerUserId || '', |
| | | checkChargerUser: row.checkChargerUser || '', |
| | | environment: row.environment || '', |
| | | checkBasis: row.checkBasis || '', |
| | | appearanceStatus: row.appearanceStatus || '', |
| | | runningStatus: row.runningStatus || '', |
| | | remark: row.remark || '', |
| | | fileName: row.fileName || '', |
| | | fileUrl: row.fileUrl || '', |
| | |
| | | this.form = createEmptyForm() |
| | | this.selectedDeviceId = '' |
| | | const now = new Date() |
| | | this.form.checkTime = now.getFullYear() + '-' + String(now.getMonth() + 1).padStart(2, '0') |
| | | this.form.checkTime = now.getFullYear() + '-' + String(now.getMonth() + 1).padStart(2, '0') + '-' + String(now.getDate()).padStart(2, '0') |
| | | this.getEquipOptions() |
| | | this.getUserList() |
| | | this.$nextTick(() => { |
| | | if (this.$refs.recordForm) { |
| | | this.$refs.recordForm.clearValidate() |
| | | } |
| | | this.draftRestore('checkRecordForm', 'form', 'new', 'dialogVisible') |
| | | if (this.form.deviceId) { |
| | | this.selectedDeviceId = this.form.deviceId |
| | | } |
| | | this.resolveAttachmentPlan() |
| | | }) |
| | | }, |
| | | // 按设备 id 回填名称和编号,避免同名设备选错 |
| | |
| | | this.form.deviceId = item.id |
| | | this.form.deviceName = item.deviceName |
| | | this.form.deviceNumber = item.managementNumber |
| | | this.form.deviceModel = item.specificationModel || '' |
| | | } else { |
| | | this.form.deviceId = '' |
| | | this.form.deviceName = '' |
| | | this.form.deviceNumber = '' |
| | | this.form.deviceModel = '' |
| | | } |
| | | this.resolveAttachmentPlan() |
| | | }, |
| | | setCheckChargerUser(value) { |
| | | const item = this.userList.find(user => user.id === value) |
| | |
| | | if (this.form.howResults) params.howResults = this.form.howResults |
| | | if (this.form.checkChargerUserId) params.checkChargerUserId = this.form.checkChargerUserId |
| | | if (this.form.checkChargerUser) params.checkChargerUser = this.form.checkChargerUser |
| | | if (this.form.deviceModel) params.deviceModel = this.form.deviceModel |
| | | params.environment = this.form.environment || '' |
| | | params.checkBasis = this.form.checkBasis || '' |
| | | params.appearanceStatus = this.form.appearanceStatus || '' |
| | | params.runningStatus = this.form.runningStatus || '' |
| | | if (this.form.remark) params.remark = this.form.remark |
| | | if (this.form.fileName) params.fileName = this.form.fileName |
| | | if (this.form.fileUrl) params.fileUrl = this.form.fileUrl |
| | | updateDeviceExaminePlanDetail(params).then(res => { |
| | | if (res.code !== 200) { |
| | | this.$message.error(res.msg || '保存核查记录失败') |
| | | this.submitFormLoading = false |
| | | return |
| | | } |
| | | addExamineRecord({ planDetailsId }).then(recordRes => { |
| | | if (recordRes.code == 200) { |
| | | this.$message.success('核查记录已提交,等待审核') |
| | | this.draftClear('checkRecordForm') |
| | | this.resetForm() |
| | | } else { |
| | | this.$message.error(recordRes.msg || '提交核查记录失败') |
| | | // 附件先暂存在页面上,确认提交时再连同核查记录一起保存,取消则什么都不留 |
| | | const attachmentRef = this.$refs.recordAttachment |
| | | const flushPending = attachmentRef ? attachmentRef.flushPending(planDetailsId) : Promise.resolve() |
| | | flushPending.then(() => { |
| | | updateDeviceExaminePlanDetail(params).then(res => { |
| | | if (res.code !== 200) { |
| | | this.$message.error(res.msg || '保存核查记录失败') |
| | | this.submitFormLoading = false |
| | | return |
| | | } |
| | | this.submitFormLoading = false |
| | | addExamineRecord({ planDetailsId }).then(recordRes => { |
| | | if (recordRes.code == 200) { |
| | | this.$message.success('核查记录已提交,等待审核') |
| | | this.resetForm() |
| | | } else { |
| | | this.$message.error(recordRes.msg || '提交核查记录失败') |
| | | } |
| | | this.submitFormLoading = false |
| | | }).catch(() => { |
| | | this.submitFormLoading = false |
| | | }) |
| | | }).catch(() => { |
| | | this.submitFormLoading = false |
| | | }) |
| | | }).catch(() => { |
| | | // 上传失败的具体原因由 request 拦截器统一提示 |
| | | this.submitFormLoading = false |
| | | }) |
| | | }, |
| | |
| | | reviewExamineRecord(params).then(res => { |
| | | if (res.code == 200) { |
| | | this.$message.success(statue === 1 ? '审核通过' : '已退回') |
| | | this.draftClear('checkRecordForm') |
| | | this.resetForm() |
| | | } |
| | | this.submitFormLoading = false |
| | |
| | | }) |
| | | }, |
| | | resetForm() { |
| | | this.draftStop('checkRecordForm') |
| | | this.dialogVisible = false |
| | | this.$emit('closeDialog1') |
| | | }, |
| | |
| | | this.userList = res.data |
| | | }) |
| | | }, |
| | | // 附件 |
| | | beforeAttachmentUpload(file) { |
| | | if (file.size > 1024 * 1024 * 10) { |
| | | this.$message.error('上传文件不超过10M') |
| | | return false |
| | | // 附件内嵌在表单里:设备+日期确定后只查可复用明细,不提前建档,避免取消后留下空记录 |
| | | resolveAttachmentPlan() { |
| | | if (this.currentStep !== 0 || !this.selectedDeviceId || !this.form.checkTime) { |
| | | this.form.planDetailsId = '' |
| | | return |
| | | } |
| | | return true |
| | | const deviceId = this.selectedDeviceId |
| | | const checkTime = this.form.checkTime |
| | | this.form.planDetailsId = '' |
| | | findExaminePlanDetail({ deviceId, checkTime }).then(res => { |
| | | if (res.code !== 200 || !res.data) { |
| | | return |
| | | } |
| | | // 请求期间用户可能已切换设备或日期,避免回填过期明细 |
| | | if (this.selectedDeviceId === deviceId && this.form.checkTime === checkTime) { |
| | | this.form.planDetailsId = res.data.planDetailsId |
| | | } |
| | | }).catch(() => { |
| | | }) |
| | | }, |
| | | handleUploadExceed() { |
| | | this.$message.warning('仅支持一个附件,请先移除已上传的附件') |
| | | }, |
| | | handleAttachmentSuccess(response) { |
| | | if (response.code == 200) { |
| | | this.form.fileName = response.data.name |
| | | this.form.fileUrl = response.data.url |
| | | this.$message.success('附件上传成功') |
| | | } else { |
| | | this.$message.error(response.msg || '附件上传失败') |
| | | } |
| | | }, |
| | | handleAttachmentRemove() { |
| | | this.form.fileName = '' |
| | | this.form.fileUrl = '' |
| | | }, |
| | | // 兼容历史单附件 |
| | | openAttachment() { |
| | | if (!this.form.fileUrl) { |
| | | return |
| | |
| | | }, |
| | | }, |
| | | computed: { |
| | | // 附件不提前上传,选好后随核查记录一起提交保存 |
| | | attachmentTip() { |
| | | return '可直接选择附件,点“确认”时随核查记录一起保存' |
| | | }, |
| | | // 责任人下拉:已保存的责任人不在候选列表时补一条,避免回显成用户ID |
| | | chargerOptions() { |
| | | const list = this.userList || [] |
| | |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .record-steps { |
| | | margin-bottom: 14px; |
| | | } |
| | | |
| | | .form-section { |
| | | padding: 12px 14px 0; |
| | | border: 1px solid #ebeef5; |
| | | border-radius: 6px; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .form-section:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .form-section-title { |
| | | display: flex; |
| | | align-items: center; |
| | | padding-left: 8px; |
| | | border-left: 3px solid var(--el-color-primary); |
| | | margin-bottom: 12px; |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | line-height: 1; |
| | | color: #303133; |
| | | } |
| | | |
| | | .form-section :deep(.el-form-item) { |
| | | margin-bottom: 12px; |
| | | } |
| | | </style> |
| | |
| | | <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> |
| | | <span class="title" style="margin-bottom: 0;">{{ planInfo.planName || (planYear ? 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="handleAddRecord">新增核查记录</el-button> |
| | | <el-button size="small" type="primary" @click="loadPlan">刷新</el-button> |
| | | <el-button size="small" type="primary" @click="loadYearOptions">刷新</el-button> |
| | | <el-button size="small" type="primary" @click="downLoadPost">导出</el-button> |
| | | </div> |
| | | </div> |
| | |
| | | <el-table-column label="核查方法" min-width="140" prop="checkMethod" show-overflow-tooltip></el-table-column> |
| | | <el-table-column label="结果如何判定" min-width="140" prop="howResults" show-overflow-tooltip></el-table-column> |
| | | <el-table-column label="核查负责人" min-width="120" prop="checkChargerUser"></el-table-column> |
| | | <el-table-column label="记录状态" min-width="100" prop="recordStatus"> |
| | | <el-table-column label="审核状态" min-width="100" prop="recordStatus"> |
| | | <template #default="scope"> |
| | | <el-tag type="" v-if="scope.row.recordStatus === 0" disable-transitions>未开始</el-tag> |
| | | <el-tag type="warning" v-if="scope.row.recordStatus === 1" disable-transitions>待批准</el-tag> |
| | |
| | | <el-tag type="danger" v-if="scope.row.recordStatus === 3" disable-transitions>不通过</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="对比状态" min-width="100" prop="recordContrastStatus"> |
| | | <template #default="scope"> |
| | | <el-tag type="" v-if="scope.row.recordContrastStatus === 0" disable-transitions>未开始</el-tag> |
| | | <el-tag type="warning" v-if="scope.row.recordContrastStatus === 1" disable-transitions>待批准</el-tag> |
| | | <el-tag type="success" v-if="scope.row.recordContrastStatus === 2" disable-transitions>通过</el-tag> |
| | | <el-tag type="danger" v-if="scope.row.recordContrastStatus === 3" disable-transitions>不通过</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="备注" min-width="130" prop="remark"></el-table-column> |
| | | <el-table-column label="附件" min-width="140"> |
| | | <template #default="scope"> |
| | | <el-link v-if="scope.row.fileUrl" type="primary" @click="openAttachment(scope.row)"> |
| | | <el-link v-if="scope.row.attachmentCount > 0" type="primary" @click="handleAttachment(scope.row)"> |
| | | 查看附件({{ scope.row.attachmentCount }}) |
| | | </el-link> |
| | | <el-link v-else-if="scope.row.fileUrl" type="primary" @click="openAttachment(scope.row)"> |
| | | {{ scope.row.fileName || '查看附件' }} |
| | | </el-link> |
| | | <span v-else>—</span> |
| | |
| | | <el-table-column align="center" fixed="right" label="操作" min-width="320"> |
| | | <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 v-if="scope.row.recordStatus === 1" size="small" link type="primary" |
| | | <el-button v-if="scope.row.recordStatus === 0 || scope.row.recordStatus === 1" |
| | | size="small" link type="primary" :disabled="!scope.row.checkChargerUser" |
| | | @click="handleRecord(scope.row)">审核</el-button> |
| | | <el-upload class="row-upload" :action="javaApi + '/deviceScope/uploadFile'" |
| | | :headers="uploadHeader" :show-file-list="false" :before-upload="beforeAttachmentUpload" |
| | | :on-success="(res) => handleAttachmentSuccess(res, scope.row)" |
| | | :on-error="handleAttachmentError"> |
| | | <el-button size="small" link type="primary">上传附件</el-button> |
| | | </el-upload> |
| | | <el-button size="small" link type="primary" @click="handleDown(scope.row)">导出</el-button> |
| | | <el-button v-if="scope.row.recordStatus === 2 || scope.row.recordStatus === 3" |
| | | size="small" link type="primary" @click="handleDown(scope.row)">导出</el-button> |
| | | <el-button v-if="scope.row.recordStatus === 0 && scope.row.recordContrastStatus === 0" |
| | | size="small" link type="danger" @click="deleteFun1(scope.row.planDetailsId)">删除</el-button> |
| | | </template> |
| | |
| | | @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="设备核查计划" |
| | | width="50%" @close="resetForm"> |
| | | <el-form ref="modelForm" :model="form" :rules="rules" label-width="110px"> |
| | | <el-form-item label="设备编号:" prop="deviceNumber"> |
| | | <el-input v-model="form.deviceNumber" :disabled="operationType === 'view'" clearable |
| | | size="small"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="设备名称:" prop="deviceName"> |
| | | <el-input v-model="form.deviceName" :disabled="operationType === 'view'" clearable |
| | | size="small"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="核查时间:" prop="checkTime"> |
| | | <el-date-picker v-model="form.checkTime" :disabled="operationType === 'view'" clearable format="YYYY-MM" |
| | | placeholder="选择日期" size="small" style="width:100%" type="month" value-format="YYYY-MM"> |
| | | </el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item label="核查指标:" prop="checkIndex"> |
| | | <el-input v-model="form.checkIndex" :disabled="operationType === 'view'" clearable |
| | | size="small"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="核查方法:" prop="checkMethod"> |
| | | <el-input v-model="form.checkMethod" :disabled="operationType === 'view'" clearable size="small" |
| | | type="textarea"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="结果如何判定:" prop="howResults"> |
| | | <el-input v-model="form.howResults" :disabled="operationType === 'view'" clearable size="small" |
| | | type="textarea"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="核查责任人:" prop="checkChargerUserId"> |
| | | <el-select v-model="form.checkChargerUserId" @change="setCheckChargerUser" |
| | | :disabled="operationType === 'view'" placeholder="请选择" size="small" style="width: 100%"> |
| | | <el-option v-for="item in chargerOptions" :key="item.id" :label="item.name" |
| | | :value="item.id"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="备注:" prop="remark"> |
| | | <el-input v-model="form.remark" :disabled="operationType === 'view'" clearable size="small"></el-input> |
| | | </el-form-item> |
| | | <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" v-model="dialogVisible" |
| | | :title="operationType === 'view' ? '设备核查记录' : '编辑核查记录'" top="5vh" width="960px" @close="resetForm"> |
| | | <el-form ref="modelForm" :model="form" :rules="rules" label-width="104px"> |
| | | <div class="form-section"> |
| | | <div class="form-section-title">基本信息</div> |
| | | <el-row :gutter="12"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="仪器名称:" prop="deviceName"> |
| | | <el-input v-model="form.deviceName" disabled size="small"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="检查日期:" prop="checkTime"> |
| | | <el-date-picker v-model="form.checkTime" :disabled="operationType === 'view'" clearable |
| | | format="YYYY-MM" placeholder="选择检查日期" size="small" style="width:100%" type="month" |
| | | value-format="YYYY-MM"> |
| | | </el-date-picker> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="管理编号:" prop="deviceNumber"> |
| | | <el-input v-model="form.deviceNumber" disabled size="small"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="设备型号:" prop="deviceModel"> |
| | | <el-input v-model="form.deviceModel" disabled size="small"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="核查人:" prop="checkChargerUserId"> |
| | | <el-select v-model="form.checkChargerUserId" @change="setCheckChargerUser" clearable filterable |
| | | :disabled="operationType === 'view'" placeholder="请选择" size="small" style="width: 100%"> |
| | | <el-option v-for="item in chargerOptions" :key="item.id" :label="item.name" |
| | | :value="item.id"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <div class="form-section"> |
| | | <div class="form-section-title">核查内容</div> |
| | | <el-row :gutter="12"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="环境温湿度:" prop="environment"> |
| | | <el-input v-model="form.environment" :disabled="operationType === 'view'" clearable size="small" |
| | | placeholder="如:25℃ / 50%RH"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="核查依据:" prop="checkBasis"> |
| | | <el-input v-model="form.checkBasis" :disabled="operationType === 'view'" clearable |
| | | size="small"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="核查指标:" prop="checkIndex"> |
| | | <el-input v-model="form.checkIndex" :disabled="operationType === 'view'" clearable |
| | | size="small"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="核查方式:" prop="checkMethod"> |
| | | <el-input v-model="form.checkMethod" :disabled="operationType === 'view'" clearable :rows="2" |
| | | size="small" type="textarea"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="结果如何判定:" prop="howResults"> |
| | | <el-input v-model="form.howResults" :disabled="operationType === 'view'" clearable :rows="2" |
| | | size="small" type="textarea"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="外观情况:"> |
| | | <el-radio-group v-model="form.appearanceStatus" :disabled="operationType === 'view'"> |
| | | <el-radio value="良好">良好</el-radio> |
| | | <el-radio value="一般">一般</el-radio> |
| | | <el-radio value="损坏">损坏</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="运行状态:"> |
| | | <el-radio-group v-model="form.runningStatus" :disabled="operationType === 'view'"> |
| | | <el-radio value="正常">正常</el-radio> |
| | | <el-radio value="异常">异常</el-radio> |
| | | <el-radio value="停机">停机</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="备注:" prop="remark"> |
| | | <el-input v-model="form.remark" :disabled="operationType === 'view'" clearable size="small"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <div class="form-section"> |
| | | <div class="form-section-title">附件资料</div> |
| | | <el-form-item label-width="0"> |
| | | <lims-attachment inline upload-url="/deviceExaminePlan/uploadAttachment" |
| | | select-url="/deviceExaminePlan/selectAttachments" delete-url="/deviceExaminePlan/deleteAttachment" |
| | | id-param="planDetailsId" name-field="deviceName" title="核查记录附件" |
| | | :main-id="form.planDetailsId" :readonly="operationType === 'view'"></lims-attachment> |
| | | <el-link v-if="form.fileUrl" type="primary" @click="openAttachment(form)"> |
| | | {{ form.fileName || '查看原附件' }} |
| | | </el-link> |
| | | </el-form-item> |
| | | </div> |
| | | </el-form> |
| | | <template #footer><span class="dialog-footer"> |
| | | <el-button @click="resetForm">取 消</el-button> |
| | |
| | | v-if="operationType !== 'view'">确 认</el-button> |
| | | </span></template> |
| | | </el-dialog> |
| | | <el-dialog v-model="downloadDialog" title="导出" width="600px"> |
| | | <span> |
| | | <el-button :loading="outLoading" type="primary" :disabled="!downRow.recordStatus" |
| | | @click="controlDown">核查记录</el-button> |
| | | <el-button :loading="outLoading" type="primary" :disabled="!downRow.recordContrastStatus" |
| | | @click="processingDown">核查比对记录</el-button> |
| | | </span> |
| | | <el-dialog v-model="downloadDialog" title="导出" width="480px"> |
| | | <div class="export-panel"> |
| | | <div class="export-panel-head"> |
| | | <span class="export-panel-name">仪器设备期间核查记录表</span> |
| | | <el-tag v-if="downRow.recordStatus === 2" type="success" disable-transitions>通过</el-tag> |
| | | <el-tag v-else-if="downRow.recordStatus === 1" type="warning" disable-transitions>待批准</el-tag> |
| | | <el-tag v-else-if="downRow.recordStatus === 3" type="danger" disable-transitions>不通过</el-tag> |
| | | <el-tag v-else type="info" disable-transitions>未开始</el-tag> |
| | | </div> |
| | | <div class="export-panel-meta"> |
| | | <div class="export-panel-item"> |
| | | <span class="export-panel-label">设备编号</span>{{ downRow.deviceNumber || '—' }} |
| | | </div> |
| | | <div class="export-panel-item"> |
| | | <span class="export-panel-label">设备名称</span>{{ downRow.deviceName || '—' }} |
| | | </div> |
| | | <div class="export-panel-item"> |
| | | <span class="export-panel-label">核查时间</span>{{ formatCheckMonth(null, null, downRow.checkTime) || '—' }} |
| | | </div> |
| | | </div> |
| | | <div v-if="!canExport" class="export-panel-tip"> |
| | | {{ downRow.recordStatus === 1 ? '该计划行尚未审核完成,审核通过或不通过后才能导出。' : '该计划行还没有核查记录,录入并提交审核后才能导出。' }} |
| | | </div> |
| | | </div> |
| | | <template #footer><span class="dialog-footer"> |
| | | <el-button @click="downloadDialog = false">取 消</el-button> |
| | | <el-button :loading="outLoading" type="primary" :disabled="!canExport" |
| | | @click="controlDown">导出记录表</el-button> |
| | | </span></template> |
| | | </el-dialog> |
| | | <check-record v-if="checkRecord" ref="checkRecord" @closeDialog1="closeDialog1"></check-record> |
| | | <lims-attachment ref="rowAttachment" upload-url="/deviceExaminePlan/uploadAttachment" |
| | | select-url="/deviceExaminePlan/selectAttachments" delete-url="/deviceExaminePlan/deleteAttachment" |
| | | id-param="planDetailsId" name-field="deviceName" title="核查记录附件" :readonly="attachmentReadonly" |
| | | @closed="getYearTableDetailData"></lims-attachment> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import CheckRecord from "./checkRecord.vue"; |
| | | import LimsAttachment from '@/components/Attachment/lims-attachment.vue' |
| | | import { |
| | | pageDeviceExaminePlan, |
| | | getExaminePlanByYear, |
| | |
| | | export default { |
| | | name: "equipment-verification-plan", |
| | | // import 引入的组件需要注入到对象中才能使用 |
| | | components: { CheckRecord }, |
| | | components: { CheckRecord, LimsAttachment }, |
| | | mixins: [draftSave], |
| | | props: { |
| | | clickNodeVal: { |
| | |
| | | form: { |
| | | deviceNumber: '', |
| | | deviceName: '', |
| | | deviceModel: '', |
| | | checkTime: '', |
| | | checkIndex: '', |
| | | checkMethod: '', |
| | | howResults: '', |
| | | checkChargerUserId: '', |
| | | checkChargerUser: '', |
| | | environment: '', |
| | | checkBasis: '', |
| | | appearanceStatus: '', |
| | | runningStatus: '', |
| | | remark: '', |
| | | fileName: '', |
| | | fileUrl: '', |
| | | planId: '', |
| | | planDetailsId: '', |
| | | }, |
| | | operationType: '', |
| | | rules: { |
| | | deviceNumber: [{ required: true, message: '请填写设备编号', trigger: 'blur' }], |
| | | checkMethod: [{ required: true, message: '请填写核查方法', trigger: 'blur' }], |
| | | checkMethod: [{ required: true, message: '请填写核查方式', trigger: 'blur' }], |
| | | }, |
| | | yearTableDetailDataLoading: false, |
| | | submitFormLoading: false, |
| | | userList: [], |
| | | attachmentReadonly: false, |
| | | checkRecord: false, |
| | | downloadDialog: false, |
| | | outLoading: false, |
| | |
| | | }, |
| | | // 方法集合 |
| | | methods: { |
| | | // 年份下拉选项:已有计划年份 + 当前年份 |
| | | // 年份下拉只保留有计划明细的年份,空年份自动消失 |
| | | loadYearOptions() { |
| | | pageDeviceExaminePlan({ |
| | | current: 1, |
| | |
| | | if (res.code == 200) { |
| | | years = (res.data.records || []).map(r => r.planYear).filter(Boolean) |
| | | } |
| | | const currentYear = String(new Date().getFullYear()) |
| | | if (years.indexOf(currentYear) === -1) { |
| | | years.push(currentYear) |
| | | const options = [...new Set(years)].sort((a, b) => b.localeCompare(a)) |
| | | this.yearOptions = options |
| | | if (options.length === 0) { |
| | | this.planYear = '' |
| | | this.planInfo = {} |
| | | this.yearTableDetailData = [] |
| | | this.pagination1.total = 0 |
| | | return |
| | | } |
| | | this.yearOptions = [...new Set(years)].sort((a, b) => b.localeCompare(a)) |
| | | this.planYear = currentYear |
| | | if (options.indexOf(this.planYear) === -1) { |
| | | const currentYear = String(new Date().getFullYear()) |
| | | this.planYear = options.indexOf(currentYear) > -1 ? currentYear : options[0] |
| | | } |
| | | this.loadPlan() |
| | | }) |
| | | }, |
| | |
| | | }, |
| | | // 查询年份计划(不存在自动创建并补全到点明细),随后刷新明细 |
| | | loadPlan() { |
| | | if (!this.planYear) { |
| | | this.planInfo = {} |
| | | this.yearTableDetailData = [] |
| | | this.pagination1.total = 0 |
| | | return |
| | | } |
| | | getExaminePlanByYear({ planYear: this.planYear }).then(res => { |
| | | if (res.code == 200) { |
| | | this.planInfo = res.data || {} |
| | |
| | | }) |
| | | }, |
| | | // 到点需核查的行标红 |
| | | // 核查时间按月份显示(兼容历史数据中的完整日期) |
| | | // 手动录入的核查日期显示到日,系统登记的月份数据仍按年月显示 |
| | | formatCheckMonth(row, column, cellValue) { |
| | | if (cellValue === null || cellValue === undefined || cellValue === '') { |
| | | return cellValue |
| | | } |
| | | const str = String(cellValue).trim().replace(/[./]/g, '-') |
| | | const dateMatched = str.match(/^(\d{4})-(\d{1,2})-(\d{1,2})/) |
| | | if (dateMatched) { |
| | | return `${dateMatched[1]}-${dateMatched[2].padStart(2, '0')}-${dateMatched[3].padStart(2, '0')}` |
| | | } |
| | | const matched = str.match(/^(\d{4})-(\d{1,2})/) |
| | | if (matched) { |
| | | return `${matched[1]}-${matched[2].padStart(2, '0')}` |
| | | } |
| | | const formatted = formatListDate(str) |
| | | const fallback = String(formatted).match(/^(\d{4})-(\d{1,2})/) |
| | | return fallback ? `${fallback[1]}-${fallback[2].padStart(2, '0')}` : cellValue |
| | | const fallback = String(formatted).match(/^(\d{4})-(\d{1,2})-(\d{1,2})/) |
| | | if (fallback) { |
| | | return `${fallback[1]}-${fallback[2].padStart(2, '0')}-${fallback[3].padStart(2, '0')}` |
| | | } |
| | | const monthFallback = String(formatted).match(/^(\d{4})-(\d{1,2})/) |
| | | return monthFallback ? `${monthFallback[1]}-${monthFallback[2].padStart(2, '0')}` : cellValue |
| | | }, |
| | | tableRowClassName({ row }) { |
| | | return row.redFlag === 1 ? 'red-row' : '' |
| | |
| | | }, |
| | | // 明细-删除 |
| | | deleteFun1(id) { |
| | | this.$confirm('此操作将永久删除该条明细, 是否继续?', '提示', { |
| | | this.$confirm('删除后,若该设备还有审核通过的核查记录,档案的最近核查日期将回退到最近一次完成记录;若没有,则清空档案的核查日期和核查周期。是否继续?', '提示', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | delDeviceExaminePlanDetail({ planDetailsId: id }).then(res => { |
| | | this.$message.success('删除成功!'); |
| | | this.getYearTableDetailData() |
| | | this.loadYearOptions() |
| | | }); |
| | | }).catch(() => { |
| | | this.$message({ |
| | |
| | | const isImage = /\.(jpg|jpeg|png|gif)$/i.test(row.fileUrl) |
| | | window.open(this.javaApi + (isImage ? '/img/' : '/word/') + row.fileUrl, '_blank') |
| | | }, |
| | | beforeAttachmentUpload(file) { |
| | | if (file.size > 1024 * 1024 * 10) { |
| | | this.$message.error('上传文件不超过10M') |
| | | return false |
| | | } |
| | | return true |
| | | }, |
| | | // 附件上传成功后保存到计划明细 |
| | | handleAttachmentSuccess(response, row) { |
| | | if (response.code == 200) { |
| | | updateDeviceExaminePlanDetail({ |
| | | planDetailsId: row.planDetailsId, |
| | | fileName: response.data.name, |
| | | fileUrl: response.data.url |
| | | }).then(res => { |
| | | if (res.code == 200) { |
| | | this.$message.success('附件上传成功') |
| | | this.getYearTableDetailData() |
| | | } else { |
| | | this.$message.error(res.msg || '附件保存失败') |
| | | } |
| | | }) |
| | | } else { |
| | | this.$message.error(response.msg || '附件上传失败') |
| | | } |
| | | }, |
| | | handleAttachmentError() { |
| | | this.$message.error('附件上传失败') |
| | | // 列表附件列只读查看(上传/删除入口只在编辑、新增弹窗内) |
| | | handleAttachment(row) { |
| | | this.attachmentReadonly = true |
| | | this.$refs.rowAttachment.open(row) |
| | | }, |
| | | // 关闭记录弹框 |
| | | closeDialog1() { |
| | | this.checkRecord = false |
| | | this.getYearTableDetailData() |
| | | this.loadYearOptions() |
| | | }, |
| | | // 打开导出弹框 |
| | | handleDown(row) { |
| | |
| | | // 是否已完成审批(批准/不批准) |
| | | isRatified() { |
| | | return this.planInfo.ratifyStatus === 0 || this.planInfo.ratifyStatus === 1; |
| | | }, |
| | | // 记录状态为通过或不通过(审核已结束)才允许导出 |
| | | canExport() { |
| | | return this.downRow.recordStatus === 2 || this.downRow.recordStatus === 3; |
| | | }, |
| | | // 责任人下拉:已保存的责任人不在候选列表时补一条,避免回显成用户ID |
| | | chargerOptions() { |
| | |
| | | background: #ffcccc !important; |
| | | } |
| | | |
| | | .row-upload { |
| | | display: inline-block; |
| | | margin-left: 10px; |
| | | vertical-align: middle; |
| | | .form-section { |
| | | padding: 12px 14px 0; |
| | | border: 1px solid #ebeef5; |
| | | border-radius: 6px; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .form-section:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .form-section-title { |
| | | display: flex; |
| | | align-items: center; |
| | | padding-left: 8px; |
| | | border-left: 3px solid var(--el-color-primary); |
| | | margin-bottom: 12px; |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | line-height: 1; |
| | | color: #303133; |
| | | } |
| | | |
| | | .form-section :deep(.el-form-item) { |
| | | margin-bottom: 12px; |
| | | } |
| | | |
| | | .export-panel { |
| | | border: 1px solid #e4e7ed; |
| | | border-radius: 6px; |
| | | padding: 18px 20px; |
| | | background: #fafbfc; |
| | | } |
| | | |
| | | .export-panel-head { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | gap: 12px; |
| | | margin-bottom: 14px; |
| | | } |
| | | |
| | | .export-panel-name { |
| | | font-size: 15px; |
| | | font-weight: 600; |
| | | color: var(--lims-text); |
| | | } |
| | | |
| | | .export-panel-meta { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 8px; |
| | | font-size: 13px; |
| | | color: #606266; |
| | | } |
| | | |
| | | .export-panel-item { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .export-panel-label { |
| | | width: 72px; |
| | | flex-shrink: 0; |
| | | color: #909399; |
| | | } |
| | | |
| | | .export-panel-tip { |
| | | margin-top: 14px; |
| | | padding: 8px 12px; |
| | | border-radius: 4px; |
| | | background: #fdf6ec; |
| | | color: #e6a23c; |
| | | font-size: 13px; |
| | | line-height: 1.5; |
| | | } |
| | | </style> |
| | |
| | | <el-form :model="search" ref="search" size="small" :inline="true"> |
| | | <el-form-item label="样品编号"> |
| | | <el-input v-model="search.sampleCode" clearable placeholder="请输入" size="small" |
| | | @keyup.enter="getTableList(clickNodeVal.value)"></el-input> |
| | | @keyup.enter="getTableList()"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="管理编号"> |
| | | <el-form-item label="设备编号"> |
| | | <el-input v-model="search.managementNumber" clearable placeholder="请输入" size="small" |
| | | @keyup.enter="getTableList(clickNodeVal.value)"></el-input> |
| | | @keyup.enter="getTableList()"></el-input> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button size="small" type="primary" @click="getTableList(clickNodeVal.value)">查询</el-button> |
| | | <el-button size="small" type="primary" @click="getTableList()">查询</el-button> |
| | | <el-button size="small" @click="resetSearch">重置</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div> |
| | | <el-button v-if="isMenuList !== 1" size="small" type="primary" @click="dialogVisible = true, openAdd()">新 建</el-button> |
| | | <el-button :loading="outLoading" size="small" type="primary" @click="openHandleOut">导 出</el-button> |
| | | </div> |
| | | </div> |
| | | <div> |
| | | <el-table ref="Recordtable" :data="formParamList" height="calc(100vh - 20em)" |
| | | v-loading="tableLoading" |
| | | border> |
| | | <!-- 表格列 --> |
| | | <el-table-column label="序号" type="index" width="70" align="center"> |
| | | <template v-slot="scope"> |
| | | <el-table ref="Recordtable" :data="formParamList" height="calc(100vh - 25em)" |
| | | v-loading="tableLoading" border> |
| | | <el-table-column label="序号" type="index" width="60" align="center"> |
| | | <template #default="scope"> |
| | | <span>{{ (search.current - 1) * search.size + scope.$index + 1 }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="样品编号" min-width="180" prop="sampleCode" /> |
| | | <el-table-column label="设备名称" min-width="150" prop="deviceName" /> |
| | | <el-table-column label="管理编号" min-width="150" prop="managementNumber" /> |
| | | <el-table-column label="使用前" min-width="120" prop="useBefore"> |
| | | <template v-slot="scope"> |
| | | {{ scope.row.useBefore === 1 ? '良好' : '异常' }} |
| | | <el-table-column label="设备名称" min-width="140" prop="deviceName" show-overflow-tooltip /> |
| | | <el-table-column label="设备型号" min-width="120" prop="specificationModel" show-overflow-tooltip /> |
| | | <el-table-column label="设备编号" min-width="130" prop="managementNumber" /> |
| | | <el-table-column label="使用日期" width="110" align="center"> |
| | | <template #default="scope"> |
| | | {{ formatDateCell(scope.row.useStartDate) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="使用后" min-width="120" prop="useAfter"> |
| | | <template v-slot="scope"> |
| | | {{ scope.row.useAfter === 1 ? '良好' : '异常' }} |
| | | <el-table-column label="样品编号" min-width="150" prop="sampleCode"> |
| | | <template #default="scope"> |
| | | <span>{{ scope.row.sampleCode }}</span> |
| | | <el-tooltip v-if="scope.row.orderCode" :content="'关联原始记录:' + scope.row.orderCode" placement="top"> |
| | | <lims-icon class="link-icon" name="el-icon-link"></lims-icon> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | <!-- <el-table-column label="异常情况" min-width="120" prop="abnormal" />--> |
| | | <el-table-column label="使用开始日期" min-width="170" prop="useStartDate" :formatter="formatDateCell" /> |
| | | <el-table-column label="使用结束日期" min-width="170" prop="useEndDate" :formatter="formatDateCell" /> |
| | | <el-table-column label="使用人" min-width="120" prop="usePerson" /> |
| | | <el-table-column label="备注" min-width="120" prop="remark" /> |
| | | <!-- 操作按钮 --> |
| | | <el-table-column label="时间(24小时制)" align="center"> |
| | | <el-table-column label="开始" width="90" align="center"> |
| | | <template #default="scope">{{ formatTimeCell(scope.row.useStartDate) }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="结束" width="90" align="center"> |
| | | <template #default="scope">{{ formatTimeCell(scope.row.useEndDate) }}</template> |
| | | </el-table-column> |
| | | </el-table-column> |
| | | <el-table-column label="设备状况" align="center"> |
| | | <el-table-column label="使用前" width="80" align="center"> |
| | | <template #default="scope">{{ formatStatus(scope.row.useBefore) }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="使用后" width="80" align="center"> |
| | | <template #default="scope">{{ formatStatus(scope.row.useAfter) }}</template> |
| | | </el-table-column> |
| | | </el-table-column> |
| | | <el-table-column label="环境条件" align="center"> |
| | | <el-table-column label="℃" width="80" align="center" prop="temperature" /> |
| | | <el-table-column label="%RH" width="80" align="center" prop="humidity" /> |
| | | </el-table-column> |
| | | <el-table-column label="使用人" width="100" prop="usePerson" /> |
| | | <el-table-column label="备注" min-width="140" prop="remark" show-overflow-tooltip /> |
| | | <el-table-column fixed="right" label="操作" width="150" align="center"> |
| | | <template #default="scope"> |
| | | <el-button size="small" link type="primary" @click="showDetailsDialog('edit', scope.row)">编辑</el-button> |
| | |
| | | @current-change="handleCurrentChange" background> |
| | | </el-pagination> |
| | | </div> |
| | | <el-dialog v-model="dialogVisible" title="仪器设备使用记录表" top="5vh" width="55%"> |
| | | <el-form ref="form" :model="form" label-width="130px"> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item :rules="[{ required: true, message: '样品编号', trigger: 'blur' }]" label="样品编号:" |
| | | <el-dialog v-model="dialogVisible" title="仪器设备运行记录" top="5vh" width="70%"> |
| | | <el-form ref="form" :model="form" label-width="105px"> |
| | | <el-row :gutter="16"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="设备名称:"> |
| | | <el-input v-model="form.deviceName" disabled size="small"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="设备型号:"> |
| | | <el-input v-model="form.specificationModel" disabled size="small"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="设备编号:"> |
| | | <el-input v-model="form.managementNumber" disabled size="small"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item :rules="[{ required: true, message: '请选择使用日期', trigger: 'change' }]" label="使用日期:" |
| | | prop="useDate"> |
| | | <el-date-picker v-model="form.useDate" :disabled="operationType === 'view'" format="YYYY-MM-DD" |
| | | placeholder="选择使用日期" size="small" style="width: 100%" type="date" value-format="YYYY-MM-DD" |
| | | :disabled-date="disabledDate"> |
| | | </el-date-picker> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item :rules="[{ required: true, message: '请输入样品编号', trigger: 'blur' }]" label="样品编号:" |
| | | prop="sampleCode"> |
| | | <el-input v-model="form.sampleCode" :disabled="operationType === 'view'" size="small" |
| | | style="width: 100%;"></el-input> |
| | | <el-input v-model="form.sampleCode" :disabled="operationType === 'view'" size="small"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设备名称:" required> |
| | | <el-input v-model="form.deviceName" :disabled="operationType === 'view'" size="small" |
| | | style="width: 100%;"></el-input> |
| | | <el-form-item :rules="[{ required: true, message: '请选择开始时间', trigger: 'change' }]" label="开始时间:" |
| | | prop="useStartTime"> |
| | | <el-time-picker v-model="form.useStartTime" :disabled="operationType === 'view'" format="HH:mm" |
| | | placeholder="选择开始时间" size="small" style="width: 100%" value-format="HH:mm:ss"> |
| | | </el-time-picker> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="管理编号:" required> |
| | | <el-input v-model="form.managementNumber" :disabled="operationType === 'view'" size="small" |
| | | style="width: 100%;"></el-input> |
| | | <el-form-item :rules="[{ required: true, message: '请选择结束时间', trigger: 'change' }]" label="结束时间:" |
| | | prop="useEndTime"> |
| | | <el-time-picker v-model="form.useEndTime" :disabled="operationType === 'view'" format="HH:mm" |
| | | placeholder="选择结束时间" size="small" style="width: 100%" value-format="HH:mm:ss"> |
| | | </el-time-picker> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item :rules="[{ required: true, message: '请选择使用前', trigger: 'change' }]" label="使用前:" |
| | | <el-form-item :rules="[{ required: true, message: '请选择使用前状态', trigger: 'change' }]" label="使用前:" |
| | | prop="useBefore"> |
| | | <el-radio-group v-model="form.useBefore" :disabled="operationType === 'view'"> |
| | | <el-radio :value="1">良好</el-radio> |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item :rules="[{ required: true, message: '请选择使用后', trigger: 'change' }]" label="使用后:" |
| | | <el-form-item :rules="[{ required: true, message: '请选择使用后状态', trigger: 'change' }]" label="使用后:" |
| | | prop="useAfter"> |
| | | <el-radio-group v-model="form.useAfter" :disabled="operationType === 'view'"> |
| | | <el-radio :value="1">良好</el-radio> |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item :rules="[{ required: true, message: '请输入使用日期', trigger: 'blur' }]" label="使用日期:" |
| | | prop="useDateList"> |
| | | <el-date-picker v-model="form.useDateList" :disabled="operationType === 'view'" end-placeholder="结束日期" |
| | | format="YYYY-MM-DD HH:mm:ss" size="small" start-placeholder="开始日期" style="width:100%" |
| | | type="datetimerange" value-format="YYYY-MM-DD HH:mm:ss" |
| | | :disabled-date="disabledDate"> |
| | | </el-date-picker> |
| | | <el-form-item label="环境温度:"> |
| | | <el-input v-model="form.temperature" :disabled="operationType === 'view'" placeholder="请输入温度" size="small"> |
| | | <template #append>℃</template> |
| | | </el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item :rules="[{ required: true, message: '请输入使用人', trigger: 'change' }]" label="使用人:" |
| | | <el-form-item label="环境湿度:"> |
| | | <el-input v-model="form.humidity" :disabled="operationType === 'view'" placeholder="请输入湿度" size="small"> |
| | | <template #append>%RH</template> |
| | | </el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item :rules="[{ required: true, message: '请选择使用人', trigger: 'change' }]" label="使用人:" |
| | | prop="usePersonId"> |
| | | <el-select @change="usePersonName" v-model="form.usePersonId" :disabled="operationType === 'view'" |
| | | placeholder="请选择" size="small" style="width: 100%"> |
| | | <el-option v-for="item in userList" :key="item.id" :label="item.name" :value="item.id"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.orderCode"> |
| | | <el-form-item label="关联原始记录:"> |
| | | <el-input v-model="form.orderCode" disabled size="small"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer><span class="dialog-footer"> |
| | | <template #footer><span class="dialog-footer"> |
| | | <el-button @click="dialogVisible = false">取 消</el-button> |
| | | <el-button v-if="operationType !== 'view'" type="primary" @click="saveRecord">确 定</el-button> |
| | | </span></template> |
| | |
| | | type="month" value-format="YYYY-MM"> |
| | | </el-date-picker> |
| | | </span> |
| | | <template #footer><span class="dialog-footer"> |
| | | <template #footer><span class="dialog-footer"> |
| | | <el-button @click="ratifyDialog = false, exportDate = ''">取 消</el-button> |
| | | <el-button :loading="outLoading" type="primary" @click="handleDown">导 出</el-button> |
| | | </span></template> |
| | |
| | | import { |
| | | deviceRecordPage, |
| | | exportUseRecord, |
| | | selectDeviceByCode, |
| | | saveDeviceRecord, |
| | | updateDeviceRecord, |
| | | deleteDeviceRecord, |
| | | } from '@/api/cnas/resourceDemand/device.js' |
| | | import { selectUserCondition } from "@/api/business/inspectionTask"; |
| | | import { formatListDate } from './dateFormat'; |
| | | import { formatDateOnly as toDateOnly } from './dateFormat'; |
| | | import { saveBlobOrShowError } from '@/utils/saveBlob' |
| | | import dayjs from 'dayjs' |
| | | |
| | | const today = () => { |
| | | const now = new Date() |
| | | return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}` |
| | | } |
| | | |
| | | const defaultForm = () => ({ |
| | | id: null, |
| | | deviceId: '', |
| | | deviceName: '', |
| | | specificationModel: '', |
| | | managementNumber: '', |
| | | insOrderId: null, |
| | | orderCode: '', |
| | | sampleCode: '', |
| | | useDate: today(), |
| | | useStartTime: '', |
| | | useEndTime: '', |
| | | temperature: '', |
| | | humidity: '', |
| | | useBefore: 1, |
| | | useAfter: 1, |
| | | abnormal: '', |
| | | usePersonId: '', |
| | | usePerson: '', |
| | | remark: '', |
| | | }) |
| | | export default { |
| | | props: { |
| | | clickNodeVal: { |
| | | type: Object, |
| | | default: () => { |
| | | return {}; |
| | | } |
| | | }, |
| | | // 判断是否是外部分离 |
| | | isMenuList: { |
| | | type: Number, |
| | | default: 0 |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | search: { |
| | |
| | | sampleCode: '', |
| | | managementNumber: '' |
| | | }, |
| | | responsiblePersonList: {}, |
| | | isShow: false, |
| | | outLoading: false, |
| | | ratifyDialog: false, |
| | | exportDate: '', |
| | | userList: [], |
| | | form: { |
| | | // deviceId:'', |
| | | processNumber: '', |
| | | deviceName: '', |
| | | managementNumber: '', |
| | | //温度 |
| | | temperature: '', |
| | | //湿度 |
| | | humidity: '', |
| | | //使用前 |
| | | useBefore: 1, |
| | | //使用后 |
| | | useAfter: 1, |
| | | //异常情况 |
| | | abnormal: '', |
| | | useDateList: [], |
| | | //使用日期 |
| | | useStartDate: null, |
| | | useEndDate: null, |
| | | //使用人 |
| | | usePerson: '', |
| | | usePersonId: '', |
| | | //备注 |
| | | remark: '', |
| | | }, |
| | | form: defaultForm(), |
| | | dialogVisible: false, |
| | | operationType: '', |
| | | formParamList: [], |
| | |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.getTableList(this.clickNodeVal.value); |
| | | this.getTableList(); |
| | | }, |
| | | methods: { |
| | | formatDateCell(row, column, cellValue) { |
| | | return formatListDate(cellValue) |
| | | formatDateCell(value) { |
| | | return toDateOnly(value) |
| | | }, |
| | | formatTimeCell(value) { |
| | | if (!value) return '' |
| | | const date = dayjs(String(value).replace('T', ' ')) |
| | | return date.isValid() ? date.format('HH:mm') : '' |
| | | }, |
| | | formatStatus(value) { |
| | | if (value === 1) return '良好' |
| | | if (value === 0) return '异常' |
| | | return '' |
| | | }, |
| | | // element-plus 的 el-date-picker 没有 picker-options,改成 :disabled-date |
| | | disabledDate(time) { |
| | |
| | | }, |
| | | handleSizeChange(val) { |
| | | this.search.size = val |
| | | this.getTableList(this.clickNodeVal.value); |
| | | this.getTableList(); |
| | | }, |
| | | handleCurrentChange(val) { |
| | | this.search.current = val |
| | | this.getTableList(this.clickNodeVal.value); |
| | | this.getTableList(); |
| | | }, |
| | | resetSearch() { |
| | | this.search = { |
| | |
| | | sampleCode: '', |
| | | managementNumber: '' |
| | | } |
| | | this.getTableList(this.clickNodeVal.value); |
| | | this.getTableList(); |
| | | }, |
| | | async getTableList(deviceId) { |
| | | if (deviceId === undefined) { |
| | | deviceId = '' |
| | | } |
| | | async getTableList() { |
| | | this.tableLoading = true |
| | | await deviceRecordPage({ |
| | | deviceId: deviceId, |
| | | ...this.search |
| | | }).then(res => { |
| | | this.tableLoading = false |
| | |
| | | handleDown() { |
| | | this.outLoading = true |
| | | exportUseRecord({ |
| | | deviceId: this.clickNodeVal.value, |
| | | sampleCode: this.search.sampleCode, |
| | | managementNumber: this.search.managementNumber, |
| | | exportDate: this.exportDate |
| | | }).then(res => { |
| | | this.outLoading = false |
| | | saveBlobOrShowError(res, '设备使用记录.doc', 'application/msword') |
| | | saveBlobOrShowError(res, '仪器设备运行记录.docx', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') |
| | | }).catch(() => { |
| | | this.outLoading = false |
| | | }) |
| | | }, |
| | | //新建 |
| | | openAdd() { |
| | | this.operationType = 'add' |
| | | this.getUserList() |
| | | selectDeviceByCode({ id: this.clickNodeVal.value }).then(res => { |
| | | this.form.deviceName = res.data.deviceName |
| | | this.form.managementNumber = res.data.managementNumber |
| | | this.$nextTick(() => { |
| | | this.$refs['form'].clearValidate() |
| | | }) |
| | | }); |
| | | resetForm() { |
| | | this.form = defaultForm() |
| | | }, |
| | | usePersonName(value) { |
| | | const index = this.userList.findIndex(item => item.id === value) |
| | |
| | | this.form.usePerson = this.userList[index].name |
| | | } |
| | | }, |
| | | //确认添加记录 |
| | | //保存修改 |
| | | saveRecord() { |
| | | this.$refs.form.validate((valid) => { |
| | | if (valid) { |
| | | this.form.useStartDate = this.form.useDateList[0] |
| | | this.form.useEndDate = this.form.useDateList[1] |
| | | this.form.deviceId = this.clickNodeVal.value |
| | | if (this.operationType === 'add') { |
| | | saveDeviceRecord(this.form).then(res => { |
| | | if (res.code == 200) { |
| | | this.$message.success('新增成功') |
| | | this.getTableList(this.clickNodeVal.value) |
| | | this.dialogVisible = false |
| | | } |
| | | }) |
| | | } else { |
| | | updateDeviceRecord(this.form).then(res => { |
| | | if (res.code == 200) { |
| | | this.$message.success('修改成功') |
| | | this.getTableList(this.clickNodeVal.value) |
| | | this.dialogVisible = false |
| | | } |
| | | }) |
| | | } |
| | | if (!valid) { |
| | | return |
| | | } |
| | | if (this.form.useStartTime >= this.form.useEndTime) { |
| | | this.$message.error('结束时间必须晚于开始时间') |
| | | return |
| | | } |
| | | const payload = { |
| | | id: this.form.id || undefined, |
| | | deviceId: this.form.deviceId, |
| | | insOrderId: this.form.insOrderId || undefined, |
| | | sampleCode: this.form.sampleCode, |
| | | temperature: this.form.temperature, |
| | | humidity: this.form.humidity, |
| | | useBefore: this.form.useBefore, |
| | | useAfter: this.form.useAfter, |
| | | abnormal: this.form.abnormal, |
| | | usePersonId: this.form.usePersonId, |
| | | usePerson: this.form.usePerson, |
| | | remark: this.form.remark, |
| | | useStartDate: `${this.form.useDate} ${this.form.useStartTime}`, |
| | | useEndDate: `${this.form.useDate} ${this.form.useEndTime}`, |
| | | } |
| | | updateDeviceRecord(payload).then(res => { |
| | | if (res.code == 200) { |
| | | this.$message.success('修改成功') |
| | | this.getTableList() |
| | | this.dialogVisible = false |
| | | } |
| | | }) |
| | | }); |
| | | }, |
| | | //查看详情 |
| | |
| | | this.dialogVisible = true; |
| | | this.getUserList() |
| | | // 复制一份再编辑,避免直接改动表格里的数据 |
| | | const useStartDate = row.useStartDate || '' |
| | | const useEndDate = row.useEndDate || '' |
| | | const start = row.useStartDate ? String(row.useStartDate).replace('T', ' ') : '' |
| | | const end = row.useEndDate ? String(row.useEndDate).replace('T', ' ') : '' |
| | | this.form = { |
| | | ...defaultForm(), |
| | | ...row, |
| | | useStartDate, |
| | | useEndDate, |
| | | useDateList: useStartDate && useEndDate ? [useStartDate, useEndDate] : [] |
| | | deviceId: row.deviceId, |
| | | deviceName: row.deviceName || '', |
| | | specificationModel: row.specificationModel || '', |
| | | managementNumber: row.managementNumber || '', |
| | | orderCode: row.orderCode || '', |
| | | useDate: start ? start.slice(0, 10) : '', |
| | | useStartTime: start.length >= 19 ? start.slice(11, 19) : '', |
| | | useEndTime: end.length >= 19 ? end.slice(11, 19) : '', |
| | | temperature: row.temperature || '', |
| | | humidity: row.humidity || '', |
| | | usePersonId: row.usePersonId || '', |
| | | usePerson: row.usePerson || '', |
| | | } |
| | | }, |
| | | handleDeleteClick(index, row) { |
| | |
| | | }, |
| | | }, |
| | | watch: { |
| | | // 监听点击el-tree的数据,进行数据刷新 |
| | | clickNodeVal(newVal) { |
| | | if (newVal.value) { |
| | | this.getTableList(newVal.value); |
| | | } |
| | | }, |
| | | dialogVisible(newVal) { |
| | | if (newVal === false) { |
| | | this.form = { |
| | | // deviceId:'', |
| | | sampleCode: '', |
| | | deviceName: '', |
| | | managementNumber: '', |
| | | //温度 |
| | | temperature: '', |
| | | //湿度 |
| | | humidity: '', |
| | | //使用前 |
| | | useBefore: 1, |
| | | //使用后 |
| | | useAfter: 1, |
| | | //异常情况 |
| | | abnormal: '', |
| | | //使用日期 |
| | | useDateList: [], |
| | | //使用人 |
| | | usePersonId: '', |
| | | //备注 |
| | | remark: '', |
| | | } |
| | | this.$refs.form.clearValidate() |
| | | this.resetForm() |
| | | this.$nextTick(() => { |
| | | this.$refs.form && this.$refs.form.clearValidate() |
| | | }) |
| | | } |
| | | } |
| | | } |
| | |
| | | height: 46px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-top: 10px; |
| | | margin-top: 4px; |
| | | } |
| | | |
| | | .link-icon { |
| | | margin-left: 4px; |
| | | color: #409eff; |
| | | font-size: 14px; |
| | | vertical-align: middle; |
| | | } |
| | | </style> |
| | |
| | | <using-external-instruments v-if="menuListActiveName == '利用外部仪器设备'" :clickNodeVal="clickNodeVal"></using-external-instruments> |
| | | </el-tab-pane> |
| | | <el-tab-pane label="使用记录" name="使用记录"> |
| | | <record v-if="menuListActiveName == '使用记录'" :isMenuList="1" /> |
| | | <record v-if="menuListActiveName == '使用记录'" /> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | </div> |
| | |
| | | </el-tab-pane> |
| | | <el-tab-pane label="设备借用" name="设备借用"> |
| | | <borrow v-if="tabListActiveName == '设备借用'" :clickNodeVal="clickNodeVal" /> |
| | | </el-tab-pane> |
| | | <el-tab-pane label="使用记录" name="使用记录"> |
| | | <record v-if="tabListActiveName == '使用记录'" :clickNodeVal="clickNodeVal" /> |
| | | </el-tab-pane> |
| | | <el-tab-pane label="设备停用/启用" name="设备停用/启用"> |
| | | <state v-if="tabListActiveName == '设备停用/启用'" :clickNodeVal="clickNodeVal" /> |