<!-- filename: dialogForm.vue author: liubin date: 2023-08-15 10:32:36 description: 弹窗的表单组件 --> <template> <el-form ref="form" :model="form" :label-position="labelPosition" v-loading="formLoading"> <el-row :gutter="20"> <!-- 维修单号 --> <el-col :span="8"> <el-form-item label="维修单号" prop="repairOrderNumber" :rules="[ { required: true, message: '维修单号不能为空', trigger: 'blur' }, ]"> <el-input v-model="form.repairOrderNumber" @change="$emit('update', form)" placeholder="请输入维修单号" :disabled="disabled" /> </el-form-item> </el-col> <!-- 产线名 --> <!-- <el-col :span="8"> <el-form-item label="产线名" prop="lineId"> <el-select v-model="formFilters.lineId" :placeholder="`请选择产线`" :disabled="disabled" clearable filterable @change="initSections"> <el-option v-for="opt in lineOptions" :key="opt.value" :label="opt.label" :value="opt.value" /> </el-select> </el-form-item> </el-col> --> <!-- 工段名 --> <!-- <el-col :span="8"> <el-form-item label="工段名" prop="sectionId"> <el-select v-model="formFilters.sectionId" :placeholder="`请选择工段`" :disabled="disabled" clearable filterable @change="handleEqTypeChange"> <el-option v-for="opt in sectionOptions" :key="opt.value" :label="opt.label" :value="opt.value" /> </el-select> </el-form-item> </el-col> --> <!-- 设备名称 --> <el-col :span="8"> <el-form-item label="设备名称" prop="equipmentId" :rules="[ { required: true, message: '设备不能为空', trigger: 'blur' }, ]"> <el-select v-model="form.equipmentId" :placeholder="`请选择设备`" :disabled="disabled" filterable clearable @change="$emit('update', form)"> <el-option v-for="opt in equipmentOptions" :key="opt.value" :label="opt.label" :value="opt.value" /> </el-select> </el-form-item> </el-col> <!-- 故障发生时间 --> <el-col :span="8"> <el-form-item label="故障发生时间" prop="faultTime" :rules="[ { required: true, message: '故障发生时间不能为空', trigger: 'blur', }, ]"> <el-date-picker v-model="form.faultTime" type="datetime" :disabled="disabled" :placeholder="`请选择故障发生时间`" value-format="timestamp" format="yyyy-MM-dd HH:mm:ss" clearable @change="$emit('update', form)" /> </el-form-item> </el-col> <!-- 故障级别 --> <el-col :span="8"> <el-form-item label="故障级别" prop="faultLevel"> <el-select v-model="form.faultLevel" placeholder="故障级别" :disabled="disabled" @change="$emit('update', form)"> <el-option v-for="opt in getDictDatas(DICT_TYPE.FAULT_LEVEL)" :key="opt.value" :label="opt.label" :value="opt.value" /> </el-select> </el-form-item> </el-col> <!-- 故障类型 - 数据字典 --> <el-col :span="8"> <el-form-item label="故障类型" prop="faultType" :rules="[ { required: true, message: '故障类型不能为空', trigger: 'blur', }, ]"> <el-select v-model="form.faultType" placeholder="故障类型" :disabled="disabled" @change="$emit('update', form)"> <el-option v-for="opt in getDictDatas(DICT_TYPE.FAULT_TYPE)" :key="opt.value" :label="opt.label" :value="opt.value" /> </el-select> </el-form-item> </el-col> <!-- 维修开始时间 --> <el-col :span="8"> <el-form-item label="维修开始时间" prop="maintenanceStartTime" :rules="[ { required: true, message: '维修开始时间不能为空', trigger: 'blur', }, ]"> <el-date-picker v-model="form.maintenanceStartTime" type="datetime" :disabled="disabled" :placeholder="`请选择维修开始时间`" value-format="timestamp" format="yyyy-MM-dd HH:mm:ss" clearable @change="$emit('update', form)" /> </el-form-item> </el-col> <!-- 维修结束时间 --> <el-col :span="8"> <el-form-item label="维修结束时间" prop="maintenanceFinishTime" :rules="[ { required: true, message: '维修结束时间不能为空', trigger: 'blur', }, ]"> <el-date-picker v-model="form.maintenanceFinishTime" type="datetime" :disabled="disabled" :placeholder="`请选择维修结束时间`" value-format="timestamp" format="yyyy-MM-dd HH:mm:ss" clearable @change="$emit('update', form)" /> </el-form-item> </el-col> <!-- 维修工 --> <el-col :span="8"> <el-form-item label="维修工" prop="repairman"> <el-select v-model="form.repairman" @change="$emit('update', form)" placeholder="请选择维修工" filterable clearable multiple :disabled="disabled"> <el-option v-for="opt in workerOptions" :key="opt.value" :label="opt.label" :value="opt.value" /> </el-select> </el-form-item> </el-col> <!-- 联系方式 --> <el-col :span="8"> <el-form-item label="联系方式" prop="repairmanPhone"> <el-input v-model="form.repairmanPhone" @change="$emit('update', form)" placeholder="请输入联系方式" :disabled="disabled" /> </el-form-item> </el-col> <!-- 维修方式 - 数据字典 --> <el-col :span="8"> <el-form-item label="维修方式" prop="repairMode"> <el-select v-model="form.repairMode" placeholder="维修方式" :disabled="disabled" @change="$emit('update', form)"> <el-option v-for="opt in getDictDatas(DICT_TYPE.REPAIR_MODE)" :key="opt.value" :label="opt.label" :value="opt.value" /> </el-select> </el-form-item> </el-col> <!-- 维修结果 - 数据字典 --> <el-col :span="8"> <el-form-item label="维修结果" prop="maintenanceResult" :rules="[ { required: true, message: '维修结果不能为空', trigger: 'blur', }, ]"> <el-select v-model="form.maintenanceResult" placeholder="维修结果" :disabled="disabled" @change="$emit('update', form)"> <el-option v-for="opt in getDictDatas(DICT_TYPE.REPAIR_RESULT)" :key="opt.value" :label="opt.label" :value="opt.value" /> </el-select> </el-form-item> </el-col> <!-- 备注 --> <el-col :span="8"> <el-form-item label="备注" prop="remark"> <el-input v-model="form.remark" @change="$emit('update', form)" placeholder="请输入备注" :disabled="disabled" /> </el-form-item> </el-col> <!-- 故障明细 --> <el-col :span="24"> <el-form-item label="故障明细" prop="faultDetail" :rules="[ { required: true, message: '故障明细不能为空', trigger: 'blur', }, ]"> <Editor key="fault-detail" :height="200" v-model="form.faultDetail" @on-change="$emit('update', form)" /> </el-form-item> </el-col> <!-- 维修描述 --> <el-col :span="24"> <el-form-item label="维修描述" prop="maintenanceDetail"> <Editor key="maintenance-detail" :height="200" v-model="form.maintenanceDetail" @on-change="$emit('update', form)" /> </el-form-item> </el-col> <!-- 维修附件 --> <el-col :span="24"> <el-form-item label="维修附件" prop="files"> <div class="upload-area" :class="uploadOpen ? '' : 'height-48'" ref="uploadArea"> <span class="close-icon" :class="uploadOpen ? 'open' : ''"> <el-button type="text" icon="el-icon-arrow-right" @click="uploadOpen = !uploadOpen" /> </span> <!-- :file-list="uploadedFileList" --> <el-upload class="upload-in-dialog" :action="uploadUrl" :headers="uploadHeaders" :show-file-list="false" icon="el-icon-upload2" :disabled="disabled" :before-upload="beforeUpload" :on-success=" (response, file, fileList) => { handleUploadSuccess(response, file, 'files'); } "> <el-button size="mini" :disabled="disabled || false"> <svg-icon icon-class="icon-upload" style="color: inherit"></svg-icon> 上传文件 </el-button> <div class="el-upload__tip" slot="tip"> 只能上传jpg/png文件, 大小不超过2MB </div> </el-upload> <uploadedFile class="file" v-for="file in form.files" :file="file" :key="file.fileUrl" :disabled="disabled" @delete="!disabled && handleDeleteFile(file, col.prop)" /> </div> </el-form-item> </el-col> <!-- 设备大类 --> <!-- <el-col :span="8"> <el-form-item label="设备大类" prop="equipmentCategory" :rules="[ { required: true, message: '设备大类不能为空', trigger: 'blur' }, ]"> <el-select v-model="form.equipmentCategory" :placeholder="`请选择设备大类`" :disabled="disabled" clearable filterable @change="handleEqTypeChange"> <el-option v-for="opt in equipmentTypeOptions" :key="opt.value" :label="opt.label" :value="opt.value" /> </el-select> </el-form-item> </el-col> --> </el-row> </el-form> </template> <script> import Editor from '@/components/Editor'; import { getAccessToken } from '@/utils/auth'; import tupleImg from '@/assets/images/tuple.png'; const uploadedFile = { name: 'UploadedFile', props: ['file', 'disabled'], data() { return {}; }, methods: { handleDelete() { this.$emit('delete', this.file); }, async handleDownload() { const data = await this.$axios({ url: this.file.fileUrl, method: 'get', responseType: 'blob', }); await this.$message.success('开始下载'); // create download link const url = window.URL.createObjectURL(data); const link = document.createElement('a'); link.href = url; link.download = this.file.fileName; document.body.appendChild(link); link.click(); document.body.removeChild(link); }, }, mounted() {}, render: function (h) { return ( <div title={this.file.fileName} onClick={this.handleDownload} style={{ background: `url(${tupleImg}) no-repeat`, backgroundSize: '14px', backgroundPosition: '0 55%', paddingLeft: '20px', paddingRight: '24px', textOverflow: 'ellipsis', whiteSpace: 'nowrap', overflow: 'hidden', cursor: 'pointer', display: 'inline-block', }}> {this.file.fileName} {!this.disabled && ( <el-button type="text" icon="el-icon-close" style="float: right; position: relative; top: 2px; left: 8px; z-index: 100" class="dialog__upload_component__close" onClick={this.handleDelete} /> )} </div> ); }, }; export default { name: 'DialogForm', model: { prop: 'dataForm', event: 'update', }, emits: ['update'], components: { Editor, uploadedFile }, props: { dataForm: { type: Object, default: () => ({}), }, disabled: { type: Boolean, default: false, }, labelPosition: { type: String, default: 'top', }, }, data() { return { isInit: true, allSpeicalEquipments: [], form: {}, formFilters: { lineId: null, sectionId: null, }, formLoading: true, dataLoaded: false, equipmentList: [], equipmentOptions: [], equipmentTypeOptions: [ { label: '安全设备', value: 1 }, { label: '消防设备', value: 2 }, { label: '特种设备', value: 3 }, ], workerOptions: [], planOptions: [], sectionOptions: [], lineOptions: [], uploadOpen: false, uploadUrl: process.env.VUE_APP_BASE_API + '/admin-api/infra/file/upload', // 上传有关的headers,url都是固定的 uploadHeaders: { Authorization: 'Bearer ' + getAccessToken() }, }; }, watch: { dataForm: { handler(val) { this.form = JSON.parse(JSON.stringify(val)); // if (this.form.equipmentCategory != null) { // setTimeout(() => { // this.equipmentOptions = this.equipmentList // .filter((item) => item.special) // .filter( // (item) => item.specialType === this.form.equipmentCategory // ) // .map((item) => ({ label: item.name, value: item.id })); // }, 1000); // } if (this.hasFiles) { if (typeof this.hasFiles == 'boolean' && this.hasFiles) { this.form.files = this.form.files ?? []; } else if (Array.isArray(this.hasFiles)) { this.hasFiles.forEach((prop) => { this.form[prop] = this.form[prop] ?? []; }); } } }, deep: true, immediate: true, }, }, mounted() { this.initOptions(); }, methods: { /** 模拟透传 ref */ validate(cb) { return this.$refs.form.validate(cb); }, resetFields(args) { return this.$refs.form.resetFields(args); }, // getCode async getCode() { const response = await this.$axios('/base/equipment-repair-log/getCode'); this.form.repairOrderNumber = response.data || ''; }, // initialize async initOptions() { this.formLoading = true; await this.getCode(); await this.initEquipment(); // await this.initLines(); await this.initWorker(); // await this.initSections(); this.formLoading = false; this.isInit = false; this.setInitWorker(); }, /** 设置默认维修工为用户自己 */ setInitWorker() { /** 获取用户自身id */ const nickname = this.$store.getters.nickname; this.$nextTick(() => { this.form.repairman = [nickname]; }); }, /** 获取产线 */ // async initLines() { // const res = await this.$axios('/base/core-production-line/listAll'); // this.lineOptions = (res.data || []).map((item) => ({ // label: item.name, // value: item.id, // })); // }, // /** 获取工段 */ // async initSections(byLineId) { // this.formLoading = !this.isInit && true; // const res = await this.$axios({ // url: // byLineId && !this.isInit // ? '/base/core-workshop-section/listByParentId?id=' + byLineId // : '/base/core-workshop-section/listAll', // }); // this.sectionOptions = (res.data || []).map((item) => ({ // label: item.name, // value: item.id, // })); // this.formLoading = !this.isInit && false; // }, /** 获取设备 */ async initEquipment(type = 'special-equipment') { const response = await this.$axios('/base/core-equipment/listAll'); this.equipmentList = response.data || []; const equipmentOptions = (response.data || []) .filter((item) => (type == 'special-equipment' ? item.special : true)) .map((item) => ({ label: item.name, value: item.id, })); this.equipmentOptions = [...equipmentOptions]; this.allSpeicalEquipments = [...equipmentOptions]; }, /** 获取维修工 - 同时从用户表和员工表拉取数据 */ async initWorker() { let list = []; /** user */ const userList = await this.$axios({ url: '/system/user/page', params: { pageNo: 1, pageSize: 100, }, }); list = list.concat( (userList.data?.list || []).map((item) => ({ label: item.nickname, value: item.nickname, })) ); /** worker */ const workerList = await this.$axios({ url: '/base/core-worker/listAll', }); list = list.concat( (workerList.data || []).map((item) => ({ label: item.name, value: item.name, })) ); /** setting */ this.workerOptions = list; }, beforeUpload(file) { const checkFileSize = () => { const isLt2M = file.size / 1024 / 1024 < 2; if (!isLt2M) { this.$modal.msgError('上传文件大小不能超过 2MB!'); } return isLt2M; }; const checkFileType = () => { const isJPG = file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/jpg'; return isJPG; }; return checkFileSize() && checkFileType(); }, // handlers handleEqTypeChange(type) { this.form.equipmentId = null; if (type) { this.equipmentOptions = this.equipmentList .filter((item) => item.special) .filter((item) => item.specialType === type) .map((item) => ({ label: item.name, value: item.id })); } else this.equipmentOptions = this.equipmentList.map((item) => ({ label: item.name, value: item.id, })); // this.$emit('update', this.form) }, handleEqChange() { this.$emit('update', this.form); }, // 修改 是否计划保养 时 handlePlanChange(val) { console.log('handlePlanChange', val); this.form.equipmentCategory = null; this.form.equipmentId = null; this.$emit('update', { ...this.form, relatePlan: val }); this.initEquipment(val == 1 ? 'special-equipment' : null); }, handleEditorInput(html) { this.$emit('update', { ...this.form, maintenanceDes: html, }); }, // upload handleFilesOpen() {}, handleUploadSuccess(response, file, prop) { console.log('response', response); if (response.code != 0) { this.$modal.msgError('上传失败: ', response.msg || '-'); return; } this.form.files.push({ fileName: file.name, fileUrl: response.data, fileType: prop == 'files' ? 2 : 1, }); this.$modal.msgSuccess('上传成功'); this.$emit('update', this.form); }, handleDeleteFile(file, prop) { this.form.files = this.form.files.filter( (item) => item.fileUrl != file.fileUrl ); this.$emit('update', this.form); }, }, }; </script> <style scoped lang="scss"> .el-date-editor, .el-select { width: 100%; } .upload-area { position: relative; overflow: hidden; transition: height 0.3s ease-out; } .upload-in-dialog { margin-right: 24px; position: relative; float: left; } .close-icon { position: absolute; top: 0; right: 12px; z-index: 100; transition: transform 0.3s ease-out; } .close-icon.open { transform: rotateZ(90deg); } .dialog__upload_component__close { color: #ccc; } .dialog__upload_component__close:hover { /* color: #777; */ color: red; } .height-48 { height: 35px !important; } :deep(.record-add__editor) { .ql-picker-label { display: flex; } } </style>