<template> <view class="incidentDetail"> <view class="head"> <view class="tab" :class="{active: tab.value === dataInfo.tabActiveValue}" v-for="tab in dataInfo.tabs" :key="tab.id" @click="clickTab(tab.value)"> {{tab.name}}<text v-if="tab.num !== ''">({{tab.num}})</text> </view> </view> <scroll-view scroll-y class="body"> <!-- 工单信息 --> <template v-if="dataInfo.tabActiveValue === '1'"> <view class="detail_head"> <text class="title">报修信息</text> <view class="other"> <text class="priority" :style="priorityStyle(dataInfo.incidentData.priority)">{{dataInfo.incidentData.priority ? dataInfo.incidentData.priority.name + ' ' : ''}}</text> <view class="status" :style="stateStyle(dataInfo.incidentData.state)">{{dataInfo.incidentData.state ? dataInfo.incidentData.state.name : ''}}</view> </view> </view> <view class="detail_item_wrap"> <view class="deital_item"> <text class="name">单号:</text> <text class="value">{{dataInfo.incidentData.incidentsign || '无'}}</text> </view> <view class="deital_item"> <text class="name">故障现象:</text> <text class="value">{{dataInfo.incidentData.category ? dataInfo.incidentData.category.mutiCategory : '无'}}</text> </view> <view class="deital_item"> <text class="name">故障描述:</text> <text class="value">{{dataInfo.incidentData.description || '无'}}</text> </view> <view class="deital_item"> <text class="name">报修图片:</text> <view class="value img"> <image class="imgItem" :src="img.thumbFilePath" mode="aspectFill" v-for="(img, i) in dataInfo.repairImgs" :key="i" @click="previewImg(i, 'repairImgs')"></image> </view> </view> <view class="deital_item"> <text class="name">联系人:</text> <text class="value">{{dataInfo.incidentData.contacts || '无'}}</text> <text v-if="dataInfo.incidentData.contactsInformation" @click="makePhoneCall(dataInfo.incidentData.contactsInformation)">{{dataInfo.incidentData.contactsInformation}}<uni-icons type="phone-filled" class="phone-filled" :size="18" :color="primaryColor"></uni-icons></text> </view> <view class="deital_item"> <text class="name">来电电话:</text> <view class="value" @click="makePhoneCall(dataInfo.incidentData.incomingPhone)" v-if="dataInfo.incidentData.incomingPhone">{{dataInfo.incidentData.incomingPhone}}<uni-icons type="phone-filled" class="phone-filled" :size="18" :color="primaryColor"></uni-icons></view> <text class="value" v-else>无</text> <uni-icons v-if="dataInfo.incidentData.callID" @click="attachmentClick" type="mic-filled" class="mic-filled" :size="22" :color="primaryColor"></uni-icons> </view> <view class="deital_item"> <text class="name">报修科室:</text> <text class="value">{{dataInfo.incidentData.department ? dataInfo.incidentData.department.dept : '无'}}</text> </view> <view class="deital_item"> <text class="name">详细地址:</text> <text class="value" v-if="dataInfo.incidentData.place || dataInfo.incidentData.houseNumber">{{dataInfo.incidentData.place ? (dataInfo.incidentData.place.area.area + dataInfo.incidentData.place.place) : ''}}{{dataInfo.incidentData.houseNumber || ''}}</text> <text class="value" v-else>无</text> </view> <view class="deital_item"> <text class="name">报修人:</text> <text class="value">{{dataInfo.incidentData.requester ? dataInfo.incidentData.requester.name : '无'}}</text> </view> <view class="deital_item"> <text class="name">预约维修时间:</text> <text class="value">{{dataInfo.incidentData.yyTime || '无'}}</text> </view> <view class="deital_item"> <text class="name">受理人:</text> <text class="value">{{dataInfo.incidentData.acceptUser ? dataInfo.incidentData.acceptUser.name : '无'}}</text> </view> <view class="deital_item"> <text class="name">登记时间:</text> <text class="value">{{formatDate(dataInfo.incidentData.acceptDate, 'yyyy-MM-dd HH:mm')}}</text> </view> <view class="deital_item"> <text class="name">逾期解决时间:</text> <text class="value">{{formatDate(dataInfo.incidentData.overdueTime, 'yyyy-MM-dd HH:mm')}}</text> </view> </view> <view class="detail_head"> <text class="title">处理信息</text> </view> <view class="detail_item_wrap"> <view class="deital_item"> <text class="name">处理方式:</text> <text class="value">{{dataInfo.incidentData.handleCategory ? dataInfo.incidentData.handleCategory.name : '无'}}</text> <text class="value">处理结果:{{dataInfo.incidentData.closecode ? dataInfo.incidentData.closecode.name : '无'}}</text> </view> <view class="deital_item"> <text class="name">处理人:</text> <text class="value" v-if="dataInfo.incidentData.state.value == 'pending' && dataInfo.incidentData.currentLog">{{dataInfo.incidentData.currentLog.workerName}}<text @click="makePhoneCall(dataInfo.incidentData.currentLog.workerPhone)" v-if="dataInfo.incidentData.currentLog.workerPhone">({{dataInfo.incidentData.currentLog.workerPhone}})<uni-icons type="phone-filled" class="phone-filled" :size="18" :color="primaryColor"></uni-icons></text></text> <text class="value" v-else-if="dataInfo.incidentData.state.value != 'pending' && dataInfo.incidentData.handlingPersonnelUser">{{dataInfo.incidentData.handlingPersonnelUser.name}}<text @click="makePhoneCall(dataInfo.incidentData.handlingPersonnelUser.phone)" v-if="dataInfo.incidentData.handlingPersonnelUser.phone">({{dataInfo.incidentData.handlingPersonnelUser.phone}})<uni-icons type="phone-filled" class="phone-filled" :size="18" :color="primaryColor"></uni-icons></text></text> <text class="value" v-else>无</text> </view> <view class="deital_item"> <text class="name">处理方案:</text> <text class="value">{{dataInfo.incidentData.handleDescription || '无'}}</text> </view> <view class="deital_item"> <text class="name">处理图片:</text> <view class="value img"> <image class="imgItem" :src="img.thumbFilePath" mode="aspectFill" v-for="(img, i) in dataInfo.handlerImgs" :key="i" @click="previewImg(i, 'handlerImgs')"></image> </view> </view> <view class="deital_item"> <text class="name">维修总价:</text> <text class="value">{{dataInfo.incidentData.rsPrice === undefined ? '无' : dataInfo.incidentData.rsPrice + '元'}}</text> </view> <view class="deital_item"> <text class="name">协同人:</text> <text class="value">{{dataInfo.incidentData.synergetic && dataInfo.incidentData.synergetic.length ? dataInfo.incidentData.synergetic.map(v => v.name).join(',') : '无'}}</text> </view> </view> </template> <!-- 维修汇总单 --> <template v-if="dataInfo.tabActiveValue === '2'"> <view class="detail_head"> <text class="title">耗材清单</text> </view> <view class="summaryItem_bodyItem" v-for="item in dataInfo.summaryObj.consumableList" :key="item.id"> <view class="summaryItem_bodyItem_top"> <text class="name ellipsis">{{ item.consumableName }}({{ item.consumableBrandModel }})</text> <text class="value">{{ item.consumableEndPrice }}元</text> </view> <view class="summaryItem_bodyItem_bottom"> <text class="name">x{{ item.consumablesNum }}</text> <text class="value">总价{{item.consumablesNum * item.consumableEndPrice}}元</text> </view> </view> <view class="summaryItem_bodyItem_total">耗材总价:{{dataInfo.summaryObj.consumablePrice}}元</view> <view class="detail_head"> <text class="title">工时清单</text> </view> <view class="summaryItem_bodyItem" v-for="item in dataInfo.summaryObj.workHourManagementList" :key="item.id"> <view class="summaryItem_bodyItem_top"> <text class="name ellipsis">{{ item.workName }}</text> <text class="value">{{ item.wage }}元</text> </view> <view class="summaryItem_bodyItem_bottom"> <text class="name">x{{ item.workHourNum2 }}{{ item.workUnit }}</text> <text class="value">总价{{item.workHourNum2 * item.wage}}元</text> </view> </view> <view class="summaryItem_bodyItem_total">工时总价:{{dataInfo.summaryObj.workHourPrice}}元</view> <view class="summaryItem_total">汇总单总价:{{dataInfo.summaryObj.totalMaintenancePrice}}元</view> </template> <!-- 处理流程 --> <template v-if="dataInfo.tabActiveValue === '3'"> <view class="process_item_wrap"> <view class="process_item" v-for="item in dataInfo.incidentLogList" :key="item.id"> <view class="process_item_top"> <text class="name">{{item.logType ? item.logType.name : ''}}</text> <text class="value ellipsis" v-if="item.remark">({{item.remark}})</text> </view> <view class="process_item_bottom"> <text class="name">{{formatDate(item.startTime, 'yyyy-MM-dd HH:mm:ss')}}</text> <text class="value" v-if="item.appointorName">{{item.appointorName}}</text> </view> </view> </view> </template> <!-- 评价信息 --> <template v-if="dataInfo.tabActiveValue === '4'"> <view class="detail_head"> <text class="title">评价信息</text> </view> <view class="appraise_detail" v-for="item in dataInfo.resolveLogs" :key="item.id"> <view class="appraise_detail_top"> <text>{{formatDate(item.startTime, 'yyyy-MM-dd HH:mm:ss')}}</text> <view v-if="dataInfo.incidentData.wxdegree"> <uni-rate readonly :value="dataInfo.incidentData.wxdegree.value" /> </view> </view> <view class="appraise_detail_bottom"> <text>{{item.remark}}</text> </view> </view> <view class="detail_head"> <text class="title">回访信息</text> </view> <view class="appraise_detail" v-for="item in dataInfo.callbackLogs" :key="item.id"> <view class="appraise_detail_top"> <text>{{formatDate(item.startTime, 'yyyy-MM-dd HH:mm:ss')}}</text> <text v-if="dataInfo.incidentData.degree">{{dataInfo.incidentData.degree.name}}</text> </view> <view class="appraise_detail_bottom"> <text>{{item.remark}}</text> </view> </view> </template> </scroll-view> <view class="foot_common_btns"> <button @click="goBack" type="default" class="primaryButton btn">返回</button> </view> <IncidentAttachment v-if="dataInfo.isAttachment" @knowEmit="knowAttachment" :incidentData="dataInfo.incidentData"></IncidentAttachment> </view> </template> <script setup> import { ref, reactive } from 'vue' import IncidentAttachment from '@/components/IncidentAttachment.vue'; import { onLoad } from '@dcloudio/uni-app' import { api_listAttachment, api_incidentDetail, api_querySummaryDoc, api_incidentLog } from "@/http/api.js" import { defaultColor } from '@/static/js/theme.js' import { useSetTitle } from '@/share/useSetTitle.js' import { useMakePhoneCall } from '@/share/useMakePhoneCall.js' import { useGoBack } from '@/share/useGoBack.js' import { useLoginUserStore } from '@/stores/loginUser' import { computedPriorityStyle } from '@/filters/computedPriorityStyle.js' import { computedStateStyle } from '@/filters/computedStateStyle.js' import { filterFormatDate } from '@/filters/filterFormatDate.js' useSetTitle(); const loginUserStore = useLoginUserStore(); const { makePhoneCall } = useMakePhoneCall(); const { goBack } = useGoBack(); const { priorityStyle } = computedPriorityStyle(); const { stateStyle } = computedStateStyle(); const { formatDate } = filterFormatDate(); // 主题颜色 const primaryColor = ref(defaultColor) // 数据 const dataInfo = reactive({ tabs: [ {id: 1, name: '工单信息', value: '1', num: ''}, // {id: 2, name: '维修汇总单', value: '2', num: ''}, {id: 3, name: '处理流程', value: '3', num: ''}, {id: 4, name: '评价信息', value: '4', num: ''}, ], tabActiveValue: 0,//当前选择的tab incidentId: undefined,//事件ID incidentData: {},//事件对象 repairImgs: [],//报修图片 handlerImgs: [],//处理图片 summaryObj: { consumableList: [],//耗材列表 workHourManagementList: [],//工时列表 },//汇总单信息 incidentLogList: [],//流程列表 resolveLogs: [],//评价 callbackLogs: [],//回访 isAttachment: false,//录音开关 }) // 点击录音 function attachmentClick(){ dataInfo.isAttachment = true; } // 知道了录音 function knowAttachment(){ dataInfo.isAttachment = false; } // 获取汇总单信息 function getSummaryList(){ uni.showLoading({ title: "加载中", mask: true, }); let postData = { "incidentId": dataInfo.incidentId, }; api_querySummaryDoc(postData).then(res => { uni.hideLoading(); if(res.status == 200){ dataInfo.summaryObj = {...{consumableList:[], workHourManagementList: []}, ...res }; }else{ uni.showToast({ icon: 'none', title: res.msg || '请求数据失败!' }); } }) } // 获取流程列表 function getIncidentLogList(){ uni.showLoading({ title: "加载中", mask: true, }); let postData = { "idx": 0, "sum": 9999, "incidentLog": { "incidentId": dataInfo.incidentId, } }; api_incidentLog(postData).then(res => { uni.hideLoading(); if(res.status == 200){ let incidentLogList = res.list || []; dataInfo.incidentLogList = incidentLogList; }else{ uni.showToast({ icon: 'none', title: res.msg || '请求数据失败!' }); } }) } // 预览图片 function previewImg(index, type){ uni.previewImage({ current: index, urls: dataInfo[type].map(v => v.previewUrl), longPressActions: { itemList: ['发送给朋友', '保存图片', '收藏'], success: function(data) { console.log('选中了第' + (data.tapIndex + 1) + '个按钮,第' + (data.index + 1) + '张图片'); }, fail: function(err) { console.log(err.errMsg); } } }); } // 初始化表单 function initForm(){ if(dataInfo.tabActiveValue === '1'){ getRepairImgs(); getHandlerImgs(); }else if(dataInfo.tabActiveValue === '2'){ getSummaryList(); }else if(dataInfo.tabActiveValue === '3'){ getIncidentLogList(); }else if(dataInfo.tabActiveValue === '4'){ } } // 点击tab function clickTab(tabValue){ if(dataInfo.tabActiveValue == tabValue){ return; } dataInfo.tabActiveValue = tabValue; initForm() } // 获取事件详情 function getIncidentDetail(){ uni.showLoading({ title: "加载中", mask: true, }); api_incidentDetail(dataInfo.incidentId).then(res => { uni.hideLoading(); if(res.status == 200){ dataInfo.incidentData = res.data || {}; let logs = dataInfo.incidentData.logs || []; dataInfo.resolveLogs = logs.filter(v => v.logType.value == 'resolve').slice(0, 1); dataInfo.callbackLogs = logs.filter(v => v.logType.value == 'callback').slice(0, 1); // 维修汇总单 if(dataInfo.incidentData.state.value == 'close' && dataInfo.incidentData.duty.addSummary == 1 && dataInfo.incidentData.repairSummary == 1){ let flag = dataInfo.tabs.some(v => v.value === '2'); !flag && dataInfo.tabs.splice(1, 0, {id: 2, name: '维修汇总单', value: '2', num: ''}); } dataInfo.tabActiveValue = dataInfo.tabs[0].value; initForm() }else{ uni.showToast({ icon: 'none', title: res.msg || '请求数据失败!' }); } }) } // 获取报修图片 function getRepairImgs(){ uni.showLoading({ title: "加载中", mask: true, }); api_listAttachment('wechatRequesterIncident', dataInfo.incidentId).then(res => { uni.hideLoading(); res.data = res.data || []; res.data.forEach(v => { v.previewUrl = location.origin + "/file" + v.relativeFilePath; v.thumbFilePath = location.origin + "/file" + v.thumbFilePath; }) dataInfo.repairImgs = res.data; }) } // 获取处理图片 function getHandlerImgs(){ uni.showLoading({ title: "加载中", mask: true, }); api_listAttachment('incident', dataInfo.incidentId).then(res => { uni.hideLoading(); res.data = res.data || []; res.data.forEach(v => { v.previewUrl = location.origin + "/file" + v.relativeFilePath; v.thumbFilePath = location.origin + "/file" + v.thumbFilePath; }) dataInfo.handlerImgs = res.data; }) } onLoad((option) => { dataInfo.incidentId = option.incidentId; getIncidentDetail(); }) </script> <style lang="scss" scoped> .incidentDetail{ height: 100%; display: flex; flex-direction: column; justify-content: space-between; .head{ height: 88rpx; display: flex; position: fixed; z-index: 99; width: 100%; background-color: #fff; font-size: 30rpx; .tab{ flex: 1; display: flex; justify-content: center; align-items: center; border-bottom: 4rpx solid transparent; position: relative; &:last-of-type{ &:after{ display: none; } } &:after{ content: ''; position: absolute; right: 0; top: 50%; transform: translateY(-50%); width: 1rpx; height: 44rpx; background-color: #515151; } &.active{ color: $uni-primary; border-color: $uni-primary; } } } .body{ margin-top: 88rpx; box-sizing: border-box; flex: 1; min-height: 0; border-top: 7rpx solid #EBEBEB; .phone-filled{ margin-left: 5rpx; } .mic-filled{ margin-right: 100rpx; } .detail_item_wrap{ padding-bottom: 24rpx; } .detail_head{ padding: 24rpx; border-top: 1rpx solid #D2D2D2; border-bottom: 1rpx solid #D2D2D2; display: flex; justify-content: space-between; align-items: center; &:first-of-type{ border-top: none; } .title{ font-size: 26rpx; color: $uni-primary; padding-left: 18rpx; position: relative; &:before{ content: ''; width: 8rpx; height: 25rpx; background-color: $uni-primary; position: absolute; left: 0; top: 50%; transform: translateY(-50%); } } .other{ display: flex; align-items: center; .priority{ font-size: 26rpx; margin-right: 15rpx; } .status{ padding: 4rpx 10rpx; border-radius: 20rpx; background-color: #DBE8FE; font-size: 22rpx; color: #006CF9; } } } .deital_item{ font-size: 26rpx; color: #555; padding: 24rpx 24rpx 0; display: flex; align-items: center; .name{ width: 7em; margin-right: 24rpx; } .value{ flex: 1; word-break: break-all; &.img{ display: flex; .imgItem{ width: 82rpx; height: 82rpx; margin-right: 24rpx; &:last-of-type{ margin-right: 0; } } } } } .summaryItem_bodyItem{ padding: 24rpx 24rpx 0; font-size: 26rpx; .summaryItem_bodyItem_top{ display: flex; justify-content: space-between; align-items: center; .value{ padding-left: 48rpx; flex-shrink: 0; } } .summaryItem_bodyItem_bottom{ margin-top: 24rpx; display: flex; justify-content: space-between; align-items: center; .name{ text-align: right; flex: 1; } .value{ width: 220rpx; text-align: right; flex-shrink: 0; } } } .summaryItem_bodyItem_total{ text-align: right; padding: 24rpx; font-size: 26rpx; } .summaryItem_total{ text-align: center; padding-top: 24rpx; font-size: 32rpx; font-weight: bold; color: $uni-primary; border-top: 1rpx solid #D2D2D2; } .process_item_wrap{ padding: 38rpx; .process_item{ &:last-of-type{ .process_item_bottom{ border-left: none; } } .process_item_top{ padding-left: 30rpx; display: flex; align-items: center; position: relative; &:before{ content: ''; position: absolute; left: -13rpx; top: 50%; width: 26rpx; height: 26rpx; border-radius: 50%; background-color: $uni-primary; transform: translateY(-50%); } .name{ font-size: 30rpx; } .value{ margin-left: 20rpx; font-size: 24rpx; color: #A1A1A1; } } .process_item_bottom{ min-height: 82rpx; border-left: 1rpx solid #B7BDC6; margin-top: 5rpx; padding-left: 30rpx; display: flex; font-size: 24rpx; color: #A1A1A1; .value{ margin-left: 20rpx; } } } } .appraise_detail{ padding: 24rpx 24rpx 24rpx 40rpx; .appraise_detail_top{ display: flex; align-items: center; justify-content: space-between; font-size: 26rpx; .name{ color: #A1A1A1; } .value{} } .appraise_detail_bottom{ font-size: 30rpx; margin-top: 24rpx; word-break: break-all; } } } } </style>