Преглед изворни кода

Merge remote-tracking branch 'origin/master'

ouyj пре 4 месеци
родитељ
комит
cb9312437d
6 измењених фајлова са 1519 додато и 30 уклоњено
  1. 20 0
      api/order/detail.uts
  2. 14 0
      pages.json
  3. 664 0
      pages/order/detail/resetIndex.uvue
  4. 670 0
      pages/order/detail/returnIndex.uvue
  5. 151 29
      pages/order/index.uvue
  6. 0 1
      utils/storage.uts

+ 20 - 0
api/order/detail.uts

@@ -69,3 +69,23 @@ export const resumeOrder = (gxtWorkOrder: acceptOrderInfo | null): Promise<any>
 		data: data
 	})
 }
+
+export const returnRepairOrder = (gxtWorkOrder: UTSJSONObject | null): Promise<any> => {
+	// const plainObject = gxtWorkOrder != null ? JSON.parse(JSON.stringify(gxtWorkOrder)) : null;
+	// const data: UTSJSONObject | null = plainObject as UTSJSONObject;
+	return request({
+		url: `/mobile/order/returnRepairOrder`,
+		method: 'PUT',
+		data: gxtWorkOrder
+	})
+}
+
+export const resetAndStart = (gxtWorkOrder: UTSJSONObject | null): Promise<any> => {
+	// const plainObject = gxtWorkOrder != null ? JSON.parse(JSON.stringify(gxtWorkOrder)) : null;
+	// const data: UTSJSONObject | null = plainObject as UTSJSONObject;
+	return request({
+		url: `/mobile/order/resetAndStart`,
+		method: 'PUT',
+		data: gxtWorkOrder
+	})
+}

+ 14 - 0
pages.json

@@ -161,6 +161,20 @@
 			"style": {
 				"navigationBarTitleText": ""
 			}
