| | |
| | | <el-dialog v-model="detailVisible" title="工单详情" width="80%" append-to-body> |
| | | <div class="detail-container"> |
| | | <div class="event-title-center">{{ currentDetail.orderName || '事件名称' }}</div> |
| | | <div v-if="totalTime" class="event-total-time" |
| | | style="text-align:center;color:#666;font-size:15px;margin-bottom:12px;"> |
| | | 总耗时:{{ totalTime }} |
| | | </div> |
| | | <!-- 工单状态流程 --> |
| | | <div class="custom-steps-container"> |
| | | <!-- 标题行 --> |
| | |
| | | <div class="media-box"> |
| | | <div class="media-title">事件图片</div> |
| | | <div class="media-content"> |
| | | <el-image |
| | | v-if="currentDetail.mediaUrl" |
| | | :src="getThumbUrl(currentDetail.mediaUrl)" |
| | | :preview-src-list="[currentDetail.mediaUrl]" |
| | | fit="cover" |
| | | style="width: 100%; height: 300px; cursor: pointer;" |
| | | > |
| | | <el-image v-if="currentDetail.mediaUrl" :src="getThumbUrl(currentDetail.mediaUrl)" |
| | | :preview-src-list="[currentDetail.mediaUrl]" fit="cover" |
| | | style="width: 100%; height: 300px; cursor: pointer;"> |
| | | <template #placeholder> |
| | | <div class="image-placeholder"> |
| | | <i class="el-icon-picture-outline"></i> |
| | |
| | | <template v-if="currentDetail.status === 5"> |
| | | <div class="media-title">工单处理图片</div> |
| | | <div class="media-content"> |
| | | <el-image |
| | | v-if="currentDetail.updatePhotoUrl" |
| | | :src="getThumbUrl(currentDetail.updatePhotoUrl)" |
| | | :preview-src-list="[currentDetail.updatePhotoUrl]" |
| | | fit="cover" |
| | | style="width: 100%; height: 300px; cursor: pointer;" |
| | | > |
| | | <el-image v-if="currentDetail.updatePhotoUrl" :src="getThumbUrl(currentDetail.updatePhotoUrl)" |
| | | :preview-src-list="[currentDetail.updatePhotoUrl]" fit="cover" |
| | | style="width: 100%; height: 300px; cursor: pointer;"> |
| | | <template #placeholder> |
| | | <div class="image-placeholder"> |
| | | <i class="el-icon-picture-outline"></i> |
| | |
| | | <div class="dialog-footer"> |
| | | <template v-if="currentDetail.status === 2"> |
| | | <!-- 待审核 --> |
| | | <el-button v-if="hasReviewBtnPermission()" type="primary" :loading="approveLoading" @click="approveTicket">通过</el-button> |
| | | <el-button v-if="hasReviewBtnPermission()" type="danger" :loading="rejectLoading" @click="rejectTicket">不通过</el-button> |
| | | <el-button v-if="hasReviewBtnPermission()" type="primary" :loading="approveLoading" |
| | | @click="approveTicket">通过</el-button> |
| | | <el-button v-if="hasReviewBtnPermission()" type="danger" :loading="rejectLoading" |
| | | @click="rejectTicket">不通过</el-button> |
| | | <el-button @click="detailVisible = false">取消</el-button> |
| | | </template> |
| | | <template v-else-if="currentDetail.status === 0"> |
| | | <el-button v-if="hasProcessingBtnPermission()" type="primary" :loading="dispatchLoading" @click="approveAndDispatch">通过并派发</el-button> |
| | | <el-button v-if="hasProcessingBtnPermission()" type="danger" :loading="rejectLoading" @click="rejectTicket">不通过</el-button> |
| | | <el-button v-if="hasProcessingBtnPermission()" type="primary" :loading="dispatchLoading" |
| | | @click="approveAndDispatch">通过并派发</el-button> |
| | | <el-button v-if="hasProcessingBtnPermission()" type="danger" :loading="rejectLoading" |
| | | @click="rejectTicket">不通过</el-button> |
| | | <el-button @click="detailVisible = false">取消</el-button> |
| | | </template> |
| | | <template v-if="currentDetail.status === 3"> |
| | | <!-- 处理中 --> |
| | | <el-button v-if="hasProcessedAndOverBtnPermission()" type="primary" :loading="completeLoading" @click="completeTicket">完成工单</el-button> |
| | | <el-button v-if="hasProcessedAndOverBtnPermission()" type="primary" :loading="completeLoading" |
| | | @click="completeTicket">完成工单</el-button> |
| | | <el-button @click="detailVisible = false">取消</el-button> |
| | | </template> |
| | | <template v-else-if="currentDetail.status === 4"> |
| | | <!-- 已完成 --> |
| | | <el-button v-if="hasProcessedAndOverBtnPermission()" type="primary" :loading="finalizeLoading" @click="finalizeTicket">完结工单</el-button> |
| | | <el-button v-if="hasProcessedAndOverBtnPermission()" type="primary" :loading="finalizeLoading" |
| | | @click="finalizeTicket">完结工单</el-button> |
| | | <el-button @click="detailVisible = false">取消</el-button> |
| | | </template> |
| | | <template v-else-if="currentDetail.status === 5"> |
| | |
| | | </div> |
| | | |
| | | <div class="review-image-container"> |
| | | <el-image |
| | | v-if="currentReviewImage" |
| | | :src="getThumbUrl(currentReviewImage)" |
| | | fit="cover" |
| | | :preview-src-list="getImageList()" |
| | | :initial-index="currentImageIndex - 1" |
| | | class="preview-image" |
| | | style="cursor: pointer;" |
| | | > |
| | | <el-image v-if="currentReviewImage" :src="getThumbUrl(currentReviewImage)" fit="cover" |
| | | :preview-src-list="getImageList()" :initial-index="currentImageIndex - 1" class="preview-image" |
| | | style="cursor: pointer;"> |
| | | <template #error> |
| | | <div class="image-error"> |
| | | <i class="el-icon-picture-outline"></i> |
| | |
| | | selection: true, // 添加多选功能 |
| | | index: true, // 保留序号功能 |
| | | indexLabel: '序号', |
| | | indexWidth: 60, |
| | | indexWidth: 60, |
| | | menuWidth: 150, |
| | | searchMenuSpan: 6, |
| | | viewBtn: false, |
| | |
| | | reviewDialogVisible: false, // 新增:审核对话框可见性 |
| | | currentReviewImage: '', // 新增:当前审核图片 |
| | | currentImageIndex: 1, // 新增:当前图片索引 |
| | | totalTime: '', |
| | | isShowInfo: false, |
| | | }; |
| | | }, |
| | |
| | | }, |
| | | |
| | | async fetchTabCounts() { |
| | | try { |
| | | // 判断是否有部门筛选 |
| | | let params = {}; |
| | | if (this.filters.department) { |
| | | params.deptId = this.filters.department; |
| | | } |
| | | const response = await getstatusCount(params); |
| | | const { statusCount, totalCount, userCount } = response.data.data; |
| | | this.tabs.forEach(tab => { |
| | | if (tab.name === 'all') { |
| | | tab.count = totalCount || 0; // 总工单数 |
| | | } else if (tab.name === 'myTickets') { |
| | | tab.count = userCount || 0; // 我发起的工单数 |
| | | } else { |
| | | tab.count = statusCount[String(tab.value)] || 0; // 根据状态值映射 |
| | | try { |
| | | // 判断是否有部门筛选 |
| | | let params = {}; |
| | | if (this.filters.department) { |
| | | params.deptId = this.filters.department; |
| | | } |
| | | const response = await getstatusCount(params); |
| | | const { statusCount, totalCount, userCount } = response.data.data; |
| | | this.tabs.forEach(tab => { |
| | | if (tab.name === 'all') { |
| | | tab.count = totalCount || 0; // 总工单数 |
| | | } else if (tab.name === 'myTickets') { |
| | | tab.count = userCount || 0; // 我发起的工单数 |
| | | } else { |
| | | tab.count = statusCount[String(tab.value)] || 0; // 根据状态值映射 |
| | | } |
| | | }); |
| | | } catch (error) { |
| | | this.$message.error('获取 tab 数据失败'); |
| | | } |
| | | }); |
| | | } catch (error) { |
| | | this.$message.error('获取 tab 数据失败'); |
| | | } |
| | | }, |
| | | }, |
| | | |
| | | handleTabChange(tab) { |
| | | this.activeTab = tab.props?.name || tab.name; |
| | |
| | | const steps = Array.isArray(stepResponse.data.data) |
| | | ? stepResponse.data.data |
| | | : stepResponse.data.data?.steps || []; |
| | | const finishedStep = steps.find(s => String(s.status) === '5'); |
| | | this.totalTime = finishedStep && finishedStep.total_time ? finishedStep.total_time : ''; |
| | | if (this.activeTab !== 'myTickets') { |
| | | this.stepInfos = steps.map(step => ({ |
| | | status: String(step.status), |