Commit dacff5e32b70abcb4b7942d919ba291d058c3439

Authored by 刘淇
1 parent 7a96cf50

养护员退回

common/utils/common.js
@@ -11,6 +11,7 @@ export const nextStepMap = { @@ -11,6 +11,7 @@ export const nextStepMap = {
11 name: '养护员待实施', 11 name: '养护员待实施',
12 btnText: '实施', 12 btnText: '实施',
13 operateTypePass: 120, 13 operateTypePass: 120,
  14 + operateTypeNoPass: 220,
14 backShow: true, 15 backShow: true,
15 renewShow: false 16 renewShow: false
16 }, 17 },
common/utils/useUploadImgs.js
@@ -19,18 +19,32 @@ export function useUploadImgs(config) { @@ -19,18 +19,32 @@ export function useUploadImgs(config) {
19 const imgList = ref([]) 19 const imgList = ref([])
20 20
21 /** 21 /**
  22 + * 新增:清空所有图片
  23 + * 功能:重置图片列表为空,并触发表单字段校验(如果有表单Ref)
  24 + */
  25 + const clearImgs = () => {
  26 + imgList.value = [];
  27 + // 优化:先判断 formRef 存在,再判断 formRef.value 存在
  28 + if (defaultConfig.formRef && defaultConfig.formRef.value && defaultConfig.fieldName) {
  29 + defaultConfig.formRef.value.validateField(defaultConfig.fieldName);
  30 + }
  31 + };
  32 +
  33 +
  34 + /**
22 * 删除图片 35 * 删除图片
23 */ 36 */
24 const deleteImg = (event) => { 37 const deleteImg = (event) => {
25 - // 确保index是有效数字  
26 - const index = Number(event.index)  
27 - if (isNaN(index) || index < 0 || index >= imgList.value.length) return  
28 -  
29 - imgList.value.splice(index, 1)  
30 - // 删除后重新校验  
31 - defaultConfig.formRef.value?.validateField(defaultConfig.fieldName)  
32 - uni.showToast({ title: '图片删除成功', icon: 'success' })  
33 - } 38 + const index = Number(event.index);
  39 + if (isNaN(index) || index < 0 || index >= imgList.value.length) return;
  40 +
  41 + imgList.value.splice(index, 1);
  42 + // 修复:先判断 formRef 存在,再访问 value
  43 + if (defaultConfig.formRef && defaultConfig.formRef.value && defaultConfig.fieldName) {
  44 + defaultConfig.formRef.value.validateField(defaultConfig.fieldName);
  45 + }
  46 + uni.showToast({ title: '图片删除成功', icon: 'success' });
  47 + };
34 48
35 /** 49 /**
36 * 上传图片(适配u-upload的file格式) 50 * 上传图片(适配u-upload的file格式)
@@ -106,7 +120,9 @@ export function useUploadImgs(config) { @@ -106,7 +120,9 @@ export function useUploadImgs(config) {
106 } 120 }
107 121
108 // 上传完成后校验 122 // 上传完成后校验
109 - defaultConfig.formRef.value?.validateField(defaultConfig.fieldName) 123 + if (defaultConfig.formRef && defaultConfig.formRef.value && defaultConfig.fieldName) {
  124 + defaultConfig.formRef.value.validateField(defaultConfig.fieldName);
  125 + }
110 } catch (err) { 126 } catch (err) {
111 console.error(`【${defaultConfig.fieldName}】图片上传失败:`, err) 127 console.error(`【${defaultConfig.fieldName}】图片上传失败:`, err)
112 // 标记所有上传失败 128 // 标记所有上传失败
@@ -147,11 +163,39 @@ export function useUploadImgs(config) { @@ -147,11 +163,39 @@ export function useUploadImgs(config) {
147 } 163 }
148 } 164 }
149 165
  166 + /**
  167 + * 新增:批量设置图片列表(图片回显核心方法,替代业务页面的setUploadImgsList)
  168 + * @param imgUrls 图片URL数组(如:['https://xxx.jpg', 'https://yyy.png'])
  169 + * 功能:将纯URL数组转换为u-upload兼容格式,实现静默回显,无数据时不提示
  170 + */
  171 + const setImgList = (imgUrls = []) => {
  172 + // 容错处理:校验参数有效性,非数组/空数组直接重置
  173 + if (!Array.isArray(imgUrls) || imgUrls.length === 0) {
  174 + imgList.value = []
  175 + return
  176 + }
  177 +
  178 + // 转换为u-upload兼容的格式(status: success 标记为已成功上传,可正常显示/删除)
  179 + const formatImgList = imgUrls.map(url => ({
  180 + url: url,
  181 + status: 'success', // 关键:标记为成功状态,兼容后续删除/校验逻辑
  182 + message: '',
  183 + name: url.substring(url.lastIndexOf('/') + 1), // 从URL截取文件名,优化显示
  184 + size: 0 // 历史图片无大小信息,默认0不影响使用
  185 + }))
  186 +
  187 + // 额外优化:限制回显数量不超过maxCount,避免异常
  188 + const finalImgList = formatImgList.slice(0, defaultConfig.maxCount)
  189 + imgList.value = finalImgList
  190 + }
  191 +
150 return { 192 return {
151 - imgList: imgList.value, // 核心修复:返回纯数组(解除响应式代理) 193 + imgList: imgList, // 核心修复:返回纯数组(解除响应式代理)
152 rawImgList: imgList, // 保留响应式引用(内部使用) 194 rawImgList: imgList, // 保留响应式引用(内部使用)
153 uploadImgs, 195 uploadImgs,
154 deleteImg, 196 deleteImg,
  197 + clearImgs,
  198 + setImgList,
155 getSuccessImgUrls, 199 getSuccessImgUrls,
156 imgValidateRule, 200 imgValidateRule,
157 uploadConfig: defaultConfig 201 uploadConfig: defaultConfig
pages-sub/daily/patrol-manage/add-patrol-record.vue
@@ -10,6 +10,7 @@ @@ -10,6 +10,7 @@
10 > 10 >
11 <!-- 1. 巡查描述(文本域) --> 11 <!-- 1. 巡查描述(文本域) -->
12 <up-form-item 12 <up-form-item
  13 + label="巡查描述"
13 prop="content" 14 prop="content"
14 class="form-item" 15 class="form-item"
15 required 16 required
pages-sub/problem/work-order-manage/add-maintain-order.vue
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 ref="workOrderFormRef" 7 ref="workOrderFormRef"
8 labelWidth="170rpx" 8 labelWidth="170rpx"
9 > 9 >
10 - <!-- 1. 工单编号(只读展示,从URL获取) --> 10 + <!-- 1. 工单编号(只读展示,从缓存获取) -->
11 <up-form-item 11 <up-form-item
12 label="工单编号" 12 label="工单编号"
13 border-bottom 13 border-bottom
@@ -285,32 +285,157 @@ const workOrderFormRules = reactive({ @@ -285,32 +285,157 @@ const workOrderFormRules = reactive({
285 reason: [ 285 reason: [
286 { type: 'string', required: true, message: '请输入处理情况描述', trigger: ['change', 'blur'] }, 286 { type: 'string', required: true, message: '请输入处理情况描述', trigger: ['change', 'blur'] },
287 { type: 'string', max: 200, message: '处理情况描述最多200字', trigger: ['change', 'blur'] } 287 { type: 'string', max: 200, message: '处理情况描述最多200字', trigger: ['change', 'blur'] }
288 - ],  
289 - // 新增5个图片字段校验  
290 - // startImgs: [startImgs.imgValidateRule],  
291 - // processingImgs: [processingImgs.imgValidateRule],  
292 - // endImgs: [endImgs.imgValidateRule],  
293 - // personImgs: [personImgs.imgValidateRule],  
294 - // materialImgs: [materialImgs.imgValidateRule] 288 + ]
295 }) 289 })
296 290
297 -// 生命周期 - 从URL获取工单编号 291 +// 生命周期 - 从本地缓存获取完整工单数据
298 onLoad((options) => { 292 onLoad((options) => {
  293 + try {
  294 + // 1. 校验tempKey是否缺失
  295 + if (!options || !options.tempKey) {
  296 + uni.showToast({
  297 + title: '缺失工单缓存Key,无法加载数据',
  298 + icon: 'none',
  299 + duration: 3000
  300 + });
  301 + console.error('onLoad异常:options或tempKey缺失');
  302 + return;
  303 + }
299 304
  305 + const { tempKey } = options;
  306 + let orderItem = {};
  307 + // 2. 读取缓存并校验缓存数据是否有效
  308 + orderItem = uni.getStorageSync(tempKey) || {};
  309 + if (JSON.stringify(orderItem) === '{}') {
  310 + uni.showToast({
  311 + title: '工单缓存数据为空,请重新进入',
  312 + icon: 'none',
  313 + duration: 3000
  314 + });
  315 + console.error('onLoad异常:工单缓存数据为空');
  316 + // 可选:返回上一页
  317 + // setTimeout(() => uni.navigateBack(), 1500);
  318 + return;
  319 + }
300 320
301 - workOrderForm.workerDataId = options.id  
302 - workOrderForm.taskId = options.taskId  
303 - workOrderForm.orderNo = options.orderNo 321 + // 可选:读取后移除缓存,避免冗余数据
  322 + uni.removeStorageSync(tempKey);
304 323
305 - console.log('从URL获取工单编号:', workOrderForm.taskId) 324 + // 3. 填充基础表单数据(存在则赋值,不存在则提示)
  325 + if (!orderItem.id) {
  326 + uni.showToast({
  327 + title: '缺失工单ID,数据异常',
  328 + icon: 'none',
  329 + duration: 2000
  330 + });
  331 + console.warn('工单数据缺失:id');
  332 + }
  333 + if (!orderItem.taskId) {
  334 + uni.showToast({
  335 + title: '缺失任务ID,提交可能失败',
  336 + icon: 'none',
  337 + duration: 2000
  338 + });
  339 + console.warn('工单数据缺失:taskId');
  340 + }
  341 + if (!orderItem.orderNo) {
  342 + uni.showToast({
  343 + title: '缺失工单编号,数据异常',
  344 + icon: 'none',
  345 + duration: 2000
  346 + });
  347 + console.warn('工单数据缺失:orderNo');
  348 + }
  349 +
  350 + workOrderForm.workerDataId = orderItem.id || '';
  351 + workOrderForm.taskId = orderItem.taskId || '';
  352 + workOrderForm.orderNo = orderItem.orderNo || '';
  353 + workOrderForm.reason = orderItem.handleResult || ''; // 处理情况回显
  354 +
  355 + // 共同处理人(如有数据则回显)
  356 + if (orderItem.coHandlers && orderItem.coHandlersName) {
  357 + workOrderForm.coProcessorId = orderItem.coHandlers;
  358 + workOrderForm.coProcessorName = orderItem.coHandlersName;
  359 + } else {
  360 + console.warn('工单数据提示:无共同处理人信息');
  361 + }
  362 +
  363 + // 4. 回显各类图片:使用 useUploadImgs 内置 setImgList 方法(自动添加 status: 'success')
  364 + // 校验图片字段是否存在,不存在则赋值空数组,避免报错
  365 + const startImgsArr = orderItem.startImgs || [];
  366 + const processingImgsArr = orderItem.processingImgs || [];
  367 + const endImgsArr = orderItem.endImgs || [];
  368 + const personImgsArr = orderItem.personImgs || [];
  369 + const materialImgsArr = orderItem.materialImgs || [];
  370 +
  371 + // 图片回显前校验数组有效性
  372 + if (!Array.isArray(startImgsArr)) {
  373 + uni.showToast({
  374 + title: '开始图片数据格式异常',
  375 + icon: 'none',
  376 + duration: 2000
  377 + });
  378 + console.error('开始图片异常:非数组格式');
  379 + }
  380 + if (!Array.isArray(endImgsArr)) {
  381 + uni.showToast({
  382 + title: '结束图片数据格式异常',
  383 + icon: 'none',
  384 + duration: 2000
  385 + });
  386 + console.error('结束图片异常:非数组格式');
  387 + }
  388 +
  389 + startImgs.setImgList(startImgsArr);
  390 + processingImgs.setImgList(processingImgsArr);
  391 + endImgs.setImgList(endImgsArr);
  392 + personImgs.setImgList(personImgsArr);
  393 + materialImgs.setImgList(materialImgsArr);
  394 +
  395 + // 5. 校验必填图片(开始/结束)是否为空,提前提示
  396 + if (startImgsArr.length === 0) {
  397 + uni.showToast({
  398 + title: '开始图片为空,请补充上传',
  399 + icon: 'none',
  400 + duration: 2000
  401 + });
  402 + console.warn('工单提示:开始图片数组为空');
  403 + }
  404 + if (endImgsArr.length === 0) {
  405 + uni.showToast({
  406 + title: '结束图片为空,请补充上传',
  407 + icon: 'none',
  408 + duration: 2000
  409 + });
  410 + console.warn('工单提示:结束图片数组为空');
  411 + }
  412 +
  413 + console.log('工单数据初始化完成:', workOrderForm);
  414 + } catch (error) {
  415 + uni.showToast({
  416 + title: '工单数据加载失败,请重试',
  417 + icon: 'none',
  418 + duration: 3000
  419 + });
  420 + console.error('获取工单缓存数据失败:', error);
  421 + // 可选:返回上一页
  422 + // setTimeout(() => uni.navigateBack(), 1500);
  423 + }
306 }) 424 })
307 425
308 // 生命周期 - 初始化表单规则 426 // 生命周期 - 初始化表单规则
309 onReady(() => { 427 onReady(() => {
310 - if (workOrderFormRef.value) {  
311 - workOrderFormRef.value.setRules(workOrderFormRules) 428 + // 校验表单实例是否存在
  429 + if (!workOrderFormRef.value) {
  430 + uni.showToast({
  431 + title: '表单实例初始化失败',
  432 + icon: 'none',
  433 + duration: 2000
  434 + });
  435 + console.error('onReady异常:workOrderFormRef.value 为空');
  436 + return;
312 } 437 }
313 - console.log('工单表单规则初始化完成') 438 + workOrderFormRef.value.setRules(workOrderFormRules)
314 }) 439 })
315 440
316 // 生命周期 - 加载共同处理人列表 441 // 生命周期 - 加载共同处理人列表
@@ -329,32 +454,77 @@ const loadCoProcessorList = async () =&gt; { @@ -329,32 +454,77 @@ const loadCoProcessorList = async () =&gt; {
329 pageSize: 100 454 pageSize: 100
330 } 455 }
331 const res = await getYlWorkersPage(queryData) 456 const res = await getYlWorkersPage(queryData)
  457 +
  458 + // 校验接口返回数据是否有效
  459 + if (!res || !res.list) {
  460 + uni.showToast({
  461 + title: '获取处理人列表失败(无数据)',
  462 + icon: 'none',
  463 + duration: 2000
  464 + });
  465 + console.error('loadCoProcessorList异常:接口返回无有效数据');
  466 + coProcessorList.value = [];
  467 + uni.hideLoading();
  468 + return;
  469 + }
  470 +
332 uni.hideLoading() 471 uni.hideLoading()
333 472
334 if (res.list && res.list.length > 0) { 473 if (res.list && res.list.length > 0) {
335 - coProcessorList.value = res.list.map(item => ({  
336 - name: item.nickname,  
337 - value: item.id,  
338 - id: item.id  
339 - }))  
340 - console.log('共同处理人列表:', coProcessorList.value) 474 + coProcessorList.value = res.list.map(item => {
  475 + // 校验列表项是否含必填字段
  476 + if (!item.id || !item.nickname) {
  477 + console.warn('处理人列表项异常:缺失id或nickname', item);
  478 + return null;
  479 + }
  480 + return {
  481 + name: item.nickname,
  482 + value: item.id,
  483 + id: item.id
  484 + }
  485 + }).filter(Boolean); // 过滤null项
341 } else { 486 } else {
342 coProcessorList.value = [] 487 coProcessorList.value = []
343 - uni.showToast({ title: '未查询到处理人数据', icon: 'none' }) 488 + uni.showToast({
  489 + title: '暂无共同处理人数据',
  490 + icon: 'none',
  491 + duration: 2000
  492 + });
  493 + console.warn('loadCoProcessorList提示:处理人列表为空');
344 } 494 }
345 } catch (err) { 495 } catch (err) {
346 uni.hideLoading() 496 uni.hideLoading()
  497 + uni.showToast({
  498 + title: '获取处理人列表失败,请重试',
  499 + icon: 'none',
  500 + duration: 3000
  501 + });
347 console.error('获取共同处理人列表失败:', err) 502 console.error('获取共同处理人列表失败:', err)
348 - uni.showToast({ title: '获取处理人失败,请重试', icon: 'none' })  
349 coProcessorList.value = [] 503 coProcessorList.value = []
350 } 504 }
351 } 505 }
352 506
353 // 打开通用下拉弹窗(仅共同处理人) 507 // 打开通用下拉弹窗(仅共同处理人)
354 const handleActionSheetOpen = (type) => { 508 const handleActionSheetOpen = (type) => {
355 - // 共同处理人列表为空提示 509 + // 校验弹窗类型是否为支持的类型
  510 + if (type !== 'coProcessor') {
  511 + uni.showToast({
  512 + title: '不支持该弹窗类型',
  513 + icon: 'none',
  514 + duration: 2000
  515 + });
  516 + console.error('handleActionSheetOpen异常:不支持的弹窗类型', type);
  517 + return;
  518 + }
  519 +
  520 + // 共同处理人列表为空时,提示并返回
356 if (type === 'coProcessor' && coProcessorList.value.length === 0) { 521 if (type === 'coProcessor' && coProcessorList.value.length === 0) {
357 - uni.showToast({ title: '暂无处理人数据可选', icon: 'none' }) 522 + uni.showToast({
  523 + title: '暂无共同处理人可选',
  524 + icon: 'none',
  525 + duration: 2000
  526 + });
  527 + console.warn('handleActionSheetOpen提示:共同处理人列表为空');
358 return 528 return
359 } 529 }
360 530
@@ -375,6 +545,7 @@ const handleActionSheetOpen = (type) =&gt; { @@ -375,6 +545,7 @@ const handleActionSheetOpen = (type) =&gt; {
375 // 关闭通用下拉弹窗 545 // 关闭通用下拉弹窗
376 const handleActionSheetClose = () => { 546 const handleActionSheetClose = () => {
377 showActionSheet.value = false 547 showActionSheet.value = false
  548 + // 重置弹窗数据,避免残留
378 currentActionSheetData.type = '' 549 currentActionSheetData.type = ''
379 currentActionSheetData.list = [] 550 currentActionSheetData.list = []
380 currentActionSheetData.title = '' 551 currentActionSheetData.title = ''
@@ -382,20 +553,45 @@ const handleActionSheetClose = () =&gt; { @@ -382,20 +553,45 @@ const handleActionSheetClose = () =&gt; {
382 553
383 // 下拉弹窗选择事件(仅处理共同处理人多选) 554 // 下拉弹窗选择事件(仅处理共同处理人多选)
384 const handleActionSheetSelect = (e) => { 555 const handleActionSheetSelect = (e) => {
385 - console.log(e) 556 + // 校验事件参数是否有效
  557 + if (!e || !e.name || !e.id) {
  558 + uni.showToast({
  559 + title: '选择处理人失败(参数异常)',
  560 + icon: 'none',
  561 + duration: 2000
  562 + });
  563 + console.error('handleActionSheetSelect异常:e参数缺失name或id', e);
  564 + showActionSheet.value = false;
  565 + return;
  566 + }
  567 +
386 const { type } = currentActionSheetData 568 const { type } = currentActionSheetData
387 // 多选场景(仅共同处理人) 569 // 多选场景(仅共同处理人)
388 if (type === 'coProcessor') { 570 if (type === 'coProcessor') {
389 workOrderForm.coProcessorName = e.name 571 workOrderForm.coProcessorName = e.name
390 workOrderForm.coProcessorId = e.id 572 workOrderForm.coProcessorId = e.id
391 - workOrderFormRef.value?.validateField('coProcessorName') 573 + // 校验表单实例是否存在,再执行字段校验
  574 + if (workOrderFormRef.value) {
  575 + workOrderFormRef.value?.validateField('coProcessorName')
  576 + } else {
  577 + console.warn('handleActionSheetSelect提示:表单实例不存在,跳过字段校验');
  578 + }
392 } 579 }
393 showActionSheet.value = false 580 showActionSheet.value = false
394 } 581 }
395 582
396 // 图片切换选择 583 // 图片切换选择
397 const imgTabChange = (item)=> { 584 const imgTabChange = (item)=> {
398 - console.log(item) 585 + // 校验切换参数是否有效
  586 + if (!item || item.index === undefined || item.index === null) {
  587 + uni.showToast({
  588 + title: '图片标签切换失败(参数异常)',
  589 + icon: 'none',
  590 + duration: 2000
  591 + });
  592 + console.error('imgTabChange异常:item参数缺失index', item);
  593 + return;
  594 + }
399 activeTab.value = item.index 595 activeTab.value = item.index
400 } 596 }
401 597
@@ -407,66 +603,141 @@ const hideKeyboard = () =&gt; { @@ -407,66 +603,141 @@ const hideKeyboard = () =&gt; {
407 // 提交工单(整合所有图片URL,增加开始/结束图片必填校验) 603 // 提交工单(整合所有图片URL,增加开始/结束图片必填校验)
408 const submitWorkOrder = async () => { 604 const submitWorkOrder = async () => {
409 try { 605 try {
410 - // ========== 新增:校验开始和结束阶段图片至少各1张 ========== 606 + // ========== 前置校验:表单实例是否存在 ==========
  607 + if (!workOrderFormRef.value) {
  608 + uni.showToast({
  609 + title: '表单实例异常,无法提交',
  610 + icon: 'none',
  611 + duration: 2000
  612 + });
  613 + console.error('submitWorkOrder异常:workOrderFormRef.value 为空');
  614 + return;
  615 + }
  616 +
  617 + // ========== 开始/结束图片必填校验 ==========
411 const startImgUrls = startImgs.getSuccessImgUrls(); // 开始阶段图片URL数组 618 const startImgUrls = startImgs.getSuccessImgUrls(); // 开始阶段图片URL数组
412 const endImgUrls = endImgs.getSuccessImgUrls(); // 结束阶段图片URL数组 619 const endImgUrls = endImgs.getSuccessImgUrls(); // 结束阶段图片URL数组
413 620
  621 + // 打印日志验证(可选,用于排查)
  622 + console.log('开始图片有效URL:', startImgUrls);
  623 + console.log('结束图片有效URL:', endImgUrls);
  624 +
414 // 判断开始图片是否为空 625 // 判断开始图片是否为空
415 - if (startImgUrls.length === 0) { 626 + if (!Array.isArray(startImgUrls) || startImgUrls.length === 0) {
416 uni.showToast({ 627 uni.showToast({
417 title: '请至少上传1张开始阶段图片', 628 title: '请至少上传1张开始阶段图片',
418 icon: 'none', 629 icon: 'none',
419 duration: 2000 630 duration: 2000
420 }); 631 });
  632 + console.warn('submitWorkOrder校验失败:开始图片为空');
421 return; // 终止提交流程 633 return; // 终止提交流程
422 } 634 }
423 635
424 // 判断结束图片是否为空 636 // 判断结束图片是否为空
425 - if (endImgUrls.length === 0) { 637 + if (!Array.isArray(endImgUrls) || endImgUrls.length === 0) {
426 uni.showToast({ 638 uni.showToast({
427 title: '请至少上传1张结束阶段图片', 639 title: '请至少上传1张结束阶段图片',
428 icon: 'none', 640 icon: 'none',
429 duration: 2000 641 duration: 2000
430 }); 642 });
  643 + console.warn('submitWorkOrder校验失败:结束图片为空');
431 return; // 终止提交流程 644 return; // 终止提交流程
432 } 645 }
433 - // ========== 图片校验结束 ==========  
434 646
435 - // 原有表单校验 647 + // ========== 处理情况必填校验(兜底,防止表单校验失效) ==========
  648 + if (!workOrderForm.reason || workOrderForm.reason.trim().length === 0) {
  649 + uni.showToast({
  650 + title: '请输入处理情况描述',
  651 + icon: 'none',
  652 + duration: 2000
  653 + });
  654 + console.warn('submitWorkOrder校验失败:处理情况为空');
  655 + return;
  656 + }
  657 + if (workOrderForm.reason.trim().length > 200) {
  658 + uni.showToast({
  659 + title: '处理情况描述不能超过200字',
  660 + icon: 'none',
  661 + duration: 2000
  662 + });
  663 + console.warn('submitWorkOrder校验失败:处理情况超过200字');
  664 + return;
  665 + }
  666 +
  667 + // ========== 原有表单校验 ==========
436 await workOrderFormRef.value.validate() 668 await workOrderFormRef.value.validate()
437 669
  670 + // ========== 校验核心提交参数 ==========
  671 + if (!workOrderForm.taskId) {
  672 + uni.showToast({
  673 + title: '缺失任务ID,无法提交',
  674 + icon: 'none',
  675 + duration: 2000
  676 + });
  677 + console.error('submitWorkOrder异常:taskId 为空');
  678 + return;
  679 + }
  680 + if (!workOrderForm.workerDataId) {
  681 + uni.showToast({
  682 + title: '缺失工单ID,无法提交',
  683 + icon: 'none',
  684 + duration: 2000
  685 + });
  686 + console.error('submitWorkOrder异常:workerDataId 为空');
  687 + return;
  688 + }
  689 +
438 // 构造所有图片URL(原有代码不变) 690 // 构造所有图片URL(原有代码不变)
439 const allImgs = { 691 const allImgs = {
440 - startImgs: startImgUrls, // 直接使用已获取的开始图片URL  
441 - processingImgs: processingImgs.getSuccessImgUrls(),  
442 - endImgs: endImgUrls, // 直接使用已获取的结束图片URL  
443 - personImgs: personImgs.getSuccessImgUrls(),  
444 - materialImgs: materialImgs.getSuccessImgUrls() 692 + startImgs: startImgUrls,
  693 + processingImgs: processingImgs.getSuccessImgUrls() || [],
  694 + endImgs: endImgUrls,
  695 + personImgs: personImgs.getSuccessImgUrls() || [],
  696 + materialImgs: materialImgs.getSuccessImgUrls() || []
445 } 697 }
446 698
447 - // 构造提交参数(可按需调整图片字段格式,此处既保留分类也提供合并数组) 699 + // 构造提交参数
448 const submitData = { 700 const submitData = {
449 taskId: workOrderForm.taskId, 701 taskId: workOrderForm.taskId,
450 taskKey:'ylWorker', 702 taskKey:'ylWorker',
451 - operateType:nextStepMap['ylWorker'].operateTypePass,  
452 - workerDataId:Number(workOrderForm.workerDataId),  
453 - // nextStepMap 703 + operateType: nextStepMap['ylWorker']?.operateTypePass || '', // 兜底:防止nextStepMap缺失属性
  704 + workerDataId: Number(workOrderForm.workerDataId) || '',
454 handleResult: workOrderForm.reason.trim(), 705 handleResult: workOrderForm.reason.trim(),
455 - coHandlers: [String(workOrderForm.coProcessorId)], // 数组格式提交,如需字符串可.join(',')  
456 - // busiLine: 'yl',  
457 - // // 分类图片URL 706 + coHandlers: workOrderForm.coProcessorId ? [String(workOrderForm.coProcessorId)] : [],
458 startImgs: allImgs.startImgs, 707 startImgs: allImgs.startImgs,
459 processingImgs: allImgs.processingImgs, 708 processingImgs: allImgs.processingImgs,
460 endImgs: allImgs.endImgs, 709 endImgs: allImgs.endImgs,
461 personImgs: allImgs.personImgs, 710 personImgs: allImgs.personImgs,
462 materialImgs: allImgs.materialImgs, 711 materialImgs: allImgs.materialImgs,
463 -  
464 problemsImgs:[] 712 problemsImgs:[]
465 } 713 }
466 - console.log(submitData) 714 +
  715 + // 校验operateType是否有效
  716 + if (!submitData.operateType) {
  717 + uni.showToast({
  718 + title: '提交类型异常,无法提交',
  719 + icon: 'none',
  720 + duration: 2000
  721 + });
  722 + console.error('submitWorkOrder异常:operateType 为空');
  723 + return;
  724 + }
467 725
468 uni.showLoading({ title: '提交中...' }) 726 uni.showLoading({ title: '提交中...' })
469 const res = await universalApproval(submitData) 727 const res = await universalApproval(submitData)
  728 +
  729 + // 校验接口返回结果
  730 + if (!res) {
  731 + uni.hideLoading();
  732 + uni.showToast({
  733 + title: '工单提交失败(接口无返回)',
  734 + icon: 'none',
  735 + duration: 3000
  736 + });
  737 + console.error('submitWorkOrder异常:universalApproval接口无有效返回');
  738 + return;
  739 + }
  740 +
470 uni.hideLoading() 741 uni.hideLoading()
471 742
472 uni.showToast({ 743 uni.showToast({
@@ -484,14 +755,16 @@ const submitWorkOrder = async () =&gt; { @@ -484,14 +755,16 @@ const submitWorkOrder = async () =&gt; {
484 } catch (error) { 755 } catch (error) {
485 uni.hideLoading() 756 uni.hideLoading()
486 757
487 - // 区分校验失败和接口失败 758 + // 区分校验失败和接口失败,仅接口失败时提示(校验失败已有内置提示)
488 if (!Array.isArray(error)) { 759 if (!Array.isArray(error)) {
489 - console.error('工单提交失败:', error)  
490 uni.showToast({ 760 uni.showToast({
491 title: '提交失败,请重试', 761 title: '提交失败,请重试',
492 icon: 'none', 762 icon: 'none',
493 duration: 2000 763 duration: 2000
494 - }) 764 + });
  765 + console.error('工单提交失败:', error)
  766 + } else {
  767 + console.warn('工单提交校验失败:', error);
495 } 768 }
496 } 769 }
497 } 770 }
@@ -501,7 +774,7 @@ const submitWorkOrder = async () =&gt; { @@ -501,7 +774,7 @@ const submitWorkOrder = async () =&gt; {
501 // 页面容器样式 774 // 页面容器样式
502 .page-container { 775 .page-container {
503 min-height: 100vh; 776 min-height: 100vh;
504 - padding-bottom: 100rpx; // 给底部按钮留空间,与参考示例一致 777 + padding-bottom: 100rpx; // 给底部按钮留空间
505 } 778 }
506 779
507 // 表单内容容器 780 // 表单内容容器
@@ -515,7 +788,7 @@ const submitWorkOrder = async () =&gt; { @@ -515,7 +788,7 @@ const submitWorkOrder = async () =&gt; {
515 background: #fff; 788 background: #fff;
516 } 789 }
517 790
518 -// 新增:Tab自定义内容样式(红色*号) 791 +// Tab自定义内容样式(红色*号)
519 .tab-item-content { 792 .tab-item-content {
520 display: flex; 793 display: flex;
521 align-items: center; 794 align-items: center;
@@ -528,8 +801,6 @@ const submitWorkOrder = async () =&gt; { @@ -528,8 +801,6 @@ const submitWorkOrder = async () =&gt; {
528 } 801 }
529 802
530 .tab-text { 803 .tab-text {
531 - font-size: 28rpx; // 与原有Tab文字大小一致 804 + font-size: 28rpx;
532 } 805 }
533 -  
534 -  
535 </style> 806 </style>
536 \ No newline at end of file 807 \ No newline at end of file
pages-sub/problem/work-order-manage/distribution-order.vue
@@ -96,6 +96,7 @@ const currentActionSheetData = reactive({ @@ -96,6 +96,7 @@ const currentActionSheetData = reactive({
96 const assigneeList = ref([]) // 养护员列表 96 const assigneeList = ref([]) // 养护员列表
97 // ========== 工单表单数据(仅保留所需字段) ========== 97 // ========== 工单表单数据(仅保留所需字段) ==========
98 const workOrderForm = reactive({ 98 const workOrderForm = reactive({
  99 + id:'',
99 taskId:'', 100 taskId:'',
100 orderNo: '', // 工单编号(对应接口参数id) 101 orderNo: '', // 工单编号(对应接口参数id)
101 assigneeId: '', // 养护员ID(对应接口参数nextAssignee) 102 assigneeId: '', // 养护员ID(对应接口参数nextAssignee)
@@ -118,7 +119,7 @@ onLoad((options) =&gt; { @@ -118,7 +119,7 @@ onLoad((options) =&gt; {
118 if (options && options.orderNo) { 119 if (options && options.orderNo) {
119 workOrderForm.orderNo = options.orderNo 120 workOrderForm.orderNo = options.orderNo
120 workOrderForm.taskId = options.taskId 121 workOrderForm.taskId = options.taskId
121 - 122 + workOrderForm.id = options.id
122 } 123 }
123 console.log('从URL获取工单编号:', workOrderForm.orderNo) 124 console.log('从URL获取工单编号:', workOrderForm.orderNo)
124 }) 125 })
@@ -229,6 +230,7 @@ const submitWorkOrder = async () =&gt; { @@ -229,6 +230,7 @@ const submitWorkOrder = async () =&gt; {
229 } 230 }
230 // 3. 构造接口所需参数 231 // 3. 构造接口所需参数
231 const submitData = { 232 const submitData = {
  233 + workerDataId:workOrderForm.id,
232 operateType: nextStepMap['ylTeamLeader'].operateTypePass, 234 operateType: nextStepMap['ylTeamLeader'].operateTypePass,
233 taskKey:'ylTeamLeader', 235 taskKey:'ylTeamLeader',
234 agree:0, 236 agree:0,
pages-sub/problem/work-order-manage/index.vue
@@ -181,28 +181,25 @@ @@ -181,28 +181,25 @@
181 > 181 >
182 <view class="reject-modal-content"> 182 <view class="reject-modal-content">
183 <!-- 回退原因 必填textarea --> 183 <!-- 回退原因 必填textarea -->
184 - <!-- <view class="textarea-label">-->  
185 - <!-- 回退原因 <text class="required-mark">*</text>-->  
186 - <!-- </view>-->  
187 <up-textarea 184 <up-textarea
188 v-model.trim="rejectReason" 185 v-model.trim="rejectReason"
189 placeholder="请输入回退原因(必填)" 186 placeholder="请输入回退原因(必填)"
190 -  
191 rows="6" 187 rows="6"
192 :count="200" 188 :count="200"
193 maxlength="200" 189 maxlength="200"
194 class="reject-textarea" 190 class="reject-textarea"
195 /> 191 />
196 - <!-- 上传图片(选填) --> 192 + <!-- 上传图片(选填)- 按照参考页面改造 -->
197 <view class="upload-wrap mt-20"> 193 <view class="upload-wrap mt-20">
198 <view class="upload-title">上传图片(选填)</view> 194 <view class="upload-title">上传图片(选填)</view>
199 <up-upload 195 <up-upload
200 - :action="uploadUrl"  
201 - :file-list="rejectFileList"  
202 - @after-read="handleAfterRead"  
203 - @delete="handleDeleteFile" 196 + :file-list="rejectImgs.imgList"
  197 + @after-read="rejectImgs.uploadImgs"
  198 + @delete="rejectImgs.deleteImg"
204 multiple 199 multiple
205 - max-count="3" 200 + :max-count="rejectImgs.uploadConfig.maxCount"
  201 + :upload-text="rejectImgs.uploadConfig.uploadText"
  202 + :size-type="rejectImgs.uploadConfig.sizeType"
206 /> 203 />
207 </view> 204 </view>
208 </view> 205 </view>
@@ -244,7 +241,7 @@ @@ -244,7 +241,7 @@
244 </template> 241 </template>
245 242
246 <script setup> 243 <script setup>
247 -import { ref, computed } from 'vue'; 244 +import { ref, computed, watch } from 'vue';
248 import { onReady, onShow } from '@dcloudio/uni-app'; 245 import { onReady, onShow } from '@dcloudio/uni-app';
249 import { timeFormat } from '@/uni_modules/uview-plus'; 246 import { timeFormat } from '@/uni_modules/uview-plus';
250 import { 247 import {
@@ -256,7 +253,9 @@ import { @@ -256,7 +253,9 @@ import {
256 // 假设从用户store获取角色信息 253 // 假设从用户store获取角色信息
257 import { useUserStore } from '@/pinia/user'; 254 import { useUserStore } from '@/pinia/user';
258 import { nextStepMap } from '@/common/utils/common' 255 import { nextStepMap } from '@/common/utils/common'
259 -import { workorderCreate } from "../../../api/work-order-manage/work-order-manage"; 256 +// 引入图片上传组合式函数(与参考页面一致)
  257 +import { useUploadImgs } from '@/common/utils/useUploadImgs'
  258 +
260 // ========== 状态管理 ========== 259 // ========== 状态管理 ==========
261 const userStore = useUserStore(); 260 const userStore = useUserStore();
262 // 标签页切换 261 // 标签页切换
@@ -284,18 +283,31 @@ const isInspector = computed(() =&gt; { @@ -284,18 +283,31 @@ const isInspector = computed(() =&gt; {
284 // 增加可选链,避免用户信息不存在报错 283 // 增加可选链,避免用户信息不存在报错
285 return userStore.userInfo?.roles?.includes('yl_inspector') || false; 284 return userStore.userInfo?.roles?.includes('yl_inspector') || false;
286 }); 285 });
287 -// 回退弹窗相关(核心修改:将rejectPopupShow改为rejectModalShow 286 +// 回退弹窗相关(核心改造:使用useUploadImgs替代原始图片管理
288 const rejectModalShow = ref(false); // 回退modal显示开关 287 const rejectModalShow = ref(false); // 回退modal显示开关
289 const rejectReason = ref(''); // 回退原因 288 const rejectReason = ref(''); // 回退原因
290 -const rejectFileList = ref([]); // 回退上传图片列表  
291 const currentRejectItem = ref(null); // 当前回退工单 289 const currentRejectItem = ref(null); // 当前回退工单
292 -// 上传地址(根据实际接口配置)  
293 -const uploadUrl = ref('https://xxx.com/upload'); 290 +
  291 +// ========== 核心改造:回退图片上传配置(与参考页面风格一致) ==========
  292 +const rejectImgs = useUploadImgs({
  293 + maxCount: 3, // 最多上传3张,与原有逻辑一致
  294 + uploadText: '选择回退图片', // 自定义上传提示文字
  295 + sizeType: ['compressed'], // 仅上传压缩图,优化性能
  296 + formRef: null, // 该弹窗无表单校验,传null即可
  297 + fieldName: 'rejectImgs' // 自定义字段名,用于标识该上传实例
  298 +})
  299 +
  300 +// 监听上传实例响应式变化,解决u-upload不刷新问题(与参考页面一致)
  301 +watch(() => rejectImgs.rawImgList.value, (newVal) => {
  302 + rejectImgs.imgList = newVal
  303 +}, { deep: true })
  304 +
294 // ========== 新增:养护组长验收弹窗相关状态 ========== 305 // ========== 新增:养护组长验收弹窗相关状态 ==========
295 const acceptModalShow = ref(false); // 验收弹窗显示开关 306 const acceptModalShow = ref(false); // 验收弹窗显示开关
296 const acceptRadioValue = ref('0'); // 单选框值,默认0(通过) 307 const acceptRadioValue = ref('0'); // 单选框值,默认0(通过)
297 const acceptReason = ref(''); // 验收原因 308 const acceptReason = ref(''); // 验收原因
298 const currentAcceptItem = ref(null); // 当前验收的工单项 309 const currentAcceptItem = ref(null); // 当前验收的工单项
  310 +
299 // 分页查询列表 311 // 分页查询列表
300 const queryList = async (pageNo, pageSize) => { 312 const queryList = async (pageNo, pageSize) => {
301 try { 313 try {
@@ -324,6 +336,7 @@ const queryList = async (pageNo, pageSize) =&gt; { @@ -324,6 +336,7 @@ const queryList = async (pageNo, pageSize) =&gt; {
324 uni.showToast({title: '加载失败,请重试', icon: 'none'}); 336 uni.showToast({title: '加载失败,请重试', icon: 'none'});
325 } 337 }
326 }; 338 };
  339 +
327 // ========== 事件处理 ========== 340 // ========== 事件处理 ==========
328 // 标签页切换 341 // 标签页切换
329 const handleTabChange = (item) => { 342 const handleTabChange = (item) => {
@@ -350,8 +363,7 @@ const handleDetail = (item) =&gt; { @@ -350,8 +363,7 @@ const handleDetail = (item) =&gt; {
350 }); 363 });
351 }; 364 };
352 365
353 -// 待办-重新提交工单(跳转到新增页面并携带工单数据)  
354 - 366 +// 生成临时key
355 const generateTempKey = () => { 367 const generateTempKey = () => {
356 return 'renew_order_' + Date.now() + '_' + Math.floor(Math.random() * 10000); 368 return 'renew_order_' + Date.now() + '_' + Math.floor(Math.random() * 10000);
357 }; 369 };
@@ -388,13 +400,31 @@ const handleProcess = async (item) =&gt; { @@ -388,13 +400,31 @@ const handleProcess = async (item) =&gt; {
388 try { 400 try {
389 if (nextStepMap[item.taskKey]?.name == '养护组长分配') { 401 if (nextStepMap[item.taskKey]?.name == '养护组长分配') {
390 uni.navigateTo({ 402 uni.navigateTo({
391 - url: `/pages-sub/problem/work-order-manage/distribution-order?taskId=${item.taskId}&orderNo=${item.orderNo}` 403 + url: `/pages-sub/problem/work-order-manage/distribution-order?taskId=${item.taskId}&orderNo=${item.orderNo}&id=${item.id}`
392 }) 404 })
393 } 405 }
394 if (nextStepMap[item.taskKey]?.name == '养护员待实施') { 406 if (nextStepMap[item.taskKey]?.name == '养护员待实施') {
  407 +
  408 + // ① 生成唯一临时key(和重新提交工单逻辑一致,避免冲突)
  409 + const tempKey = `maintain_order_${Date.now()}_${Math.floor(Math.random() * 10000)}`;
  410 +
  411 + // ② 存储完整item到本地缓存(同步存储,确保立即生效)
  412 + try {
  413 + uni.setStorageSync(tempKey, item);
  414 + } catch (error) {
  415 + console.error('存储养护工单数据失败:', error);
  416 + uni.showToast({title: '数据存储异常,无法跳转', icon: 'none'});
  417 + return;
  418 + }
  419 +
  420 + // ③ URL仅传递临时key(可选:携带必要简单参数,方便目标页面快速使用)
395 uni.navigateTo({ 421 uni.navigateTo({
396 - url: `/pages-sub/problem/work-order-manage/add-maintain-order?taskId=${item.taskId}&id=${item.id}&orderNo=${item.orderNo}` 422 + url: `/pages-sub/problem/work-order-manage/add-maintain-order?tempKey=${tempKey}`
397 }) 423 })
  424 +
  425 + // uni.navigateTo({
  426 + // url: `/pages-sub/problem/work-order-manage/add-maintain-order?taskId=${item.taskId}&id=${item.id}&orderNo=${item.orderNo}`
  427 + // })
398 } 428 }
399 // 养护组长验收 - 打开弹窗 429 // 养护组长验收 - 打开弹窗
400 if (nextStepMap[item.taskKey]?.name == '养护组长验收') { 430 if (nextStepMap[item.taskKey]?.name == '养护组长验收') {
@@ -414,7 +444,6 @@ const handleProcess = async (item) =&gt; { @@ -414,7 +444,6 @@ const handleProcess = async (item) =&gt; {
414 // 发起人确认 444 // 发起人确认
415 if (nextStepMap[item.taskKey]?.name == '发起人确认') { 445 if (nextStepMap[item.taskKey]?.name == '发起人确认') {
416 console.log(item) 446 console.log(item)
417 - // currentAcceptItem.value = item; // 存储当前工单信息  
418 uni.showModal({ 447 uni.showModal({
419 title: "结束工单", 448 title: "结束工单",
420 content: "请确定是否结束工单?", 449 content: "请确定是否结束工单?",
@@ -422,7 +451,7 @@ const handleProcess = async (item) =&gt; { @@ -422,7 +451,7 @@ const handleProcess = async (item) =&gt; {
422 if (res.confirm) { 451 if (res.confirm) {
423 // 构建请求参数 452 // 构建请求参数
424 const requestData = { 453 const requestData = {
425 - // fileUrls: rejectFileList.value.map(file => file.url || ''), 454 + "returnImgs": rejectImgs.getSuccessImgUrls(), // 改造后:获取上传成功的图片URL
426 "workerDataId": item.id, 455 "workerDataId": item.id,
427 "taskKey": item.taskKey, 456 "taskKey": item.taskKey,
428 "taskId": item.taskId, 457 "taskId": item.taskId,
@@ -441,14 +470,12 @@ const handleProcess = async (item) =&gt; { @@ -441,14 +470,12 @@ const handleProcess = async (item) =&gt; {
441 }, 470 },
442 }); 471 });
443 } 472 }
444 -  
445 -  
446 -  
447 } catch (error) { 473 } catch (error) {
448 console.error('处理工单失败:', error); 474 console.error('处理工单失败:', error);
449 uni.showToast({title: '处理失败,请重试', icon: 'none'}); 475 uni.showToast({title: '处理失败,请重试', icon: 'none'});
450 } 476 }
451 }; 477 };
  478 +
452 // 待办-回退工单(打开回退modal) 479 // 待办-回退工单(打开回退modal)
453 const handleReject = (item) => { 480 const handleReject = (item) => {
454 console.log('123213') 481 console.log('123213')
@@ -459,15 +486,17 @@ const handleReject = (item) =&gt; { @@ -459,15 +486,17 @@ const handleReject = (item) =&gt; {
459 } 486 }
460 currentRejectItem.value = item; 487 currentRejectItem.value = item;
461 rejectReason.value = ''; // 清空上次输入 488 rejectReason.value = ''; // 清空上次输入
462 - rejectFileList.value = []; // 清空上次上传图片 489 + rejectImgs.clearImgs(); // 改造后:使用组合式函数的清空方法
463 rejectModalShow.value = true; // 显示回退modal 490 rejectModalShow.value = true; // 显示回退modal
464 }; 491 };
  492 +
465 // 回退modal - 取消按钮 493 // 回退modal - 取消按钮
466 const handleRejectModalCancel = () => { 494 const handleRejectModalCancel = () => {
467 rejectModalShow.value = false; 495 rejectModalShow.value = false;
468 rejectReason.value = ''; 496 rejectReason.value = '';
469 - rejectFileList.value = []; 497 + rejectImgs.clearImgs(); // 改造后:使用组合式函数的清空方法
470 }; 498 };
  499 +
471 // 确认回退工单 500 // 确认回退工单
472 const confirmReject = async () => { 501 const confirmReject = async () => {
473 // 严格校验回退原因(去除首尾空格) 502 // 严格校验回退原因(去除首尾空格)
@@ -485,9 +514,10 @@ const confirmReject = async () =&gt; { @@ -485,9 +514,10 @@ const confirmReject = async () =&gt; {
485 try { 514 try {
486 // 显示加载中,防止重复提交 515 // 显示加载中,防止重复提交
487 uni.showLoading({title: '提交中...', mask: true}); 516 uni.showLoading({title: '提交中...', mask: true});
  517 +
488 // 构建请求参数 518 // 构建请求参数
489 const requestData = { 519 const requestData = {
490 - // fileUrls: rejectFileList.value.map(file => file.url || ''), 520 + "returnImgs": rejectImgs.getSuccessImgUrls(), // 改造后:获取上传成功的图片URL数组
491 "workerDataId": currentRejectItem.value.id, 521 "workerDataId": currentRejectItem.value.id,
492 "taskKey": currentRejectItem.value.taskKey, 522 "taskKey": currentRejectItem.value.taskKey,
493 "taskId": currentRejectItem.value.taskId, 523 "taskId": currentRejectItem.value.taskId,
@@ -508,25 +538,14 @@ const confirmReject = async () =&gt; { @@ -508,25 +538,14 @@ const confirmReject = async () =&gt; {
508 uni.hideLoading(); 538 uni.hideLoading();
509 } 539 }
510 }; 540 };
  541 +
511 // 新增工单 542 // 新增工单
512 const handleAddOrder = () => { 543 const handleAddOrder = () => {
513 uni.navigateTo({ 544 uni.navigateTo({
514 url: '/pages-sub/problem/work-order-manage/add-order' 545 url: '/pages-sub/problem/work-order-manage/add-order'
515 }); 546 });
516 }; 547 };
517 -// 上传图片-读取后(避免重复添加)  
518 -const handleAfterRead = (file) => {  
519 - if (!file) return;  
520 - const isExist = rejectFileList.value.some(item => item.url === file.url);  
521 - if (!isExist && rejectFileList.value.length < 3) {  
522 - rejectFileList.value.push(file);  
523 - }  
524 -};  
525 -// 上传图片-删除(安全删除,避免索引越界)  
526 -const handleDeleteFile = (index) => {  
527 - if (index < 0 || index >= rejectFileList.value.length) return;  
528 - rejectFileList.value.splice(index, 1);  
529 -}; 548 +
530 // ========== 新增:养护组长验收弹窗事件 ========== 549 // ========== 新增:养护组长验收弹窗事件 ==========
531 // 验收弹窗 - 确定按钮(含表单校验) 550 // 验收弹窗 - 确定按钮(含表单校验)
532 const handleAcceptModalConfirm = async () => { 551 const handleAcceptModalConfirm = async () => {
@@ -547,6 +566,7 @@ const handleAcceptModalConfirm = async () =&gt; { @@ -547,6 +566,7 @@ const handleAcceptModalConfirm = async () =&gt; {
547 if (currentAcceptItem.value?.taskKey == 'ylTeamLeaderConfirm') { // 养护组长验收 566 if (currentAcceptItem.value?.taskKey == 'ylTeamLeaderConfirm') { // 养护组长验收
548 postData = { 567 postData = {
549 "taskKey": "ylTeamLeaderConfirm", 568 "taskKey": "ylTeamLeaderConfirm",
  569 + "workerDataId": currentAcceptItem.value.id,
550 "taskId": currentAcceptItem.value.taskId, 570 "taskId": currentAcceptItem.value.taskId,
551 "operateType": acceptRadioValue.value == 0 ? nextStepMap['ylTeamLeaderConfirm'].operateTypePass : nextStepMap['ylTeamLeaderConfirm'].operateTypeNoPass, 571 "operateType": acceptRadioValue.value == 0 ? nextStepMap['ylTeamLeaderConfirm'].operateTypePass : nextStepMap['ylTeamLeaderConfirm'].operateTypeNoPass,
552 "reason": acceptReason.value.trim() 572 "reason": acceptReason.value.trim()
@@ -556,6 +576,7 @@ const handleAcceptModalConfirm = async () =&gt; { @@ -556,6 +576,7 @@ const handleAcceptModalConfirm = async () =&gt; {
556 postData = { 576 postData = {
557 "taskKey": "ylTeamLeaderConfirm", 577 "taskKey": "ylTeamLeaderConfirm",
558 "taskId": currentAcceptItem.value.taskId, 578 "taskId": currentAcceptItem.value.taskId,
  579 + "workerDataId": currentAcceptItem.value.id,
559 "operateType": acceptRadioValue.value == 0 ? nextStepMap['ylTeamLeaderConfirm'].operateTypePass : nextStepMap['ylTeamLeaderConfirm'].operateTypeNoPass, 580 "operateType": acceptRadioValue.value == 0 ? nextStepMap['ylTeamLeaderConfirm'].operateTypePass : nextStepMap['ylTeamLeaderConfirm'].operateTypeNoPass,
560 "reason": acceptReason.value.trim(), 581 "reason": acceptReason.value.trim(),
561 "agree": acceptRadioValue.value 582 "agree": acceptRadioValue.value
@@ -573,6 +594,7 @@ const handleAcceptModalConfirm = async () =&gt; { @@ -573,6 +594,7 @@ const handleAcceptModalConfirm = async () =&gt; {
573 uni.showToast({title: '验收提交失败,请重试', icon: 'none', duration: 2000}); 594 uni.showToast({title: '验收提交失败,请重试', icon: 'none', duration: 2000});
574 } 595 }
575 }; 596 };
  597 +
576 // 页面初始化 598 // 页面初始化
577 onShow(() => { 599 onShow(() => {
578 // 初始化加载列表 600 // 初始化加载列表
pages-sub/problem/work-order-manage/order-detail.vue
@@ -11,16 +11,19 @@ @@ -11,16 +11,19 @@
11 <!-- 主内容容器 --> 11 <!-- 主内容容器 -->
12 <view v-else class="main-content"> 12 <view v-else class="main-content">
13 <!-- 顶部固定Tabs --> 13 <!-- 顶部固定Tabs -->
14 - <up-tabs  
15 - v-model="activeTopTab"  
16 - :list="topTabList"  
17 - :scrollable="false"  
18 - sticky  
19 - active-color="#3c9cff"  
20 - inactive-color="#666"  
21 - class="top-tabs"  
22 - @click="activeTopTabClick"  
23 - ></up-tabs> 14 + <up-sticky :bgColor="'#fff'">
  15 + <up-tabs
  16 + v-model="activeTopTab"
  17 + :list="topTabList"
  18 + :scrollable="false"
  19 + sticky
  20 + active-color="#3c9cff"
  21 + inactive-color="#666"
  22 + class="top-tabs"
  23 + @click="activeTopTabClick"
  24 + ></up-tabs>
  25 + </up-sticky>
  26 +
24 27
25 <!-- 顶部Tab内容区 --> 28 <!-- 顶部Tab内容区 -->
26 <view class="tab-content"> 29 <view class="tab-content">
@@ -107,10 +110,22 @@ @@ -107,10 +110,22 @@
107 ></up-cell> 110 ></up-cell>
108 </up-cell-group> 111 </up-cell-group>
109 112
  113 +
110 <!-- 图片分类Tabs区块 --> 114 <!-- 图片分类Tabs区块 -->
111 - <view class="img-tabs-block"> 115 + <view class="img-tabs-block" v-if="orderDetail.startImgs.length>0">
  116 + <up-cell-group :border="false">
  117 + <up-cell>
  118 + <template #title>
  119 + <view style="min-width: 200rpx">共同处理人</view>
  120 + </template>
  121 + <template #value>
  122 + <view class="common-text-color up-line-1">{{ orderDetail.coHandlersName || '--' }}</view>
  123 + </template>
  124 + </up-cell>
  125 + </up-cell-group>
  126 + <!-- coHandlersName-->
112 <up-tabs 127 <up-tabs
113 - @change = 'imgTabChange' 128 + @change='imgTabChange'
114 v-model="activeImgTab" 129 v-model="activeImgTab"
115 :list="imgTabList" 130 :list="imgTabList"
116 :scrollable="false" 131 :scrollable="false"
@@ -136,10 +151,10 @@ @@ -136,10 +151,10 @@
136 151
137 <!-- 2. 流程节点Tab --> 152 <!-- 2. 流程节点Tab -->
138 <view v-show="activeTopTab == 1" class="process-content"> 153 <view v-show="activeTopTab == 1" class="process-content">
139 -<!-- <up-empty-->  
140 -<!-- mode="data"-->  
141 -<!-- ></up-empty>-->  
142 -<!-- &lt;!&ndash; 可根据实际需求补充流程节点展示逻辑 &ndash;&gt;--> 154 + <!-- <up-empty-->
  155 + <!-- mode="data"-->
  156 + <!-- ></up-empty>-->
  157 + <!-- &lt;!&ndash; 可根据实际需求补充流程节点展示逻辑 &ndash;&gt;-->
143 </view> 158 </view>
144 </view> 159 </view>
145 </view> 160 </view>
@@ -147,10 +162,15 @@ @@ -147,10 +162,15 @@
147 </template> 162 </template>
148 163
149 <script setup lang="ts"> 164 <script setup lang="ts">
150 -import { ref, computed } from 'vue';  
151 -import { onLoad, onShow } from '@dcloudio/uni-app';  
152 -import { timeFormat } from '@/uni_modules/uview-plus';  
153 -import { getMyTaskDetail, getDoneTaskDetail, getTodoTaskDetail, getApprovalDetail } from '@/api/work-order-manage/work-order-manage'; 165 +import {ref, computed} from 'vue';
  166 +import {onLoad, onShow} from '@dcloudio/uni-app';
  167 +import {timeFormat} from '@/uni_modules/uview-plus';
  168 +import {
  169 + getMyTaskDetail,
  170 + getDoneTaskDetail,
  171 + getTodoTaskDetail,
  172 + getApprovalDetail
  173 +} from '@/api/work-order-manage/work-order-manage';
154 174
155 // 状态管理 175 // 状态管理
156 const loading = ref(true); 176 const loading = ref(true);
@@ -159,29 +179,29 @@ const activeImgTab = ref(0); // 图片分类Tab激活索引 @@ -159,29 +179,29 @@ const activeImgTab = ref(0); // 图片分类Tab激活索引
159 179
160 // 顶部Tab列表 180 // 顶部Tab列表
161 const topTabList = ref([ 181 const topTabList = ref([
162 - { name: '工单详情' },  
163 - { name: '流程节点' } 182 + {name: '工单详情'},
  183 + {name: '流程节点'}
164 ]); 184 ]);
165 185
166 const activeTopTabClick = async (item: any) => { 186 const activeTopTabClick = async (item: any) => {
167 console.log(item) 187 console.log(item)
168 activeTopTab.value = item.index 188 activeTopTab.value = item.index
169 - if(activeTopTab.value ==1){ 189 + if (activeTopTab.value == 1) {
170 let getData = { 190 let getData = {
171 - processInstanceId:processInstanceId.value, 191 + processInstanceId: processInstanceId.value,
172 } 192 }
173 - const res = await getApprovalDetail(getData) 193 + const res = await getApprovalDetail(getData)
174 console.log(res) 194 console.log(res)
175 } 195 }
176 } 196 }
177 197
178 // 图片分类Tab列表(带角标配置) 198 // 图片分类Tab列表(带角标配置)
179 const imgTabList = ref([ 199 const imgTabList = ref([
180 - { name: '开始', badge: { isDot: true } },  
181 - { name: '进行中' },  
182 - { name: '结束', badge: { isDot: true } },  
183 - { name: '人员' },  
184 - { name: '材料' } 200 + {name: '开始', badge: {isDot: true}},
  201 + {name: '进行中'},
  202 + {name: '结束', badge: {isDot: true}},
  203 + {name: '人员'},
  204 + {name: '材料'}
185 ]); 205 ]);
186 206
187 // 工单详情数据(初始化赋值,可被接口数据覆盖) 207 // 工单详情数据(初始化赋值,可被接口数据覆盖)
@@ -242,7 +262,7 @@ const orderDetail = ref&lt;any&gt;({ @@ -242,7 +262,7 @@ const orderDetail = ref&lt;any&gt;({
242 const currentImgList = ref([]) 262 const currentImgList = ref([])
243 263
244 const tabKeyMap = ['startImgs', 'processingImgs', 'endImgs', 'personImgs', 'materialImgs']; 264 const tabKeyMap = ['startImgs', 'processingImgs', 'endImgs', 'personImgs', 'materialImgs'];
245 -const imgTabChange = (({index})=>{ 265 +const imgTabChange = (({index}) => {
246 console.log(index) 266 console.log(index)
247 const currentKey = tabKeyMap[index] 267 const currentKey = tabKeyMap[index]
248 console.log(currentKey) 268 console.log(currentKey)
@@ -263,24 +283,24 @@ const DetailQuery = async (taskIdStr: string) =&gt; { @@ -263,24 +283,24 @@ const DetailQuery = async (taskIdStr: string) =&gt; {
263 let res: any; 283 let res: any;
264 284
265 if (tabType === 0) { 285 if (tabType === 0) {
266 - res = await getTodoTaskDetail({ taskId: taskIdStr }); 286 + res = await getTodoTaskDetail({taskId: taskIdStr});
267 } else if (tabType === 1) { 287 } else if (tabType === 1) {
268 - res = await getMyTaskDetail({ taskId: taskIdStr }); 288 + res = await getMyTaskDetail({taskId: taskIdStr});
269 } else if (tabType === 2) { 289 } else if (tabType === 2) {
270 - res = await getDoneTaskDetail({ taskId: taskIdStr }); 290 + res = await getDoneTaskDetail({taskId: taskIdStr});
271 } else { 291 } else {
272 - uni.showToast({ title: '无效的工单类型', icon: 'none' }); 292 + uni.showToast({title: '无效的工单类型', icon: 'none'});
273 return; 293 return;
274 } 294 }
275 295
276 // 覆盖工单详情数据 296 // 覆盖工单详情数据
277 if (res) { 297 if (res) {
278 orderDetail.value = res; 298 orderDetail.value = res;
279 - currentImgList.value = orderDetail.value.startImgs 299 + currentImgList.value = orderDetail.value.startImgs
280 } 300 }
281 } catch (error) { 301 } catch (error) {
282 console.error('获取工单详情失败:', error); 302 console.error('获取工单详情失败:', error);
283 - uni.showToast({ title: '加载失败,请重试', icon: 'none' }); 303 + uni.showToast({title: '加载失败,请重试', icon: 'none'});
284 } finally { 304 } finally {
285 loading.value = false; 305 loading.value = false;
286 } 306 }
@@ -292,20 +312,21 @@ const activeTab = ref(&#39;&#39;) @@ -292,20 +312,21 @@ const activeTab = ref(&#39;&#39;)
292 const processInstanceId = ref('') 312 const processInstanceId = ref('')
293 onLoad((options: any) => { 313 onLoad((options: any) => {
294 console.log('页面入参:', options) 314 console.log('页面入参:', options)
295 - const { taskId: taskIdOpt, activeTab: activeTabOpt, processInstanceId:processInstanceIdOpt } = options; 315 + const {taskId: taskIdOpt, activeTab: activeTabOpt, processInstanceId: processInstanceIdOpt} = options;
296 // 0-待办 1-我发起的 2-已办 316 // 0-待办 1-我发起的 2-已办
297 taskId.value = taskIdOpt || ''; 317 taskId.value = taskIdOpt || '';
298 activeTab.value = activeTabOpt || '0'; 318 activeTab.value = activeTabOpt || '0';
299 - processInstanceId.value = processInstanceIdOpt ; 319 + processInstanceId.value = processInstanceIdOpt;
  320 + DetailQuery(taskId.value);
300 }); 321 });
301 322
302 onShow(() => { 323 onShow(() => {
303 - if (taskId.value) {  
304 - DetailQuery(taskId.value);  
305 - } else {  
306 - loading.value = false;  
307 - uni.showToast({ title: '缺少工单ID参数', icon: 'none' });  
308 - } 324 + // if (taskId.value) {
  325 + // DetailQuery(taskId.value);
  326 + // } else {
  327 + // loading.value = false;
  328 + // uni.showToast({title: '缺少工单ID参数', icon: 'none'});
  329 + // }
309 }); 330 });
310 </script> 331 </script>
311 332
@@ -327,7 +348,7 @@ onShow(() =&gt; { @@ -327,7 +348,7 @@ onShow(() =&gt; {
327 348
328 // Tab内容区 349 // Tab内容区
329 .tab-content { 350 .tab-content {
330 - padding: 16rpx; 351 + //padding: 16rpx;
331 } 352 }
332 353
333 // 工单详情内容 354 // 工单详情内容