+		},
+		{
+			"path": "pages/order/detail/returnIndex",
+			"style": {
+				"navigationBarTitleText": "退回",
+				"navigationStyle": "#custom"
+			}
+		},
+		{
+			"path": "pages/order/detail/resetIndex",
+			"style": {
+				"navigationBarTitleText": "复启",
+				"navigationStyle": "#custom"
+			}
 		}
 	],
 	"globalStyle": {

+ 664 - 0
pages/order/detail/resetIndex.uvue

@@ -0,0 +1,664 @@
+<template>
+    <view class="detail-page">
+        <scroll-view class="detail-content" :scroll-y="true">
+            <!-- 工单信息 -->
+            <view class="info-section">
+                <view class="section-title">
+                    <text class="section-title-text">工单信息</text>
+                </view>
+                <view class="info-card">
+                    <view class="info-item">
+                        <text class="info-label">工单编码</text>
+                        <text class="info-value">{{ workOrderProjectNo ?? '' }}</text>
+                    </view>
+                    <view class="info-item">
+                        <text class="info-label">工单类型</text>
+                        <text class="info-value">{{ orderType == '1' ? '维修工单' : '维保工单' }}</text>
+                    </view>
+                    <view class="info-item">
+                        <text class="info-label">风机编号</text>
+                        <text class="info-value">{{ pcsDeviceName ?? '' }}</text>
+                    </view>
+					<view class="info-item">
+					    <text class="info-label">维保中心</text>
+					    <text class="info-value">{{ gxtCenter ?? '' }}</text>
+					</view>
+                    <view class="info-item">
+                        <text class="info-label">场站</text>
+                        <text class="info-value">{{ pcsStationName ?? '' }}</text>
+                    </view>
+					<!-- <view class="info-item">
+					    <text class="info-label">品牌</text>
+					    <text class="info-value">{{ detailData.model ?? '' }}</text>
+					</view> -->
+                    <view class="info-item">
+                        <text class="info-label">机型</text>
+                        <text class="info-value">{{ brand ?? '' }} {{ model ?? '' }}</text>
+                    </view>
+					<view class="info-item">
+					    <text class="info-label">接单时间</text>
+					    <text class="info-value">{{ acceptTime ?? '' }}</text>
+					</view>
+					<!-- <view class="info-item">
+					    <text class="info-label">挂起原因</text>
+					    <view class="form-picker" @click="showReasonPicker = true">
+					        <view class="picker-display">
+					            <text v-if="suspendReason" class="selected-value">{{ suspendReason }}</text>
+					            <text v-else class="placeholder">请选择挂起原因</text>
+					            <text class="arrow">▼</text>
+					        </view>
+					    </view>
+					</view> -->
+                </view>
+            </view>
+			<!-- <view class="info-section">
+				<view class="section-title">
+					<text class="section-title-text">工作负责人</text>
+				</view>
+				<view class="info-card">
+					<view class="info-item">
+						<input class="input" type="text" placeholder="请输入工作负责人" v-model="teamLeaderName" />
+					</view>
+				</view>
+			</view> -->
+			<!-- 工作负责人选择 -->
+			<view class="info-section">
+			    <!-- <view class="section-title">
+			        <text class="section-title-text">退回类型</text>
+			    </view> -->
+			    <view class="info-card">
+			        <view class="info-item">
+						<view class="info-label">
+							<text class="form-label required">复位方式</text>
+						</view>
+						<view class="info-value">
+						    <view class="form-picker" @click="showReasonPicker = true">
+						        <view class="picker-display">
+						            <text v-if="resetMethod" class="selected-value">{{ returnTypeLabel }}</text>
+						            <text v-else class="placeholder">请选择复位方式</text>
+						            <text class="arrow">▼</text>
+						        </view>
+						    </view>
+						</view>
+					</view>
+					<view class="info-item">
+						<view class="info-label">
+							<text class="form-label required">真实故障原因</text>
+						</view>
+						<view class="info-value">
+							 <textarea
+								class="reject-reason-textarea"
+								placeholder="请输入真实故障原因"
+								v-model="realFailureReason"
+								maxlength="500"
+								:show-confirm-bar="false"
+								auto-height
+							></textarea>
+						</view>
+					</view>
+			    </view>
+			</view>
+
+			<!-- 自定义选择器弹窗 -->
+			<view v-if="showReasonPicker" class="picker-modal">
+			    <view class="modal-mask" @click="showReasonPicker = false"></view>
+			    <view class="modal-content">
+			        <view class="modal-header">
+			            <text class="modal-title">复位方式</text>
+			            <text class="modal-close" @click="showReasonPicker = false">取消</text>
+			        </view>
+			        <scroll-view class="modal-body" scroll-y="true">
+			            <view
+			                v-for="(option, index) in returnTypeOptions"
+			                :key="index"
+			                class="picker-option"
+			                :class="{ 'selected': index === selectedReasonIndex }"
+			                @click="selectLeaderManually(index)"
+			            >
+			                <text class="option-text">{{ option.label }}</text>
+			                <text v-if="index === selectedReasonIndex" class="option-check">✓</text>
+			            </view>
+			        </scroll-view>
+			    </view>
+			</view>
+        </scroll-view>
+
+        <!-- 接单按钮 -->
+            <view class="accept-button-container" v-if="checkPermi(orderType == '2' ? ['gxt:maintenance:order:suspend'] : ['gxt:repairOrder:suspend'])">
+            <button class="accept-button" @click="handleSuspendOrder">{{ isDealing ? '复启中...' : '复 启' }}</button>
+        </view>
+
+        <!-- 加载中状态 -->
+        <view v-if="loading" class="loading-mask">
+            <text class="loading-text">加载中...</text>
+        </view>
+    </view>
+</template>
+
+<script setup lang="uts">
+    import { ref } from 'vue'
+    import type { acceptOrderInfo } from '../../../types/order'
+    import type { WorkOrderFlow } from '../../../types/flow'
+    import { getOrderInfoById, getRepairOrderInfoById, resetAndStart } from '../../../api/order/detail'
+	import type { SysDictData } from '../../../types/dict'
+	import { getDictDataByType } from '../../../api/dict/index'
+	import { getUserList } from '../../../api/user/list'
+	import type { UserInfo } from '../../../types/user'
+	import {checkPermi} from '../../../utils/storage'
+
+	// 工单信息
+	const orderId = ref<string>('')
+	const workOrderProjectNo = ref<string>('')
+	const workOrderStatus = ref<string>('')
+	const orderType = ref<string>('')
+	const pcsDeviceName = ref<string>('')
+	const gxtCenter = ref<string>('')
+	const pcsStationName = ref<string>('')
+	const brand = ref<string>('')
+	const model = ref<string>('')
+	const acceptTime = ref<string>('')
+	const resetMethod = ref<string>('')
+	const realFailureReason = ref<string>("")
+	const returnTypeLabel = ref<string>("")
+	
+	const teamLeaderName = ref<string>("")
+	// 添加字典加载状态
+	const dictLoaded = ref<boolean>(false)
+
+	// 选择器选项类型
+	type PickerOption = {
+	    label: string
+	    value: string
+	}
+
+	// 选中的挂起原因
+	
+	const selectedReasonIndex = ref<number>(-1)
+	const returnTypeOptions = ref<PickerOption[]>([])
+	const showReasonPicker = ref<boolean>(false)
+
+	// 获取负责人列表(使用用户列表接口)
+	const dictList = async (): Promise<void> => {
+	    try {
+	        const result = await getDictDataByType('gxt_reset_method')
+	        const resultObj = result as UTSJSONObject
+
+	        if (resultObj['code'] == 200) {
+				const data = resultObj['data'] as any[]
+				const options: PickerOption[] = []
+	            if (data.length > 0) {
+	                for (let i = 0; i < data.length; i++) {
+	                    const item = data[i] as UTSJSONObject
+	                    let dictItem: SysDictData = {
+							dictValue: item['dictValue'] as string | null,
+							dictLabel: item['dictLabel'] as string | null,
+							dictCode: null,
+							dictSort: null,
+							dictType: null,
+							cssClass: null,
+							listClass: null,
+							isDefault: null,
+							status: null,
+							default: null,
+							createTime: null,
+							remark: null
+	                    }
+						// 构建选择器选项
+						options.push({
+							label: dictItem.dictLabel ?? '',
+							value: dictItem.dictValue ?? ''
+						})
+	                }
+	            }
+
+				returnTypeOptions.value = options
+	        }
+	    } catch (e: any) {
+	        console.error('获取挂起原因失败:', e.message)
+	    }
+	}
+
+	// 手动选择负责人
+	const selectLeaderManually = (index: number): void => {
+	    selectedReasonIndex.value = index
+	    if (index >= 0 && index < returnTypeOptions.value.length) {
+	        const selectedOption = returnTypeOptions.value[index]
+	        returnTypeLabel.value = selectedOption.label
+			resetMethod.value = selectedOption.value
+	    }
+	    showReasonPicker.value = false
+	}
+
+	const isDealing = ref(false)
+	const hasDealed = ref(false)
+	// 处理接单操作
+	const handleSuspendOrder = async (): Promise<void> => {
+		if (resetMethod.value == '') {
+			uni.showToast({
+				title: '请选择复位方式',
+				icon: 'none'
+			})
+			return
+		}
+		
+		if (isDealing.value || hasDealed.value) return // 双重保险
+		isDealing.value = true
+		const subOrder = {
+			id: orderId.value,
+			orderType: orderType.value,
+			workOrderProjectNo: workOrderProjectNo.value,
+			workOrderStatus: workOrderStatus.value,
+			resetMethod: resetMethod.value,
+			realFailureReason: realFailureReason.value,
+			repairMethod: "2"
+		} as UTSJSONObject
+		
+		try {
+			const result = await resetAndStart(subOrder)
+			const resultObj = result as UTSJSONObject
+			const code = resultObj['code'] as number
+			if (code == 200) {
+				uni.showToast({
+					title: '挂起成功',
+					icon: 'success'
+				})
+				hasDealed.value = true
+
+				// 使用事件总线通知列表页面刷新
+				uni.$emit('refreshOrderList', {})
+				uni.$emit('refreshAssignedCount')
+				uni.$emit('refreshOverdueCount')
+				// 接单成功后返回上一页
+				setTimeout(() => {
+					uni.navigateBack()
+				}, 800)
+			} else {
+			    // 处理业务错误
+			    uni.showToast({
+				    title: resultObj['msg'] as string,
+				    icon: 'none'
+			    })
+			}
+		} catch (error: any) {
+		    console.error('请求失败:', error);
+			uni.showToast({
+			    title: error.message ?? '挂起失败',
+			    icon: 'none'
+			})
+		} finally {
+			isDealing.value = false // 无论成功失败都解锁
+		}
+
+	}
+
+    const loading = ref<boolean>(false)
+
+    // 加载详情数据
+    const loadDetail = async (id: string, orderType?: string): Promise<void> => {
+        try {
+            loading.value = true
+			
+			await dictList()
+
+            let result: any;
+
+            // 根据orderType决定调用哪个API
+            if (orderType == '1') {
+                // 维修工单
+                result = await getRepairOrderInfoById(id)
+            } else {
+                // 维保工单
+                result = await getOrderInfoById(id)
+            }
+
+            // 提取响应数据
+            const resultObj = result as UTSJSONObject
+			const code = resultObj['code'] as number
+            const data = resultObj['data'] as UTSJSONObject | null
+
+            if (code == 200 && data != null) {
+				workOrderStatus.value = (data['workOrderStatus'] as string | null) ?? ''
+				workOrderProjectNo.value = (data['workOrderProjectNo'] as string | null) ?? ''
+				pcsDeviceName.value = (data['pcsDeviceName'] as string | null) ?? ''
+				gxtCenter.value = (data['gxtCenter'] as string | null) ?? ''
+				pcsStationName.value = (data['pcsStationName'] as string | null) ?? ''
+				brand.value = (data['brand'] as string | null) ?? ''
+				model.value = (data['model'] as string | null) ?? ''
+				acceptTime.value = (data['acceptTime'] as string | null) ?? ''
+				resetMethod.value = (data['resetMethod'] as string | null) ?? ''
+				realFailureReason.value = (data['realFailureReason'] as string | null) ?? ''
+				if (returnTypeOptions.value.length > 0 && resetMethod.value != '') {
+					// 循环匹配
+				    for (const option of returnTypeOptions.value) {
+						// 严格匹配value
+						if (resetMethod.value == option.value) {
+						  returnTypeLabel.value = option.label;
+						  break; // 匹配成功后跳出循环,提升性能
+						}
+					}
+				}
+
+            } else {
+                const msg = resultObj['msg'] as string | null
+                uni.showToast({
+                    title: msg ?? '加载失败',
+                    icon: 'none'
+                })
+            }
+
+        } catch (e: any) {
+            uni.showToast({
+                title: e.message ?? '加载失败',
+                icon: 'none'
+            })
+        } finally {
+            loading.value = false
+        }
+    }
+
+    // 页面加载
+    onLoad((options: any) => {
+        const params = options as UTSJSONObject
+        const id = params['id'] as string | null
+		const orderTypeParam = params['orderType'] as string | null
+        if (id != null && orderTypeParam != null) {
+            // 先尝试从参数中获取orderType
+            // const orderTypeNumber = parseInt(orderTypeParam)
+			orderType.value = orderTypeParam
+			orderId.value = id
+            loadDetail(id, orderTypeParam)
+        }
+    })
+	// 初始化
+	onMounted(() => {
+	})
+</script>
+
+<style lang="scss">
+    .detail-page {
+        flex: 1;
+        background-color: #e8f0f9;
+    }
+
+    .detail-content {
+        flex: 1;
+        padding: 20rpx 0;
+    }
+
+    .info-section {
+        margin: 0 30rpx 24rpx;
+
+        .section-title {
+            position: relative;
+            padding-left: 20rpx;
+            margin-bottom: 20rpx;
+
+            &::before {
+                // content: '';
+                position: absolute;
+                left: 0;
+                top: 50%;
+                transform: translateY(-50%);
+                width: 8rpx;
+                height: 32rpx;
+                background-color: #007aff;
+                border-radius: 4rpx;
+            }
+
+            &-text {
+                font-size: 32rpx;
+                font-weight: bold;
+                color: #333333;
+            }
+        }
+
+        .info-card {
+            background-color: #ffffff;
+            border-radius: 16rpx;
+            padding: 30rpx;
+
+            .info-item {
+                flex-direction: row;
+                padding: 20rpx 0;
+                border-bottom: 1rpx solid #f0f0f0;
+
+                &:last-child {
+                    border-bottom: none;
+                }
+
+                &.full-width {
+                    flex-direction: column;
+
+                    .info-label {
+                        margin-bottom: 12rpx;
+                    }
+
+                    .info-value {
+                        line-height: 44rpx;
+                    }
+                }
+
+                .info-label {
+                    width: 240rpx;
+                    font-size: 28rpx;
+                    color: #666666;
+                    white-space: nowrap;
+                }
+
+                .info-value {
+                    flex: 1;
+                    font-size: 28rpx;
+                    color: #333333;
+                    text-align: right;
+
+                    &.highlight {
+                        color: #007aff;
+                        font-weight: bold;
+                    }
+
+                    &.input {
+                        text-align: left;
+                        border: 1rpx solid #e0e0e0;
+                        border-radius: 8rpx;
+                        padding: 10rpx;
+                    }
+                }
+            }
+
+            .flow-item {
+                padding: 20rpx 0;
+                border-bottom: 1rpx solid #f0f0f0;
+
+                &:last-child {
+                    border-bottom: none;
+                }
+
+                .flow-header {
+                    flex-direction: row;
+                    justify-content: space-between;
+                    margin-bottom: 10rpx;
+
+                    .flow-operator {
+                        font-size: 28rpx;
+                        color: #333333;
+                        font-weight: bold;
+                    }
+
+                    .flow-time {
+                        font-size: 24rpx;
+                        color: #999999;
+                    }
+                }
+
+                .flow-content {
+                    flex-direction: column;
+
+                    .flow-action {
+                        font-size: 26rpx;
+                        color: #666666;
+                        margin-bottom: 8rpx;
+                    }
+
+                    .flow-remark {
+                        font-size: 24rpx;
+                        color: #999999;
+                        background-color: #f5f5f5;
+                        padding: 10rpx;
+                        border-radius: 8rpx;
+                    }
+                }
+            }
+
+            .no-data {
+                text-align: center;
+                padding: 40rpx 0;
+                font-size: 28rpx;
+                color: #999999;
+            }
+        }
+    }
+
+    .accept-button-container {
+        padding: 30rpx 30rpx 50rpx;
+        background-color: #ffffff;
+
+        .accept-button {
+            width: 100%;
+            height: 80rpx;
+            background-color: #007aff;
+            color: #ffffff;
+            font-size: 32rpx;
+            border-radius: 16rpx;
+            border: none;
+
+            &:active {
+                background-color: #0062cc;
+            }
+        }
+    }
+
+    .loading-mask {
+        position: absolute;
+        top: 0;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        justify-content: center;
+        align-items: center;
+        background-color: rgba(0, 0, 0, 0.3);
+
+        .loading-text {
+            padding: 30rpx 60rpx;
+            background-color: rgba(0, 0, 0, 0.7);
+            color: #ffffff;
+            font-size: 28rpx;
+            border-radius: 12rpx;
+        }
+    }
+	.picker-modal {
+	    position: fixed;
+	    top: 0;
+	    left: 0;
+	    right: 0;
+	    bottom: 0;
+	    z-index: 1000;
+	}
+
+	.modal-mask {
+	    position: absolute;
+	    top: 0;
+	    left: 0;
+	    right: 0;
+	    bottom: 0;
+	    background-color: rgba(0, 0, 0, 0.5);
+	}
+
+	.modal-content {
+	    position: absolute;
+	    bottom: 0;
+	    left: 0;
+	    right: 0;
+	    background-color: #ffffff;
+	    border-top-left-radius: 16rpx;
+	    border-top-right-radius: 16rpx;
+	    min-height: 700rpx;
+	}
+
+	.modal-header {
+	    flex-direction: row;
+	    justify-content: space-between;
+	    align-items: center;
+	    padding: 30rpx;
+	    border-bottom: 1rpx solid #f0f0f0;
+	}
+
+	.modal-title {
+	    font-size: 32rpx;
+	    font-weight: bold;
+	    color: #333333;
+	}
+
+	.modal-close {
+	    font-size: 28rpx;
+	    color: #007aff;
+	}
+
+	.modal-body {
+	    max-height: 600rpx;
+	}
+
+	.picker-option {
+	    flex-direction: row;
+	    justify-content: space-between;
+	    align-items: center;
+	    padding: 24rpx 30rpx;
+	    border-bottom: 1rpx solid #f0f0f0;
+	}
+
+	.picker-option.selected {
+	    background-color: #f8f9fa;
+	}
+
+	.option-text {
+	    font-size: 28rpx;
+	    color: #333333;
+	}
+
+	.option-check {
+	    font-size: 28rpx;
+	    color: #007aff;
+	}
+
+	.form-picker {
+	    flex: 1;
+	}
+
+	.picker-display {
+	    flex-direction: row;
+	    justify-content: space-between;
+	    align-items: center;
+	    min-height: 40rpx;
+	}
+
+	.selected-value {
+	    font-size: 28rpx;
+	    color: #333333;
+	}
+
+	.placeholder {
+	    font-size: 28rpx;
+	    color: #999999;
+	}
+
+	.arrow {
+	    font-size: 24rpx;
+	    color: #999999;
+	    margin-left: 12rpx;
+	}
+.form-item {
+	flex-direction: row;
+	padding: 20rpx 0;
+	border-bottom: 1rpx solid #f0f0f0;
+}
+</style>
+

+ 670 - 0
pages/order/detail/returnIndex.uvue

@@ -0,0 +1,670 @@
+<template>
+    <view class="detail-page">
+        <scroll-view class="detail-content" :scroll-y="true">
+            <!-- 工单信息 -->
+            <view class="info-section">
+                <view class="section-title">
+                    <text class="section-title-text">工单信息</text>
+                </view>
+                <view class="info-card">
+                    <view class="info-item">
+                        <text class="info-label">工单编码</text>
+                        <text class="info-value">{{ workOrderProjectNo ?? '' }}</text>
+                    </view>
+                    <view class="info-item">
+                        <text class="info-label">工单类型</text>
+                        <text class="info-value">{{ orderType == '1' ? '维修工单' : '维保工单' }}</text>
+                    </view>
+                    <view class="info-item">
+                        <text class="info-label">风机编号</text>
+                        <text class="info-value">{{ pcsDeviceName ?? '' }}</text>
+                    </view>
+					<view class="info-item">
+					    <text class="info-label">维保中心</text>
+					    <text class="info-value">{{ gxtCenter ?? '' }}</text>
+					</view>
+                    <view class="info-item">
+                        <text class="info-label">场站</text>
+                        <text class="info-value">{{ pcsStationName ?? '' }}</text>
+                    </view>
+					<!-- <view class="info-item">
+					    <text class="info-label">品牌</text>
+					    <text class="info-value">{{ detailData.model ?? '' }}</text>
+					</view> -->
+                    <view class="info-item">
+                        <text class="info-label">机型</text>
+                        <text class="info-value">{{ brand ?? '' }} {{ model ?? '' }}</text>
+                    </view>
+					<view class="info-item">
+					    <text class="info-label">接单时间</text>
+					    <text class="info-value">{{ acceptTime ?? '' }}</text>
+					</view>
+					<!-- <view class="info-item">
+					    <text class="info-label">挂起原因</text>
+					    <view class="form-picker" @click="showReasonPicker = true">
+					        <view class="picker-display">
+					            <text v-if="suspendReason" class="selected-value">{{ suspendReason }}</text>
+					            <text v-else class="placeholder">请选择挂起原因</text>
+					            <text class="arrow">▼</text>
+					        </view>
+					    </view>
+					</view> -->
+                </view>
+            </view>
+			<!-- <view class="info-section">
+				<view class="section-title">
+					<text class="section-title-text">工作负责人</text>
+				</view>
+				<view class="info-card">
+					<view class="info-item">
+						<input class="input" type="text" placeholder="请输入工作负责人" v-model="teamLeaderName" />
+					</view>
+				</view>
+			</view> -->
+			<!-- 工作负责人选择 -->
+			<view class="info-section">
+			    <!-- <view class="section-title">
+			        <text class="section-title-text">退回类型</text>
+			    </view> -->
+			    <view class="info-card">
+			        <view class="info-item">
+						<view class="info-label">
+							<text class="form-label required">退回类型</text>
+						</view>
+						<view class="info-value">
+						    <view class="form-picker" @click="showReasonPicker = true">
+						        <view class="picker-display">
+						            <text v-if="returnType" class="selected-value">{{ returnTypeLabel }}</text>
+						            <text v-else class="placeholder">请选择退回类型</text>
+						            <text class="arrow">▼</text>
+						        </view>
+						    </view>
+						</view>
+					</view>
+					<view class="info-item">
+						<view class="info-label">
+							<text class="form-label required">退回原因</text>
+						</view>
+						<view class="info-value">
+							 <textarea
+								class="reject-reason-textarea"
+								placeholder="请输入退回原因(必填)"
+								v-model="returnReason"
+								maxlength="100"
+								:show-confirm-bar="false"
+								auto-height
+							></textarea>
+						</view>
+					</view>
+			    </view>
+			</view>
+
+			<!-- 自定义选择器弹窗 -->
+			<view v-if="showReasonPicker" class="picker-modal">
+			    <view class="modal-mask" @click="showReasonPicker = false"></view>
+			    <view class="modal-content">
+			        <view class="modal-header">
+			            <text class="modal-title">退回类型</text>
+			            <text class="modal-close" @click="showReasonPicker = false">取消</text>
+			        </view>
+			        <scroll-view class="modal-body" scroll-y="true">
+			            <view
+			                v-for="(option, index) in returnTypeOptions"
+			                :key="index"
+			                class="picker-option"
+			                :class="{ 'selected': index === selectedReasonIndex }"
+			                @click="selectLeaderManually(index)"
+			            >
+			                <text class="option-text">{{ option.label }}</text>
+			                <text v-if="index === selectedReasonIndex" class="option-check">✓</text>
+			            </view>
+			        </scroll-view>
+			    </view>
+			</view>
+        </scroll-view>
+
+        <!-- 接单按钮 -->
+            <view class="accept-button-container" v-if="checkPermi(orderType == '2' ? ['gxt:maintenance:order:suspend'] : ['gxt:repairOrder:suspend'])">
+            <button class="accept-button" @click="handleSuspendOrder">{{ isDealing ? '退回中...' : '退 回' }}</button>
+        </view>
+
+        <!-- 加载中状态 -->
+        <view v-if="loading" class="loading-mask">
+            <text class="loading-text">加载中...</text>
+        </view>
+    </view>
+</template>
+
+<script setup lang="uts">
+    import { ref } from 'vue'
+    import type { acceptOrderInfo } from '../../../types/order'
+    import type { WorkOrderFlow } from '../../../types/flow'
+    import { getOrderInfoById, getRepairOrderInfoById, returnRepairOrder } from '../../../api/order/detail'
+	import type { SysDictData } from '../../../types/dict'
+	import { getDictDataByType } from '../../../api/dict/index'
+	import { getUserList } from '../../../api/user/list'
+	import type { UserInfo } from '../../../types/user'
+	import {checkPermi} from '../../../utils/storage'
+
+	// 工单信息
+	const orderId = ref<string>('')
+	const workOrderProjectNo = ref<string>('')
+	const workOrderStatus = ref<string>('')
+	const orderType = ref<string>('')
+	const pcsDeviceName = ref<string>('')
+	const gxtCenter = ref<string>('')
+	const pcsStationName = ref<string>('')
+	const brand = ref<string>('')
+	const model = ref<string>('')
+	const acceptTime = ref<string>('')
+	const returnType = ref<string>('')
+	const returnReason = ref<string>("")
+	const returnTypeLabel = ref<string>("")
+	
+	const teamLeaderName = ref<string>("")
+	// 添加字典加载状态
+	const dictLoaded = ref<boolean>(false)
+	
+	// 选择器选项类型
+	type PickerOption = {
+	    label: string
+	    value: string
+	}
+
+	// 选中的挂起原因
+	
+	const selectedReasonIndex = ref<number>(-1)
+	const returnTypeOptions = ref<PickerOption[]>([])
+	const showReasonPicker = ref<boolean>(false)
+
+	// 获取负责人列表(使用用户列表接口)
+	const dictList = async (): Promise<void> => {
+	    try {
+	        const result = await getDictDataByType('gxt_return_type')
+	        const resultObj = result as UTSJSONObject
+
+	        if (resultObj['code'] == 200) {
+				const data = resultObj['data'] as any[]
+				const options: PickerOption[] = []
+	            if (data.length > 0) {
+	                for (let i = 0; i < data.length; i++) {
+	                    const item = data[i] as UTSJSONObject
+	                    let dictItem: SysDictData = {
+							dictValue: item['dictValue'] as string | null,
+							dictLabel: item['dictLabel'] as string | null,
+							dictCode: null,
+							dictSort: null,
+							dictType: null,
+							cssClass: null,
+							listClass: null,
+							isDefault: null,
+							status: null,
+							default: null,
+							createTime: null,
+							remark: null
+	                    }
+						// 构建选择器选项
+						options.push({
+							label: dictItem.dictLabel ?? '',
+							value: dictItem.dictValue ?? ''
+						})
+	                }
+	            }
+
+				returnTypeOptions.value = options
+	        }
+	    } catch (e: any) {
+	        console.error('获取挂起原因失败:', e.message)
+	    }
+	}
+
+	// 手动选择负责人
+	const selectLeaderManually = (index: number): void => {
+	    selectedReasonIndex.value = index
+	    if (index >= 0 && index < returnTypeOptions.value.length) {
+	        const selectedOption = returnTypeOptions.value[index]
+	        returnTypeLabel.value = selectedOption.label
+			returnType.value = selectedOption.value
+	    }
+	    showReasonPicker.value = false
+	}
+
+	const isDealing = ref(false)
+	const hasDealed = ref(false)
+	// 处理接单操作
+	const handleSuspendOrder = async (): Promise<void> => {
+		if (returnType.value == '') {
+			uni.showToast({
+				title: '请选择退回类型',
+				icon: 'none'
+			})
+			return
+		}
+		if (returnReason.value == '' || returnReason.value.trim() === '') {
+			uni.showToast({
+				title: '请选输入退回原因',
+				icon: 'none'
+			})
+			return
+		}
+		if (isDealing.value || hasDealed.value) return // 双重保险
+		isDealing.value = true
+		const subOrder = {
+			id: orderId.value,
+			orderType: orderType.value,
+			workOrderProjectNo: workOrderProjectNo.value,
+			workOrderStatus: workOrderStatus.value,
+			returnType: returnType.value,
+			returnReason: returnReason.value
+			// gxtRepairOrder:
+		} as UTSJSONObject
+		
+		try {
+			const result = await returnRepairOrder(subOrder)
+			const resultObj = result as UTSJSONObject
+			const code = resultObj['code'] as number
+			if (code == 200) {
+				uni.showToast({
+					title: '挂起成功',
+					icon: 'success'
+				})
+				hasDealed.value = true
+
+				// 使用事件总线通知列表页面刷新
+				uni.$emit('refreshOrderList', {})
+				uni.$emit('refreshAssignedCount')
+				uni.$emit('refreshOverdueCount')
+				// 接单成功后返回上一页
+				setTimeout(() => {
+					uni.navigateBack()
+				}, 800)
+			} else {
+			    // 处理业务错误
+			    uni.showToast({
+				    title: resultObj['msg'] as string,
+				    icon: 'none'
+			    })
+			}
+		} catch (error: any) {
+		    console.error('请求失败:', error);
+			uni.showToast({
+			    title: error.message ?? '挂起失败',
+			    icon: 'none'
+			})
+		} finally {
+			isDealing.value = false // 无论成功失败都解锁
+		}
+
+	}
+
+    const loading = ref<boolean>(false)
+
+    // 加载详情数据
+    const loadDetail = async (id: string, orderType?: string): Promise<void> => {
+        try {
+            loading.value = true
+			
+			await dictList()
+
+            let result: any;
+
+            // 根据orderType决定调用哪个API
+            if (orderType == '1') {
+                // 维修工单
+                result = await getRepairOrderInfoById(id)
+            } else {
+                // 维保工单
+                result = await getOrderInfoById(id)
+            }
+
+            // 提取响应数据
+            const resultObj = result as UTSJSONObject
+			const code = resultObj['code'] as number
+            const data = resultObj['data'] as UTSJSONObject | null
+
+            if (code == 200 && data != null) {
+				workOrderStatus.value = (data['workOrderStatus'] as string | null) ?? ''
+				workOrderProjectNo.value = (data['workOrderProjectNo'] as string | null) ?? ''
+				pcsDeviceName.value = (data['pcsDeviceName'] as string | null) ?? ''
+				gxtCenter.value = (data['gxtCenter'] as string | null) ?? ''
+				pcsStationName.value = (data['pcsStationName'] as string | null) ?? ''
+				brand.value = (data['brand'] as string | null) ?? ''
+				model.value = (data['model'] as string | null) ?? ''
+				acceptTime.value = (data['acceptTime'] as string | null) ?? ''
+				returnType.value = (data['returnType'] as string | null) ?? ''
+				returnReason.value = (data['returnReason'] as string | null) ?? ''
+				if (returnTypeOptions.value.length > 0 && returnType.value != '') {
+					// 循环匹配
+				    for (const option of returnTypeOptions.value) {
+						// 严格匹配value
+						if (returnType.value == option.value) {
+						  returnTypeLabel.value = option.label;
+						  break; // 匹配成功后跳出循环,提升性能
+						}
+					}
+				}
+
+            } else {
+                const msg = resultObj['msg'] as string | null
+                uni.showToast({
+                    title: msg ?? '加载失败',
+                    icon: 'none'
+                })
+            }
+
+        } catch (e: any) {
+            uni.showToast({
+                title: e.message ?? '加载失败',
+                icon: 'none'
+            })
+        } finally {
+            loading.value = false
+        }
+    }
+
+    // 页面加载
+    onLoad((options: any) => {
+        const params = options as UTSJSONObject
+        const id = params['id'] as string | null
+		const orderTypeParam = params['orderType'] as string | null
+        if (id != null && orderTypeParam != null) {
+            // 先尝试从参数中获取orderType
+            // const orderTypeNumber = parseInt(orderTypeParam)
+			orderType.value = orderTypeParam
+			orderId.value = id
+            loadDetail(id, orderTypeParam)
+        }
+    })
+	// 初始化
+	onMounted(() => {
+	})
+</script>
+
+<style lang="scss">
+    .detail-page {
+        flex: 1;
+        background-color: #e8f0f9;
+    }
+
+    .detail-content {
+        flex: 1;
+        padding: 20rpx 0;
+    }
+
+    .info-section {
+        margin: 0 30rpx 24rpx;
+
+        .section-title {
+            position: relative;
+            padding-left: 20rpx;
+            margin-bottom: 20rpx;
+
+            &::before {
+                // content: '';
+                position: absolute;
+                left: 0;
+                top: 50%;
+                transform: translateY(-50%);
+                width: 8rpx;
+                height: 32rpx;
+                background-color: #007aff;
+                border-radius: 4rpx;
+            }
+
+            &-text {
+                font-size: 32rpx;
+                font-weight: bold;
+                color: #333333;
+            }
+        }
+
+        .info-card {
+            background-color: #ffffff;
+            border-radius: 16rpx;
+            padding: 30rpx;
+
+            .info-item {
+                flex-direction: row;
+                padding: 20rpx 0;
+                border-bottom: 1rpx solid #f0f0f0;
+
+                &:last-child {
+                    border-bottom: none;
+                }
+
+                &.full-width {
+                    flex-direction: column;
+
+                    .info-label {
+                        margin-bottom: 12rpx;
+                    }
+
+                    .info-value {
+                        line-height: 44rpx;
+                    }
+                }
+
+                .info-label {
+                    width: 240rpx;
+                    font-size: 28rpx;
+                    color: #666666;
+                    white-space: nowrap;
+                }
+
+                .info-value {
+                    flex: 1;
+                    font-size: 28rpx;
+                    color: #333333;
+                    text-align: right;
+
+                    &.highlight {
+                        color: #007aff;
+                        font-weight: bold;
+                    }
+
+                    &.input {
+                        text-align: left;
+                        border: 1rpx solid #e0e0e0;
+                        border-radius: 8rpx;
+                        padding: 10rpx;
+                    }
+                }
+            }
+
+            .flow-item {
+                padding: 20rpx 0;
+                border-bottom: 1rpx solid #f0f0f0;
+
+                &:last-child {
+                    border-bottom: none;
+                }
+
+                .flow-header {
+                    flex-direction: row;
+                    justify-content: space-between;
+                    margin-bottom: 10rpx;
+
+                    .flow-operator {
+                        font-size: 28rpx;
+                        color: #333333;
+                        font-weight: bold;
+                    }
+
+                    .flow-time {
+                        font-size: 24rpx;
+                        color: #999999;
+                    }
+                }
+
+                .flow-content {
+                    flex-direction: column;
+
+                    .flow-action {
+                        font-size: 26rpx;
+                        color: #666666;
+                        margin-bottom: 8rpx;
+                    }
+
+                    .flow-remark {
+                        font-size: 24rpx;
+                        color: #999999;
+                        background-color: #f5f5f5;
+                        padding: 10rpx;
+                        border-radius: 8rpx;
+                    }
+                }
+            }
+
+            .no-data {
+                text-align: center;
+                padding: 40rpx 0;
+                font-size: 28rpx;
+                color: #999999;
+            }
+        }
+    }
+
+    .accept-button-container {
+        padding: 30rpx 30rpx 50rpx;
+        background-color: #ffffff;
+
+        .accept-button {
+            width: 100%;
+            height: 80rpx;
+            background-color: #007aff;
+            color: #ffffff;
+            font-size: 32rpx;
+            border-radius: 16rpx;
+            border: none;
+
+            &:active {
+                background-color: #0062cc;
+            }
+        }
+    }
+
+    .loading-mask {
+        position: absolute;
+        top: 0;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        justify-content: center;
+        align-items: center;
+        background-color: rgba(0, 0, 0, 0.3);
+
+        .loading-text {
+            padding: 30rpx 60rpx;
+            background-color: rgba(0, 0, 0, 0.7);
+            color: #ffffff;
+            font-size: 28rpx;
+            border-radius: 12rpx;
+        }
+    }
+	.picker-modal {
+	    position: fixed;
+	    top: 0;
+	    left: 0;
+	    right: 0;
+	    bottom: 0;
+	    z-index: 1000;
+	}
+
+	.modal-mask {
+	    position: absolute;
+	    top: 0;
+	    left: 0;
+	    right: 0;
+	    bottom: 0;
+	    background-color: rgba(0, 0, 0, 0.5);
+	}
+
+	.modal-content {
+	    position: absolute;
+	    bottom: 0;
+	    left: 0;
+	    right: 0;
+	    background-color: #ffffff;
+	    border-top-left-radius: 16rpx;
+	    border-top-right-radius: 16rpx;
+	    min-height: 700rpx;
+	}
+
+	.modal-header {
+	    flex-direction: row;
+	    justify-content: space-between;
+	    align-items: center;
+	    padding: 30rpx;
+	    border-bottom: 1rpx solid #f0f0f0;
+	}
+
+	.modal-title {
+	    font-size: 32rpx;
+	    font-weight: bold;
+	    color: #333333;
+	}
+
+	.modal-close {
+	    font-size: 28rpx;
+	    color: #007aff;
+	}
+
+	.modal-body {
+	    max-height: 600rpx;
+	}
+
+	.picker-option {
+	    flex-direction: row;
+	    justify-content: space-between;
+	    align-items: center;
+	    padding: 24rpx 30rpx;
+	    border-bottom: 1rpx solid #f0f0f0;
+	}
+
+	.picker-option.selected {
+	    background-color: #f8f9fa;
+	}
+
+	.option-text {
+	    font-size: 28rpx;
+	    color: #333333;
+	}
+
+	.option-check {
+	    font-size: 28rpx;
+	    color: #007aff;
+	}
+
+	.form-picker {
+	    flex: 1;
+	}
+
+	.picker-display {
+	    flex-direction: row;
+	    justify-content: space-between;
+	    align-items: center;
+	    min-height: 40rpx;
+	}
+
+	.selected-value {
+	    font-size: 28rpx;
+	    color: #333333;
+	}
+
+	.placeholder {
+	    font-size: 28rpx;
+	    color: #999999;
+	}
+
+	.arrow {
+	    font-size: 24rpx;
+	    color: #999999;
+	    margin-left: 12rpx;
+	}
+.form-item {
+	flex-direction: row;
+	padding: 20rpx 0;
+	border-bottom: 1rpx solid #f0f0f0;
+}
+</style>
+

+ 151 - 29
pages/order/index.uvue

@@ -46,7 +46,7 @@
             :hasMore="hasMore"
             @refresh="handleRefresh"
             @loadMore="loadMore"
-            @itemClick="handleItemClick"
+            @itemClick="handleView"
         >
             <template #default="{ item, index }">
                 <view class="list-item">
@@ -63,36 +63,101 @@
 								<text class="text-gray">{{ getDisplayTime(item) }}</text>
 							</view>
 							<view class="info-value">
-								<button
-									v-if="getOrderStatus(item) == 'assigned' && canHandleOrder(item)"
+								<!-- <button
+									v-if="getOrderStatus(item) == 'assigned' && canHandleOrder(item,'')"
 									class="btn-primary info-value"
-									@click.stop="handleItemClick(item)"
+									@click.stop="handleItemClick(item,'')"
 									>
 									接单
 								</button>
 								<button
-									v-else-if="getOrderStatus(item) == 'to_approve' && canHandleOrder(item)"
+									v-else-if="getOrderStatus(item) == 'to_approve' && canHandleOrder(item,'')"
 									class="btn-primary info-value"
-									@click.stop="handleItemClick(item)"
+									@click.stop="handleItemClick(item,'')"
 									>
 									审批
 								</button>
 								<button
-									v-else-if="getOrderStatus(item) == 'to_finish' && canHandleOrder(item)"
+									v-else-if="getOrderStatus(item) == 'suspended' && canHandleOrder(item,'')"
 									class="btn-primary info-value"
-									@click.stop="handleItemClick(item)"
+									@click.stop="handleItemClick(item,'')"
 									>
-									挂起
+									恢复
 								</button>
 								<button
-									v-else-if="getOrderStatus(item) == 'suspended' && canHandleOrder(item)"
+									v-else-if="getOrderStatus(item) == 'return' && canHandleOrder(item,'acceptReturn')"
 									class="btn-primary info-value"
-									@click.stop="handleItemClick(item)"
+									@click.stop="handleItemClick(item,'acceptReturn')"
 									>
-									恢复
+									退回
 								</button>
+								<button
+									v-if="getOrderStatus(item) == 'assigned' && canHandleOrder(item,'acceptReturn')"
+									class="btn-primary info-value"
+									@click.stop="handleItemClick(item,'acceptReturn')"
+									>
+									退回
+								</button> -->
 							</view>
 						</view>
+						<view class="btn-group">
+							<button
+								v-if="getOrderStatus(item) == 'assigned' && canHandleOrder(item,'accept')"
+								class="btn-primary info-value"
+								@click.stop="handleItemClick(item,'')"
+								>
+								接单
+							</button>
+							<button
+								v-if="getOrderStatus(item) == 'to_approve' && canHandleOrder(item,'')"
+								class="btn-primary info-value"
+								@click.stop="handleItemClick(item,'')"
+								>
+								审批
+							</button>
+							<button
+								v-if="getOrderStatus(item) == 'suspended' && canHandleOrder(item,'')"
+								class="btn-primary info-value"
+								@click.stop="handleItemClick(item,'')"
+								>
+								恢复
+							</button>
+							<button
+								v-if="getOrderStatus(item) == 'return' && canHandleOrder(item,'acceptReturn')"
+								class="btn-primary info-value"
+								@click.stop="handleItemClick(item,'acceptReturn')"
+								>
+								退回
+							</button>
+							<button
+								v-if="getOrderStatus(item) == 'assigned' && canHandleOrder(item,'acceptReturn')"
+								class="btn-primary info-value"
+								@click.stop="handleItemClick(item,'acceptReturn')"
+								>
+								退回
+							</button>
+							<button
+								v-if="getOrderStatus(item) == 'to_finish' && canHandleOrder(item, 'return')"
+								class="btn-primary info-value"
+								@click.stop="handleItemClick(item, 'return')"
+								>
+								退回
+							</button>
+							<button
+								v-if="getOrderStatus(item) == 'to_finish' && canHandleOrder(item, 'suspend')"
+								class="btn-primary info-value"
+								@click.stop="handleItemClick(item, 'suspend')"
+								>
+								挂起
+							</button>
+							<button
+								v-if="getOrderStatus(item) == 'to_finish' && canHandleOrder(item, 'finalize')"
+								class="btn-primary info-value"
+								@click.stop="handleItemClick(item, 'finalize')"
+								>
+								复启
+							</button>
+						</view>
                     </view>
                 </view>
             </template>
@@ -452,23 +517,39 @@ const statusConfig: StatusItem[] = [
 	}
 
 	// 方法:判断当前工单是否显示操作按钮(基于 orderType)
-	const canHandleOrder = (item: any | null): boolean => {
+	const canHandleOrder = (item: any | null, buttonType: string | ''): boolean => {
 	  if (item == null) return false
 	  let permit: string[] = []
 	  const orderItem = item as acceptOrderInfo
-	  if(orderItem.workOrderStatus == 'assigned') {
-	  	// 接单
-	  	permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:accept'] : ['gxt:repairOrder:accept']
+	  if(orderItem.workOrderStatus == 'assigned' && buttonType != '' && buttonType == "acceptReturn" && orderItem.orderType == 1) {
+			// 接单退回
+			permit = ['gxt:repairOrder:acceptReturn']
+	  } else if(orderItem.workOrderStatus == 'assigned' && buttonType != '' && buttonType == "accept") {
+		  // 接单
+		  permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:accept'] : ['gxt:repairOrder:accept']
 	  } else if(orderItem.workOrderStatus == 'to_finish') {
-	  	// 挂起
-	  	permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:suspend'] : ['gxt:repairOrder:suspend']
+		  if(buttonType != '' && buttonType == "suspend") {
+			  // 挂起
+			  permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:suspend'] : ['gxt:repairOrder:suspend']
+		  } else if(buttonType != '' && buttonType == "return" && orderItem.orderType == 1) {
+			  // 退回
+			  permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:return'] : ['gxt:repairOrder:return']
+		  } else if(buttonType != '' && buttonType == "finalize" && orderItem.orderType == 1) {
+			  // 复启
+			  permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:finalize'] : ['gxt:repairOrder:finalize']
+		  }
+	  	
 	  } else if(orderItem.workOrderStatus == 'to_approve') {
 	  	// 审批
 	  	permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:approve'] : ['gxt:repairOrder:approve']
 	  } else if(orderItem.workOrderStatus == 'suspended') {
 	  	// 恢复
 	  	permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:resume'] : ['gxt:repairOrder:resume']
-	  } else {
+	  } else if(orderItem.workOrderStatus == 'return') {
+	  	// 接单退回
+	  	permit = ['gxt:repairOrder:acceptReturn']
+	  }
+	   else {
 		  return false
 	  }
 
@@ -478,7 +559,7 @@ const statusConfig: StatusItem[] = [
 
 
     // 点击列表项
-    const handleItemClick = (item: any | null): void => {
+    const handleItemClick = (item: any | null, buttonType: string | ''): void => {
         if (item == null) return
         const orderItem = item as acceptOrderInfo
 		// if(currentStatus.value === '' || currentStatus.value === 'completed' || currentStatus.value === 'all') {
@@ -488,15 +569,34 @@ const statusConfig: StatusItem[] = [
 		// 	})
 		// } else
 		if(orderItem.workOrderStatus == 'assigned') {
-			// 跳转到接单页面
-			uni.navigateTo({
-			    url: `/pages/order/detail/acceptIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
-			})
+			if(buttonType != '' && buttonType == "acceptReturn") {
+				// 跳转到退回页面
+				uni.navigateTo({
+					url: `/pages/order/detail/returnIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
+				})
+			} else {
+				// 跳转到接单页面
+				uni.navigateTo({
+				    url: `/pages/order/detail/acceptIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
+				})
+			}
 		} else if(orderItem.workOrderStatus == 'to_finish') {
-			// 跳转到待结单页面
-			uni.navigateTo({
-			    url: `/pages/order/detail/suspendIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
-			})
+			if(buttonType != '' && buttonType == "suspend") {
+				// 跳转到待结单页面
+				uni.navigateTo({
+					url: `/pages/order/detail/suspendIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
+				})
+			} else if(buttonType != '' && buttonType == "return") {
+				// 跳转到退回页面
+				uni.navigateTo({
+					url: `/pages/order/detail/returnIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
+				})
+			} else if(buttonType != '' && buttonType == "finalize") {
+				// 跳转到复启页面
+				uni.navigateTo({
+					url: `/pages/order/detail/resetIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
+				})
+			}
 		} else if(orderItem.workOrderStatus == 'to_approve') {
 			// 跳转到待审批页面
 			uni.navigateTo({
@@ -507,6 +607,11 @@ const statusConfig: StatusItem[] = [
 			uni.navigateTo({
 			    url: `/pages/order/detail/resumeIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
 			})
+		} else if(orderItem.workOrderStatus == 'return') {
+			// 跳转到退回页面
+			uni.navigateTo({
+			    url: `/pages/order/detail/returnIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
+			})
 		} else {
 			uni.navigateTo({
 				url: `/pages/order/detail/index?id=${orderItem.id}&orderType=${orderItem.orderType}`
@@ -514,6 +619,16 @@ const statusConfig: StatusItem[] = [
 		}
 
     }
+	
+	// 点击列表项
+	const handleView = (item: any | null): void => {
+	    if (item == null) return
+	    const orderItem = item as acceptOrderInfo
+		uni.navigateTo({
+			url: `/pages/order/detail/index?id=${orderItem.id}&orderType=${orderItem.orderType}`
+		})
+	
+	}
 
     // 查看工单详情
     const showWorkOrderDetail = (item: any | null): void => {
@@ -683,7 +798,7 @@ const statusConfig: StatusItem[] = [
 		z-index: 999;
 		border-radius: 10rpx;
 		font-size: 24rpx;
-		white-space: nowrap;
+		// white-space: nowrap;
 		margin-left: 20rpx;
 		background-color: #165DFF;
 		line-height: 45rpx;
@@ -834,4 +949,11 @@ const statusConfig: StatusItem[] = [
 	color: #fff;
   }
 }
+
+.btn-group {
+  flex-direction: row;
+  align-items: center;
+  justify-content: flex-end;
+  margin-top: 20rpx;
+}
 </style>

+ 0 - 1
utils/storage.uts

@@ -132,7 +132,6 @@ export const checkPermi = (value: string[]): boolean => {
 
     return hasPermission
   } else {
-    console.error(`need roles! Like checkPermi="['system:user:add','system:user:edit']"`)
     return false
   }
 }