Commit 2f1e317685883e87c449af0e779743548d5fb3f2
1 parent
4fa8cf12
图片参数处理
Showing
7 changed files
with
426 additions
and
139 deletions
common/utils/common.js
| ... | ... | @@ -42,16 +42,6 @@ export const nextStepMap = { |
| 42 | 42 | }, |
| 43 | 43 | } |
| 44 | 44 | |
| 45 | -// ylTeamLeader 养护组长退回:210 | |
| 46 | -// ylTeamLeader 养护组长分配:110 | |
| 47 | -// ylInspectorStart 巡查员结束工单:200 | |
| 48 | -// ylInspectorStart 巡查员重新发起:100 | |
| 49 | -// ylWorker 养护员退回 :220 | |
| 50 | -// ylWorker 养护员实施 :120 | |
| 51 | -// ylTeamLeaderConfirm 养护组长验收通过: 130 | |
| 52 | -// ylTeamLeaderConfirm 养护组长验收不通过:230 | |
| 53 | -// ylInspector 巡查员验收通过:140 | |
| 54 | -// ylInspector 巡查员验收不通过:240 | |
| 55 | 45 | |
| 56 | 46 | export const buzStatusMap = { |
| 57 | 47 | '000' :'巡查员发起', | ... | ... |
pages-sub/daily/maintain-manage/add-record.vue
| ... | ... | @@ -116,38 +116,14 @@ export default { |
| 116 | 116 | } |
| 117 | 117 | } |
| 118 | 118 | ], |
| 119 | - // progress: [ | |
| 120 | - // { | |
| 121 | - // | |
| 122 | - // required: true, | |
| 123 | - // message: '请设置完成进度', | |
| 124 | - // trigger: ['change'], | |
| 125 | - // validator: (rule, value, callback) => { | |
| 126 | - // // 第一步:校验是否为空/0 | |
| 127 | - // if (!value && value !== 0) { | |
| 128 | - // callback(new Error('请设置完成进度')) | |
| 129 | - // } | |
| 130 | - // // 第二步:校验是否大于初始进度 | |
| 131 | - // else if (value <= this.initProgress) { | |
| 132 | - // callback(new Error(`完成进度必须大于${this.initProgress}%`)) | |
| 133 | - // } | |
| 134 | - // // 校验通过 | |
| 135 | - // else { | |
| 136 | - // callback() | |
| 137 | - // } | |
| 138 | - // } | |
| 139 | - // } | |
| 140 | - // ] | |
| 119 | + | |
| 141 | 120 | } |
| 142 | 121 | } |
| 143 | 122 | }, |
| 144 | 123 | onLoad(option) { |
| 145 | 124 | console.log('页面参数:', option) |
| 146 | 125 | this.paramsOptins = option |
| 147 | - // // 初始化初始进度 | |
| 148 | - // this.initProgress = option.finishPercent ? Number(option.finishPercent)+1 : 0 | |
| 149 | - // // 关键修复:初始进度值设为 初始进度+1,避免刚进入就触发校验失败 | |
| 150 | - // this.inspectForm.progress = this.initProgress | |
| 126 | + | |
| 151 | 127 | |
| 152 | 128 | }, |
| 153 | 129 | onReady() { |
| ... | ... | @@ -158,30 +134,7 @@ export default { |
| 158 | 134 | /** |
| 159 | 135 | * 进度滑块变化处理 - 核心优化:实时触发校验 + 状态更新 |
| 160 | 136 | */ |
| 161 | - handleProgressChange(value) { | |
| 162 | - // // 1. 强制修正非法值(兜底) | |
| 163 | - // console.log(value) | |
| 164 | - // if (value <= this.initProgress) { | |
| 165 | - // console.log('123') | |
| 166 | - // this.inspectForm.progress = this.initProgress + 1 | |
| 167 | - // uni.showToast({ | |
| 168 | - // title: `进度不能低于${this.initProgress}%`, | |
| 169 | - // icon: 'none', | |
| 170 | - // duration: 1500 | |
| 171 | - // }) | |
| 172 | - // } | |
| 173 | - // | |
| 174 | - // // 2. 关键:手动触发progress字段的校验,实时更新提示状态 | |
| 175 | - // this.$nextTick(async () => { | |
| 176 | - // try { | |
| 177 | - // // 触发单个字段校验 | |
| 178 | - // await this.$refs.inspectFormRef.validateField('progress') | |
| 179 | - // } catch (err) { | |
| 180 | - // // 校验失败时uView会自动显示提示,此处无需额外处理 | |
| 181 | - // console.log('进度校验失败:', err) | |
| 182 | - // } | |
| 183 | - // }) | |
| 184 | - }, | |
| 137 | + | |
| 185 | 138 | |
| 186 | 139 | /** |
| 187 | 140 | * 删除图片 | ... | ... |
pages-sub/daily/quick-order/add-order.vue
| ... | ... | @@ -445,8 +445,8 @@ export default { |
| 445 | 445 | const submitData = { |
| 446 | 446 | roadId: this.workOrderForm.roadId, |
| 447 | 447 | roadName: this.workOrderForm.roadName, |
| 448 | - imgs: this.getImgUrlList(this.problemImgsList), | |
| 449 | - longRangeImgList: this.getImgUrlList(this.completeImgsList), | |
| 448 | + problemsImgs: this.getImgUrlList(this.problemImgsList), | |
| 449 | + endImgs : this.getImgUrlList(this.completeImgsList), | |
| 450 | 450 | remark: this.workOrderForm.problemDesc.trim(), |
| 451 | 451 | handleResult: this.workOrderForm.handleResult.trim(), |
| 452 | 452 | latLonType: 2, | ... | ... |
pages-sub/daily/quick-order/index.vue
| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | <up-sticky> |
| 5 | 5 | <view class="search-header"> |
| 6 | 6 | <!-- 左侧下拉框:替换为uView Plus的Select组件 --> |
| 7 | - <view class="select-wrap"> | |
| 7 | + <view class="select-wrap common-text-color"> | |
| 8 | 8 | <up-select |
| 9 | 9 | v-model:current="selectedSortValue" |
| 10 | 10 | :options="sortOptions" |
| ... | ... | @@ -173,8 +173,7 @@ const handleAddOrder = () => { |
| 173 | 173 | |
| 174 | 174 | // 下拉选择框容器 |
| 175 | 175 | .select-wrap { |
| 176 | - width: 80px; | |
| 177 | - color: #333; | |
| 176 | + width: 60px; | |
| 178 | 177 | margin-right: 20rpx; |
| 179 | 178 | // 适配up-select样式 |
| 180 | 179 | :deep(.u-select) { | ... | ... |
pages-sub/problem/work-order-manage/add-order.vue
| ... | ... | @@ -118,11 +118,11 @@ |
| 118 | 118 | <!-- 完成时间 --> |
| 119 | 119 | <up-form-item |
| 120 | 120 | label="希望完成时间" |
| 121 | - prop="finishDate" | |
| 121 | + prop="expectedFinishDate" | |
| 122 | 122 | @click="show=true;hideKeyboard()" |
| 123 | 123 | > |
| 124 | 124 | <up-input |
| 125 | - v-model="workOrderForm.finishDate" | |
| 125 | + v-model="workOrderForm.expectedFinishDate" | |
| 126 | 126 | border="none" |
| 127 | 127 | readonly |
| 128 | 128 | placeholder="点击选择时间" |
| ... | ... | @@ -155,11 +155,11 @@ |
| 155 | 155 | <!-- 完成时间选择器 --> |
| 156 | 156 | <up-datetime-picker |
| 157 | 157 | :show="show" |
| 158 | - v-model="finishDate" | |
| 158 | + v-model="expectedFinishDate" | |
| 159 | 159 | mode="datetime" |
| 160 | 160 | :min-date="new Date()" |
| 161 | 161 | @cancel="show = false" |
| 162 | - @confirm="finishDateConfirm" | |
| 162 | + @confirm="expectedFinishDateConfirm" | |
| 163 | 163 | ></up-datetime-picker> |
| 164 | 164 | </view> |
| 165 | 165 | </template> |
| ... | ... | @@ -201,7 +201,7 @@ const currentActionSheetData = reactive({ |
| 201 | 201 | }) |
| 202 | 202 | // 完成时间选择器控制 |
| 203 | 203 | const show = ref(false) |
| 204 | -const finishDate = ref(Date.now()) | |
| 204 | +const expectedFinishDate = ref(Date.now()) | |
| 205 | 205 | |
| 206 | 206 | // ========== 重新提交相关状态(核心:本地存储读取) ========== |
| 207 | 207 | const isRenew = ref(false); // 是否为重新提交状态 |
| ... | ... | @@ -223,7 +223,7 @@ const workOrderForm = reactive({ |
| 223 | 223 | problemDesc: '', // 情况描述 |
| 224 | 224 | lat: 0, // 纬度 |
| 225 | 225 | lon: 0, // 经度 |
| 226 | - finishDate: '', // 完成时间 | |
| 226 | + expectedFinishDate: '', // 希望完成时间 | |
| 227 | 227 | }) |
| 228 | 228 | |
| 229 | 229 | // ========== 表单校验规则 ========== |
| ... | ... | @@ -318,7 +318,7 @@ const echoOrderData = (orderItem) => { |
| 318 | 318 | workOrderForm.problemDesc = orderItem.remark || ''; |
| 319 | 319 | workOrderForm.lat = orderItem.lat || 0; |
| 320 | 320 | workOrderForm.lon = orderItem.lon || 0; |
| 321 | - workOrderForm.finishDate = orderItem.finishDate || timeFormat(new Date(), 'yyyy-mm-dd hh:MM:ss'); | |
| 321 | + workOrderForm.expectedFinishDate = orderItem.expectedFinishDate || timeFormat(new Date(), 'yyyy-mm-dd hh:MM:ss'); | |
| 322 | 322 | |
| 323 | 323 | // 2. 上传图片回显(兼容useUploadImgs格式) |
| 324 | 324 | if (orderItem.problemsImgs && Array.isArray(orderItem.problemsImgs) && orderItem.problemsImgs.length > 0) { |
| ... | ... | @@ -480,9 +480,9 @@ const chooseWorkLocation = () => { |
| 480 | 480 | /** |
| 481 | 481 | * 完成时间确认 |
| 482 | 482 | */ |
| 483 | -const finishDateConfirm = (e) => { | |
| 483 | +const expectedFinishDateConfirm = (e) => { | |
| 484 | 484 | console.log('选择的完成时间:', e) |
| 485 | - workOrderForm.finishDate = timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss') | |
| 485 | + workOrderForm.expectedFinishDate = timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss') | |
| 486 | 486 | show.value = false |
| 487 | 487 | } |
| 488 | 488 | |
| ... | ... | @@ -505,7 +505,7 @@ const submitWorkOrder = async () => { |
| 505 | 505 | const commonSubmitData = { |
| 506 | 506 | roadId: workOrderForm.roadId, |
| 507 | 507 | roadName: workOrderForm.roadName, |
| 508 | - imgs: problemImgs.getSuccessImgUrls(), // 复用上传逻辑的URL获取方法 | |
| 508 | + problemsImgs: problemImgs.getSuccessImgUrls(), // 复用上传逻辑的URL获取方法 | |
| 509 | 509 | remark: workOrderForm.problemDesc.trim(), |
| 510 | 510 | latLonType: 2, |
| 511 | 511 | lat: workOrderForm.lat, |
| ... | ... | @@ -513,7 +513,7 @@ const submitWorkOrder = async () => { |
| 513 | 513 | lonLatAddress: workOrderForm.workLocation, |
| 514 | 514 | pressingType: workOrderForm.pressingType, |
| 515 | 515 | orderName: workOrderForm.orderName, |
| 516 | - finishDate: workOrderForm.finishDate, | |
| 516 | + expectedFinishDate: workOrderForm.expectedFinishDate, | |
| 517 | 517 | sourceId: 1, |
| 518 | 518 | sourceName: '园林', |
| 519 | 519 | busiLine: 'yl' | ... | ... |
pages-sub/problem/work-order-manage/index.vue
| ... | ... | @@ -510,12 +510,12 @@ const confirmReject = async () => { |
| 510 | 510 | // 严格校验回退原因(去除首尾空格) |
| 511 | 511 | const rejectReasonTrim = rejectReason.value.trim(); |
| 512 | 512 | if (!rejectReasonTrim) { |
| 513 | - uni.showToast({title: '请填写回退原因', icon: 'none', duration: 2000}); | |
| 513 | + uni.showToast({title: '请填写回退原因', icon: 'none', duration: 1000}); | |
| 514 | 514 | return; |
| 515 | 515 | } |
| 516 | 516 | // 校验当前工单有效性 |
| 517 | 517 | if (!currentRejectItem.value || !currentRejectItem.value.id) { |
| 518 | - uni.showToast({title: '工单信息异常,无法提交', icon: 'none', duration: 2000}); | |
| 518 | + uni.showToast({title: '工单信息异常,无法提交', icon: 'none', duration:1000}); | |
| 519 | 519 | rejectModalShow.value = false; |
| 520 | 520 | return; |
| 521 | 521 | } |
| ... | ... | @@ -559,12 +559,12 @@ const handleAddOrder = () => { |
| 559 | 559 | const handleAcceptModalConfirm = async () => { |
| 560 | 560 | // 1. 校验验收原因是否为空 |
| 561 | 561 | if (!acceptReason.value.trim()) { |
| 562 | - uni.showToast({title: '请填写验收原因', icon: 'none', duration: 2000}); | |
| 562 | + uni.showToast({title: '请填写验收原因', icon: 'none', duration: 1000}); | |
| 563 | 563 | return; |
| 564 | 564 | } |
| 565 | 565 | // 2. 校验验收原因长度 |
| 566 | 566 | if (acceptReason.value.length > 200) { |
| 567 | - uni.showToast({title: '验收原因最多200字', icon: 'none', duration: 2000}); | |
| 567 | + uni.showToast({title: '验收原因最多200字', icon: 'none', duration: 1000}); | |
| 568 | 568 | return; |
| 569 | 569 | } |
| 570 | 570 | try { |
| ... | ... | @@ -592,14 +592,14 @@ const handleAcceptModalConfirm = async () => { |
| 592 | 592 | } |
| 593 | 593 | const acceptRes = await universalApproval(postData); |
| 594 | 594 | // 4. 操作成功处理 |
| 595 | - uni.showToast({title: '提交成功', icon: 'success', duration: 1500}); | |
| 595 | + uni.showToast({title: '提交成功', icon: 'success', duration: 1000}); | |
| 596 | 596 | acceptModalShow.value = false; |
| 597 | 597 | acceptReason.value = ''; // 清空验收原因 |
| 598 | 598 | paging.value?.reload(); // 刷新工单列表 |
| 599 | 599 | } catch (error) { |
| 600 | 600 | // 5. 操作失败处理 |
| 601 | 601 | console.error('养护组长验收失败:', error); |
| 602 | - uni.showToast({title: '验收提交失败,请重试', icon: 'none', duration: 2000}); | |
| 602 | + uni.showToast({title: '验收提交失败,请重试', icon: 'none', duration: 1000}); | |
| 603 | 603 | } |
| 604 | 604 | }; |
| 605 | 605 | |
| ... | ... | @@ -679,12 +679,6 @@ onShow(() => { |
| 679 | 679 | } |
| 680 | 680 | } |
| 681 | 681 | |
| 682 | -.reject-textarea { | |
| 683 | - font-size: 28rpx; | |
| 684 | - padding: 16rpx; | |
| 685 | - border: 1rpx solid #e4e7ed; | |
| 686 | - border-radius: 8rpx; | |
| 687 | -} | |
| 688 | 682 | |
| 689 | 683 | .upload-wrap { |
| 690 | 684 | margin-top: 20rpx; | ... | ... |
pages-sub/problem/work-order-manage/order-detail.vue
| ... | ... | @@ -110,7 +110,7 @@ |
| 110 | 110 | <!-- 希望完成时间 --> |
| 111 | 111 | <up-cell |
| 112 | 112 | title="希望完成时间" |
| 113 | - :value="orderDetail.finishDate === 0 ? '未设置' : timeFormat(orderDetail.finishDate, 'yyyy-mm-dd hh:MM:ss')" | |
| 113 | + :value="orderDetail.expectedFinishDate === 0 ? '未设置' : timeFormat(orderDetail.expectedFinishDate, 'yyyy-mm-dd hh:MM:ss')" | |
| 114 | 114 | align="middle" |
| 115 | 115 | :border="false" |
| 116 | 116 | ></up-cell> |
| ... | ... | @@ -131,7 +131,9 @@ |
| 131 | 131 | <view style="min-width: 200rpx">共同处理人</view> |
| 132 | 132 | </template> |
| 133 | 133 | <template #value> |
| 134 | - <view class="common-text-color up-line-1">{{ orderDetail.coHandlersName.join(',') || '--' }}</view> | |
| 134 | + <view class="common-text-color up-line-1"> | |
| 135 | + {{ Array.isArray(orderDetail.coHandlersName) && orderDetail.coHandlersName.length > 0 ? orderDetail.coHandlersName.join(',') : '--' }} | |
| 136 | + </view> | |
| 135 | 137 | </template> |
| 136 | 138 | </up-cell> |
| 137 | 139 | </up-cell-group> |
| ... | ... | @@ -167,10 +169,10 @@ |
| 167 | 169 | v-if="processData.activityNodes && processData.activityNodes.length" |
| 168 | 170 | :list="processData.activityNodes" |
| 169 | 171 | :current="getCurrentStepIndex()" |
| 170 | - direction="column" | |
| 171 | - active-color="#3c9cff" | |
| 172 | - inactive-color="#999" | |
| 173 | - class="vertical-steps" | |
| 172 | + direction="column" | |
| 173 | + active-color="#3c9cff" | |
| 174 | + inactive-color="#999" | |
| 175 | + class="vertical-steps" | |
| 174 | 176 | > |
| 175 | 177 | <template > |
| 176 | 178 | <up-steps-item |
| ... | ... | @@ -193,7 +195,7 @@ |
| 193 | 195 | <!-- 时间行 --> |
| 194 | 196 | <view class="time-line"> |
| 195 | 197 | 处理时间:{{ timeFormat(item.startTime, 'yyyy-mm-dd hh:MM:ss') }} |
| 196 | - <text v-if="item.endTime"> - {{ timeFormat(item.endTime, 'yyyy-mm-dd hh:MM:ss') }}</text> | |
| 198 | + <text v-if="item.endTime"> 至 {{ timeFormat(item.endTime, 'yyyy-mm-dd hh:MM:ss') }}</text> | |
| 197 | 199 | <text v-else class="processing-tag">(处理中)</text> |
| 198 | 200 | </view> |
| 199 | 201 | <!-- 原因行 --> |
| ... | ... | @@ -230,19 +232,98 @@ |
| 230 | 232 | </view> |
| 231 | 233 | </view> |
| 232 | 234 | </view> |
| 235 | + | |
| 236 | + <!-- activeTab==0的时候才出现, 也就是待办 --> | |
| 237 | + <view v-if="activeTab==0&&nextStepMap[orderDetail.taskKey]" class="fixed-bottom-btn-wrap"> | |
| 238 | + <view class="u-body-item u-flex common-justify-between common-item-center "> | |
| 239 | + <up-button type="warning" size="normal" @click="handleReject(orderDetail)" | |
| 240 | + v-show="nextStepMap[orderDetail.taskKey].backShow">回退 | |
| 241 | + </up-button> | |
| 242 | + | |
| 243 | + <up-button type="success" size="normal" @click="handleRenew(orderDetail)" | |
| 244 | + v-show="nextStepMap[orderDetail.taskKey].renewShow">重新提交 | |
| 245 | + </up-button> | |
| 246 | + | |
| 247 | + <up-button type="primary" size="normal" @click="handleProcess(orderDetail)">{{ | |
| 248 | + nextStepMap[orderDetail.taskKey].btnText | |
| 249 | + }} | |
| 250 | + </up-button> | |
| 251 | + | |
| 252 | + </view> | |
| 253 | + </view> | |
| 254 | + | |
| 255 | + <!-- 回退原因弹窗 --> | |
| 256 | + <up-modal | |
| 257 | + :show="rejectModalShow" | |
| 258 | + title="回退原因" | |
| 259 | + :closeOnClickOverlay="false" | |
| 260 | + :showConfirmButton="true" | |
| 261 | + :showCancelButton="true" | |
| 262 | + @cancel="handleRejectModalCancel" | |
| 263 | + @confirm="confirmReject" | |
| 264 | + > | |
| 265 | + <view class="reject-modal-content"> | |
| 266 | + <up-textarea | |
| 267 | + v-model.trim="rejectReason" | |
| 268 | + placeholder="请输入回退原因(必填)" | |
| 269 | + rows="6" | |
| 270 | + :count="200" | |
| 271 | + maxlength="200" | |
| 272 | + class="reject-textarea" | |
| 273 | + /> | |
| 274 | + </view> | |
| 275 | + </up-modal> | |
| 276 | + | |
| 277 | + <!-- 验收弹窗 --> | |
| 278 | + <up-modal | |
| 279 | + :show="acceptModalShow" | |
| 280 | + title="验收" | |
| 281 | + :closeOnClickOverlay="false" | |
| 282 | + :showConfirmButton="true" | |
| 283 | + :showCancelButton="true" | |
| 284 | + @cancel="acceptModalShow=false" | |
| 285 | + @confirm="handleAcceptModalConfirm" | |
| 286 | + > | |
| 287 | + <view class="accept-modal-content"> | |
| 288 | + <!-- 第一行:单选框(通过/不通过,默认通过) --> | |
| 289 | + <view class="radio-group-wrap"> | |
| 290 | + <up-radio-group v-model="acceptRadioValue"> | |
| 291 | + <up-radio name="0" label="通过"></up-radio> | |
| 292 | + <up-radio name="1" label="不通过"></up-radio> | |
| 293 | + </up-radio-group> | |
| 294 | + </view> | |
| 295 | + | |
| 296 | + <!-- 第二行:必填textarea,最多200字 --> | |
| 297 | + <view class="textarea-wrap mt-30"> | |
| 298 | + <up-textarea | |
| 299 | + v-model.trim="acceptReason" | |
| 300 | + placeholder="请输入验收原因(必填,最多200字)" | |
| 301 | + :required="true" | |
| 302 | + maxlength="200" | |
| 303 | + rows="5" | |
| 304 | + count | |
| 305 | + /> | |
| 306 | + </view> | |
| 307 | + </view> | |
| 308 | + </up-modal> | |
| 309 | + | |
| 233 | 310 | </view> |
| 234 | 311 | </template> |
| 235 | 312 | |
| 236 | 313 | <script setup lang="ts"> |
| 237 | -import {ref, computed} from 'vue'; | |
| 314 | +import {ref, watch} from 'vue'; | |
| 238 | 315 | import {onLoad, onShow} from '@dcloudio/uni-app'; |
| 239 | 316 | import {timeFormat} from '@/uni_modules/uview-plus'; |
| 240 | 317 | import { |
| 241 | 318 | getMyTaskDetail, |
| 242 | 319 | getDoneTaskDetail, |
| 243 | 320 | getTodoTaskDetail, |
| 244 | - getApprovalDetail | |
| 321 | + getApprovalDetail, | |
| 322 | + universalApproval | |
| 245 | 323 | } from '@/api/work-order-manage/work-order-manage'; |
| 324 | +import { nextStepMap, buzStatusMap } from '@/common/utils/common' | |
| 325 | +// 引入图片上传组合式函数 | |
| 326 | +import { useUploadImgs } from '@/common/utils/useUploadImgs' | |
| 246 | 327 | |
| 247 | 328 | // 状态管理 |
| 248 | 329 | const loading = ref(true); |
| ... | ... | @@ -263,36 +344,6 @@ const processData = ref<any>({ |
| 263 | 344 | todoTask: null |
| 264 | 345 | }); |
| 265 | 346 | |
| 266 | -const activeTopTabClick = async (item: any) => { | |
| 267 | - console.log(item) | |
| 268 | - activeTopTab.value = item.index | |
| 269 | - if (activeTopTab.value == 1) { | |
| 270 | - let getData = { | |
| 271 | - processInstanceId: processInstanceId.value, | |
| 272 | - } | |
| 273 | - const res = await getApprovalDetail(getData) | |
| 274 | - console.log(res) | |
| 275 | - // 关键:格式化数据,补充up-steps要求的title字段 | |
| 276 | - if (res && res.activityNodes && res.activityNodes.length) { | |
| 277 | - // 1. 先过滤:剔除 name 为 "结束" 的节点 | |
| 278 | - const filteredActivityNodes = res.activityNodes.filter(node => { | |
| 279 | - // 返回 true 保留节点,返回 false 剔除节点 | |
| 280 | - return node.name !== '结束'; | |
| 281 | - }); | |
| 282 | - const formatActivityNodes = filteredActivityNodes.map(node => ({ | |
| 283 | - ...node, | |
| 284 | - title: node.name // 补充强制字段,满足3.3.48版本组件要求 | |
| 285 | - })); | |
| 286 | - processData.value = { | |
| 287 | - ...res, | |
| 288 | - activityNodes: formatActivityNodes | |
| 289 | - }; | |
| 290 | - } else { | |
| 291 | - processData.value = res; | |
| 292 | - } | |
| 293 | - } | |
| 294 | -} | |
| 295 | - | |
| 296 | 347 | // 图片分类Tab列表(带角标配置) |
| 297 | 348 | const imgTabList = ref([ |
| 298 | 349 | {name: '开始', badge: {isDot: true}}, |
| ... | ... | @@ -318,6 +369,7 @@ const orderDetail = ref<any>({ |
| 318 | 369 | curingLevelName: '', |
| 319 | 370 | commitDate: 0, |
| 320 | 371 | finishDate: 0, |
| 372 | + expectedFinishDate:0, | |
| 321 | 373 | pressingType: 0, |
| 322 | 374 | userId: 0, |
| 323 | 375 | userName: '', |
| ... | ... | @@ -360,7 +412,7 @@ const orderDetail = ref<any>({ |
| 360 | 412 | const currentImgList = ref([]) |
| 361 | 413 | |
| 362 | 414 | const tabKeyMap = ['startImgs', 'processingImgs', 'endImgs', 'personImgs', 'materialImgs']; |
| 363 | -const imgTabChange = (({index}) => { | |
| 415 | +const imgTabChange = (({index}: {index: number}) => { | |
| 364 | 416 | console.log(index) |
| 365 | 417 | const currentKey = tabKeyMap[index] |
| 366 | 418 | console.log(currentKey) |
| ... | ... | @@ -389,16 +441,6 @@ const getCurrentStepIndex = () => { |
| 389 | 441 | const { activityNodes } = processData.value; |
| 390 | 442 | if (!activityNodes || !activityNodes.length) return 0; |
| 391 | 443 | |
| 392 | - // item.tasks && item.tasks[0]?.assigneeUser?.nickname | |
| 393 | - // 1. 查找第一个状态为1(处理中)的节点,即为当前步骤 | |
| 394 | - // const processingNodeIndex = activityNodes.findIndex(node => node.name === '结束'); | |
| 395 | - // console.log(processingNodeIndex) | |
| 396 | - // if (processingNodeIndex !== -1) { | |
| 397 | - // return activityNodes.length - 2 | |
| 398 | - // }else{ | |
| 399 | - // return activityNodes.length - 1 | |
| 400 | - // } | |
| 401 | - | |
| 402 | 444 | // 2. 若没有处理中的节点(全部已完成),则激活最后一个节点 |
| 403 | 445 | return activityNodes.length - 1; |
| 404 | 446 | } |
| ... | ... | @@ -442,6 +484,281 @@ const DetailQuery = async (taskIdStr: string) => { |
| 442 | 484 | const taskId = ref('') |
| 443 | 485 | const activeTab = ref('') |
| 444 | 486 | const processInstanceId = ref('') |
| 487 | + | |
| 488 | +const activeTopTabClick = async (item: any) => { | |
| 489 | + console.log(item) | |
| 490 | + activeTopTab.value = item.index | |
| 491 | + if (activeTopTab.value == 1) { | |
| 492 | + let getData = { | |
| 493 | + processInstanceId: processInstanceId.value, | |
| 494 | + } | |
| 495 | + const res = await getApprovalDetail(getData) | |
| 496 | + console.log(res) | |
| 497 | + // 关键:格式化数据,补充up-steps要求的title字段 | |
| 498 | + if (res && res.activityNodes && res.activityNodes.length) { | |
| 499 | + // 1. 先过滤:剔除 name 为 "结束" 的节点 | |
| 500 | + const filteredActivityNodes = res.activityNodes.filter(node => { | |
| 501 | + // 返回 true 保留节点,返回 false 剔除节点 | |
| 502 | + return node.name !== '结束'; | |
| 503 | + }); | |
| 504 | + const formatActivityNodes = filteredActivityNodes.map(node => ({ | |
| 505 | + ...node, | |
| 506 | + title: node.name // 补充强制字段,满足3.3.48版本组件要求 | |
| 507 | + })); | |
| 508 | + processData.value = { | |
| 509 | + ...res, | |
| 510 | + activityNodes: formatActivityNodes | |
| 511 | + }; | |
| 512 | + } else { | |
| 513 | + processData.value = res; | |
| 514 | + } | |
| 515 | + } | |
| 516 | +} | |
| 517 | + | |
| 518 | + | |
| 519 | +// ========== 新增:回退弹窗相关状态 ========== | |
| 520 | +const rejectModalShow = ref(false); // 回退modal显示开关 | |
| 521 | +const rejectReason = ref(''); // 回退原因 | |
| 522 | +const currentRejectItem = ref<any>(null); // 当前回退工单 | |
| 523 | +// 回退图片上传配置 | |
| 524 | +const rejectImgs = useUploadImgs({ | |
| 525 | + maxCount: 3, | |
| 526 | + uploadText: '选择回退图片', | |
| 527 | + sizeType: ['compressed'], | |
| 528 | + formRef: null, | |
| 529 | + fieldName: 'rejectImgs' | |
| 530 | +}) | |
| 531 | +// 监听上传实例响应式变化 | |
| 532 | +watch(() => rejectImgs.rawImgList.value, (newVal) => { | |
| 533 | + rejectImgs.imgList = newVal | |
| 534 | +}, { deep: true }) | |
| 535 | + | |
| 536 | +// ========== 新增:验收弹窗相关状态 ========== | |
| 537 | +const acceptModalShow = ref(false); // 验收弹窗显示开关 | |
| 538 | +const acceptRadioValue = ref('0'); // 单选框值,默认0(通过) | |
| 539 | +const acceptReason = ref(''); // 验收原因 | |
| 540 | +const currentAcceptItem = ref<any>(null); // 当前验收的工单项 | |
| 541 | + | |
| 542 | +// ========== 新增:生成临时key ========== | |
| 543 | +const generateTempKey = () => { | |
| 544 | + return 'renew_order_' + Date.now() + '_' + Math.floor(Math.random() * 10000); | |
| 545 | +}; | |
| 546 | + | |
| 547 | +// ========== 新增:handleRenew 重新提交工单 ========== | |
| 548 | +const handleRenew = (item: any) => { | |
| 549 | + // 校验工单有效性 | |
| 550 | + if (!item || !item.id) { | |
| 551 | + uni.showToast({title: '工单信息异常,无法重新提交', icon: 'none'}); | |
| 552 | + return; | |
| 553 | + } | |
| 554 | + | |
| 555 | + // 1. 生成唯一临时标识 | |
| 556 | + const tempKey = generateTempKey(); | |
| 557 | + | |
| 558 | + // 2. 将完整工单数据存入本地临时存储(同步存储,确保数据立即生效) | |
| 559 | + try { | |
| 560 | + uni.setStorageSync(tempKey, item); | |
| 561 | + } catch (error) { | |
| 562 | + console.error('存储工单数据失败:', error); | |
| 563 | + uni.showToast({title: '数据存储异常,无法重新提交', icon: 'none'}); | |
| 564 | + return; | |
| 565 | + } | |
| 566 | + | |
| 567 | + // 3. URL 仅传递「唯一标识」和「重新提交标记」 | |
| 568 | + uni.navigateTo({ | |
| 569 | + url: `/pages-sub/problem/work-order-manage/add-order?isRenew=1&tempKey=${tempKey}` | |
| 570 | + }); | |
| 571 | +}; | |
| 572 | + | |
| 573 | +// ========== 新增:handleReject 打开回退弹窗 ========== | |
| 574 | +const handleReject = (item: any) => { | |
| 575 | + // 校验工单有效性 | |
| 576 | + if (!item || !item.id) { | |
| 577 | + uni.showToast({title: '工单信息异常,无法回退', icon: 'none'}); | |
| 578 | + return; | |
| 579 | + } | |
| 580 | + currentRejectItem.value = item; | |
| 581 | + rejectReason.value = ''; // 清空上次输入 | |
| 582 | + rejectImgs.clearImgs(); // 清空上传图片 | |
| 583 | + rejectModalShow.value = true; // 显示回退modal | |
| 584 | +}; | |
| 585 | + | |
| 586 | +// ========== 新增:回退弹窗取消按钮 ========== | |
| 587 | +const handleRejectModalCancel = () => { | |
| 588 | + rejectModalShow.value = false; | |
| 589 | + rejectReason.value = ''; | |
| 590 | + rejectImgs.clearImgs(); // 清空上传图片 | |
| 591 | +}; | |
| 592 | + | |
| 593 | +// ========== 新增:确认回退工单 ========== | |
| 594 | +const confirmReject = async () => { | |
| 595 | + // 严格校验回退原因(去除首尾空格) | |
| 596 | + const rejectReasonTrim = rejectReason.value.trim(); | |
| 597 | + if (!rejectReasonTrim) { | |
| 598 | + uni.showToast({title: '请填写回退原因', icon: 'none', duration: 1000}); | |
| 599 | + return; | |
| 600 | + } | |
| 601 | + // 校验当前工单有效性 | |
| 602 | + if (!currentRejectItem.value || !currentRejectItem.value.id) { | |
| 603 | + uni.showToast({title: '工单信息异常,无法提交', icon: 'none', duration: 1000}); | |
| 604 | + rejectModalShow.value = false; | |
| 605 | + return; | |
| 606 | + } | |
| 607 | + try { | |
| 608 | + // 显示加载中,防止重复提交 | |
| 609 | + uni.showLoading({title: '提交中...', mask: true}); | |
| 610 | + | |
| 611 | + // 构建请求参数 | |
| 612 | + const requestData = { | |
| 613 | + "returnImgs": rejectImgs.getSuccessImgUrls(), | |
| 614 | + "workerDataId": currentRejectItem.value.id, | |
| 615 | + "taskKey": currentRejectItem.value.taskKey, | |
| 616 | + "taskId": currentRejectItem.value.taskId, | |
| 617 | + "operateType": nextStepMap[currentRejectItem.value.taskKey].operateTypeNoPass, | |
| 618 | + "agree": 1, | |
| 619 | + "reason": rejectReasonTrim | |
| 620 | + }; | |
| 621 | + // 调用回退工单接口 | |
| 622 | + const res = await universalApproval(requestData); | |
| 623 | + uni.showToast({title: '回退成功', icon: 'success', duration: 1000}); | |
| 624 | + rejectModalShow.value = false; | |
| 625 | + // 重新获取工单详情,刷新页面 | |
| 626 | + await DetailQuery(taskId.value); | |
| 627 | + } catch (error) { | |
| 628 | + console.error('回退工单失败:', error); | |
| 629 | + uni.showToast({title: '网络异常,回退失败', icon: 'none', duration: 1000}); | |
| 630 | + } finally { | |
| 631 | + // 隐藏加载中 | |
| 632 | + uni.hideLoading(); | |
| 633 | + } | |
| 634 | +}; | |
| 635 | + | |
| 636 | +// ========== 新增:handleProcess 处理工单 ========== | |
| 637 | +const handleProcess = async (item: any) => { | |
| 638 | + console.log(nextStepMap[item.taskKey]?.name) | |
| 639 | + try { | |
| 640 | + if (nextStepMap[item.taskKey]?.name == '养护组长分配') { | |
| 641 | + uni.navigateTo({ | |
| 642 | + url: `/pages-sub/problem/work-order-manage/distribution-order?taskId=${item.taskId}&orderNo=${item.orderNo}&id=${item.id}` | |
| 643 | + }) | |
| 644 | + } | |
| 645 | + if (nextStepMap[item.taskKey]?.name == '养护员待实施') { | |
| 646 | + // ① 生成唯一临时key | |
| 647 | + const tempKey = `maintain_order_${Date.now()}_${Math.floor(Math.random() * 10000)}`; | |
| 648 | + | |
| 649 | + // ② 存储完整item到本地缓存 | |
| 650 | + try { | |
| 651 | + uni.setStorageSync(tempKey, item); | |
| 652 | + } catch (error) { | |
| 653 | + console.error('存储养护工单数据失败:', error); | |
| 654 | + uni.showToast({title: '数据存储异常,无法跳转', icon: 'none'}); | |
| 655 | + return; | |
| 656 | + } | |
| 657 | + | |
| 658 | + // ③ URL仅传递临时key | |
| 659 | + uni.navigateTo({ | |
| 660 | + url: `/pages-sub/problem/work-order-manage/add-maintain-order?tempKey=${tempKey}` | |
| 661 | + }) | |
| 662 | + } | |
| 663 | + // 养护组长验收 - 打开弹窗 | |
| 664 | + if (nextStepMap[item.taskKey]?.name == '养护组长验收') { | |
| 665 | + currentAcceptItem.value = item; // 存储当前工单信息 | |
| 666 | + acceptReason.value = ''; // 清空上次的验收原因 | |
| 667 | + acceptRadioValue.value = '0'; // 重置默认选中“通过” | |
| 668 | + acceptModalShow.value = true; // 显示验收弹窗 | |
| 669 | + } | |
| 670 | + // 巡查员验收 - 打开弹窗 | |
| 671 | + if (nextStepMap[item.taskKey]?.name == '巡查员验收') { | |
| 672 | + currentAcceptItem.value = item; // 存储当前工单信息 | |
| 673 | + acceptReason.value = ''; // 清空上次的验收原因 | |
| 674 | + acceptRadioValue.value = '0'; // 重置默认选中“通过” | |
| 675 | + acceptModalShow.value = true; // 显示验收弹窗 | |
| 676 | + } | |
| 677 | + | |
| 678 | + // 发起人确认 | |
| 679 | + if (nextStepMap[item.taskKey]?.name == '发起人确认') { | |
| 680 | + console.log(item) | |
| 681 | + uni.showModal({ | |
| 682 | + title: "结束工单", | |
| 683 | + content: "请确定是否结束工单?", | |
| 684 | + success: async function (res) { | |
| 685 | + if (res.confirm) { | |
| 686 | + // 构建请求参数 | |
| 687 | + const requestData = { | |
| 688 | + "returnImgs": rejectImgs.getSuccessImgUrls(), | |
| 689 | + "workerDataId": item.id, | |
| 690 | + "taskKey":'ylInspectorStart', | |
| 691 | + "taskId": item.taskId, | |
| 692 | + "operateType": 200, | |
| 693 | + "agree": 1, | |
| 694 | + "reason": '结束工单' | |
| 695 | + }; | |
| 696 | + // 调用回退工单接口 | |
| 697 | + const res = await universalApproval(requestData); | |
| 698 | + uni.showToast({title: '结束成功', icon: 'success', duration: 1000}); | |
| 699 | + // 重新获取工单详情,刷新页面 | |
| 700 | + await DetailQuery(taskId.value); | |
| 701 | + } else if (res.cancel) { | |
| 702 | + console.log("用户点击取消"); | |
| 703 | + } | |
| 704 | + }, | |
| 705 | + }); | |
| 706 | + } | |
| 707 | + } catch (error) { | |
| 708 | + console.error('处理工单失败:', error); | |
| 709 | + uni.showToast({title: '处理失败,请重试', icon: 'none'}); | |
| 710 | + } | |
| 711 | +}; | |
| 712 | + | |
| 713 | +// ========== 新增:验收弹窗确认按钮 ========== | |
| 714 | +const handleAcceptModalConfirm = async () => { | |
| 715 | + // 1. 校验验收原因是否为空 | |
| 716 | + if (!acceptReason.value.trim()) { | |
| 717 | + uni.showToast({title: '请填写验收原因', icon: 'none', duration: 1000}); | |
| 718 | + return; | |
| 719 | + } | |
| 720 | + // 2. 校验验收原因长度 | |
| 721 | + if (acceptReason.value.length > 200) { | |
| 722 | + uni.showToast({title: '验收原因最多200字', icon: 'none', duration: 1000}); | |
| 723 | + return; | |
| 724 | + } | |
| 725 | + try { | |
| 726 | + // 3. 调用验收接口 | |
| 727 | + console.log(currentAcceptItem.value) | |
| 728 | + let postData: any = {} | |
| 729 | + if (currentAcceptItem.value?.taskKey == 'ylTeamLeaderConfirm') { // 养护组长验收 | |
| 730 | + postData = { | |
| 731 | + "taskKey": currentAcceptItem.value.taskKey, // ylTeamLeaderConfirm | |
| 732 | + "workerDataId": currentAcceptItem.value.id, | |
| 733 | + "taskId": currentAcceptItem.value.taskId, | |
| 734 | + "operateType": acceptRadioValue.value == 0 ? nextStepMap[currentAcceptItem.value.taskKey].operateTypePass : nextStepMap[currentAcceptItem.value.taskKey].operateTypeNoPass, | |
| 735 | + "reason": acceptReason.value.trim() | |
| 736 | + } | |
| 737 | + } | |
| 738 | + if (currentAcceptItem.value?.taskKey == 'ylInspector') { // 巡查员验收 | |
| 739 | + postData = { | |
| 740 | + "taskKey": currentAcceptItem.value.taskKey, //ylInspector | |
| 741 | + "taskId": currentAcceptItem.value.taskId, | |
| 742 | + "workerDataId": currentAcceptItem.value.id, | |
| 743 | + "operateType": acceptRadioValue.value == 0 ? nextStepMap[currentAcceptItem.value.taskKey].operateTypePass : nextStepMap[currentAcceptItem.value.taskKey].operateTypeNoPass, | |
| 744 | + "reason": acceptReason.value.trim(), | |
| 745 | + "agree": acceptRadioValue.value | |
| 746 | + } | |
| 747 | + } | |
| 748 | + const acceptRes = await universalApproval(postData); | |
| 749 | + // 4. 操作成功处理 | |
| 750 | + uni.showToast({title: '提交成功', icon: 'success', duration: 1000}); | |
| 751 | + acceptModalShow.value = false; | |
| 752 | + acceptReason.value = ''; // 清空验收原因 | |
| 753 | + // 重新获取工单详情,刷新页面 | |
| 754 | + await DetailQuery(taskId.value); | |
| 755 | + } catch (error) { | |
| 756 | + // 5. 操作失败处理 | |
| 757 | + console.error('验收失败:', error); | |
| 758 | + uni.showToast({title: '验收提交失败,请重试', icon: 'none', duration: 1000}); | |
| 759 | + } | |
| 760 | +}; | |
| 761 | + | |
| 445 | 762 | onLoad((options: any) => { |
| 446 | 763 | console.log('页面入参:', options) |
| 447 | 764 | const {taskId: taskIdOpt, activeTab: activeTabOpt, processInstanceId: processInstanceIdOpt} = options; |
| ... | ... | @@ -465,7 +782,7 @@ onShow(() => { |
| 465 | 782 | |
| 466 | 783 | // 主内容容器 |
| 467 | 784 | .main-content { |
| 468 | - padding-bottom: 20rpx; | |
| 785 | + padding-bottom: 80rpx; | |
| 469 | 786 | } |
| 470 | 787 | |
| 471 | 788 | // 顶部Tabs |
| ... | ... | @@ -601,4 +918,38 @@ onShow(() => { |
| 601 | 918 | } |
| 602 | 919 | } |
| 603 | 920 | } |
| 921 | + | |
| 922 | + | |
| 923 | + | |
| 924 | +// 回退弹窗样式 | |
| 925 | +.reject-modal-content { | |
| 926 | + width: 100%; | |
| 927 | + box-sizing: border-box; | |
| 928 | + padding: 10rpx 0; | |
| 929 | +} | |
| 930 | + | |
| 931 | + | |
| 932 | +// 验收弹窗样式 | |
| 933 | +.accept-modal-content { | |
| 934 | + width: 100%; | |
| 935 | + box-sizing: border-box; | |
| 936 | +} | |
| 937 | + | |
| 938 | +.radio-group-wrap { | |
| 939 | + display: flex; | |
| 940 | + align-items: center; | |
| 941 | + gap: 40rpx; | |
| 942 | + font-size: 28rpx; | |
| 943 | + margin-bottom: 20rpx; | |
| 944 | +} | |
| 945 | + | |
| 946 | +.textarea-wrap { | |
| 947 | + width: 100%; | |
| 948 | + margin-top: 30rpx; | |
| 949 | +} | |
| 950 | + | |
| 951 | + | |
| 952 | +.mt-30 { | |
| 953 | + margin-top: 30rpx; | |
| 954 | +} | |
| 604 | 955 | </style> |
| 605 | 956 | \ No newline at end of file | ... | ... |