Commit 9120066cfe0aed12a4ed7dfe25d6b4f1a3fac6c4

Authored by 王彪总
1 parent 5902ef3e

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

... ... @@ -136,7 +136,7 @@ page {
136 136 top: var(--btn-top, 100px);
137 137 right: 15px;
138 138 //transform: translateX(-50%);
139   - background-color: #3c9cff;
  139 + background-color: #3b9dff;
140 140 color: #ffffff;
141 141 border: none;
142 142 border-radius: 4px;
... ...
common/config/env.js
... ... @@ -2,12 +2,12 @@
2 2 const env = {
3 3 // 开发环境
4 4 development: {
5   - baseUrl: 'https://test.jichengshanshui.com.cn:28302',
  5 + // baseUrl: 'https://test.jichengshanshui.com.cn:28302',
6 6 // https://test.jichengshanshui.com.cn:28302
7 7  
8   - // baseUrl: 'http://192.168.1.111:48081',
  8 + baseUrl: 'http://192.168.1.163:48081',
9 9  
10   - uploadUrl: 'https://test.jichengshanshui.com.cn:28302',
  10 + uploadUrl: 'http://192.168.1.163:48081',
11 11 // baseApi:'admin-api',
12 12 // appApi:'app-api'
13 13 },
... ...
common/utils/common.js
... ... @@ -124,6 +124,17 @@ export const getActionButtonType = (code) => {
124 124 }
125 125  
126 126 /**
  127 + * 操作按钮行每行按钮数:单个按钮占一半宽度(左对齐),多个按钮等分,最多 5 个一行
  128 + * @param {number} count - 按钮总数
  129 + * @returns {number} 栅格列数
  130 + */
  131 +export const getActionRowCols = (count) => {
  132 + const total = Number(count) || 0
  133 + // 1 个按钮时用 2 列,按钮占 1 列即页面一半
  134 + return total <= 1 ? 2 : Math.min(total, 5)
  135 +}
  136 +
  137 +/**
127 138 * 计算两个时间的时间差,返回格式化字符串(天/小时/分钟/秒,按需显示,无无效单位)
128 139 * @param {string | Date | number} startTime - 开始时间(时间字符串/Date对象/10位/13位时间戳)
129 140 * @param {string | Date | number} endTime - 结束时间(时间字符串/Date对象/10位/13位时间戳)
... ...
pages-sub/daily/maintain-manage/index.vue
... ... @@ -82,7 +82,7 @@
82 82 <!-- </view>-->
83 83  
84 84 <view class="common-custom-btn" style="--btn-top: 48px;" @click="goToDetail(item)">
85   - 养护任务
  85 + 执行任务
86 86 </view>
87 87 <!-- <view class="u-body-item u-flex">-->
88 88 <!-- <view class="u-body-item-title">批次号:</view>-->
... ...
pages-sub/daily/maintain-manage/now-list-page.vue
... ... @@ -145,9 +145,18 @@ const handleAddReport = () =&gt; {
145 145 align-items: center;
146 146 margin-bottom: 0;
147 147 }
  148 + // 查看按钮:与其他操作按钮统一蓝色样式
148 149 .look-btn {
149   - font-size: 28rpx;
150   - color: #1989fa;
  150 + box-sizing: border-box;
  151 + width: 132rpx;
  152 + height: 48rpx;
  153 + line-height: 48rpx;
  154 + font-size: 24rpx;
  155 + text-align: center;
  156 + color: #fff;
  157 + background-color: #3b9dff;
  158 + border-radius: 6rpx;
  159 + flex-shrink: 0;
151 160 }
152 161 }
153 162 .empty-wrap {
... ...
pages-sub/daily/maintain-manage/type-list-page.vue
... ... @@ -348,13 +348,18 @@ onUnload(() =&gt; {
348 348 color: #666;
349 349 flex: 1;
350 350 }
  351 +// 统一样式:去作业/去查看/结束任务 统一蓝色,固定宽高保证上下对齐时大小一致
351 352 .mini-btn {
  353 + box-sizing: border-box;
  354 + width: 132rpx;
  355 + height: 48rpx;
  356 + line-height: 48rpx;
352 357 font-size: 24rpx;
353   - color: #333;
354   - background: #f5f5f5;
355   - border: 1rpx solid #ddd;
  358 + text-align: center;
  359 + color: #fff;
  360 + background: #3b9dff;
356 361 border-radius: 6rpx;
357   - padding: 8rpx 20rpx;
  362 + padding: 0;
358 363 flex-shrink: 0;
359 364 }
360 365 .invalid-modal-content {
... ...
pages-sub/problem/ai-manage/index.vue
... ... @@ -95,7 +95,8 @@
95 95 <view class="u-line-1 u-body-value">{{ timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss') }}</view>
96 96 </view>
97 97 <!-- 操作按钮行:已配置工作流动作时按配置逐个渲染按钮,点击直接执行对应动作 -->
98   - <view class="u-body-item task-btn-row mt-20">
  98 + <view class="u-body-item task-btn-row mt-20"
  99 + :style="{'--cols': getActionRowCols(actionBtnCount(item))}">
99 100 <template v-if="hasConfiguredActions(item)">
100 101 <view
101 102 v-for="action in item.configuredActions"
... ... @@ -103,7 +104,7 @@
103 104 :class="['task-btn', 'task-btn--' + getActionButtonType(action.code)]"
104 105 @click.stop="handleUnifiedProcess(item, action)"
105 106 >{{ action.name }}</view>
106   - <view class="task-btn task-btn--info" @click.stop="handleDetail(item)">详情</view>
  107 + <view class="task-btn task-btn--primary" @click.stop="handleDetail(item)">详情</view>
107 108 </template>
108 109 <!-- 未配置:沿用原有节点按钮 -->
109 110 <template v-else>
... ... @@ -111,7 +112,7 @@
111 112 @click.stop="handleUnifiedReject(item)">回退</view>
112 113 <view class="task-btn task-btn--primary"
113 114 @click.stop="handleUnifiedProcess(item)">{{ getProcessButtonText(item) }}</view>
114   - <view class="task-btn task-btn--info" @click.stop="handleDetail(item)">详情</view>
  115 + <view class="task-btn task-btn--primary" @click.stop="handleDetail(item)">详情</view>
115 116 </template>
116 117 </view>
117 118 </view>
... ... @@ -276,7 +277,7 @@ import {
276 277 } from '@/api/regional-order-manage/regional-order-manage'
277 278 import { getTaskActions } from '@/api/work-order-manage/work-order-manage'
278 279 import { useUserStore } from '@/pinia/user';
279   -import { nextStepMap, buzStatusMap, getActionButtonType, toWorkerImplementPage } from '@/common/utils/common'
  280 +import { nextStepMap, buzStatusMap, getActionButtonType, getActionRowCols, toWorkerImplementPage } from '@/common/utils/common'
280 281 import { useUploadImgs } from '@/common/utils/useUploadImgs'
281 282  
282 283 // ========== 全局实例 & 常量 ==========
... ... @@ -510,6 +511,16 @@ const getProcessButtonText = (item) =&gt; {
510 511 const hasConfiguredActions = (item) =>
511 512 Array.isArray(item?.configuredActions) && item.configuredActions.length > 0
512 513  
  514 +/** 操作按钮行按钮数量:单个占一半宽度,多个等分,最多 5 个一行 */
  515 +const actionBtnCount = (item) => {
  516 + if (hasConfiguredActions(item)) {
  517 + return item.configuredActions.length + 1 // 配置动作 + 详情
  518 + }
  519 + let count = 2 // 主按钮 + 详情
  520 + if (showRejectButton(item)) count++
  521 + return count
  522 +}
  523 +
513 524 /** 待办-处理工单:已配置统一动作时直接执行点击的配置动作,否则回退原有处理 */
514 525 const handleUnifiedProcess = async (item, action = null) => {
515 526 const actions = Array.isArray(item?.configuredActions)
... ... @@ -749,11 +760,12 @@ onShow(() =&gt; {
749 760 box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
750 761 }
751 762  
752   -// 卡片操作按钮:自动换行、右对齐,动作多时每行 3~4 个,不再整行铺满
  763 +// 卡片操作按钮:单个占一半宽度,多个等分,每行最多 5 个
753 764 .task-btn-row {
754   - display: flex;
755   - flex-wrap: wrap;
756   - justify-content: flex-end;
  765 + display: grid;
  766 + grid-template-columns: repeat(var(--cols, 5), minmax(0, 1fr));
  767 + column-gap: 12rpx;
  768 + row-gap: 10rpx;
757 769 margin-bottom: -10rpx;
758 770 }
759 771  
... ... @@ -761,20 +773,23 @@ onShow(() =&gt; {
761 773 box-sizing: border-box;
762 774 height: 56rpx;
763 775 line-height: 56rpx;
764   - padding: 0 24rpx;
765   - margin: 0 0 10rpx 12rpx;
  776 + padding: 0 12rpx;
766 777 border-radius: 8rpx;
767 778 font-size: 24rpx;
768 779 color: #fff;
  780 + text-align: center;
769 781 white-space: nowrap;
  782 + overflow: hidden;
  783 + text-overflow: ellipsis;
770 784 }
771 785  
  786 +/* 按动作编码配色:通过/实施/结束类动作绿色,退回类橙色 */
772 787 .task-btn--primary {
773   - background-color: #3c9cff;
  788 + background-color: #3b9dff;
774 789 }
775 790  
776 791 .task-btn--success {
777   - background-color: #5ac725;
  792 + background-color: #078d0a;
778 793 }
779 794  
780 795 .task-btn--warning {
... ... @@ -789,7 +804,6 @@ onShow(() =&gt; {
789 804 background-color: #909399;
790 805 }
791 806  
792   -
793 807 // 弹窗公共样式
794 808 .reject-modal-content, .accept-modal-content {
795 809 width: 100%;
... ...
pages-sub/problem/regional-order-manage/index.vue
... ... @@ -107,7 +107,8 @@
107 107 </view>
108 108  
109 109 <!-- 待办工单(0):已配置工作流动作时按配置逐个渲染按钮,点击直接执行对应动作 -->
110   - <view v-if="activeTab === 0" class="u-body-item task-btn-row mt-20">
  110 + <view v-if="activeTab === 0" class="u-body-item task-btn-row mt-20"
  111 + :style="{'--cols': getActionRowCols(actionBtnCount(item))}">
111 112 <template v-if="hasConfiguredActions(item)">
112 113 <view
113 114 v-for="action in item.configuredActions"
... ... @@ -115,7 +116,7 @@
115 116 :class="['task-btn', 'task-btn--' + getActionButtonType(action.code)]"
116 117 @click.stop="handleUnifiedProcess(item, action)"
117 118 >{{ action.name }}</view>
118   - <view class="task-btn task-btn--info" @click.stop="handleDetail(item)">详情</view>
  119 + <view class="task-btn task-btn--primary" @click.stop="handleDetail(item)">详情</view>
119 120 </template>
120 121 <!-- 未配置:沿用原有节点按钮 -->
121 122 <template v-else>
... ... @@ -125,7 +126,7 @@
125 126 @click.stop="handleRenew(item)">重新提交</view>
126 127 <view class="task-btn task-btn--primary"
127 128 @click.stop="handleUnifiedProcess(item)">{{ getProcessButtonText(item) }}</view>
128   - <view class="task-btn task-btn--info" @click.stop="handleDetail(item)">详情</view>
  129 + <view class="task-btn task-btn--primary" @click.stop="handleDetail(item)">详情</view>
129 130 </template>
130 131 </view>
131 132  
... ... @@ -241,7 +242,7 @@ import {
241 242 } from '@/api/regional-order-manage/regional-order-manage'
242 243 import { getTaskActions } from '@/api/work-order-manage/work-order-manage'
243 244 import { useUserStore } from '@/pinia/user';
244   -import { nextStepMap, buzStatusMap, getActionButtonType, toWorkerImplementPage } from '@/common/utils/common'
  245 +import { nextStepMap, buzStatusMap, getActionButtonType, getActionRowCols, toWorkerImplementPage } from '@/common/utils/common'
245 246 import { useUploadImgs } from '@/common/utils/useUploadImgs'
246 247  
247 248 // ========== 全局实例 & 常量 ==========
... ... @@ -491,6 +492,17 @@ const getProcessButtonText = (item) =&gt; {
491 492 const hasConfiguredActions = (item) =>
492 493 Array.isArray(item?.configuredActions) && item.configuredActions.length > 0
493 494  
  495 +/** 操作按钮行按钮数量:单个占一半宽度,多个等分,最多 5 个一行 */
  496 +const actionBtnCount = (item) => {
  497 + if (hasConfiguredActions(item)) {
  498 + return item.configuredActions.length + 1 // 配置动作 + 详情
  499 + }
  500 + let count = 2 // 主按钮 + 详情
  501 + if (showRejectButton(item)) count++
  502 + if (nextStepMap[item.taskKey]?.renewShow) count++
  503 + return count
  504 +}
  505 +
494 506 /** 待办-处理工单:已配置统一动作时直接执行点击的配置动作,否则回退原有处理 */
495 507 const handleUnifiedProcess = async (item, action = null) => {
496 508 const actions = Array.isArray(item?.configuredActions)
... ... @@ -576,7 +588,6 @@ const handleProcess = async (item) =&gt; {
576 588 });
577 589 }
578 590  
579   -
580 591 // 验收弹窗
581 592 else if (['巡查员验收', '养护组长验收'].includes(stepName)) {
582 593 currentAcceptItem.value = item;
... ... @@ -745,11 +756,12 @@ onLoad(() =&gt; {
745 756 box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
746 757 }
747 758  
748   -// 卡片操作按钮:自动换行、右对齐,动作多时每行 3~4 个,不再整行铺满
  759 +// 卡片操作按钮:单个占页面一半宽度(左对齐),多个等分,每行最多 5 个,超出自动换行
749 760 .task-btn-row {
750   - display: flex;
751   - flex-wrap: wrap;
752   - justify-content: flex-end;
  761 + display: grid;
  762 + grid-template-columns: repeat(var(--cols, 5), minmax(0, 1fr));
  763 + column-gap: 12rpx;
  764 + row-gap: 10rpx;
753 765 margin-bottom: -10rpx;
754 766 }
755 767  
... ... @@ -757,20 +769,23 @@ onLoad(() =&gt; {
757 769 box-sizing: border-box;
758 770 height: 56rpx;
759 771 line-height: 56rpx;
760   - padding: 0 24rpx;
761   - margin: 0 0 10rpx 12rpx;
  772 + padding: 0 12rpx;
762 773 border-radius: 8rpx;
763 774 font-size: 24rpx;
764 775 color: #fff;
  776 + text-align: center;
765 777 white-space: nowrap;
  778 + overflow: hidden;
  779 + text-overflow: ellipsis;
766 780 }
767 781  
  782 +/* 按动作编码配色:通过/实施/结束类动作绿色,退回类橙色 */
768 783 .task-btn--primary {
769   - background-color: #3c9cff;
  784 + background-color: #3b9dff;
770 785 }
771 786  
772 787 .task-btn--success {
773   - background-color: #5ac725;
  788 + background-color: #078d0a;
774 789 }
775 790  
776 791 .task-btn--warning {
... ... @@ -785,7 +800,6 @@ onLoad(() =&gt; {
785 800 background-color: #909399;
786 801 }
787 802  
788   -
789 803 // 新增样式:解决按钮和文字间距、排版问题
790 804 .flex-1 { flex: 1; }
791 805 .text-right { text-align: right; }
... ...
pages-sub/problem/regional-order-manage/list-detail.vue
... ... @@ -178,7 +178,7 @@
178 178 <template #content>
179 179 <view class="step-content-wrap">
180 180 <view class="step-title">
181   - {{ item.name ? item.name.replace('大区经理', '业务调度员') : item.name }}
  181 + {{ item.name }}
182 182 </view>
183 183 <view class="step-desc">
184 184 <view class="operator-name up-line-1" v-if="item.tasks">
... ... @@ -225,8 +225,9 @@
225 225 <!-- 底部操作按钮 -->
226 226 <view v-if="activeTab === '0' && (configuredActions || nextStepMap[orderDetail.taskKey])"
227 227 class="fixed-bottom-btn-wrap order-action-bar">
228   - <!-- 已配置工作流动作:每行最多 3 个、超出自动换行,点击直接执行对应动作,不再弹「请选择操作」 -->
229   - <view v-if="hasConfiguredActions" class="order-action-row">
  228 + <!-- 已配置工作流动作:每行最多 5 个、超出自动换行,点击直接执行对应动作,不再弹「请选择操作」 -->
  229 + <view v-if="hasConfiguredActions" class="order-action-row"
  230 + :style="{'--cols': getActionRowCols(configuredActions.length)}">
230 231 <view
231 232 v-for="action in configuredActions"
232 233 :key="action.code"
... ... @@ -234,8 +235,8 @@
234 235 @click.stop="handleUnifiedProcess(orderDetail, action)"
235 236 >{{ action.name }}</view>
236 237 </view>
237   - <!-- 未配置:沿用原有节点按钮(整行展示) -->
238   - <view v-else class="order-action-row order-action-row--single">
  238 + <!-- 未配置:沿用原有节点按钮 -->
  239 + <view v-else class="order-action-row" :style="{'--cols': getActionRowCols(legacyActionCount)}">
239 240 <view v-if="showRejectButton" class="order-action-btn order-action-btn--warning"
240 241 @click.stop="handleUnifiedReject(orderDetail)">回退</view>
241 242 <view v-if="nextStepMap[orderDetail.taskKey]?.renewShow" class="order-action-btn order-action-btn--success"
... ... @@ -337,7 +338,7 @@ import { timeFormat } from &#39;@/uni_modules/uview-plus&#39;
337 338 import { getApprovalDetail,workOrderDetailByID } from '@/api/regional-order-manage/regional-order-manage'
338 339 import { getTaskActions } from '@/api/work-order-manage/work-order-manage'
339 340  
340   -import { nextStepMap, calculateFormatTimeDiff, getActionButtonType, toWorkerImplementPage } from '@/common/utils/common'
  341 +import { nextStepMap, calculateFormatTimeDiff, getActionButtonType, getActionRowCols, toWorkerImplementPage } from '@/common/utils/common'
341 342 import { useUploadImgs } from '@/common/utils/useUploadImgs'
342 343 import { useUserStore } from '@/pinia/user'
343 344  
... ... @@ -523,15 +524,20 @@ const showRejectButton = computed(() =&gt; {
523 524 const hasConfiguredActions = computed(() =>
524 525 Array.isArray(configuredActions.value) && configuredActions.value.length > 0)
525 526  
  527 +/** 未配置统一动作时的按钮个数(与模板渲染顺序一致) */
  528 +const legacyActionCount = computed(() => {
  529 + let count = 1
  530 + if (showRejectButton.value) count++
  531 + if (nextStepMap[orderDetail.value.taskKey]?.renewShow) count++
  532 + return count
  533 +})
  534 +
526 535 /** 底部操作栏行数:详情内容据此预留底部间距,避免按钮遮挡内容 */
527 536 const actionBarRows = computed(() => {
528 537 if (hasConfiguredActions.value) {
529   - return Math.ceil(configuredActions.value.length / 3)
  538 + return Math.ceil(configuredActions.value.length / 5)
530 539 }
531   - let rows = 1
532   - if (showRejectButton.value) rows++
533   - if (nextStepMap[orderDetail.value.taskKey]?.renewShow) rows++
534   - return rows
  540 + return 1
535 541 })
536 542  
537 543 /** 主按钮文案:已配置统一动作时取配置的动作名称,未配置时沿用原有节点规则 */
... ... @@ -1025,8 +1031,7 @@ onLoad((options: any) =&gt; {
1025 1031 height: 70px !important;
1026 1032 }
1027 1033  
1028   -// 底部动作按钮:动作多时自动换行
1029   -// 底部操作栏:白底 + 顶部投影,按钮每行最多 3 个,避免多动作时整屏遮挡工单详情
  1034 +// 底部操作栏:白底 + 顶部投影,按钮每行最多 5 个,避免多动作时整屏遮挡工单详情
1030 1035 .order-action-bar {
1031 1036 background-color: #fff;
1032 1037 box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.06);
... ... @@ -1035,18 +1040,17 @@ onLoad((options: any) =&gt; {
1035 1040 padding-bottom: calc(10rpx + env(safe-area-inset-bottom));
1036 1041 }
1037 1042  
  1043 +// 底部操作按钮:单按钮占一半宽度,多个按钮等分,每行最多 5 个
1038 1044 .order-action-row {
1039   - display: flex;
1040   - flex-wrap: wrap;
1041   - margin: -6rpx;
  1045 + display: grid;
  1046 + grid-template-columns: repeat(var(--cols, 5), minmax(0, 1fr));
  1047 + gap: 12rpx;
1042 1048 }
1043 1049  
1044 1050 .order-action-btn {
1045 1051 box-sizing: border-box;
1046   - width: calc((100% - 36rpx) / 3);
1047 1052 height: 68rpx;
1048 1053 line-height: 68rpx;
1049   - margin: 6rpx;
1050 1054 padding: 0 8rpx;
1051 1055 border-radius: 8rpx;
1052 1056 font-size: 26rpx;
... ... @@ -1057,17 +1061,13 @@ onLoad((options: any) =&gt; {
1057 1061 text-overflow: ellipsis;
1058 1062 }
1059 1063  
1060   -// 未配置统一动作时按钮整行展示,保持原有观感
1061   -.order-action-row--single .order-action-btn {
1062   - width: 100%;
1063   -}
1064   -
  1064 +/* 按动作编码配色:通过/实施/结束类动作绿色,退回类橙色 */
1065 1065 .order-action-btn--primary {
1066   - background-color: #3c9cff;
  1066 + background-color: #3b9dff;
1067 1067 }
1068 1068  
1069 1069 .order-action-btn--success {
1070   - background-color: #5ac725;
  1070 + background-color: #078d0a;
1071 1071 }
1072 1072  
1073 1073 .order-action-btn--warning {
... ...
pages-sub/problem/regional-order-manage/order-detail.vue
... ... @@ -198,7 +198,7 @@
198 198 <view class="step-content-wrap">
199 199 <!-- 1. 原标题内容:节点名称 + 操作人 -->
200 200 <view class="step-title">
201   - {{ item.name ? item.name.replace('大区经理', '业务调度员') : item.name }}
  201 + {{ item.name }}
202 202 </view>
203 203  
204 204 <!-- 2. 原描述内容:时间 + 处理说明(最多200字) -->
... ... @@ -255,8 +255,9 @@
255 255 <!-- activeTab==0的时候才出现, 也就是待办 -->
256 256 <view v-if="activeTab==0&&(configuredActions||nextStepMap[orderDetail.taskKey])"
257 257 class="fixed-bottom-btn-wrap order-action-bar">
258   - <!-- 已配置工作流动作:每行最多 3 个、超出自动换行,点击直接执行对应动作,不再弹「请选择操作」 -->
259   - <view v-if="hasConfiguredActions" class="order-action-row">
  258 + <!-- 已配置工作流动作:每行最多 5 个、超出自动换行,点击直接执行对应动作,不再弹「请选择操作」 -->
  259 + <view v-if="hasConfiguredActions" class="order-action-row"
  260 + :style="{'--cols': getActionRowCols(configuredActions.length)}">
260 261 <view
261 262 v-for="action in configuredActions"
262 263 :key="action.code"
... ... @@ -264,8 +265,8 @@
264 265 @click.stop="handleUnifiedProcess(orderDetail, action)"
265 266 >{{ action.name }}</view>
266 267 </view>
267   - <!-- 未配置:沿用原有节点按钮(整行展示) -->
268   - <view v-else class="order-action-row order-action-row--single">
  268 + <!-- 未配置:沿用原有节点按钮 -->
  269 + <view v-else class="order-action-row" :style="{'--cols': getActionRowCols(legacyActionCount)}">
269 270 <view v-if="showRejectButton" class="order-action-btn order-action-btn--warning"
270 271 @click.stop="handleUnifiedReject(orderDetail)">回退</view>
271 272 <view v-if="nextStepMap[orderDetail.taskKey]?.renewShow" class="order-action-btn order-action-btn--success"
... ... @@ -381,7 +382,7 @@ import {
381 382 dcyUniversalApproval,
382 383 aiUniversalApproval
383 384 } from '@/api/regional-order-manage/regional-order-manage';
384   -import {nextStepMap, buzStatusMap, calculateFormatTimeDiff, getActionButtonType, toWorkerImplementPage} from '@/common/utils/common'
  385 +import {nextStepMap, buzStatusMap, calculateFormatTimeDiff, getActionButtonType, getActionRowCols, toWorkerImplementPage} from '@/common/utils/common'
385 386 import {getTaskActions} from '@/api/work-order-manage/work-order-manage';
386 387 import {useUploadImgs} from '@/common/utils/useUploadImgs'
387 388 import { useUserStore } from '@/pinia/user';
... ... @@ -392,7 +393,6 @@ const USER_ROLES = userStore.userInfo?.roles || [];
392 393 // ========== 页面通信事件通道 解决未定义BUG ==========
393 394 const eventChannel = ref<any>(null);
394 395  
395   -
396 396 // ========== 公共封装方法 (和列表页完全一致) ==========
397 397 /**
398 398 * 统一提示方法
... ... @@ -593,15 +593,20 @@ const showRejectButton = computed(() =&gt; {
593 593 const hasConfiguredActions = computed(() =>
594 594 Array.isArray(configuredActions.value) && configuredActions.value.length > 0)
595 595  
596   -/** 底部操作栏行数:详情内容据此预留底部间距,避免按钮遮挡内容 */
  596 +/** 未配置统一动作时的按钮数量:主按钮 + 可选的回退/重新提交 */
  597 +const legacyActionCount = computed(() => {
  598 + let count = 1
  599 + if (showRejectButton.value) count++
  600 + if (nextStepMap[orderDetail.value.taskKey]?.renewShow) count++
  601 + return count
  602 +})
  603 +
  604 +/** 底部操作栏行数:详情内容据此预留底部间距,避免按钮遮挡内容(每行最多 5 个) */
597 605 const actionBarRows = computed(() => {
598 606 if (hasConfiguredActions.value) {
599   - return Math.ceil(configuredActions.value.length / 3)
  607 + return Math.ceil(configuredActions.value.length / 5)
600 608 }
601   - let rows = 1
602   - if (showRejectButton.value) rows++
603   - if (nextStepMap[orderDetail.value.taskKey]?.renewShow) rows++
604   - return rows
  609 + return 1
605 610 })
606 611  
607 612 /** 主按钮文案:已配置统一动作时取配置的动作名称,未配置时沿用原有节点规则 */
... ... @@ -1173,7 +1178,7 @@ onShow(() =&gt; {});
1173 1178 }
1174 1179  
1175 1180 // 底部动作按钮:动作多时自动换行
1176   -// 底部操作栏:白底 + 顶部投影,按钮每行最多 3 个,避免多动作时整屏遮挡工单详情
  1181 +// 底部操作栏:白底 + 顶部投影,按钮每行最多 5 个,避免多动作时整屏遮挡工单详情
1177 1182 .order-action-bar {
1178 1183 background-color: #fff;
1179 1184 box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.06);
... ... @@ -1183,17 +1188,16 @@ onShow(() =&gt; {});
1183 1188 }
1184 1189  
1185 1190 .order-action-row {
1186   - display: flex;
1187   - flex-wrap: wrap;
1188   - margin: -6rpx;
  1191 + display: grid;
  1192 + grid-template-columns: repeat(var(--cols, 5), minmax(0, 1fr));
  1193 + column-gap: 12rpx;
  1194 + row-gap: 12rpx;
1189 1195 }
1190 1196  
1191 1197 .order-action-btn {
1192 1198 box-sizing: border-box;
1193   - width: calc((100% - 36rpx) / 3);
1194 1199 height: 68rpx;
1195 1200 line-height: 68rpx;
1196   - margin: 6rpx;
1197 1201 padding: 0 8rpx;
1198 1202 border-radius: 8rpx;
1199 1203 font-size: 26rpx;
... ... @@ -1204,17 +1208,13 @@ onShow(() =&gt; {});
1204 1208 text-overflow: ellipsis;
1205 1209 }
1206 1210  
1207   -// 未配置统一动作时按钮整行展示,保持原有观感
1208   -.order-action-row--single .order-action-btn {
1209   - width: 100%;
1210   -}
1211   -
  1211 +/* 按动作编码配色:通过/实施/结束类动作绿色,退回类橙色 */
1212 1212 .order-action-btn--primary {
1213   - background-color: #3c9cff;
  1213 + background-color: #3b9dff;
1214 1214 }
1215 1215  
1216 1216 .order-action-btn--success {
1217   - background-color: #5ac725;
  1217 + background-color: #078d0a;
1218 1218 }
1219 1219  
1220 1220 .order-action-btn--warning {
... ...
pages-sub/problem/work-order-manage/index.vue
... ... @@ -101,7 +101,8 @@
101 101 <view class="u-line-1 u-body-value">{{ timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss') }}</view>
102 102 </view>
103 103 <!-- 操作按钮行 -->
104   - <view class="u-body-item task-btn-row mt-20">
  104 + <view class="u-body-item task-btn-row mt-20"
  105 + :style="{'--cols': getActionRowCols(actionBtnCount(item))}">
105 106 <!-- 已配置工作流动作:按配置逐个渲染按钮,点击直接执行对应动作,不再弹「请选择操作」 -->
106 107 <template v-if="hasConfiguredActions(item)">
107 108 <view
... ... @@ -110,7 +111,7 @@
110 111 :class="['task-btn', 'task-btn--' + getActionButtonType(action.code)]"
111 112 @click.stop="handleUnifiedProcess(item, action)"
112 113 >{{ action.name }}</view>
113   - <view class="task-btn task-btn--info" @click.stop="handleDetail(item)">详情</view>
  114 + <view class="task-btn task-btn--primary" @click.stop="handleDetail(item)">详情</view>
114 115 </template>
115 116 <!-- 未配置:沿用原有节点按钮 -->
116 117 <template v-else>
... ... @@ -120,7 +121,7 @@
120 121 @click.stop="handleRenew(item)">重新提交</view>
121 122 <view class="task-btn task-btn--primary"
122 123 @click.stop="handleUnifiedProcess(item)">{{ getProcessButtonText(item) }}</view>
123   - <view class="task-btn task-btn--info" @click.stop="handleDetail(item)">详情</view>
  124 + <view class="task-btn task-btn--primary" @click.stop="handleDetail(item)">详情</view>
124 125 </template>
125 126 </view>
126 127 </view>
... ... @@ -298,7 +299,7 @@ import {
298 299 } from '@/api/work-order-manage/work-order-manage'
299 300 // 从用户store获取角色信息
300 301 import { useUserStore } from '@/pinia/user';
301   -import { nextStepMap, buzStatusMap, getActionButtonType, toWorkerImplementPage } from '@/common/utils/common'
  302 +import { nextStepMap, buzStatusMap, getActionButtonType, getActionRowCols, toWorkerImplementPage } from '@/common/utils/common'
302 303 // 引入图片上传组合式函数(与参考页面一致)
303 304 import { useUploadImgs } from '@/common/utils/useUploadImgs'
304 305  
... ... @@ -346,7 +347,6 @@ const rejectImgs = useUploadImgs({
346 347 fieldName: 'rejectImgs' // 自定义字段名
347 348 })
348 349  
349   -
350 350 // ========== 验收弹窗相关状态(含图片上传) ==========
351 351 const acceptModalShow = ref(false); // 验收弹窗显示开关
352 352 const acceptRadioValue = ref('0'); // 单选框值,默认0(通过)
... ... @@ -389,7 +389,6 @@ const openMapNav = (item) =&gt; {
389 389 // });
390 390 };
391 391  
392   -
393 392 // 分页查询列表
394 393 const queryList = async (pageNo, pageSize) => {
395 394 try {
... ... @@ -550,6 +549,17 @@ const getProcessButtonText = (item) =&gt; {
550 549 const hasConfiguredActions = (item) =>
551 550 Array.isArray(item?.configuredActions) && item.configuredActions.length > 0
552 551  
  552 +/** 操作按钮行按钮数量:单个占一半宽度,多个等分,最多 5 个一行 */
  553 +const actionBtnCount = (item) => {
  554 + if (hasConfiguredActions(item)) {
  555 + return item.configuredActions.length + 1 // 配置动作 + 详情
  556 + }
  557 + let count = 2 // 主按钮 + 详情
  558 + if (showRejectButton(item)) count++
  559 + if (nextStepMap[item.taskKey]?.renewShow) count++
  560 + return count
  561 +}
  562 +
553 563 /** 待办-处理工单:已配置统一动作时直接执行点击的配置动作,否则回退原有处理 */
554 564 const handleUnifiedProcess = async (item, action = null) => {
555 565 const actions = Array.isArray(item?.configuredActions)
... ... @@ -859,11 +869,12 @@ onUnload(() =&gt; {
859 869 border-radius: 12rpx;
860 870 box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
861 871 }
862   -// 卡片操作按钮:自动换行、右对齐,动作多时每行 3~4 个,不再整行铺满
  872 +// 卡片操作按钮:单个占页面一半宽度(左对齐),多个等分,每行最多 5 个,超出自动换行
863 873 .task-btn-row {
864   - display: flex;
865   - flex-wrap: wrap;
866   - justify-content: flex-end;
  874 + display: grid;
  875 + grid-template-columns: repeat(var(--cols, 5), minmax(0, 1fr));
  876 + column-gap: 12rpx;
  877 + row-gap: 10rpx;
867 878 margin-bottom: -10rpx;
868 879 }
869 880  
... ... @@ -871,20 +882,23 @@ onUnload(() =&gt; {
871 882 box-sizing: border-box;
872 883 height: 56rpx;
873 884 line-height: 56rpx;
874   - padding: 0 24rpx;
875   - margin: 0 0 10rpx 12rpx;
  885 + padding: 0 12rpx;
876 886 border-radius: 8rpx;
877 887 font-size: 24rpx;
878 888 color: #fff;
  889 + text-align: center;
879 890 white-space: nowrap;
  891 + overflow: hidden;
  892 + text-overflow: ellipsis;
880 893 }
881 894  
  895 +/* 按动作编码配色:通过/实施/结束类动作绿色,退回类橙色 */
882 896 .task-btn--primary {
883   - background-color: #3c9cff;
  897 + background-color: #3b9dff;
884 898 }
885 899  
886 900 .task-btn--success {
887   - background-color: #5ac725;
  901 + background-color: #078d0a;
888 902 }
889 903  
890 904 .task-btn--warning {
... ... @@ -899,8 +913,6 @@ onUnload(() =&gt; {
899 913 background-color: #909399;
900 914 }
901 915  
902   -
903   -
904 916 // 回退modal样式
905 917 .reject-modal-content {
906 918 width: 100%;
... ...
pages-sub/problem/work-order-manage/order-detail.vue
... ... @@ -116,7 +116,6 @@
116 116 </template>
117 117 </up-cell>
118 118  
119   -
120 119  
121 120 <up-cell title="重点巡检区域" :value="orderDetail.keyInspection==0?'否':'是'" align="middle"></up-cell>
122 121  
... ... @@ -237,7 +236,7 @@
237 236 <view class="step-content-wrap">
238 237 <!-- 1. 原标题内容:节点名称 + 操作人 -->
239 238 <view class="step-title">
240   - {{ item.name ? item.name.replace('大区经理', '业务调度员') : item.name }}
  239 + {{ item.name }}
241 240 </view>
242 241  
243 242 <!-- 2. 原描述内容:时间 + 处理说明(最多200字) -->
... ... @@ -294,8 +293,9 @@
294 293 <!-- activeTab==0的时候才出现, 也就是待办 -->
295 294 <view v-if="activeTab==0&&(configuredActions||nextStepMap[orderDetail.taskKey])"
296 295 class="fixed-bottom-btn-wrap order-action-bar">
297   - <!-- 已配置工作流动作:每行最多 3 个、超出自动换行,点击直接执行对应动作,不再弹「请选择操作」 -->
298   - <view v-if="hasConfiguredActions" class="order-action-row">
  296 + <!-- 已配置工作流动作:每行最多 5 个、超出自动换行,点击直接执行对应动作,不再弹「请选择操作」 -->
  297 + <view v-if="hasConfiguredActions" class="order-action-row"
  298 + :style="{'--cols': getActionRowCols(configuredActions.length)}">
299 299 <view
300 300 v-for="action in configuredActions"
301 301 :key="action.code"
... ... @@ -303,8 +303,8 @@
303 303 @click.stop="handleUnifiedProcess(orderDetail, action)"
304 304 >{{ action.name }}</view>
305 305 </view>
306   - <!-- 未配置:沿用原有节点按钮(整行展示) -->
307   - <view v-else class="order-action-row order-action-row--single">
  306 + <!-- 未配置:沿用原有节点按钮 -->
  307 + <view v-else class="order-action-row" :style="{'--cols': getActionRowCols(legacyActionCount)}">
308 308 <view v-if="showRejectButton" class="order-action-btn order-action-btn--warning"
309 309 @click.stop="handleUnifiedReject(orderDetail)">回退</view>
310 310 <view v-if="nextStepMap[orderDetail.taskKey]?.renewShow" class="order-action-btn order-action-btn--success"
... ... @@ -418,7 +418,7 @@ import {
418 418 getTaskActions
419 419 } from '@/api/work-order-manage/work-order-manage';
420 420 import {getWorkRecordValues} from '@/api/common'
421   -import {nextStepMap, buzStatusMap, calculateFormatTimeDiff, getActionButtonType, toWorkerImplementPage} from '@/common/utils/common'
  421 +import {nextStepMap, buzStatusMap, calculateFormatTimeDiff, getActionButtonType, getActionRowCols, toWorkerImplementPage} from '@/common/utils/common'
422 422 // 引入图片上传组合式函数
423 423 import {useUploadImgs} from '@/common/utils/useUploadImgs'
424 424  
... ... @@ -813,15 +813,20 @@ const showRejectButton = computed(() =&gt; {
813 813 const hasConfiguredActions = computed(() =>
814 814 Array.isArray(configuredActions.value) && configuredActions.value.length > 0)
815 815  
816   -/** 底部操作栏行数:详情内容据此预留底部间距,避免按钮遮挡内容 */
  816 +/** 未配置统一动作时的按钮数量:主按钮 + 可选的回退/重新提交 */
  817 +const legacyActionCount = computed(() => {
  818 + let count = 1
  819 + if (showRejectButton.value) count++
  820 + if (nextStepMap[orderDetail.value.taskKey]?.renewShow) count++
  821 + return count
  822 +})
  823 +
  824 +/** 底部操作栏行数:详情内容据此预留底部间距,避免按钮遮挡内容(每行最多 5 个) */
817 825 const actionBarRows = computed(() => {
818 826 if (hasConfiguredActions.value) {
819   - return Math.ceil(configuredActions.value.length / 3)
  827 + return Math.ceil(configuredActions.value.length / 5)
820 828 }
821   - let rows = 1
822   - if (showRejectButton.value) rows++
823   - if (nextStepMap[orderDetail.value.taskKey]?.renewShow) rows++
824   - return rows
  829 + return 1
825 830 })
826 831  
827 832 /** 主按钮文案:已配置统一动作时取配置的动作名称,未配置时沿用原有节点规则 */
... ... @@ -1261,7 +1266,7 @@ onShow(() =&gt; {
1261 1266 }
1262 1267  
1263 1268 // 底部动作按钮:动作多时自动换行
1264   -// 底部操作栏:白底 + 顶部投影,按钮每行最多 3 个,避免多动作时整屏遮挡工单详情
  1269 +// 底部操作栏:白底 + 顶部投影,按钮每行最多 5 个,避免多动作时整屏遮挡工单详情
1265 1270 .order-action-bar {
1266 1271 background-color: #fff;
1267 1272 box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.06);
... ... @@ -1271,17 +1276,16 @@ onShow(() =&gt; {
1271 1276 }
1272 1277  
1273 1278 .order-action-row {
1274   - display: flex;
1275   - flex-wrap: wrap;
1276   - margin: -6rpx;
  1279 + display: grid;
  1280 + grid-template-columns: repeat(var(--cols, 5), minmax(0, 1fr));
  1281 + column-gap: 12rpx;
  1282 + row-gap: 12rpx;
1277 1283 }
1278 1284  
1279 1285 .order-action-btn {
1280 1286 box-sizing: border-box;
1281   - width: calc((100% - 36rpx) / 3);
1282 1287 height: 68rpx;
1283 1288 line-height: 68rpx;
1284   - margin: 6rpx;
1285 1289 padding: 0 8rpx;
1286 1290 border-radius: 8rpx;
1287 1291 font-size: 26rpx;
... ... @@ -1292,17 +1296,13 @@ onShow(() =&gt; {
1292 1296 text-overflow: ellipsis;
1293 1297 }
1294 1298  
1295   -// 未配置统一动作时按钮整行展示,保持原有观感
1296   -.order-action-row--single .order-action-btn {
1297   - width: 100%;
1298   -}
1299   -
  1299 +/* 按动作编码配色:通过/实施/结束类动作绿色,退回类橙色 */
1300 1300 .order-action-btn--primary {
1301   - background-color: #3c9cff;
  1301 + background-color: #3b9dff;
1302 1302 }
1303 1303  
1304 1304 .order-action-btn--success {
1305   - background-color: #5ac725;
  1305 + background-color: #078d0a;
1306 1306 }
1307 1307  
1308 1308 .order-action-btn--warning {
... ...