| | |
| | | <template> |
| | | <GlobalWindow width="820px" title="工单详情" :visible.sync="visible" :confirm-working="isWorking" @close="close" |
| | | <GlobalWindow width="960px" title="工单详情" :visible.sync="visible" :confirm-working="isWorking" @close="close" |
| | | @confirm="confirm"> |
| | | <div class="main"> |
| | | <div class="title"> |
| | | <span>工单详情</span> |
| | | <div> |
| | | <div class="status primaryColor" v-if="info.dealStatus == 0 || info.dealStatus == null">待指派</div> |
| | | <div class="status" v-if="info.dealStatus == 1">已指派</div> |
| | | <div class="status green" v-if="info.dealStatus == 1">已指派</div> |
| | | <div class="status gray" v-if="info.dealStatus == 2">已处理</div> |
| | | </div> |
| | | </div> |
| | | <div class="list"> |
| | | <div class="item"> |
| | | <div class="la">位置类型</div> |
| | | <div class="val">{{ info.areaType == 0 ? '室内维修' : '公共维修' }}</div> |
| | | <div class="main_content"> |
| | | <div class="list"> |
| | | <div class="item"> |
| | | <div class="la">位置类型</div> |
| | | <div class="val">{{ info.areaType == 0 ? '室内维修' : '公共维修' }}</div> |
| | | </div> |
| | | <div class="item"> |
| | | <div class="la">对应位置</div> |
| | | <div class="val">{{ info.projectName }}/{{ info.buildingName }} / {{ info.roomNum || info.floorName }}</div> |
| | | </div> |
| | | <div class="item"> |
| | | <div class="la">工单分类</div> |
| | | <div class="val">{{ info.categoryName }}</div> |
| | | </div> |
| | | <div class="item"> |
| | | <div class="la">上报人</div> |
| | | <div class="val">{{ info.creatorName }}{{ info.creatorCompany ? "-" + info.creatorCompany : '' }}</div> |
| | | </div> |
| | | <div class="item"> |
| | | <div class="la">上报人电话</div> |
| | | <div class="val">{{ info.creatorPhone || info.creatorMobile }}</div> |
| | | </div> |
| | | <div class="item"> |
| | | <div class="la">上报时间</div> |
| | | <div class="val">{{ info.createDate }}</div> |
| | | </div> |
| | | <div class="item max" v-if="info.areaType == 0"> |
| | | <div class="la">上门时间</div> |
| | | <div class="val">{{ info.getDate }}</div> |
| | | </div> |
| | | <div class="item max"> |
| | | <div class="la">问题描述</div> |
| | | <div class="val">{{ info.content }}</div> |
| | | </div> |
| | | <div class="item max"> |
| | | <div class="la">问题图片</div> |
| | | <div class="value" v-if="info.fileList == null || !info.fileList.length">无</div> |
| | | <div class="value" v-if="info.fileList != null && info.fileList.length"> |
| | | <div v-for="item in info.fileList" :key="item.id" style="display: inline;margin-right: 20px"> |
| | | <!-- <video v-if="item.fileurlFull && item.fileurlFull.endsWith('.mp4')" ref="videoRef" controls |
| | | preload="auto" style="width: 80px;height: 80px;object-fit: contain;" :src="item.fileurlFull" /> --> |
| | | <el-image v-if="item.type == 0" style="width:80px; height: 80px" :src="item.fileurlFull" |
| | | :preview-src-list="[item.fileurlFull]"> |
| | | </el-image> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div v-if="info.fileList && info.fileList.length > 0 && info.fileList.filter(i => i.type == 1).length > 0" |
| | | class="item max"> |
| | | <div class="la">问题视频</div> |
| | | <div class="value"> |
| | | <div v-for="item in info.fileList" :key="item.id" style="display: inline;margin-right: 20px"> |
| | | <video v-if="item.type == 1" ref="videoRef" controls preload="auto" |
| | | style="width: 240px;height: 160px;object-fit: contain;" :src="item.fileurlFull" /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="item"> |
| | | <div class="la">对应位置</div> |
| | | <div class="val">{{ info.buildingName }} / {{ info.roomNum || info.floorName }}</div> |
| | | </div> |
| | | <div class="item"> |
| | | <div class="la">工单类别</div> |
| | | <div class="val">{{ info.categoryName }}</div> |
| | | </div> |
| | | <div class="item"> |
| | | <div class="la">上报人</div> |
| | | <div class="val">{{ info.creatorName }}</div> |
| | | </div> |
| | | <div class="item"> |
| | | <div class="la">上报人电话</div> |
| | | <div class="val">{{ info.creatorPhone }}</div> |
| | | </div> |
| | | <div class="item"> |
| | | <div class="la">上报时间</div> |
| | | <div class="val">{{ info.createDate }}</div> |
| | | </div> |
| | | <div class="item max"> |
| | | <div class="la">上门时间</div> |
| | | <div class="val">{{ info.getDate }}</div> |
| | | </div> |
| | | <div class="item max"> |
| | | <div class="la">问题描述</div> |
| | | <div class="val">{{ info.content }}</div> |
| | | </div> |
| | | <div class="item max"> |
| | | <div class="la">问题图片</div> |
| | | <div class="value" v-if="info.fileList == null || !info.fileList.length">无</div> |
| | | <div class="value" v-if="info.fileList != null && info.fileList.length"> |
| | | <div v-for="item in info.fileList" :key="item.id" style="display: inline;margin-right: 20px"> |
| | | <video v-if="item.fileurlFull && item.fileurlFull.endsWith('.mp4')" ref="videoRef" controls preload="auto" |
| | | style="width: 80px;height: 80px;object-fit: contain;" :src="item.fileurlFull" /> |
| | | <el-image v-else-if="item.fileurlFull" style="width:80px; height: 80px" :src="item.fileurlFull" |
| | | :preview-src-list="[item.fileurlFull]"> |
| | | </el-image> |
| | | <div class="side"> |
| | | <div class="title">工单流转记录</div> |
| | | <div class="flow_list"> |
| | | <div class="item" v-for="item, i in info.logList"> |
| | | <div class="icon"> |
| | | <div class="dian"></div> |
| | | <div v-if="i < info.logList.length - 1" class="line"></div> |
| | | </div> |
| | | <div class="content"> |
| | | <div class="name">{{ item.title }}</div> |
| | | <div class="time">操作时间:{{ item.createDate }}</div> |
| | | <div class="creator">操作人:{{ item.param1 }}</div> |
| | | <div class="creator" v-if="item.param2">指派给:{{ item.param2 }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="title">工单处理</div> |
| | | <div class="title" |
| | | v-if="info.dealStatus == 2 || info.dealStatus == 0 || (info.dealStatus == 1 && info.dealUserId === userInfo.id)"> |
| | | {{ info.dealStatus == 0 || info.dealStatus == 1 ? '工单处理' : '处理结果' }}</div> |
| | | <el-form :model="param" ref="form" :rules="rules"> |
| | | <template v-if="info.dealStatus == 0 || info.dealStatus == null"> |
| | | <el-form-item label="处理方式" prop="dealType"> |
| | |
| | | <el-date-picker type="datetime" class="w400" v-model="param.getDate" format="yyyy-MM-dd HH:mm" |
| | | value-format="yyyy-MM-dd HH:mm:ss" placeholder="请选择"></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item label="回复内容" prop="dealInfo"> |
| | | <el-form-item label="处理说明" prop="dealInfo"> |
| | | <el-input type="textarea" class="w400" :rows="4" v-model="param.dealInfo" placeholder="请填写说明"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="现场图片"> |
| | | <div class="file_list"> |
| | | <el-upload class="avatar-uploader" :data="uploadData" multiple :limit="6" :auto-upload="true" :action="uploadImgUrl" |
| | | <el-upload class="avatar-uploader" :data="uploadData" :auto-upload="true" :action="uploadImgUrl" |
| | | :show-file-list="false" :on-success="uploadAvatarSuccess" :on-error="uploadError" |
| | | :before-upload="beforeUpload"> |
| | | <div class="upload_wrap"> |
| | |
| | | <template v-if="info.dealStatus == 2"> |
| | | <div class="list"> |
| | | <div class="item item2"> |
| | | <div class="la">处理时间:</div> |
| | | <div class="val">{{ info.getDate }}</div> |
| | | <div class="la">{{ info.dispatchUserId ? '处理人' : '回复人' }}:</div> |
| | | <div class="val">{{ info.dealUserName }}{{ info.dealUserCompany ? '-' + info.dealUserCompany : '' }}</div> |
| | | </div> |
| | | <div class="item item2"> |
| | | <div class="la">处理备注:</div> |
| | | <div class="la">{{ info.dispatchUserId ? '处理时间' : '回复时间' }}:</div> |
| | | <div class="val">{{ info.dealDate || info.getDate }}</div> |
| | | </div> |
| | | <div class="item item2"> |
| | | <div class="la">{{ info.dispatchUserId ? '处理说明' : '回复内容' }}:</div> |
| | | <div class="val">{{ info.dealInfo }}</div> |
| | | </div> |
| | | <div class="item item2"> |
| | | <div v-if="info.dealFileList != null && info.dealFileList.length" class="item item2"> |
| | | <div class="la">现场照片:</div> |
| | | <div class="value" v-if="info.dealFileList == null || !info.dealFileList.length">无</div> |
| | | <div class="value" v-if="info.dealFileList != null && info.dealFileList.length"> |
| | |
| | | import { detailById, dispatchOrder, dealOrder } from '@/api/workorder/ywWorkorder' |
| | | import { getUserList } from '@/api/system/user' |
| | | import { Message, Loading } from 'element-ui' |
| | | import dayjs from 'dayjs' |
| | | export default { |
| | | components: { |
| | | GlobalWindow |
| | |
| | | uploadImgUrl: process.env.VUE_APP_API_PREFIX + '/visitsAdmin/cloudService/public/uploadBatch', |
| | | dealFileList: [], |
| | | uploadData: { |
| | | folder: 'HIDDEN_DANGER_FILE' |
| | | folder: 'YW_WORKORDER_FILE' |
| | | }, |
| | | } |
| | | }, |
| | |
| | | if (valid) { |
| | | const { param, id, dealFileList, info } = this |
| | | let fn = null |
| | | if(info.dealStatus == 0 || info.dealStatus == null){ |
| | | if (info.dealStatus == 0 || info.dealStatus == null) { |
| | | fn = param.dealType == 0 ? dispatchOrder : dealOrder |
| | | }else{ |
| | | } else { |
| | | fn = dealOrder |
| | | } |
| | | fn({ |
| | |
| | | const { id } = this |
| | | detailById(id).then(res => { |
| | | this.info = res |
| | | if (this.info.dealStatus == 1) { |
| | | this.$set(this.param, 'getDate', dayjs().format('YYYY-MM-DD HH:mm:ss')) |
| | | } |
| | | }) |
| | | }, |
| | | getStaff() { |
| | |
| | | align-items: center; |
| | | |
| | | .status { |
| | | padding: 0 6px; |
| | | height: 22px; |
| | | line-height: 22px; |
| | | padding: 0 12px; |
| | | height: 24px; |
| | | line-height: 24px; |
| | | border-radius: 2px; |
| | | border: 1px solid #00BA92; |
| | | color: #00BA92; |
| | |
| | | } |
| | | |
| | | .primaryColor { |
| | | border: 1px solid $primary-color; |
| | | border: 1px solid rgba(63, 126, 239, .2); |
| | | background-color: rgba(63, 126, 239, .2); |
| | | } |
| | | |
| | | .green { |
| | | background-color: rgba(83, 183, 148, .2); |
| | | border: 1px solid rgba(83, 183, 148, .2); |
| | | } |
| | | |
| | | .gray { |
| | | color: gray; |
| | | border: 1px solid gray; |
| | | color: #333333; |
| | | background-color: rgba(128, 128, 128, .2); |
| | | border: 1px solid rgba(128, 128, 128, .2); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | .item { |
| | | width: 33.3%; |
| | | margin-bottom: 12px; |
| | | margin-bottom: 14px; |
| | | |
| | | .la { |
| | | color: #7f7f7f; |
| | | margin-top: 2px; |
| | | margin-bottom: 6px; |
| | | } |
| | | } |
| | | |
| | |
| | | width: 100%; |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | .la { |
| | | margin-bottom: 0; |
| | | width: 72px; |
| | | } |
| | | } |
| | | |
| | | .max { |
| | | width: 100%; |
| | | } |
| | | } |
| | | |
| | | .main_content { |
| | | display: flex; |
| | | |
| | | .side { |
| | | width: 370px; |
| | | |
| | | .title { |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .flow_list { |
| | | .item { |
| | | display: flex; |
| | | |
| | | .icon { |
| | | width: 28px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | |
| | | .dian { |
| | | width: 12px; |
| | | height: 12px; |
| | | border-radius: 50%; |
| | | background-color: #e89e42; |
| | | } |
| | | |
| | | .line { |
| | | width: 1px; |
| | | height: 100%; |
| | | background-color: #e89e42; |
| | | } |
| | | } |
| | | |
| | | .content { |
| | | font-size: 12px; |
| | | color: #999999; |
| | | padding-bottom: 12px; |
| | | |
| | | .name { |
| | | font-size: 13px; |
| | | color: #333333; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .file_list { |