| | |
| | | <template> |
| | | <div class="main-container"> |
| | | <el-form :model="problem" label-width="auto" style="max-width: 95%"> |
| | | <el-form-item label="问题位置" prop="locationid"> |
| | | <el-select |
| | | v-model="deepCopyProblem.locationid" |
| | | @change="onProLocationChange" |
| | | class="row" |
| | | :disabled="readonly" |
| | | > |
| | | <el-option |
| | | v-for="item in posList" |
| | | :key="item.index" |
| | | :label="item.text" |
| | | :value="item.index" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="问题类型" prop="proType"> |
| | | <el-select v-model="proType" @change="onProTypeChange" class="row" :disabled="readonly"> |
| | | <el-select |
| | | v-model="proType" |
| | | @change="onProTypeChange" |
| | | class="row" |
| | | :disabled="readonly" |
| | | > |
| | | <el-option |
| | | v-for="item in problemTypeOptions" |
| | | :key="item.typeid" |
| | |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="问题位置" prop="locationid"> |
| | | <el-select |
| | | v-model="deepCopyProblem.locationid" |
| | | @change="onProLocationChange" |
| | | <el-form-item label="补充说明" :disabled="readonly" prop="proRemark"> |
| | | <el-input |
| | | v-model="proRemark" |
| | | type="textarea" |
| | | @change="onProRemarkChange" |
| | | class="row" |
| | | placeholder="请输入" |
| | | :disabled="readonly" |
| | | > |
| | | <el-option |
| | | v-for="item in posList" |
| | | :key="item.index" |
| | | :label="item.text" |
| | | :value="item.index" |
| | | /> |
| | | </el-select> |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="问题建议" prop="advise"> |
| | | <el-select v-model="deepCopyProblem.advise" class="row" :disabled="readonly"> |
| | | <el-select |
| | | v-model="deepCopyProblem.advise" |
| | | class="row" |
| | | :disabled="readonly" |
| | | @change="onProAdviseChange" |
| | | > |
| | | <el-option |
| | | v-for="item in adviseOptions" |
| | | :key="item.adGuid" |
| | |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="补充说明" :disabled="readonly" prop="proRemark"> |
| | | <el-form-item |
| | | v-show="deepCopyProblem.advise && deepCopyProblem.advise != ''" |
| | | label="问题建议修正" |
| | | prop="_adviseEdit" |
| | | :disabled="false" |
| | | > |
| | | <el-input |
| | | v-model="proRemark" |
| | | v-model="deepCopyProblem._adviseEdit" |
| | | type="textarea" |
| | | @change="onProRemarkChange" |
| | | @change="onProAdviseEditChange" |
| | | class="row" |
| | | placeholder="请输入" |
| | | placeholder="请输入问题建议修正" |
| | | :disabled="readonly" |
| | | /> |
| | | </el-form-item> |
| | | <div class="t-card_item"> |
| | | 问题图片 |
| | | <div> |
| | | <el-button @click="chosePicFromAnyPic" v-show="!readonly">从任意图片选取</el-button> |
| | | <el-button @click="chosePicFromDevicePic" v-show="!readonly">从设备图片选取</el-button> |
| | | <el-button @click="chosePicFromLedgerPic" v-show="!readonly">从台账选取</el-button> |
| | | <el-button @click="choseChangePic" v-show="!readonly">从文件夹选取</el-button> |
| | | <el-button |
| | | @click="chosePicFromAnyPic" |
| | | v-show="!readonly" |
| | | :disabled="fileList.length >= 3" |
| | | >从场景图片选取</el-button |
| | | > |
| | | <el-button |
| | | @click="chosePicFromDevicePic" |
| | | v-show="!readonly" |
| | | :disabled="fileList.length >= 3" |
| | | >从设备图片选取</el-button |
| | | > |
| | | <el-button |
| | | @click="chosePicFromLedgerPic" |
| | | v-show="!readonly" |
| | | :disabled="fileList.length >= 3" |
| | | >从台账选取</el-button |
| | | > |
| | | <el-button |
| | | @click="choseChangePic" |
| | | v-show="!readonly" |
| | | :disabled="fileList.length >= 3" |
| | | >从文件夹选取</el-button |
| | | > |
| | | </div> |
| | | </div> |
| | | <el-upload |
| | |
| | | :disabled="readonly" |
| | | accept="image/*" |
| | | > |
| | | <el-button type="primary" id="uploadBtnId" style="display: none"></el-button> |
| | | <el-icon v-show="fileList.length != 3"> |
| | | <Plus /> |
| | | </el-icon> |
| | | <template #trigger v-if="fileList.length < 3 && !readonly"> |
| | | <el-button |
| | | v-if="fileList.length < 3" |
| | | type="primary" |
| | | id="uploadBtnId" |
| | | style="display: none" |
| | | ></el-button> |
| | | <el-icon> |
| | | <Plus /> |
| | | </el-icon> |
| | | </template> |
| | | <template #tip> |
| | | <div style="color: #f56c6c">最少上传一张图片,最多选择三张图片</div> |
| | | </template> |
| | | </el-upload> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="onSubmit" v-show="!readonly">保存</el-button> |
| | | <el-button @click="this.$emit('submited', false)" v-show="!readonly">取消</el-button> |
| | | <el-button type="primary" @click="onSubmit" v-show="!readonly" |
| | | >保存</el-button |
| | | > |
| | | <el-button @click="this.$emit('submited', false)" v-show="!readonly" |
| | | >取消</el-button |
| | | > |
| | | </el-form-item> |
| | | </el-form> |
| | | <el-dialog |
| | | title="任意图片" |
| | | width="80%" |
| | | v-model="anyPhotoDialog" |
| | | :before-close="beforeAnyPhotoDialogclose" |
| | | class="dialog_style" |
| | | |
| | | <ArbitraryPhoto |
| | | :max-select="maxSelectImgCount - fileList.length" |
| | | v-if="anyPhotoDialog" |
| | | v-model:dialog-visible="anyPhotoDialog" |
| | | @submit="handleSelectedAnyPhono" |
| | | :subtask="subtask" |
| | | :defaultFile="fileList" |
| | | ref="arbitraryPhotoRef" |
| | | > |
| | | <ArbitraryPhoto |
| | | v-if="anyPhotoDialog" |
| | | @selectByAnyPhonoEvent="handleSelectedAnyPhono" |
| | | :subtask="subtask" |
| | | :defaultFile="fileList" |
| | | ref="arbitraryPhotoRef" |
| | | > |
| | | </ArbitraryPhoto> |
| | | </el-dialog> |
| | | <el-dialog |
| | | title="台账图片" |
| | | width="80%" |
| | | v-model="ledgerPicDialog" |
| | | :before-close="beforeLedgerPicDialogclose" |
| | | class="dialog_style" |
| | | </ArbitraryPhoto> |
| | | <CompLedgerPhoto |
| | | :max-select="maxSelectImgCount - fileList.length" |
| | | v-if="ledgerPicDialog" |
| | | v-model:dialog-visible="ledgerPicDialog" |
| | | @submit="handleLedgerPicPhono" |
| | | :subtask="subtask" |
| | | :defaultFile="fileList" |
| | | ref="ledgerPhotoRef" |
| | | ></CompLedgerPhoto> |
| | | <CompDevicePhoto |
| | | :max-select="maxSelectImgCount - fileList.length" |
| | | v-if="deiveceImgDialog" |
| | | v-model:dialog-visible="deiveceImgDialog" |
| | | @submit="handleSelectedDevicePhono" |
| | | :subtask="subtask" |
| | | :defaultFile="fileList" |
| | | ref="deiveceImgDialogRef" |
| | | > |
| | | <LedgerPic |
| | | v-if="ledgerPicDialog" |
| | | @selectByLedgerPicEvent="handleLedgerPicPhono" |
| | | :month="month" |
| | | :subtask="subtask" |
| | | :defaultFile="fileList" |
| | | ref="ledgerPicRef" |
| | | > |
| | | </LedgerPic> |
| | | </el-dialog> |
| | | <el-dialog |
| | | title="设备图片" |
| | | width="80%" |
| | | v-model="deiveceImgDialog" |
| | | :before-close="beforeDeiveceImgDialogclose" |
| | | class="dialog_style" |
| | | > |
| | | <CompDevicePhono |
| | | v-if="deiveceImgDialog" |
| | | @selectPhonoEvent="handleSelectedDevicePhono" |
| | | :imgPathsDataSource="deviceImgObjList" |
| | | :defaultFile="fileList" |
| | | ref="deiveceImgDialogRef" |
| | | > |
| | | </CompDevicePhono> |
| | | </el-dialog> |
| | | </CompDevicePhoto> |
| | | |
| | | <el-dialog v-model="previewDialogVisible"> |
| | | <img w-full :src="previewDialogImageUrl" alt="预览" class="preview-pic" /> |
| | | </el-dialog> |
| | |
| | | <script> |
| | | import ArbitraryPhoto from './ArbitraryPhoto.vue'; |
| | | import LedgerPic from './CompLedgerPic.vue'; |
| | | import CompDevicePhono from './CompDevicePhono.vue'; |
| | | import CompLedgerPhoto from './CompLedgerPhoto.vue'; |
| | | import CompDevicePhoto from './CompDevicePhoto.vue'; |
| | | import problemApi from '@/api/fysp/problemApi.js'; |
| | | |
| | | import { $fysp } from '@/api/index.js'; |
| | | import fileUtil from '@/utils/fileUtils.js'; |
| | | import { get, useCloned } from '@vueuse/core'; |
| | | import { useCloned } from '@vueuse/core'; |
| | | import { ElMessage } from 'element-plus'; |
| | | import deviceApi from '@/api/fysp/deviceApi'; |
| | | export default { |
| | | components: { |
| | | ArbitraryPhoto, |
| | | LedgerPic, |
| | | CompDevicePhono |
| | | CompDevicePhoto, |
| | | CompLedgerPhoto |
| | | }, |
| | | props: { |
| | | readonly: { |
| | |
| | | }, |
| | | data() { |
| | | return { |
| | | // 图片选择最大数量 |
| | | maxSelectImgCount: 3, |
| | | previewDialogVisible: false, |
| | | previewDialogImageUrl: '', |
| | | // 设备图片列表 |
| | |
| | | month: -1, |
| | | ledgerPicDialog: false, |
| | | rules: { |
| | | proType: { required: true, message: '问题类型不能为空', trigger: 'change' }, |
| | | description: { required: true, message: '问题描述不能为空', trigger: 'change' }, |
| | | locationid: { required: true, message: '问题位置不能为空', trigger: 'change' }, |
| | | advise: { required: true, message: '问题建议不能为空', trigger: 'change' }, |
| | | proRemark: { required: true, message: '补充说明不能为空', trigger: 'change' } |
| | | proType: { |
| | | required: true, |
| | | message: '问题类型不能为空', |
| | | trigger: 'change' |
| | | }, |
| | | description: { |
| | | required: true, |
| | | message: '问题描述不能为空', |
| | | trigger: 'change' |
| | | }, |
| | | locationid: { |
| | | required: true, |
| | | message: '问题位置不能为空', |
| | | trigger: 'change' |
| | | }, |
| | | advise: { |
| | | required: true, |
| | | message: '问题建议不能为空', |
| | | trigger: 'change' |
| | | }, |
| | | proRemark: { |
| | | required: true, |
| | | message: '补充说明不能为空', |
| | | trigger: 'change' |
| | | } |
| | | }, |
| | | deviceTopTypes: [ |
| | | { id: 0, label: '监控设备' }, |
| | |
| | | this.pictureValidate(); |
| | | }, |
| | | deep: true |
| | | }, |
| | | // 当问题建议改变时问题建议修正跟着改变 |
| | | deepCopyProblem: { |
| | | handler(nv, ov) { |
| | | // 图片校验 |
| | | nv._adviseEdit = ov.advise; |
| | | }, |
| | | deep: true |
| | | } |
| | | }, |
| | | computed: { |
| | | descriptionOptions() { |
| | | const descriptions = []; |
| | | |
| | | |
| | | this.problemTypeList.forEach((item) => { |
| | | if (item.typename == this.proType) { |
| | | descriptions.push(item); |
| | | } |
| | | }); |
| | | |
| | | |
| | | return descriptions; |
| | | }, |
| | | problemTypeOptions() { |
| | |
| | | }, []); |
| | | }, |
| | | adviseOptions() { |
| | | var problemGuid = this.currProTypeGuid || this.problem.guid; |
| | | var array = this.suggestions.filter((item) => item.adProblemtypeguid == problemGuid); |
| | | console.log(this.currProTypeGuid, this.problem.guid, this.suggestions); |
| | | |
| | | let problemGuid = this.currProTypeGuid || this.problem.guid; |
| | | let array = this.suggestions.filter( |
| | | (item) => item.adProblemtypeguid == problemGuid |
| | | ); |
| | | console.log( |
| | | this.suggestions.filter( |
| | | (item) => item.adProblemtypeguid == problemGuid |
| | | ), |
| | | this.adviseOptions |
| | | ); |
| | | |
| | | return array; |
| | | } |
| | | }, |
| | |
| | | this.getDeviceImgList(); |
| | | }, |
| | | methods: { |
| | | onProAdviseChange(value) { |
| | | this.deepCopyProblem._adviseEdit = this.deepCopyProblem.advise; |
| | | }, |
| | | handlePictureCardPreview(uploadFile) { |
| | | this.previewDialogVisible = true; |
| | | this.previewDialogImageUrl = uploadFile.url; |
| | |
| | | const newObj = {}; |
| | | for (const key in obj) { |
| | | let newKey = key; |
| | | if (key.startsWith('di')) { |
| | | newKey = key.substring(2); |
| | | } else if (key.startsWith('wi')) { |
| | | newKey = key.substring(2); |
| | | } else if (key.startsWith('pi')) { |
| | | newKey = key.substring(2); |
| | | } |
| | | newKey = newKey.charAt(0).toLowerCase() + newKey.slice(1); |
| | | newObj[newKey] = obj[key]; |
| | | if (key.startsWith('di')) { |
| | | newKey = key.substring(2); |
| | | } else if (key.startsWith('wi')) { |
| | | newKey = key.substring(2); |
| | | } else if (key.startsWith('pi')) { |
| | | newKey = key.substring(2); |
| | | } |
| | | newKey = newKey.charAt(0).toLowerCase() + newKey.slice(1); |
| | | newObj[newKey] = obj[key]; |
| | | } |
| | | return newObj; |
| | | }, |
| | |
| | | this.deviceImgObjList = []; |
| | | for (const deviceTopTypeElement of this.deviceTopTypes) { |
| | | const topTypeId = deviceTopTypeElement.id; |
| | | await deviceApi.fetchDevices(this.subtask.sceneId, topTypeId).then((result) => { |
| | | // 标准化属性名 |
| | | for (let i = 0; i < result.data.length; i++) { |
| | | var element = this.convertKeys(result.data[i]); |
| | | // 获取设备状态信息 |
| | | let data = { |
| | | deviceId: element.id, |
| | | sceneId: element.sceneGuid, |
| | | deviceTypeId: topTypeId |
| | | }; |
| | | deviceApi |
| | | .fetchDeviceStatus(data) |
| | | .then((status) => { |
| | | var statusData = status.data; |
| | | var imgPaths = []; |
| | | await deviceApi |
| | | .fetchDevices(this.subtask.sceneId, topTypeId) |
| | | .then((result) => { |
| | | // 标准化属性名 |
| | | for (let i = 0; i < result.data.length; i++) { |
| | | var element = this.convertKeys(result.data[i]); |
| | | // 获取设备状态信息 |
| | | let data = { |
| | | deviceId: element.id, |
| | | sceneId: element.sceneGuid, |
| | | deviceTypeId: topTypeId |
| | | }; |
| | | deviceApi |
| | | .fetchDeviceStatus(data) |
| | | .then((status) => { |
| | | var statusData = status.data; |
| | | var imgPaths = []; |
| | | |
| | | if (statusData) { |
| | | if (statusData.length == 0) { |
| | | this.deviceImgObjList.push(element); |
| | | return; |
| | | } |
| | | element = this.convertKeys(result.data[i]); |
| | | for (let j = 0; j < statusData.length; j++) { |
| | | // 复制出一个设备对象 |
| | | var newDevice = useCloned(element).cloned.value; |
| | | const statusItem = statusData[j]; |
| | | // 设备对象添加一个属性列表属性用来保存设备状态 |
| | | this.saveStatus(newDevice, statusItem); |
| | | newDevice.dlLocation = statusItem.dlLocation; |
| | | newDevice.topTypeId = topTypeId; |
| | | if (statusData) { |
| | | if (statusData.length == 0) { |
| | | this.deviceImgObjList.push(element); |
| | | return; |
| | | } |
| | | element = this.convertKeys(result.data[i]); |
| | | for (let j = 0; j < statusData.length; j++) { |
| | | // 复制出一个设备对象 |
| | | var newDevice = useCloned(element).cloned.value; |
| | | const statusItem = statusData[j]; |
| | | // 设备对象添加一个属性列表属性用来保存设备状态 |
| | | this.saveStatus(newDevice, statusItem); |
| | | newDevice.dlLocation = statusItem.dlLocation; |
| | | newDevice.topTypeId = topTypeId; |
| | | |
| | | this.deviceImgObjList.push(newDevice); |
| | | this.deviceImgObjList.push(newDevice); |
| | | } |
| | | } |
| | | } |
| | | }) |
| | | .catch((err) => {}); |
| | | } |
| | | }); |
| | | }) |
| | | .catch((err) => {}); |
| | | } |
| | | }); |
| | | } |
| | | }, |
| | | initOptions() { |
| | |
| | | this.deepCopyProblem = {}; |
| | | } else { |
| | | this.deepCopyProblem = useCloned(this.problem).cloned.value; |
| | | this.currProTypeGuid = this.problem.guid; |
| | | this.deepCopyProblem._adviseEdit = this.deepCopyProblem.advise; |
| | | } |
| | | |
| | | this.type = 'guid' in this.deepCopyProblem ? 1 : 0; |
| | | |
| | | // 获取问题类型 |
| | | let data = { |
| | | sceneTypeId: this.subtask.sceneTypeId, |
| | |
| | | this.deepCopyProblem.description = currDescription; |
| | | this.proRemark = ''; |
| | | } else { |
| | | currDescription = currProName.substring(0, currProName.lastIndexOf('(')); |
| | | currDescription = currProName.substring( |
| | | 0, |
| | | currProName.lastIndexOf('(') |
| | | ); |
| | | |
| | | this.problemTypeList.forEach((item) => { |
| | | if (item.description === currDescription) { |
| | |
| | | } |
| | | }, |
| | | handleLedgerPicPhono(data) { |
| | | this.beforeLedgerPicDialogclose(); |
| | | let isExist = false; |
| | | for (const item of data) { |
| | | for (const already of this.fileList) { |
| | |
| | | onProRemarkChange(value) { |
| | | this.changeProblemname(); |
| | | }, |
| | | onProAdviseEditChange(value) {}, |
| | | onProTypeChange(value) { |
| | | this.deepCopyProblem.description = ''; |
| | | this.deepCopyProblem.advise = ''; |
| | | // 默认问题描述和问题建议为第一个 |
| | | this.currProTypeGuid = this.descriptionOptions[0].guid; |
| | | this.deepCopyProblem.description = this.descriptionOptions[0].description; |
| | | this.deepCopyProblem.advise = this.adviseOptions[0].adName; |
| | | this.deepCopyProblem._adviseEdit = this.deepCopyProblem.advise; |
| | | }, |
| | | findProByProDesName(name) { |
| | | let result |
| | | this.problemTypeList.forEach(item=>{ |
| | | let result; |
| | | this.problemTypeList.forEach((item) => { |
| | | if (item.description == name) { |
| | | result = item; |
| | | } |
| | | }) |
| | | return result |
| | | }); |
| | | return result; |
| | | }, |
| | | onProDesChange(value) { |
| | | let currPro = this.findProByProDesName(value) |
| | | let currPro = this.findProByProDesName(value); |
| | | this.deepCopyProblem.advise = ''; |
| | | this.currProTypeGuid = currPro.guid; |
| | | // this.deepCopyProblem.description = currPro.description; |
| | | this.changeProblemname(); |
| | | this.deepCopyProblem.advise = ''; |
| | | |
| | | var adName = this.adviseOptions.length == 0 ? '' : this.adviseOptions[0].adName; |
| | | var adName = |
| | | this.adviseOptions.length == 0 ? '' : this.adviseOptions[0].adName; |
| | | this.deepCopyProblem.advise = adName; |
| | | }, |
| | | onProLocationChange(value) { |
| | |
| | | delete deepCopyPro['description']; |
| | | deepCopyPro.proName = deepCopyPro.problemname; |
| | | delete deepCopyPro['problemname']; |
| | | deepCopyPro.ptGuid = that.findProTypeByGuid(that.currProTypeGuid).guid; |
| | | deepCopyPro.ptGuid = that.findProTypeByGuid( |
| | | that.currProTypeGuid |
| | | ).guid; |
| | | deepCopyPro.locationId = deepCopyPro.locationid; |
| | | delete deepCopyPro['locationid']; |
| | | data.append('problemVo', JSON.stringify(deepCopyPro)); |
| | |
| | | } |
| | | }, |
| | | handleSelectedDevicePhono(data) { |
| | | this.beforeDeiveceImgDialogclose(); |
| | | let isExist = false; |
| | | for (const item of data) { |
| | | for (const already of this.fileList) { |
| | | if (item._picUrl == already.url) { |
| | | if (item.url == already.url) { |
| | | isExist = true; |
| | | } |
| | | } |
| | | if (!isExist) { |
| | | this.fileList.push({ |
| | | url: item._picUrl, |
| | | url: item.url, |
| | | name: '1' |
| | | }); |
| | | } |
| | |
| | | } |
| | | .row { |
| | | width: 100%; |
| | | } |
| | | ::v-deep .el-dialog { |
| | | --el-dialog-margin-top: 2vh; |
| | | height: 98vh; |
| | | } |
| | | ::v-deep .el-dialog__body { |
| | | width: 95%; |
| | | height: 100%; |
| | | } |
| | | ::v-deep .el-upload-list--picture-card .el-upload-list__item-thumbnail { |
| | | object-fit: cover !important; |