Commit 397b30ae6a39cfd4ad6c271fe9e1c4d4f3b5f329

Authored by 王彪总
1 parent 3c73dfc0

业务线 小程序不用写死,从后端接口获取

pages-sub/problem/regional-order-manage/index.vue
@@ -108,9 +108,9 @@ @@ -108,9 +108,9 @@
108 108
109 <!-- 待办工单(0) 保留原来的操作按钮区 不变 --> 109 <!-- 待办工单(0) 保留原来的操作按钮区 不变 -->
110 <view v-if="activeTab === 0" class="u-body-item u-body-item-btn-wrap u-flex common-justify-between common-item-center mt-20"> 110 <view v-if="activeTab === 0" class="u-body-item u-body-item-btn-wrap u-flex common-justify-between common-item-center mt-20">
111 - <up-button type="warning" size="large" @click="handleUnifiedReject(item)" v-show="nextStepMap[item.taskKey].backShow">回退</up-button> 111 + <up-button type="warning" size="large" @click="handleUnifiedReject(item)" v-show="showRejectButton(item)">回退</up-button>
112 <up-button type="success" size="large" @click="handleRenew(item)" v-show="nextStepMap[item.taskKey].renewShow">重新提交</up-button> 112 <up-button type="success" size="large" @click="handleRenew(item)" v-show="nextStepMap[item.taskKey].renewShow">重新提交</up-button>
113 - <up-button type="primary" size="large" @click="handleUnifiedProcess(item)">{{ nextStepMap[item.taskKey].btnText }}</up-button> 113 + <up-button type="primary" size="large" @click="handleUnifiedProcess(item)">{{ getProcessButtonText(item) }}</up-button>
114 <up-button type="info" size="large" @click="handleDetail(item)">详情</up-button> 114 <up-button type="info" size="large" @click="handleDetail(item)">详情</up-button>
115 </view> 115 </view>
116 116
@@ -366,6 +366,10 @@ const queryList = async (pageNo, pageSize) =&gt; { @@ -366,6 +366,10 @@ const queryList = async (pageNo, pageSize) =&gt; {
366 if (activeTab.value === 0) res = await todoBuzSimplePage(params); 366 if (activeTab.value === 0) res = await todoBuzSimplePage(params);
367 else if (activeTab.value === 2) res = await myBuzSimplePage(params); 367 else if (activeTab.value === 2) res = await myBuzSimplePage(params);
368 else res = await doneBuzSimplePage(params); 368 else res = await doneBuzSimplePage(params);
  369 + // 待办列表:预取各任务的统一动作配置,供底部按钮显隐使用
  370 + if (activeTab.value === 0) {
  371 + await attachConfiguredActions(res?.list);
  372 + }
369 pagingHandle('complete', res?.list || [], res?.total || 0); 373 pagingHandle('complete', res?.list || [], res?.total || 0);
370 } catch (error) { 374 } catch (error) {
371 console.error('加载工单失败:', error); 375 console.error('加载工单失败:', error);
@@ -440,9 +444,39 @@ const queryUnifiedActions = async (item) =&gt; { @@ -440,9 +444,39 @@ const queryUnifiedActions = async (item) =&gt; {
440 return null 444 return null
441 } 445 }
442 446
  447 +/** 待办列表:批量预取统一动作配置,挂在行数据上供按钮显隐复用 */
  448 +const attachConfiguredActions = async (list) => {
  449 + if (!Array.isArray(list) || list.length === 0) return
  450 + await Promise.all(list.map(async (item) => {
  451 + item.configuredActions = await queryUnifiedActions(item)
  452 + }))
  453 +}
  454 +
  455 +/** 驳回类动作编码:只有配置了这些动作,才展示「回退」按钮 */
  456 +const REJECT_ACTION_CODES = ['REJECT', 'RETURN', 'RETURN_PREV']
  457 +
  458 +/** 回退按钮显隐:已配置统一动作时以配置为准,未配置时沿用原有节点规则 */
  459 +const showRejectButton = (item) => {
  460 + if (Array.isArray(item?.configuredActions)) {
  461 + return item.configuredActions.some((action) => REJECT_ACTION_CODES.includes(action.code))
  462 + }
  463 + return !!nextStepMap[item.taskKey]?.backShow
  464 +}
  465 +
  466 +/** 主按钮文案:已配置统一动作时取配置的动作名称,未配置时沿用原有节点规则 */
  467 +const getProcessButtonText = (item) => {
  468 + const actions = item?.configuredActions
  469 + if (Array.isArray(actions) && actions.length > 0) {
  470 + return actions[0].name || actions[0].code
  471 + }
  472 + return nextStepMap[item.taskKey]?.btnText
  473 +}
  474 +
443 /** 待办-处理工单:已配置统一动作时走新逻辑,否则回退原有处理 */ 475 /** 待办-处理工单:已配置统一动作时走新逻辑,否则回退原有处理 */
444 const handleUnifiedProcess = async (item) => { 476 const handleUnifiedProcess = async (item) => {
445 - const actions = await queryUnifiedActions(item) 477 + const actions = Array.isArray(item?.configuredActions)
  478 + ? item.configuredActions
  479 + : await queryUnifiedActions(item)
446 if (actions) { 480 if (actions) {
447 unifiedActionsRef.value?.open(item, actions) 481 unifiedActionsRef.value?.open(item, actions)
448 return 482 return
@@ -452,7 +486,9 @@ const handleUnifiedProcess = async (item) =&gt; { @@ -452,7 +486,9 @@ const handleUnifiedProcess = async (item) =&gt; {
452 486
453 /** 待办-回退:已配置统一动作时走新逻辑,否则回退原有弹窗 */ 487 /** 待办-回退:已配置统一动作时走新逻辑,否则回退原有弹窗 */
454 const handleUnifiedReject = async (item) => { 488 const handleUnifiedReject = async (item) => {
455 - const actions = await queryUnifiedActions(item) 489 + const actions = Array.isArray(item?.configuredActions)
  490 + ? item.configuredActions
  491 + : await queryUnifiedActions(item)
456 if (actions) { 492 if (actions) {
457 const rejectActions = actions.filter((action) => 493 const rejectActions = actions.filter((action) =>
458 ['REJECT', 'RETURN', 'RETURN_PREV'].includes(action.code) 494 ['REJECT', 'RETURN', 'RETURN_PREV'].includes(action.code)
pages-sub/problem/regional-order-manage/list-detail.vue
@@ -229,7 +229,7 @@ @@ -229,7 +229,7 @@
229 type="warning" 229 type="warning"
230 size="normal" 230 size="normal"
231 @click="handleReject(orderDetail)" 231 @click="handleReject(orderDetail)"
232 - v-show="nextStepMap[orderDetail.taskKey].backShow" 232 + v-show="showRejectButton"
233 >回退</up-button> 233 >回退</up-button>
234 <up-button 234 <up-button
235 type="success" 235 type="success"
@@ -238,7 +238,7 @@ @@ -238,7 +238,7 @@
238 v-show="nextStepMap[orderDetail.taskKey].renewShow" 238 v-show="nextStepMap[orderDetail.taskKey].renewShow"
239 >重新提交</up-button> 239 >重新提交</up-button>
240 <up-button type="primary" size="normal" @click="handleProcess(orderDetail)"> 240 <up-button type="primary" size="normal" @click="handleProcess(orderDetail)">
241 - {{ nextStepMap[orderDetail.taskKey].btnText }} 241 + {{ processButtonText }}
242 </up-button> 242 </up-button>
243 </view> 243 </view>
244 </view> 244 </view>
@@ -326,10 +326,11 @@ @@ -326,10 +326,11 @@
326 </template> 326 </template>
327 327
328 <script setup lang="ts"> 328 <script setup lang="ts">
329 -import { ref } from 'vue' 329 +import { ref, computed } from 'vue'
330 import { onLoad } from '@dcloudio/uni-app' 330 import { onLoad } from '@dcloudio/uni-app'
331 import { timeFormat } from '@/uni_modules/uview-plus' 331 import { timeFormat } from '@/uni_modules/uview-plus'
332 import { getApprovalDetail,workOrderDetailByID } from '@/api/regional-order-manage/regional-order-manage' 332 import { getApprovalDetail,workOrderDetailByID } from '@/api/regional-order-manage/regional-order-manage'
  333 +import { getTaskActions } from '@/api/work-order-manage/work-order-manage'
333 334
334 import { nextStepMap, calculateFormatTimeDiff } from '@/common/utils/common' 335 import { nextStepMap, calculateFormatTimeDiff } from '@/common/utils/common'
335 import { useUploadImgs } from '@/common/utils/useUploadImgs' 336 import { useUploadImgs } from '@/common/utils/useUploadImgs'
@@ -484,6 +485,44 @@ const getCurrentStepIndex = () =&gt; { @@ -484,6 +485,44 @@ const getCurrentStepIndex = () =&gt; {
484 return activityNodes.length 485 return activityNodes.length
485 } 486 }
486 487
  488 +// ========== 统一节点动作(工作流配置化) ==========
  489 +/** 当前任务已配置的统一动作;null 表示未配置(回退原有按钮逻辑) */
  490 +const configuredActions = ref<any>(null)
  491 +
  492 +/** 查询当前任务是否已配置统一动作;未配置或接口异常时返回 null */
  493 +const queryUnifiedActions = async (taskId: any) => {
  494 + if (!taskId) return null
  495 + try {
  496 + const data = await getTaskActions(taskId)
  497 + if (data && data.configured && Array.isArray(data.actions) && data.actions.length > 0) {
  498 + return data.actions
  499 + }
  500 + } catch (e) {
  501 + console.warn('查询统一节点动作失败,回退原有逻辑', e)
  502 + }
  503 + return null
  504 +}
  505 +
  506 +/** 驳回类动作编码:只有配置了这些动作,才展示「回退」按钮 */
  507 +const REJECT_ACTION_CODES = ['REJECT', 'RETURN', 'RETURN_PREV']
  508 +
  509 +/** 回退按钮显隐:已配置统一动作时以配置为准,未配置时沿用原有节点规则 */
  510 +const showRejectButton = computed(() => {
  511 + if (Array.isArray(configuredActions.value)) {
  512 + return configuredActions.value.some((action: any) => REJECT_ACTION_CODES.includes(action.code))
  513 + }
  514 + return !!nextStepMap[orderDetail.value.taskKey]?.backShow
  515 +})
  516 +
  517 +/** 主按钮文案:已配置统一动作时取配置的动作名称,未配置时沿用原有节点规则 */
  518 +const processButtonText = computed(() => {
  519 + const actions = configuredActions.value
  520 + if (Array.isArray(actions) && actions.length > 0) {
  521 + return actions[0].name || actions[0].code
  522 + }
  523 + return nextStepMap[orderDetail.value.taskKey]?.btnText
  524 +})
  525 +
487 /** 526 /**
488 * 核心:工单详情接口 workOrderDetailByID 527 * 核心:工单详情接口 workOrderDetailByID
489 * @param id 上一页传递的工单ID 528 * @param id 上一页传递的工单ID
@@ -494,6 +533,8 @@ const DetailQuery = async (id: string | number) =&gt; { @@ -494,6 +533,8 @@ const DetailQuery = async (id: string | number) =&gt; {
494 loading.value = true 533 loading.value = true
495 const res = await workOrderDetailByID({ id }) 534 const res = await workOrderDetailByID({ id })
496 if (res) { 535 if (res) {
  536 + // 待办详情:预取当前任务的统一动作配置,用于底部按钮显隐
  537 + configuredActions.value = activeTab.value === '0' ? await queryUnifiedActions(res.taskId) : null
497 orderDetail.value = res 538 orderDetail.value = res
498 currentImgList.value = orderDetail.value.startImgs 539 currentImgList.value = orderDetail.value.startImgs
499 // 赋值流程实例ID,供流程节点接口使用 540 // 赋值流程实例ID,供流程节点接口使用
pages-sub/problem/regional-order-manage/order-detail.vue
@@ -256,7 +256,7 @@ @@ -256,7 +256,7 @@
256 <view v-if="activeTab==0&&nextStepMap[orderDetail.taskKey]" class="fixed-bottom-btn-wrap"> 256 <view v-if="activeTab==0&&nextStepMap[orderDetail.taskKey]" class="fixed-bottom-btn-wrap">
257 <view class="u-body-item u-flex common-justify-between common-item-center "> 257 <view class="u-body-item u-flex common-justify-between common-item-center ">
258 <up-button type="warning" size="normal" @click="handleReject(orderDetail)" 258 <up-button type="warning" size="normal" @click="handleReject(orderDetail)"
259 - v-show="nextStepMap[orderDetail.taskKey].backShow">回退 259 + v-show="showRejectButton">回退
260 </up-button> 260 </up-button>
261 261
262 <up-button type="success" size="normal" @click="handleRenew(orderDetail)" 262 <up-button type="success" size="normal" @click="handleRenew(orderDetail)"
@@ -264,7 +264,7 @@ @@ -264,7 +264,7 @@
264 </up-button> 264 </up-button>
265 265
266 <up-button type="primary" size="normal" @click="handleProcess(orderDetail)">{{ 266 <up-button type="primary" size="normal" @click="handleProcess(orderDetail)">{{
267 - nextStepMap[orderDetail.taskKey].btnText 267 + processButtonText
268 }} 268 }}
269 </up-button> 269 </up-button>
270 270
@@ -375,6 +375,7 @@ import { @@ -375,6 +375,7 @@ import {
375 aiUniversalApproval 375 aiUniversalApproval
376 } from '@/api/regional-order-manage/regional-order-manage'; 376 } from '@/api/regional-order-manage/regional-order-manage';
377 import {nextStepMap, buzStatusMap, calculateFormatTimeDiff} from '@/common/utils/common' 377 import {nextStepMap, buzStatusMap, calculateFormatTimeDiff} from '@/common/utils/common'
  378 +import {getTaskActions} from '@/api/work-order-manage/work-order-manage';
378 import {useUploadImgs} from '@/common/utils/useUploadImgs' 379 import {useUploadImgs} from '@/common/utils/useUploadImgs'
379 import { useUserStore } from '@/pinia/user'; 380 import { useUserStore } from '@/pinia/user';
380 381
@@ -552,6 +553,44 @@ const getCurrentStepIndex = () =&gt; { @@ -552,6 +553,44 @@ const getCurrentStepIndex = () =&gt; {
552 return activityNodes.length; 553 return activityNodes.length;
553 } 554 }
554 555
  556 +// ========== 统一节点动作(工作流配置化) ==========
  557 +/** 当前任务已配置的统一动作;null 表示未配置(回退原有按钮逻辑) */
  558 +const configuredActions = ref<any>(null)
  559 +
  560 +/** 查询当前任务是否已配置统一动作;未配置或接口异常时返回 null */
  561 +const queryUnifiedActions = async (taskIdStr: string) => {
  562 + if (!taskIdStr) return null
  563 + try {
  564 + const data = await getTaskActions(taskIdStr)
  565 + if (data && data.configured && Array.isArray(data.actions) && data.actions.length > 0) {
  566 + return data.actions
  567 + }
  568 + } catch (e) {
  569 + console.warn('查询统一节点动作失败,回退原有逻辑', e)
  570 + }
  571 + return null
  572 +}
  573 +
  574 +/** 驳回类动作编码:只有配置了这些动作,才展示「回退」按钮 */
  575 +const REJECT_ACTION_CODES = ['REJECT', 'RETURN', 'RETURN_PREV']
  576 +
  577 +/** 回退按钮显隐:已配置统一动作时以配置为准,未配置时沿用原有节点规则 */
  578 +const showRejectButton = computed(() => {
  579 + if (Array.isArray(configuredActions.value)) {
  580 + return configuredActions.value.some((action: any) => REJECT_ACTION_CODES.includes(action.code))
  581 + }
  582 + return !!nextStepMap[orderDetail.value.taskKey]?.backShow
  583 +})
  584 +
  585 +/** 主按钮文案:已配置统一动作时取配置的动作名称,未配置时沿用原有节点规则 */
  586 +const processButtonText = computed(() => {
  587 + const actions = configuredActions.value
  588 + if (Array.isArray(actions) && actions.length > 0) {
  589 + return actions[0].name || actions[0].code
  590 + }
  591 + return nextStepMap[orderDetail.value.taskKey]?.btnText
  592 +})
  593 +
555 /** 594 /**
556 * 获取工单详情 595 * 获取工单详情
557 */ 596 */
@@ -560,6 +599,8 @@ const DetailQuery = async (taskIdStr: string) =&gt; { @@ -560,6 +599,8 @@ const DetailQuery = async (taskIdStr: string) =&gt; {
560 try { 599 try {
561 loading.value = true; 600 loading.value = true;
562 const tabType = Number(activeTab.value); 601 const tabType = Number(activeTab.value);
  602 + // 待办详情:与详情请求并行预取当前任务的统一动作配置,用于底部按钮显隐
  603 + const actionPromise = tabType === 0 ? queryUnifiedActions(taskIdStr) : Promise.resolve(null);
563 let res: any; 604 let res: any;
564 // 0-待办 1-已办 2-我发起的任务 605 // 0-待办 1-已办 2-我发起的任务
565 if (tabType === 0) { 606 if (tabType === 0) {
@@ -574,6 +615,7 @@ const DetailQuery = async (taskIdStr: string) =&gt; { @@ -574,6 +615,7 @@ const DetailQuery = async (taskIdStr: string) =&gt; {
574 } 615 }
575 616
576 if (res) { 617 if (res) {
  618 + configuredActions.value = await actionPromise;
577 orderDetail.value = res; 619 orderDetail.value = res;
578 currentImgList.value = orderDetail.value.startImgs 620 currentImgList.value = orderDetail.value.startImgs
579 } 621 }
pages-sub/problem/work-order-manage/index.vue
@@ -103,7 +103,7 @@ @@ -103,7 +103,7 @@
103 <!-- 操作按钮行 --> 103 <!-- 操作按钮行 -->
104 <view class="u-body-item u-body-item-btn-wrap u-flex common-justify-between common-item-center mt-20"> 104 <view class="u-body-item u-body-item-btn-wrap u-flex common-justify-between common-item-center mt-20">
105 <up-button type="warning" size="large" @click="handleUnifiedReject(item)" 105 <up-button type="warning" size="large" @click="handleUnifiedReject(item)"
106 - v-show="nextStepMap[item.taskKey].backShow">回退 106 + v-show="showRejectButton(item)">回退
107 </up-button> 107 </up-button>
108 108
109 <up-button type="success" size="large" @click="handleRenew(item)" 109 <up-button type="success" size="large" @click="handleRenew(item)"
@@ -111,7 +111,7 @@ @@ -111,7 +111,7 @@
111 </up-button> 111 </up-button>
112 112
113 <up-button type="primary" size="large" @click="handleUnifiedProcess(item)">{{ 113 <up-button type="primary" size="large" @click="handleUnifiedProcess(item)">{{
114 - nextStepMap[item.taskKey].btnText 114 + getProcessButtonText(item)
115 }} 115 }}
116 </up-button> 116 </up-button>
117 <up-button type="info" size="large" @click="handleDetail(item)">详情</up-button> 117 <up-button type="info" size="large" @click="handleDetail(item)">详情</up-button>
@@ -404,6 +404,10 @@ const queryList = async (pageNo, pageSize) =&gt; { @@ -404,6 +404,10 @@ const queryList = async (pageNo, pageSize) =&gt; {
404 // 已办工单 404 // 已办工单
405 res = await doneBuzSimplePage(apiParams); 405 res = await doneBuzSimplePage(apiParams);
406 } 406 }
  407 + // 待办列表:预取各任务的统一动作配置,供底部按钮显隐使用
  408 + if (activeTab.value == 0) {
  409 + await attachConfiguredActions(res.list);
  410 + }
407 // 适配z-paging分页 411 // 适配z-paging分页
408 paging.value.complete(res.list, res.total); 412 paging.value.complete(res.list, res.total);
409 } catch (error) { 413 } catch (error) {
@@ -507,9 +511,39 @@ const queryUnifiedActions = async (item) =&gt; { @@ -507,9 +511,39 @@ const queryUnifiedActions = async (item) =&gt; {
507 return null 511 return null
508 } 512 }
509 513
  514 +/** 待办列表:批量预取统一动作配置,挂在行数据上供按钮显隐复用 */
  515 +const attachConfiguredActions = async (list) => {
  516 + if (!Array.isArray(list) || list.length === 0) return
  517 + await Promise.all(list.map(async (item) => {
  518 + item.configuredActions = await queryUnifiedActions(item)
  519 + }))
  520 +}
  521 +
  522 +/** 驳回类动作编码:只有配置了这些动作,才展示「回退」按钮 */
  523 +const REJECT_ACTION_CODES = ['REJECT', 'RETURN', 'RETURN_PREV']
  524 +
  525 +/** 回退按钮显隐:已配置统一动作时以配置为准,未配置时沿用原有节点规则 */
  526 +const showRejectButton = (item) => {
  527 + if (Array.isArray(item?.configuredActions)) {
  528 + return item.configuredActions.some((action) => REJECT_ACTION_CODES.includes(action.code))
  529 + }
  530 + return !!nextStepMap[item.taskKey]?.backShow
  531 +}
  532 +
  533 +/** 主按钮文案:已配置统一动作时取配置的动作名称,未配置时沿用原有节点规则 */
  534 +const getProcessButtonText = (item) => {
  535 + const actions = item?.configuredActions
  536 + if (Array.isArray(actions) && actions.length > 0) {
  537 + return actions[0].name || actions[0].code
  538 + }
  539 + return nextStepMap[item.taskKey]?.btnText
  540 +}
  541 +
510 /** 待办-处理工单:已配置统一动作时走新逻辑,否则回退原有处理 */ 542 /** 待办-处理工单:已配置统一动作时走新逻辑,否则回退原有处理 */
511 const handleUnifiedProcess = async (item) => { 543 const handleUnifiedProcess = async (item) => {
512 - const actions = await queryUnifiedActions(item) 544 + const actions = Array.isArray(item?.configuredActions)
  545 + ? item.configuredActions
  546 + : await queryUnifiedActions(item)
513 if (actions) { 547 if (actions) {
514 unifiedActionsRef.value?.open(item, actions) 548 unifiedActionsRef.value?.open(item, actions)
515 return 549 return
@@ -519,7 +553,9 @@ const handleUnifiedProcess = async (item) =&gt; { @@ -519,7 +553,9 @@ const handleUnifiedProcess = async (item) =&gt; {
519 553
520 /** 待办-回退:已配置统一动作时走新逻辑,否则回退原有弹窗 */ 554 /** 待办-回退:已配置统一动作时走新逻辑,否则回退原有弹窗 */
521 const handleUnifiedReject = async (item) => { 555 const handleUnifiedReject = async (item) => {
522 - const actions = await queryUnifiedActions(item) 556 + const actions = Array.isArray(item?.configuredActions)
  557 + ? item.configuredActions
  558 + : await queryUnifiedActions(item)
523 if (actions) { 559 if (actions) {
524 const rejectActions = actions.filter((action) => 560 const rejectActions = actions.filter((action) =>
525 ['REJECT', 'RETURN', 'RETURN_PREV'].includes(action.code) 561 ['REJECT', 'RETURN', 'RETURN_PREV'].includes(action.code)
pages-sub/problem/work-order-manage/order-detail.vue
@@ -259,7 +259,7 @@ @@ -259,7 +259,7 @@
259 <view v-if="activeTab==0&&nextStepMap[orderDetail.taskKey]" class="fixed-bottom-btn-wrap"> 259 <view v-if="activeTab==0&&nextStepMap[orderDetail.taskKey]" class="fixed-bottom-btn-wrap">
260 <view class="u-body-item u-flex common-justify-between common-item-center "> 260 <view class="u-body-item u-flex common-justify-between common-item-center ">
261 <up-button type="warning" size="normal" @click="handleUnifiedReject(orderDetail)" 261 <up-button type="warning" size="normal" @click="handleUnifiedReject(orderDetail)"
262 - v-show="nextStepMap[orderDetail.taskKey].backShow">回退 262 + v-show="showRejectButton">回退
263 </up-button> 263 </up-button>
264 264
265 <up-button type="success" size="normal" @click="handleRenew(orderDetail)" 265 <up-button type="success" size="normal" @click="handleRenew(orderDetail)"
@@ -267,7 +267,7 @@ @@ -267,7 +267,7 @@
267 </up-button> 267 </up-button>
268 268
269 <up-button type="primary" size="normal" @click="handleUnifiedProcess(orderDetail)">{{ 269 <up-button type="primary" size="normal" @click="handleUnifiedProcess(orderDetail)">{{
270 - nextStepMap[orderDetail.taskKey].btnText 270 + processButtonText
271 }} 271 }}
272 </up-button> 272 </up-button>
273 </view> 273 </view>
@@ -365,7 +365,7 @@ @@ -365,7 +365,7 @@
365 </template> 365 </template>
366 366
367 <script setup lang="ts"> 367 <script setup lang="ts">
368 -import {ref, watch} from 'vue'; 368 +import {ref, computed, watch} from 'vue';
369 import {onLoad, onShow} from '@dcloudio/uni-app'; 369 import {onLoad, onShow} from '@dcloudio/uni-app';
370 import {timeFormat} from '@/uni_modules/uview-plus'; 370 import {timeFormat} from '@/uni_modules/uview-plus';
371 import { 371 import {
@@ -513,6 +513,8 @@ const DetailQuery = async (taskIdStr: string) =&gt; { @@ -513,6 +513,8 @@ const DetailQuery = async (taskIdStr: string) =&gt; {
513 loading.value = true; 513 loading.value = true;
514 // 转换activeTab为数字类型,避免类型不一致导致接口调用失败 514 // 转换activeTab为数字类型,避免类型不一致导致接口调用失败
515 const tabType = Number(activeTab.value); 515 const tabType = Number(activeTab.value);
  516 + // 待办详情:与详情请求并行预取当前任务的统一动作配置,用于底部按钮显隐
  517 + const actionPromise = tabType === 0 ? queryUnifiedActions({taskId: taskIdStr}) : Promise.resolve(null);
516 let res: any; 518 let res: any;
517 // 0-待办 1-已办 2-我发起的任务 519 // 0-待办 1-已办 2-我发起的任务
518 if (tabType === 0) { 520 if (tabType === 0) {
@@ -528,6 +530,7 @@ const DetailQuery = async (taskIdStr: string) =&gt; { @@ -528,6 +530,7 @@ const DetailQuery = async (taskIdStr: string) =&gt; {
528 530
529 // 覆盖工单详情数据 531 // 覆盖工单详情数据
530 if (res) { 532 if (res) {
  533 + configuredActions.value = await actionPromise;
531 orderDetail.value = res; 534 orderDetail.value = res;
532 currentImgList.value = orderDetail.value.startImgs 535 currentImgList.value = orderDetail.value.startImgs
533 } 536 }
@@ -705,6 +708,29 @@ const confirmReject = async () =&gt; { @@ -705,6 +708,29 @@ const confirmReject = async () =&gt; {
705 // ========== 统一节点动作(工作流配置化) ========== 708 // ========== 统一节点动作(工作流配置化) ==========
706 const unifiedActionsRef = ref(null) 709 const unifiedActionsRef = ref(null)
707 710
  711 +/** 当前任务已配置的统一动作;null 表示未配置(回退原有按钮逻辑) */
  712 +const configuredActions = ref<any>(null)
  713 +
  714 +/** 驳回类动作编码:只有配置了这些动作,才展示「回退」按钮 */
  715 +const REJECT_ACTION_CODES = ['REJECT', 'RETURN', 'RETURN_PREV']
  716 +
  717 +/** 回退按钮显隐:已配置统一动作时以配置为准,未配置时沿用原有节点规则 */
  718 +const showRejectButton = computed(() => {
  719 + if (Array.isArray(configuredActions.value)) {
  720 + return configuredActions.value.some((action: any) => REJECT_ACTION_CODES.includes(action.code))
  721 + }
  722 + return !!nextStepMap[orderDetail.value.taskKey]?.backShow
  723 +})
  724 +
  725 +/** 主按钮文案:已配置统一动作时取配置的动作名称,未配置时沿用原有节点规则 */
  726 +const processButtonText = computed(() => {
  727 + const actions = configuredActions.value
  728 + if (Array.isArray(actions) && actions.length > 0) {
  729 + return actions[0].name || actions[0].code
  730 + }
  731 + return nextStepMap[orderDetail.value.taskKey]?.btnText
  732 +})
  733 +
708 /** 查询当前任务是否已配置统一动作;未配置或接口异常时返回 null,回退原有逻辑 */ 734 /** 查询当前任务是否已配置统一动作;未配置或接口异常时返回 null,回退原有逻辑 */
709 const queryUnifiedActions = async (item: any) => { 735 const queryUnifiedActions = async (item: any) => {
710 if (!item || !item.taskId) return null 736 if (!item || !item.taskId) return null
@@ -721,7 +747,9 @@ const queryUnifiedActions = async (item: any) =&gt; { @@ -721,7 +747,9 @@ const queryUnifiedActions = async (item: any) =&gt; {
721 747
722 /** 处理工单:已配置统一动作时走新逻辑,否则回退原有处理 */ 748 /** 处理工单:已配置统一动作时走新逻辑,否则回退原有处理 */
723 const handleUnifiedProcess = async (item: any) => { 749 const handleUnifiedProcess = async (item: any) => {
724 - const actions = await queryUnifiedActions(item) 750 + const actions = Array.isArray(configuredActions.value)
  751 + ? configuredActions.value
  752 + : await queryUnifiedActions(item)
725 if (actions) { 753 if (actions) {
726 unifiedActionsRef.value?.open(item, actions) 754 unifiedActionsRef.value?.open(item, actions)
727 return 755 return
@@ -731,7 +759,9 @@ const handleUnifiedProcess = async (item: any) =&gt; { @@ -731,7 +759,9 @@ const handleUnifiedProcess = async (item: any) =&gt; {
731 759
732 /** 回退:已配置统一动作时走新逻辑,否则回退原有弹窗 */ 760 /** 回退:已配置统一动作时走新逻辑,否则回退原有弹窗 */
733 const handleUnifiedReject = async (item: any) => { 761 const handleUnifiedReject = async (item: any) => {
734 - const actions = await queryUnifiedActions(item) 762 + const actions = Array.isArray(configuredActions.value)
  763 + ? configuredActions.value
  764 + : await queryUnifiedActions(item)
735 if (actions) { 765 if (actions) {
736 const rejectActions = actions.filter((action: any) => 766 const rejectActions = actions.filter((action: any) =>
737 ['REJECT', 'RETURN', 'RETURN_PREV'].includes(action.code) 767 ['REJECT', 'RETURN', 'RETURN_PREV'].includes(action.code)