Commit 28e3b4f3d4f5db106f43e22235fce841d8e71c6f
1 parent
98689726
业务线 小程序不用写死,从后端接口获取
Showing
10 changed files
with
91 additions
and
27 deletions
api/common.js
| @@ -57,6 +57,16 @@ export const getByType = (params) => { | @@ -57,6 +57,16 @@ export const getByType = (params) => { | ||
| 57 | }; | 57 | }; |
| 58 | 58 | ||
| 59 | /** | 59 | /** |
| 60 | + * 拉取「已配置填报项」的作业类型 | ||
| 61 | + * 填报页进入时若该业务线只配了一个作业类型,直接选中并加载动态字段,避免用户不知道要先选作业类型。 | ||
| 62 | + * @param {Object} params {`businessType`、`bizType`} | ||
| 63 | + * @returns {Promise} List<{workTypeId, workTypeName}> | ||
| 64 | + */ | ||
| 65 | +export const getConfiguredWorkTypes = (params) => { | ||
| 66 | + return get('/app-api/app/garden/work-field-config/work-types', params); | ||
| 67 | +}; | ||
| 68 | + | ||
| 69 | +/** | ||
| 60 | * 拉取选项 用于 fieldType 3(枚举)/6(多选)/9(关联记录) 且 field.options 为空(即非静态来源)时获取可选项。 | 70 | * 拉取选项 用于 fieldType 3(枚举)/6(多选)/9(关联记录) 且 field.options 为空(即非静态来源)时获取可选项。 |
| 61 | * @param {Object} params {} | 71 | * @param {Object} params {} |
| 62 | * @returns {Promise} | 72 | * @returns {Promise} |
common/config/env.js
| @@ -2,12 +2,12 @@ | @@ -2,12 +2,12 @@ | ||
| 2 | const env = { | 2 | const env = { |
| 3 | // 开发环境 | 3 | // 开发环境 |
| 4 | development: { | 4 | development: { |
| 5 | - baseUrl: 'https://test.jichengshanshui.com.cn:28302', | 5 | + baseUrl: 'http://192.168.1.55:48081', |
| 6 | // https://test.jichengshanshui.com.cn:28302 | 6 | // https://test.jichengshanshui.com.cn:28302 |
| 7 | 7 | ||
| 8 | // baseUrl: 'http://192.168.1.111:48081', | 8 | // baseUrl: 'http://192.168.1.111:48081', |
| 9 | 9 | ||
| 10 | - uploadUrl: 'https://test.jichengshanshui.com.cn:28302', | 10 | + uploadUrl: 'http://192.168.1.55:48081', |
| 11 | // baseApi:'admin-api', | 11 | // baseApi:'admin-api', |
| 12 | // appApi:'app-api' | 12 | // appApi:'app-api' |
| 13 | }, | 13 | }, |
common/utils/common.js
| @@ -286,6 +286,9 @@ export const translateRoles = (roles = []) => { | @@ -286,6 +286,9 @@ export const translateRoles = (roles = []) => { | ||
| 286 | .join(','); | 286 | .join(','); |
| 287 | } | 287 | } |
| 288 | 288 | ||
| 289 | +/** 配置了工单(biz_type=1)动态字段的业务线;其他业务线走统一动作弹窗 */ | ||
| 290 | +const WORKER_IMPLEMENT_BIZ_LINES = ['yl', 'hj']; | ||
| 291 | + | ||
| 289 | /** | 292 | /** |
| 290 | * 跳转「作业填报」页(养护员实施) | 293 | * 跳转「作业填报」页(养护员实施) |
| 291 | * | 294 | * |
| @@ -293,11 +296,20 @@ export const translateRoles = (roles = []) => { | @@ -293,11 +296,20 @@ export const translateRoles = (roles = []) => { | ||
| 293 | * 上传开始/进行中/结束/人员/材料五组照片,统一动作弹窗只有原因+单个附件,承载不了, | 296 | * 上传开始/进行中/结束/人员/材料五组照片,统一动作弹窗只有原因+单个附件,承载不了, |
| 294 | * 因此实施动作固定进「作业填报」页。 | 297 | * 因此实施动作固定进「作业填报」页。 |
| 295 | * | 298 | * |
| 299 | + * 只有养护(yl)、环卫(hj)配置了工单动态字段,秩序(zx)/市政(sz)/物业(wy)没有配置, | ||
| 300 | + * 这类工单仍走统一动作弹窗,保持原有处理流程。 | ||
| 301 | + * | ||
| 296 | * 工单数据存本地缓存,URL 只带临时 key,避免参数过长。 | 302 | * 工单数据存本地缓存,URL 只带临时 key,避免参数过长。 |
| 297 | * @param {Object} item 待办行数据,需包含 id(工单ID)与 taskId(流程任务ID) | 303 | * @param {Object} item 待办行数据,需包含 id(工单ID)与 taskId(流程任务ID) |
| 298 | - * @returns {Boolean} 是否成功跳转 | 304 | + * @param {String} from 来源列表页标识:work-order / regional / ai,提交后回到对应列表 |
| 305 | + * @returns {Boolean} 是否已跳转;返回 false 时由调用方继续走统一动作弹窗 | ||
| 299 | */ | 306 | */ |
| 300 | -export const toWorkerImplementPage = (item) => { | 307 | +export const toWorkerImplementPage = (item, from = 'work-order') => { |
| 308 | + // 业务线可能多选(逗号分隔),任一命中即视为养护类工单 | ||
| 309 | + const bizLines = String(item?.busiLine || '').split(',').map(v => v.trim()).filter(Boolean); | ||
| 310 | + if (!bizLines.some(v => WORKER_IMPLEMENT_BIZ_LINES.includes(v))) { | ||
| 311 | + return false; | ||
| 312 | + } | ||
| 301 | if (!item || !item.id || !item.taskId) { | 313 | if (!item || !item.id || !item.taskId) { |
| 302 | uni.showToast({ title: '工单信息异常,无法实施', icon: 'none' }); | 314 | uni.showToast({ title: '工单信息异常,无法实施', icon: 'none' }); |
| 303 | return false; | 315 | return false; |
| @@ -311,7 +323,7 @@ export const toWorkerImplementPage = (item) => { | @@ -311,7 +323,7 @@ export const toWorkerImplementPage = (item) => { | ||
| 311 | return false; | 323 | return false; |
| 312 | } | 324 | } |
| 313 | uni.navigateTo({ | 325 | uni.navigateTo({ |
| 314 | - url: `/pages-sub/problem/work-order-manage/add-maintain-order?tempKey=${tempKey}` | 326 | + url: `/pages-sub/problem/work-order-manage/add-maintain-order?tempKey=${tempKey}&from=${from}` |
| 315 | }); | 327 | }); |
| 316 | return true; | 328 | return true; |
| 317 | } | 329 | } |
| 318 | \ No newline at end of file | 330 | \ No newline at end of file |
pages-sub/problem/ai-manage/index.vue
| @@ -517,9 +517,9 @@ const handleUnifiedProcess = async (item, action = null) => { | @@ -517,9 +517,9 @@ const handleUnifiedProcess = async (item, action = null) => { | ||
| 517 | : await queryUnifiedActions(item) | 517 | : await queryUnifiedActions(item) |
| 518 | if (actions) { | 518 | if (actions) { |
| 519 | const target = action || actions[0] | 519 | const target = action || actions[0] |
| 520 | - // 实施动作要选作业类型、填动态字段、传五组照片,统一动作弹窗承载不了,进「作业填报」页 | ||
| 521 | - if (target?.code === 'HANDLE') { | ||
| 522 | - toWorkerImplementPage(item) | 520 | + // 实施动作要选作业类型、填动态字段、传五组照片,统一动作弹窗承载不了,进「作业填报」页; |
| 521 | + // 该业务线未配置工单动态字段时返回 false,继续走统一动作弹窗 | ||
| 522 | + if (target?.code === 'HANDLE' && toWorkerImplementPage(item, 'ai')) { | ||
| 523 | return | 523 | return |
| 524 | } | 524 | } |
| 525 | // 传入的动作即用户点击的配置按钮,直接执行该动作,不再弹「请选择操作」二次选择 | 525 | // 传入的动作即用户点击的配置按钮,直接执行该动作,不再弹「请选择操作」二次选择 |
pages-sub/problem/regional-order-manage/index.vue
| @@ -498,9 +498,9 @@ const handleUnifiedProcess = async (item, action = null) => { | @@ -498,9 +498,9 @@ const handleUnifiedProcess = async (item, action = null) => { | ||
| 498 | : await queryUnifiedActions(item) | 498 | : await queryUnifiedActions(item) |
| 499 | if (actions) { | 499 | if (actions) { |
| 500 | const target = action || actions[0] | 500 | const target = action || actions[0] |
| 501 | - // 实施动作要选作业类型、填动态字段、传五组照片,统一动作弹窗承载不了,进「作业填报」页 | ||
| 502 | - if (target?.code === 'HANDLE') { | ||
| 503 | - toWorkerImplementPage(item) | 501 | + // 实施动作要选作业类型、填动态字段、传五组照片,统一动作弹窗承载不了,进「作业填报」页; |
| 502 | + // 该业务线未配置工单动态字段时返回 false,继续走统一动作弹窗 | ||
| 503 | + if (target?.code === 'HANDLE' && toWorkerImplementPage(item, 'regional')) { | ||
| 504 | return | 504 | return |
| 505 | } | 505 | } |
| 506 | // 传入的动作即用户点击的配置按钮,直接执行该动作,不再弹「请选择操作」二次选择 | 506 | // 传入的动作即用户点击的配置按钮,直接执行该动作,不再弹「请选择操作」二次选择 |
pages-sub/problem/regional-order-manage/list-detail.vue
| @@ -553,9 +553,9 @@ const handleUnifiedProcess = async (item: any, action: any = null) => { | @@ -553,9 +553,9 @@ const handleUnifiedProcess = async (item: any, action: any = null) => { | ||
| 553 | : await queryUnifiedActions(item?.taskId) | 553 | : await queryUnifiedActions(item?.taskId) |
| 554 | if (actions) { | 554 | if (actions) { |
| 555 | const target = action || actions[0] | 555 | const target = action || actions[0] |
| 556 | - // 实施动作要选作业类型、填动态字段、传五组照片,统一动作弹窗承载不了,进「作业填报」页 | ||
| 557 | - if (target?.code === 'HANDLE') { | ||
| 558 | - toWorkerImplementPage(item) | 556 | + // 实施动作要选作业类型、填动态字段、传五组照片,统一动作弹窗承载不了,进「作业填报」页; |
| 557 | + // 该业务线未配置工单动态字段时返回 false,继续走统一动作弹窗 | ||
| 558 | + if (target?.code === 'HANDLE' && toWorkerImplementPage(item, 'regional')) { | ||
| 559 | return | 559 | return |
| 560 | } | 560 | } |
| 561 | // 传入的动作即用户点击的配置按钮,直接执行该动作,不再弹「请选择操作」二次选择 | 561 | // 传入的动作即用户点击的配置按钮,直接执行该动作,不再弹「请选择操作」二次选择 |
pages-sub/problem/regional-order-manage/order-detail.vue
| @@ -623,9 +623,9 @@ const handleUnifiedProcess = async (item: any, action: any = null) => { | @@ -623,9 +623,9 @@ const handleUnifiedProcess = async (item: any, action: any = null) => { | ||
| 623 | : await queryUnifiedActions(item?.taskId) | 623 | : await queryUnifiedActions(item?.taskId) |
| 624 | if (actions) { | 624 | if (actions) { |
| 625 | const target = action || actions[0] | 625 | const target = action || actions[0] |
| 626 | - // 实施动作要选作业类型、填动态字段、传五组照片,统一动作弹窗承载不了,进「作业填报」页 | ||
| 627 | - if (target?.code === 'HANDLE') { | ||
| 628 | - toWorkerImplementPage(item) | 626 | + // 实施动作要选作业类型、填动态字段、传五组照片,统一动作弹窗承载不了,进「作业填报」页; |
| 627 | + // 该业务线未配置工单动态字段时返回 false,继续走统一动作弹窗 | ||
| 628 | + if (target?.code === 'HANDLE' && toWorkerImplementPage(item, 'regional')) { | ||
| 629 | return | 629 | return |
| 630 | } | 630 | } |
| 631 | // 传入的动作即用户点击的配置按钮,直接执行该动作,不再弹「请选择操作」二次选择 | 631 | // 传入的动作即用户点击的配置按钮,直接执行该动作,不再弹「请选择操作」二次选择 |
pages-sub/problem/work-order-manage/add-maintain-order.vue
| @@ -221,7 +221,7 @@ import { ref, reactive, watch } from 'vue' | @@ -221,7 +221,7 @@ import { ref, reactive, watch } from 'vue' | ||
| 221 | import { onLoad, onReady, onShow } from '@dcloudio/uni-app'; | 221 | import { onLoad, onReady, onShow } from '@dcloudio/uni-app'; |
| 222 | import { useUploadImgs } from '@/common/utils/useUploadImgs' | 222 | import { useUploadImgs } from '@/common/utils/useUploadImgs' |
| 223 | import { getYlWorkersPage, universalApproval } from '@/api/work-order-manage/work-order-manage' | 223 | import { getYlWorkersPage, universalApproval } from '@/api/work-order-manage/work-order-manage' |
| 224 | -import { workRecordSubmit } from '@/api/common' | 224 | +import { workRecordSubmit, getConfiguredWorkTypes } from '@/api/common' |
| 225 | import { nextStepMap } from '@/common/utils/common' | 225 | import { nextStepMap } from '@/common/utils/common' |
| 226 | import { useUserStore } from '@/pinia/user'; | 226 | import { useUserStore } from '@/pinia/user'; |
| 227 | const userStore = useUserStore(); | 227 | const userStore = useUserStore(); |
| @@ -243,6 +243,15 @@ const dynamicFieldCount = ref(0) | @@ -243,6 +243,15 @@ const dynamicFieldCount = ref(0) | ||
| 243 | // 动态字段提交幂等流水号:同一页面生命周期内保持不变,网络重试只落一条记录 | 243 | // 动态字段提交幂等流水号:同一页面生命周期内保持不变,网络重试只落一条记录 |
| 244 | let workRecordClientSeq = '' | 244 | let workRecordClientSeq = '' |
| 245 | 245 | ||
| 246 | +// 来源列表页标识(work-order/regional/ai),提交后回到用户进入时的列表 | ||
| 247 | +let fromPage = 'work-order' | ||
| 248 | +// 来源标识 -> 列表页路径 | ||
| 249 | +const BACK_URL_MAP = { | ||
| 250 | + 'work-order': '/pages-sub/problem/work-order-manage/index', | ||
| 251 | + 'regional': '/pages-sub/problem/regional-order-manage/index', | ||
| 252 | + 'ai': '/pages-sub/problem/ai-manage/index' | ||
| 253 | +} | ||
| 254 | + | ||
| 246 | // 页面状态 | 255 | // 页面状态 |
| 247 | const showActionSheet = ref(false) | 256 | const showActionSheet = ref(false) |
| 248 | const currentActionSheetData = reactive({ | 257 | const currentActionSheetData = reactive({ |
| @@ -372,6 +381,8 @@ onLoad((options) => { | @@ -372,6 +381,8 @@ onLoad((options) => { | ||
| 372 | } | 381 | } |
| 373 | 382 | ||
| 374 | const { tempKey } = options; | 383 | const { tempKey } = options; |
| 384 | + // 来源列表页:养护员实施可能从工单管理、区域工单、AI 工单进入,提交后回原列表 | ||
| 385 | + fromPage = options.from || 'work-order'; | ||
| 375 | let orderItem = {}; | 386 | let orderItem = {}; |
| 376 | // 2. 读取缓存并校验缓存数据是否有效 | 387 | // 2. 读取缓存并校验缓存数据是否有效 |
| 377 | orderItem = uni.getStorageSync(tempKey) || {}; | 388 | orderItem = uni.getStorageSync(tempKey) || {}; |
| @@ -425,6 +436,9 @@ onLoad((options) => { | @@ -425,6 +436,9 @@ onLoad((options) => { | ||
| 425 | if (orderItem.workTypeId) { | 436 | if (orderItem.workTypeId) { |
| 426 | workOrderForm.workTypeId = orderItem.workTypeId | 437 | workOrderForm.workTypeId = orderItem.workTypeId |
| 427 | workOrderForm.workTypeName = uni.$dict.getDictLabel('maintain_type', orderItem.workTypeId) || '' | 438 | workOrderForm.workTypeName = uni.$dict.getDictLabel('maintain_type', orderItem.workTypeId) || '' |
| 439 | + } else { | ||
| 440 | + // 该业务线只配了一个作业类型的字段时自动选中,进页即可看到填报项 | ||
| 441 | + loadDefaultWorkType() | ||
| 428 | } | 442 | } |
| 429 | // 共同处理人(如有数据则回显,转换为数组格式) | 443 | // 共同处理人(如有数据则回显,转换为数组格式) |
| 430 | if (orderItem.coHandlers && orderItem.coHandlersName) { | 444 | if (orderItem.coHandlers && orderItem.coHandlersName) { |
| @@ -728,6 +742,34 @@ const onDynamicFieldsLoaded = (count) => { | @@ -728,6 +742,34 @@ const onDynamicFieldsLoaded = (count) => { | ||
| 728 | dynamicFieldCount.value = count || 0 | 742 | dynamicFieldCount.value = count || 0 |
| 729 | } | 743 | } |
| 730 | 744 | ||
| 745 | +/** | ||
| 746 | + * 自动带出作业类型:该业务线下只有一个作业类型配置了填报项时直接选中, | ||
| 747 | + * 动态字段块随之渲染(v-if 绑在 workTypeId 上),用户不用先猜该选哪个作业类型。 | ||
| 748 | + * 配了多个时不自动选,交给用户手选。 | ||
| 749 | + */ | ||
| 750 | +const loadDefaultWorkType = async () => { | ||
| 751 | + if (!workOrderForm.businessType) { | ||
| 752 | + return | ||
| 753 | + } | ||
| 754 | + try { | ||
| 755 | + const list = await getConfiguredWorkTypes({ | ||
| 756 | + businessType: workOrderForm.businessType, | ||
| 757 | + bizType: 1 | ||
| 758 | + }) | ||
| 759 | + if (!Array.isArray(list) || list.length !== 1) { | ||
| 760 | + return | ||
| 761 | + } | ||
| 762 | + const only = list[0] | ||
| 763 | + workOrderForm.workTypeId = only.workTypeId | ||
| 764 | + workOrderForm.workTypeName = only.workTypeName | ||
| 765 | + || uni.$dict.getDictLabel('maintain_type', only.workTypeId) | ||
| 766 | + || '' | ||
| 767 | + dynamicFieldCount.value = 0 | ||
| 768 | + } catch (error) { | ||
| 769 | + console.warn('获取已配置填报项的作业类型失败:', error) | ||
| 770 | + } | ||
| 771 | +} | ||
| 772 | + | ||
| 731 | // 动态字段提交幂等流水号(后端按 userId+clientSeq 去重) | 773 | // 动态字段提交幂等流水号(后端按 userId+clientSeq 去重) |
| 732 | const genClientSeq = () => `${Date.now()}-${Math.random().toString(16).slice(2, 10)}` | 774 | const genClientSeq = () => `${Date.now()}-${Math.random().toString(16).slice(2, 10)}` |
| 733 | 775 | ||
| @@ -916,10 +958,10 @@ const submitWorkOrder = async () => { | @@ -916,10 +958,10 @@ const submitWorkOrder = async () => { | ||
| 916 | duration: 1000 | 958 | duration: 1000 |
| 917 | }) | 959 | }) |
| 918 | 960 | ||
| 919 | - // 延迟跳转 | 961 | + // 延迟跳转:来源列表页在 onShow 中不做刷新,用 reLaunch 重建页面保证待办数据最新 |
| 920 | setTimeout(() => { | 962 | setTimeout(() => { |
| 921 | uni.reLaunch({ | 963 | uni.reLaunch({ |
| 922 | - url: '/pages-sub/problem/work-order-manage/index' | 964 | + url: BACK_URL_MAP[fromPage] || BACK_URL_MAP['work-order'] |
| 923 | }) | 965 | }) |
| 924 | }, 1000) | 966 | }, 1000) |
| 925 | } catch (error) { | 967 | } catch (error) { |
pages-sub/problem/work-order-manage/index.vue
| @@ -557,9 +557,9 @@ const handleUnifiedProcess = async (item, action = null) => { | @@ -557,9 +557,9 @@ const handleUnifiedProcess = async (item, action = null) => { | ||
| 557 | : await queryUnifiedActions(item) | 557 | : await queryUnifiedActions(item) |
| 558 | if (actions) { | 558 | if (actions) { |
| 559 | const target = action || actions[0] | 559 | const target = action || actions[0] |
| 560 | - // 实施动作要选作业类型、填动态字段、传五组照片,统一动作弹窗承载不了,进「作业填报」页 | ||
| 561 | - if (target?.code === 'HANDLE') { | ||
| 562 | - toWorkerImplementPage(item) | 560 | + // 实施动作要选作业类型、填动态字段、传五组照片,统一动作弹窗承载不了,进「作业填报」页; |
| 561 | + // 该业务线未配置工单动态字段时返回 false,继续走统一动作弹窗 | ||
| 562 | + if (target?.code === 'HANDLE' && toWorkerImplementPage(item, 'work-order')) { | ||
| 563 | return | 563 | return |
| 564 | } | 564 | } |
| 565 | // 传入的动作即用户点击的配置按钮,直接执行该动作,不再弹「请选择操作」二次选择 | 565 | // 传入的动作即用户点击的配置按钮,直接执行该动作,不再弹「请选择操作」二次选择 |
| @@ -595,7 +595,7 @@ const handleUnifiedSuccess = () => { | @@ -595,7 +595,7 @@ const handleUnifiedSuccess = () => { | ||
| 595 | 595 | ||
| 596 | // 待办-处理工单 | 596 | // 待办-处理工单 |
| 597 | const handleProcess = async (item) => { | 597 | const handleProcess = async (item) => { |
| 598 | - console.log(nextStepMap[item.taskKey].name) | 598 | + console.log(nextStepMap[item.taskKey]?.name) |
| 599 | try { | 599 | try { |
| 600 | if (nextStepMap[item.taskKey]?.name == '养护组长分配') { | 600 | if (nextStepMap[item.taskKey]?.name == '养护组长分配') { |
| 601 | uni.navigateTo({ | 601 | uni.navigateTo({ |
pages-sub/problem/work-order-manage/order-detail.vue
| @@ -854,9 +854,9 @@ const handleUnifiedProcess = async (item: any, action: any = null) => { | @@ -854,9 +854,9 @@ const handleUnifiedProcess = async (item: any, action: any = null) => { | ||
| 854 | : await queryUnifiedActions(item) | 854 | : await queryUnifiedActions(item) |
| 855 | if (actions) { | 855 | if (actions) { |
| 856 | const target = action || actions[0] | 856 | const target = action || actions[0] |
| 857 | - // 实施动作要选作业类型、填动态字段、传五组照片,统一动作弹窗承载不了,进「作业填报」页 | ||
| 858 | - if (target?.code === 'HANDLE') { | ||
| 859 | - toWorkerImplementPage(item) | 857 | + // 实施动作要选作业类型、填动态字段、传五组照片,统一动作弹窗承载不了,进「作业填报」页; |
| 858 | + // 该业务线未配置工单动态字段时返回 false,继续走统一动作弹窗 | ||
| 859 | + if (target?.code === 'HANDLE' && toWorkerImplementPage(item, 'work-order')) { | ||
| 860 | return | 860 | return |
| 861 | } | 861 | } |
| 862 | // 传入的动作即用户点击的配置按钮,直接执行该动作,不再弹「请选择操作」二次选择 | 862 | // 传入的动作即用户点击的配置按钮,直接执行该动作,不再弹「请选择操作」二次选择 |