Przeglądaj źródła

Merge remote-tracking branch 'origin/master'

ouyj 4 miesięcy temu
rodzic
commit
a2d8e3ecd4

+ 33 - 0
api/order/detail.uts

@@ -36,3 +36,36 @@ export const acceptOrder = (gxtWorkOrder: acceptOrderInfo | null): Promise<any>
 		data: data
 	})
 }
+
+// 挂起
+export const suspendOrder = (gxtWorkOrder: acceptOrderInfo | 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/suspend`,
+		method: 'PUT',
+		data: data
+	})
+}
+
+// 审批
+export const approveOrder = (gxtWorkOrder: acceptOrderInfo | 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/approve`,
+		method: 'PUT',
+		data: data
+	})
+}
+
+// 
+export const resumeOrder = (gxtWorkOrder: acceptOrderInfo | 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/resume`,
+		method: 'PUT',
+		data: data
+	})
+}

+ 20 - 8
pages/order/detail/acceptIndex.uvue

@@ -19,17 +19,25 @@
                         <text class="info-label">风机编号</text>
                         <text class="info-value">{{ detailData.pcsDeviceName ?? '' }}</text>
                     </view>
+					<view class="info-item">
+					    <text class="info-label">维保中心</text>
+					    <text class="info-value">{{ detailData.gxtCenter ?? '' }}</text>
+					</view>
                     <view class="info-item">
                         <text class="info-label">场站</text>
                         <text class="info-value">{{ detailData.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">{{ detailData.brand ?? '' }} {{ detailData.model ?? '' }}</text>
                     </view>
 					<view class="info-item">
-					    <text class="info-label">创建时间</text>
-					    <text class="info-value">{{ detailData.createTime ?? '' }}</text>
+					    <text class="info-label">下发时间</text>
+					    <text class="info-value">{{ detailData.assignTime ?? '' }}</text>
 					</view>
 
                 </view>
@@ -111,7 +119,7 @@
 
         <!-- 接单按钮 -->
         <view class="accept-button-container">
-            <button class="accept-button" @click="handleAcceptOrder">接单</button>
+            <button class="accept-button" @click="handleAcceptOrder">接 单</button>
         </view>
 
         <!-- 加载中状态 -->
@@ -159,7 +167,9 @@
 		brand: null,
 		model: null,
 		createTime: null,
-		workOrderFlowList: null
+		workOrderFlowList: null,
+		suspendReason: null,
+		rejectionReason: null
 	})
 
 	// 选择器选项类型
@@ -273,7 +283,7 @@
 
 	// 处理接单操作
 	const handleAcceptOrder = async (): Promise<void> => {
-		if (selectedTeamLeaderName.value == null || selectedTeamLeaderName.value.trim() === '') {
+		if (selectedTeamLeaderName.value.trim() === '') {
 			uni.showToast({
 				title: '请选择工作负责人',
 				icon: 'none'
@@ -367,7 +377,7 @@
 				    // 维保工单
 				    flowList = data['workOrderFlowList'] as UTSJSONObject[]
 				}
-                if (flowList != null) {
+                if (flowList.length > 0 && flowList != null) {
                     workOrderFlowList = []
                     for (let i = 0; i < flowList.length; i++) {
                         const flowItem = flowList[i]
@@ -412,7 +422,9 @@
                     brand: data['brand'] as string | null,
                     model: data['model'] as string | null,
                     createTime: data['createTime'] as string | null,
-                    workOrderFlowList: workOrderFlowList
+                    workOrderFlowList: workOrderFlowList,
+					suspendReason: data['suspendReason'] as string | null,
+					rejectionReason: data['rejectionReason'] as string | null
                 }
                 detailData.value = orderDtail
 
@@ -601,7 +613,7 @@
     }
 
     .accept-button-container {
-        padding: 20rpx 30rpx;
+        padding: 30rpx 30rpx 50rpx;
         background-color: #ffffff;
 
         .accept-button {

+ 758 - 0
pages/order/detail/approveIndex.uvue

@@ -0,0 +1,758 @@
+<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">{{ detailData.workOrderProjectNo ?? '' }}</text>
+                    </view>
+                    <view class="info-item">
+                        <text class="info-label">工单类型</text>
+                        <text class="info-value">{{ detailData.orderType == 1 ? '维修工单' : '维保工单' }}</text>
+                    </view>
+                    <view class="info-item">
+                        <text class="info-label">风机编号</text>
+                        <text class="info-value">{{ detailData.pcsDeviceName ?? '' }}</text>
+                    </view>
+					<view class="info-item">
+					    <text class="info-label">维保中心</text>
+					    <text class="info-value">{{ detailData.gxtCenter ?? '' }}</text>
+					</view>
+                    <view class="info-item">
+                        <text class="info-label">场站</text>
+                        <text class="info-value">{{ detailData.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">{{ detailData.brand ?? '' }} {{ detailData.model ?? '' }}</text>
+                    </view>
+					<view class="info-item">
+					    <text class="info-label">下发时间</text>
+					    <text class="info-value">{{ detailData.assignTime ?? '' }}</text>
+					</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="form-item">
+			             <textarea 
+							class="reject-reason-textarea"
+							placeholder="请输入审批意见(必填)"
+							v-model="rejectReason"
+							maxlength="100"
+							:show-confirm-bar="false"
+							auto-height
+						></textarea>
+			        </view>
+			    </view>
+			</view>
+
+
+            <!-- 工单流转 -->
+            <!-- <view class="info-section">
+                <view class="section-title">
+                    <text class="section-title-text">工单流转</text>
+                </view>
+                <view class="info-card" v-if="detailData.workOrderFlowList != null && detailData.workOrderFlowList.length > 0">
+                    <view class="flow-item" v-for="(flow, index) in detailData.workOrderFlowList" :key="index">
+                        <view class="flow-header">
+                            <text class="flow-operator">{{ flow.operatorName ?? '未知操作人' }}</text>
+                            <text class="flow-time">{{ flow.actionTime ?? '' }}</text>
+                        </view>
+                        <view class="flow-content">
+                            <text class="flow-action">{{ getActionTypeName(flow.actionType) }}</text>
+                            <text class="flow-remark" v-if="flow.actionRemark">{{ flow.actionRemark }}</text>
+                        </view>
+                    </view>
+                </view>
+                <view class="info-card" v-else>
+                    <view class="no-data">暂无流转记录</view>
+                </view>
+            </view> -->
+        </scroll-view>
+
+        <!-- 接单按钮 -->
+        <view class="accept-button-container">
+			<button class="reject-btn" @click="handleRejectOrder">驳回</button>
+            <button class="accept-button" @click="handleAcceptOrder">通过</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, approveOrder } 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'
+
+	const teamLeaderName = ref<string>("")
+	const statusDictList = ref<SysDictData[]>([]) // 工单状态字典列表
+	// 添加字典加载状态
+	const dictLoaded = ref<boolean>(false)
+
+	// 详情数据
+	const detailData = ref<acceptOrderInfo>({
+		orderType: 0,
+		id: 0,
+		teamLeaderId: 0,
+		acceptUserId: 0,
+		teamLeaderName: null,
+		acceptUserName: null,
+		acceptTime: null,
+		assignTime:  null,
+		assignUserName: null,
+		status: 0,
+		workOrderProjectNo: null,
+		workOrderStatus: null,
+		gxtCenterId: 0,
+		gxtCenter: null,
+		pcsStationId:  0,
+		pcsStationName: null,
+		pcsDeviceId: 0,
+		pcsDeviceName: null,
+		brand: null,
+		model: null,
+		createTime: null,
+		workOrderFlowList: null,
+		suspendReason: null,
+		rejectionReason: null
+	})
+
+	// 选择器选项类型
+	type PickerOption = {
+	    label: string
+	    value: string
+	}
+
+	// 选中的负责人信息
+	const selectedTeamLeaderId = ref<string>('')
+	const rejectReason = ref<string>('')
+	const selectedTeamLeaderIndex = ref<number>(-1)
+	const teamLeaderNameOptions = ref<PickerOption[]>([])
+	const showLeaderPicker = ref<boolean>(false)
+
+	// 获取负责人列表(使用用户列表接口)
+	const loadTeamLeaderList = async (): Promise<void> => {
+	    try {
+			const deptId = detailData.value.gxtCenterId
+	        const result = await getUserList(deptId)
+	        const resultObj = result as UTSJSONObject
+
+	        if (resultObj['code'] == 200) {
+	            const data = resultObj['data'] as any[]
+	            const leaders: UserInfo[] = []
+				const options: PickerOption[] = []
+
+	            if (data.length > 0) {
+	                for (let i = 0; i < data.length; i++) {
+	                    const item = data[i] as UTSJSONObject
+	                    let leader: UserInfo = {
+							userName: item['userName'] as string,
+							nickName: item['nickName'] as string,
+							userId: new Int32Array([item['userId'] != null ? (item['userId'] as number) : 0]),
+							phone: item['phonenumber'] as string,
+							deptName : item['deptName'] != null ? (item['deptName'] as string) : ''
+	                    }
+	                    leaders.push(leader)
+
+						// 构建选择器选项(只使用用户名)
+						options.push({
+						    label: leader.nickName,
+						    value: leader.userId.toString()
+						})
+	                }
+	            }
+
+	            // teamLeaderList.value = leaders
+				teamLeaderNameOptions.value = options
+	        }
+	    } catch (e: any) {
+	        console.error('获取负责人列表失败:', e.message)
+	    }
+	}
+
+	// 获取工单状态字典列表
+	const loadStatusDictList = async (): Promise<void> => {
+	    try {
+	        const result = await getDictDataByType('gxt_repair_order_flow_action_type')
+	        const resultObj = result as UTSJSONObject
+
+	        if (resultObj['code'] == 200) {
+	            const data = resultObj['data'] as any[]
+	            const dictData: SysDictData[] = []
+
+	            if (data.length > 0) {
+	                for (let i = 0; i < data.length; i++) {
+	                    const item = data[i] as UTSJSONObject
+	                    // 只提取需要的字段
+	                    const 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
+						}
+	                    dictData.push(dictItem)
+	                }
+	            }
+
+	            statusDictList.value = dictData
+	            dictLoaded.value = true
+	        }
+	    } catch (e: any) {
+	        console.error('获取工单状态字典失败:', e.message)
+	        dictLoaded.value = true
+	    }
+	}
+
+	// 处理驳回操作
+	const handleRejectOrder = async (): Promise<void> => {
+		if (rejectReason.value.trim() === '' ) {
+			uni.showToast({
+				title: '请输入审批意见',
+				icon: 'none'
+			})
+			return
+		}
+		detailData.value.rejectionReason = rejectReason.value
+		detailData.value.workOrderStatus = 'to_finish'
+		try {
+			const result = await approveOrder(detailData.value)
+			const resultObj = result as UTSJSONObject
+			const code = resultObj['code'] as number
+			if (code == 200) {
+				uni.showToast({
+					title: '审批成功',
+					icon: 'success'
+				})
+
+				// 使用事件总线通知列表页面刷新
+				uni.$emit('refreshOrderList', {})
+				// 审批成功后返回上一页
+				setTimeout(() => {
+					uni.navigateBack()
+				}, 1000)
+			}
+		} catch (error) {
+		  console.error('请求失败:', error);
+		}
+
+	}
+	
+	// 处理接单操作
+	const handleAcceptOrder = async (): Promise<void> => {
+		detailData.value.rejectionReason = rejectReason.value
+		detailData.value.workOrderStatus = 'suspended'
+		try {
+			const result = await approveOrder(detailData.value)
+			const resultObj = result as UTSJSONObject
+			const code = resultObj['code'] as number
+			if (code == 200) {
+				uni.showToast({
+					title: '审批成功',
+					icon: 'success'
+				})
+
+				// 使用事件总线通知列表页面刷新
+				uni.$emit('refreshOrderList', {})
+				// 接单成功后返回上一页
+				setTimeout(() => {
+					uni.navigateBack()
+				}, 1000)
+			}
+		} catch (error) {
+		  console.error('请求失败:', error);
+		}
+	
+	}
+
+
+
+    const loading = ref<boolean>(false)
+
+	// 获取操作类型名称
+	const getActionTypeName = (item: string | null): string | null => {
+	    if (item == null) return ''
+	    // const orderInfoItem = item as orderInfo
+	    const rawStatus = item
+
+	    if (rawStatus==null) return ''
+
+		// 如果字典尚未加载,返回原始值
+		if (!dictLoaded.value) {
+			return rawStatus
+		}
+
+	    // 查找字典中对应的标签
+	    const dictItem = statusDictList.value.find(dict => dict.dictValue == rawStatus)
+	    return dictItem!=null ? dictItem.dictLabel : rawStatus
+	}
+
+    // 加载详情数据
+    const loadDetail = async (id: string, orderType?: number): Promise<void> => {
+        try {
+            loading.value = true
+
+            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) {
+                // 处理工单流转列表
+                let workOrderFlowList: WorkOrderFlow[] | null = null
+				let flowList: UTSJSONObject[] = []
+				if (orderType == 1) {
+				    // 维修工单
+				    flowList = data['repairOrderFlowList'] as UTSJSONObject[]
+				} else {
+				    // 维保工单
+				    flowList = data['workOrderFlowList'] as UTSJSONObject[]
+				}
+                if (flowList.length > 0) {
+                    workOrderFlowList = []
+                    for (let i = 0; i < flowList.length; i++) {
+                        const flowItem = flowList[i]
+                        const flow: WorkOrderFlow = {
+                            id: flowItem['id'] as Number,
+                            orderId: flowItem['orderId'] as Number,
+                            orderCode: flowItem['orderCode'] as string,
+                            actionType: flowItem['actionType'] as string,
+                            fromStatus: flowItem['fromStatus'] as string | null,
+                            toStatus: flowItem['toStatus'] as string,
+                            operatorId: flowItem['operatorId'] as Number | null,
+                            operatorName: flowItem['operatorName'] as string | null,
+                            actionTime: flowItem['actionTime'] as string,
+                            actionRemark: flowItem['actionRemark'] as string | null,
+                            createBy: flowItem['createBy'] as string | null,
+                            createTime: flowItem['createTime'] as string | null
+                        }
+                        workOrderFlowList.push(flow)
+                    }
+                }
+
+                // 转换数据
+                const orderDtail: acceptOrderInfo = {
+                    orderType: data['orderType'] as Number,
+                    id: data['id'] as Number,
+  					teamLeaderId: data['teamLeaderId'] != null ? (data['teamLeaderId'] as Number) : 0,
+  					acceptUserId: data['acceptUserId'] != null ? (data['acceptUserId'] as Number) : 0,
+                    teamLeaderName: data['teamLeaderName'] as string | null,
+                    acceptUserName: data['acceptUserName'] as string | null,
+                    acceptTime: data['acceptTime'] as string | null,
+                    assignTime: data['assignTime'] as string | null,
+                    assignUserName: data['assignUserName'] as string | null,
+                    status: (data['status']==null)?0:data['status'] as Number,
+                    workOrderProjectNo: data['workOrderProjectNo'] as string | null,
+                    workOrderStatus: data['workOrderStatus'] as string | null,
+                    gxtCenterId: data['gxtCenterId'] as Number | 0,
+                    gxtCenter: data['gxtCenter'] as string | null,
+                    pcsStationId: data['pcsStationId'] as Number | 0,
+                    pcsStationName: data['pcsStationName'] as string | null,
+                    pcsDeviceId: data['pcsDeviceId'] as Number | 0,
+                    pcsDeviceName: data['pcsDeviceName'] as string | null,
+                    brand: data['brand'] as string | null,
+                    model: data['model'] as string | null,
+                    createTime: data['createTime'] as string | null,
+                    workOrderFlowList: workOrderFlowList,
+					suspendReason: data['suspendReason'] as string | null,
+					rejectionReason: data['rejectionReason'] as string | null
+                }
+                detailData.value = orderDtail
+
+				// 如果工单数据中已有负责人信息,设置到输入框中
+				if (orderDtail.teamLeaderName != null && orderDtail.teamLeaderName.length > 0) {
+					teamLeaderName.value = orderDtail.teamLeaderName as string
+				}
+				loadTeamLeaderList()
+            } 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)
+            loadDetail(id, orderTypeNumber)
+        }
+    })
+	// 初始化
+	onMounted(() => {
+	    loadStatusDictList()
+	})
+</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;
+		display: flex;
+		flex-direction: row;
+		justify-content: space-between;
+		align-items: center;
+
+        .accept-button {
+            width: 45%;
+            height: 80rpx;
+            background-color: #007aff;
+            color: #ffffff;
+            font-size: 32rpx;
+            border-radius: 16rpx;
+            border: none;
+
+            &:active {
+                background-color: #0062cc;
+            }
+        }
+		.reject-btn {
+		    width: 45%;
+		    height: 80rpx;
+		    background-color: #ff4d4f;
+		    color: #ffffff;
+		    font-size: 32rpx;
+		    border-radius: 16rpx;
+		    border: none;
+		
+		    &:active {
+		        background-color: #d9363e;
+		    }
+		}
+    }
+
+    .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;
+	    max-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;
+	}
+.reject-reason-textarea {
+    width: 100%;
+    min-height: 100rpx;
+    line-height: 1.5;
+}
+</style>
+

+ 7 - 3
pages/order/detail/index.uvue

@@ -47,7 +47,7 @@
                         </view>
                         <view class="flow-content">
                             <text class="flow-action">{{ getActionTypeName(flow.actionType) }}</text>
-                            <text class="flow-remark" v-if="flow.actionRemark">{{ flow.actionRemark }}</text>
+                            <!-- <text class="flow-remark" v-if="flow.actionRemark">{{ flow.actionRemark }}</text> -->
                         </view>
                     </view>
                 </view>
@@ -139,7 +139,9 @@
 		brand: null,
 		model: null,
 		createTime: null,
-		workOrderFlowList: null
+		workOrderFlowList: null,
+		suspendReason: null,
+		rejectionReason: null
     })
 
     const loading = ref<boolean>(false)
@@ -239,7 +241,9 @@
                     brand: data['brand'] as string | null,
                     model: data['model'] as string | null,
                     createTime: data['createTime'] as string | null,
-                    workOrderFlowList: workOrderFlowList
+                    workOrderFlowList: workOrderFlowList,
+					suspendReason: data['suspendReason'] as string | null,
+					rejectionReason: data['rejectionReason'] as string | null
                 }
                 detailData.value = orderDtail
             } else {

+ 740 - 0
pages/order/detail/suspendIndex.uvue

@@ -0,0 +1,740 @@
+<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">{{ detailData.workOrderProjectNo ?? '' }}</text>
+                    </view>
+                    <view class="info-item">
+                        <text class="info-label">工单类型</text>
+                        <text class="info-value">{{ detailData.orderType == 1 ? '维修工单' : '维保工单' }}</text>
+                    </view>
+                    <view class="info-item">
+                        <text class="info-label">风机编号</text>
+                        <text class="info-value">{{ detailData.pcsDeviceName ?? '' }}</text>
+                    </view>
+					<view class="info-item">
+					    <text class="info-label">维保中心</text>
+					    <text class="info-value">{{ detailData.gxtCenter ?? '' }}</text>
+					</view>
+                    <view class="info-item">
+                        <text class="info-label">场站</text>
+                        <text class="info-value">{{ detailData.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">{{ detailData.brand ?? '' }} {{ detailData.model ?? '' }}</text>
+                    </view>
+					<view class="info-item">
+					    <text class="info-label">接单时间</text>
+					    <text class="info-value">{{ detailData.acceptTime ?? '' }}</text>
+					</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="form-item">
+			            <text class="form-label required">挂起原因</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 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 suspendReasonOptions"
+			                :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>
+
+            <!-- 工单流转 -->
+            <!-- <view class="info-section">
+                <view class="section-title">
+                    <text class="section-title-text">工单流转</text>
+                </view>
+                <view class="info-card" v-if="detailData.workOrderFlowList != null && detailData.workOrderFlowList.length > 0">
+                    <view class="flow-item" v-for="(flow, index) in detailData.workOrderFlowList" :key="index">
+                        <view class="flow-header">
+                            <text class="flow-operator">{{ flow.operatorName ?? '未知操作人' }}</text>
+                            <text class="flow-time">{{ flow.actionTime ?? '' }}</text>
+                        </view>
+                        <view class="flow-content">
+                            <text class="flow-action">{{ getActionTypeName(flow.actionType) }}</text>
+                            <text class="flow-remark" v-if="flow.actionRemark">{{ flow.actionRemark }}</text>
+                        </view>
+                    </view>
+                </view>
+                <view class="info-card" v-else>
+                    <view class="no-data">暂无流转记录</view>
+                </view>
+            </view> -->
+        </scroll-view>
+
+        <!-- 接单按钮 -->
+        <view class="accept-button-container">
+            <button class="accept-button" @click="handleSuspendOrder">挂 起</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, suspendOrder } 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'
+
+	const teamLeaderName = ref<string>("")
+	const statusDictList = ref<SysDictData[]>([]) // 工单状态字典列表
+	// 添加字典加载状态
+	const dictLoaded = ref<boolean>(false)
+
+	// 详情数据
+	const detailData = ref<acceptOrderInfo>({
+		orderType: 0,
+		id: 0,
+		teamLeaderId: 0,
+		acceptUserId: 0,
+		teamLeaderName: null,
+		acceptUserName: null,
+		acceptTime: null,
+		assignTime:  null,
+		assignUserName: null,
+		status: 0,
+		workOrderProjectNo: null,
+		workOrderStatus: null,
+		gxtCenterId: 0,
+		gxtCenter: null,
+		pcsStationId:  0,
+		pcsStationName: null,
+		pcsDeviceId: 0,
+		pcsDeviceName: null,
+		brand: null,
+		model: null,
+		createTime: null,
+		workOrderFlowList: null,
+		suspendReason: null,
+		rejectionReason: null
+	})
+
+	// 选择器选项类型
+	type PickerOption = {
+	    label: string
+	    value: string
+	}
+
+	// 选中的挂起原因
+	const suspendReason = ref<string>('')
+	const selectedReasonIndex = ref<number>(-1)
+	const suspendReasonOptions = ref<PickerOption[]>([])
+	const showReasonPicker = ref<boolean>(false)
+
+	// 获取负责人列表(使用用户列表接口)
+	const dictList = async (): Promise<void> => {
+	    try {
+	        const result = await getDictDataByType('gxt_order_suspend_reason')
+	        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 ?? ''
+						})
+	                }
+	            }
+
+				suspendReasonOptions.value = options
+	        }
+	    } catch (e: any) {
+	        console.error('获取挂起原因失败:', e.message)
+	    }
+	}
+
+	// 手动选择负责人
+	const selectLeaderManually = (index: number): void => {
+	    selectedReasonIndex.value = index
+	    if (index >= 0 && index < suspendReasonOptions.value.length) {
+	        const selectedOption = suspendReasonOptions.value[index]
+	        suspendReason.value = selectedOption.label
+			detailData.value.suspendReason = selectedOption.value
+			console.log("=======",detailData.value.suspendReason)
+	    }
+	    showReasonPicker.value = false
+	}
+
+	// 获取工单状态字典列表
+	const loadStatusDictList = async (): Promise<void> => {
+	    try {
+	        const result = await getDictDataByType('gxt_repair_order_flow_action_type')
+	        const resultObj = result as UTSJSONObject
+
+	        if (resultObj['code'] == 200) {
+	            const data = resultObj['data'] as any[]
+	            const dictData: SysDictData[] = []
+
+	            if (data.length > 0) {
+	                for (let i = 0; i < data.length; i++) {
+	                    const item = data[i] as UTSJSONObject
+	                    // 只提取需要的字段
+	                    const 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
+						}
+	                    dictData.push(dictItem)
+	                }
+	            }
+
+	            statusDictList.value = dictData
+	            dictLoaded.value = true
+	        }
+	    } catch (e: any) {
+	        console.error('获取工单状态字典失败:', e.message)
+	        dictLoaded.value = true
+	    }
+	}
+
+	// 处理接单操作
+	const handleSuspendOrder = async (): Promise<void> => {
+		if (suspendReason.value == null || suspendReason.value.trim() === '') {
+			uni.showToast({
+				title: '请选择挂起原因',
+				icon: 'none'
+			})
+			return
+		}
+
+		detailData.value.workOrderStatus = 'to_approve'
+			try {
+				const result = await suspendOrder(detailData.value)
+				const resultObj = result as UTSJSONObject
+				const code = resultObj['code'] as number
+				if (code == 200) {
+					uni.showToast({
+						title: '挂起成功',
+						icon: 'success'
+					})
+
+				// 使用事件总线通知列表页面刷新
+				uni.$emit('refreshOrderList', {})
+				// 接单成功后返回上一页
+				setTimeout(() => {
+					uni.navigateBack()
+				}, 1000)
+			}
+		} catch (error) {
+		  console.error('请求失败:', error);
+		}
+
+	}
+
+    const loading = ref<boolean>(false)
+
+	// 获取操作类型名称
+	const getActionTypeName = (item: string | null): string | null => {
+	    if (item == null) return ''
+	    // const orderInfoItem = item as orderInfo
+	    const rawStatus = item
+
+	    if (rawStatus==null) return ''
+
+		// 如果字典尚未加载,返回原始值
+		if (!dictLoaded.value) {
+			return rawStatus
+		}
+
+	    // 查找字典中对应的标签
+	    const dictItem = statusDictList.value.find(dict => dict.dictValue == rawStatus)
+	    return dictItem!=null ? dictItem.dictLabel : rawStatus
+	}
+
+    // 加载详情数据
+    const loadDetail = async (id: string, orderType?: number): Promise<void> => {
+        try {
+            loading.value = true
+
+            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) {
+                // 处理工单流转列表
+                let workOrderFlowList: WorkOrderFlow[] | null = null
+				let flowList: UTSJSONObject[] = []
+				if (orderType == 1) {
+				    // 维修工单
+				    flowList = data['repairOrderFlowList'] as UTSJSONObject[]
+				} else {
+				    // 维保工单
+				    flowList = data['workOrderFlowList'] as UTSJSONObject[]
+				}
+                if (flowList != null) {
+                    workOrderFlowList = []
+                    for (let i = 0; i < flowList.length; i++) {
+                        const flowItem = flowList[i]
+                        const flow: WorkOrderFlow = {
+                            id: flowItem['id'] as Number,
+                            orderId: flowItem['orderId'] as Number,
+                            orderCode: flowItem['orderCode'] as string,
+                            actionType: flowItem['actionType'] as string,
+                            fromStatus: flowItem['fromStatus'] as string | null,
+                            toStatus: flowItem['toStatus'] as string,
+                            operatorId: flowItem['operatorId'] as Number | null,
+                            operatorName: flowItem['operatorName'] as string | null,
+                            actionTime: flowItem['actionTime'] as string,
+                            actionRemark: flowItem['actionRemark'] as string | null,
+                            createBy: flowItem['createBy'] as string | null,
+                            createTime: flowItem['createTime'] as string | null
+                        }
+                        workOrderFlowList.push(flow)
+                    }
+                }
+
+                // 转换数据
+                const orderDtail: acceptOrderInfo = {
+                    orderType: data['orderType'] as Number,
+                    id: data['id'] as Number,
+  					teamLeaderId: data['teamLeaderId'] != null ? (data['teamLeaderId'] as Number) : 0,
+  					acceptUserId: data['acceptUserId'] != null ? (data['acceptUserId'] as Number) : 0,
+                    teamLeaderName: data['teamLeaderName'] as string | null,
+                    acceptUserName: data['acceptUserName'] as string | null,
+                    acceptTime: data['acceptTime'] as string | null,
+                    assignTime: data['assignTime'] as string | null,
+                    assignUserName: data['assignUserName'] as string | null,
+                    status: (data['status']==null)?0:data['status'] as Number,
+                    workOrderProjectNo: data['workOrderProjectNo'] as string | null,
+                    workOrderStatus: data['workOrderStatus'] as string | null,
+                    gxtCenterId: data['gxtCenterId'] as Number | 0,
+                    gxtCenter: data['gxtCenter'] as string | null,
+                    pcsStationId: data['pcsStationId'] as Number | 0,
+                    pcsStationName: data['pcsStationName'] as string | null,
+                    pcsDeviceId: data['pcsDeviceId'] as Number | 0,
+                    pcsDeviceName: data['pcsDeviceName'] as string | null,
+                    brand: data['brand'] as string | null,
+                    model: data['model'] as string | null,
+                    createTime: data['createTime'] as string | null,
+                    workOrderFlowList: workOrderFlowList,
+					suspendReason: data['suspendReason'] as string | null,
+					rejectionReason: data['rejectionReason'] as string | null
+                }
+                detailData.value = orderDtail
+
+				// 如果工单数据中已有负责人信息,设置到输入框中
+				if (orderDtail.teamLeaderName != null && orderDtail.teamLeaderName.length > 0) {
+					teamLeaderName.value = orderDtail.teamLeaderName as string
+				}
+				dictList()
+            } 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)
+            loadDetail(id, orderTypeNumber)
+        }
+    })
+	// 初始化
+	onMounted(() => {
+	    loadStatusDictList()
+	})
+</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;
+	    max-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;
+	}
+</style>
+

+ 81 - 101
pages/order/index.uvue

@@ -11,13 +11,16 @@
         </view>
 
 		<view class="status-bar">
-			<view class="status-box">
-				<text class="status-txt" :class="{'stauts-sel': currentStatus === ''}" @click="switchStatus('')">全部</text>
-				<text class="status-txt" :class="{'stauts-sel': currentStatus === 'assigned'}" @click="switchStatus('assigned')">待接单</text>
-				<text class="status-txt" :class="{'stauts-sel': currentStatus === 'to_finish'}" @click="switchStatus('to_finish')">待结单</text>
-				<text class="status-txt" :class="{'stauts-sel': currentStatus === 'to_approve'}" @click="switchStatus('to_approve')">待审批</text>
-				<text class="status-txt" :class="{'stauts-sel': currentStatus === 'completed'}" @click="switchStatus('completed')">已完成</text>
-			</view>
+			<scroll-view class="status-scroll" scroll-x="true" show-scrollbar="false">
+				<view class="status-box">
+					<text class="status-txt" :class="{'stauts-sel': currentStatus === ''}" @click="switchStatus('')">全部</text>
+					<text class="status-txt" :class="{'stauts-sel': currentStatus === 'assigned'}" @click="switchStatus('assigned')">待接单</text>
+					<text class="status-txt" :class="{'stauts-sel': currentStatus === 'to_finish'}" @click="switchStatus('to_finish')">待结单</text>
+					<text class="status-txt" :class="{'stauts-sel': currentStatus === 'to_approve'}" @click="switchStatus('to_approve')">待审批</text>
+					<text class="status-txt" :class="{'stauts-sel': currentStatus === 'suspended'}" @click="switchStatus('suspended')">已挂起</text>
+					<text class="status-txt" :class="{'stauts-sel': currentStatus === 'completed'}" @click="switchStatus('completed')">已完成</text>
+				</view>
+			</scroll-view>
 		</view>
         <!-- 列表内容 -->
         <common-list
@@ -39,64 +42,27 @@
 							<text class="item-title">{{ getWorkOrderProjectNo(item) }}-{{ getPcsDeviceName(item) }}{{ getOrderType(item) }}</text>
 							<text class="info-value">{{ getWorkOrderStatus(item) }}</text>
                         </view>
-						<!-- <view class="flex justify-between items-center"> -->
-						<view class="info-card">
-						<!-- <view class="info-item"> -->
-							<view class="info-item">
-								<text class="info-label">{{ getDisplayTime(item) }}</text>
-								<button
-									v-if="currentStatus === 'assigned'"
-									class="info-value btn-primary"
-									@click.stop="acceptOrder(item)">
-									接单
-								</button>
-								<button
-									v-else-if="currentStatus === 'to_approve'"
-									class="info-value btn-primary"
-									@click="approveOrder(item)">
-									审批
-								</button>
+						<view class="info-row">
+							<view class="info-label">
+								<text class="text-gray">{{ getDisplayTime(item) }}</text>
 							</view>
 							<!-- <view class="info-value">
 								<button
 									v-if="currentStatus === 'assigned'"
-									class="btn-primary"
-									@click="acceptOrder(item)">
+									class="btn-primary info-value"
+									@click.stop="acceptOrder(item)"
+									>
 									接单
 								</button>
 								<button
 									v-else-if="currentStatus === 'to_approve'"
-									class="btn-primary"
-									@click="approveOrder(item)">
+									class="btn-primary info-value"
+									@click="approveOrder(item)"
+									>
 									审批
 								</button>
 							</view> -->
 						</view>
-						<!-- </view> -->
-						<!-- </view> -->
-
-                        <!-- <view class="item-info">
-                            <view class="info-row">
-                                <view class="info-item">
-                                    <text class="info-label">工单状态</text>
-                                    <text class="info-value">{{ getWorkOrderStatus(item) }}</text>
-                                </view>
-								<view class="info-item">
-								    <text class="info-label">场站</text>
-								    <text class="info-value">{{ getPcsStationName(item) }}</text>
-								</view>
-							</view>
-                            <view class="info-row">
-                                <view class="info-item">
-                                    <text class="info-label">设备名</text>
-                                    <text class="info-value">{{ getPcsDeviceName(item) }}</text>
-                                </view>
-                                <view class="info-item">
-                                    <text class="info-label">派单时间</text>
-                                    <text class="info-value">{{ getAssignTime(item) }}</text>
-                                </view>
-                            </view>
-                        </view> -->
                     </view>
                 </view>
             </template>
@@ -223,7 +189,9 @@ import { getDictDataByType } from '../../api/dict/index'
                         pcsDeviceName: item['pcsDeviceName'] as string | null,
                         brand: item['brand'] as string | null,
                         model: item['model'] as string | null,
-                        createTime: item['createTime'] as string | null
+                        createTime: item['createTime'] as string | null,
+						suspendReason: item['suspendReason'] as string | null,
+						rejectionReason: item['rejectionReason'] as string | null
                     }
                     newData.push(orderItem)
                 }
@@ -390,16 +358,26 @@ import { getDictDataByType } from '../../api/dict/index'
     const handleItemClick = (item: any | null, index: number): void => {
         if (item == null) return
         const orderItem = item as acceptOrderInfo
-		if(currentStatus.value === '' || currentStatus.value === 'to_finish' || currentStatus.value === 'completed') {
+		if(currentStatus.value === '' || currentStatus.value === 'completed') {
 			// 传递orderType参数以便详情页决定调用哪个API
 			uni.navigateTo({
 			    url: `/pages/order/detail/index?id=${orderItem.id}&orderType=${orderItem.orderType}`
 			})
-		// } else if(currentStatus.value === 'assigned') {
-		// 	// 跳转到接单页面
-		// 	uni.navigateTo({
-		// 	    url: `/pages/order/detail/acceptIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
-		// 	})
+		} else if(currentStatus.value === 'assigned') {
+			// 跳转到接单页面
+			uni.navigateTo({
+			    url: `/pages/order/detail/acceptIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
+			})
+		} else if(currentStatus.value === 'to_finish') {
+			// 跳转到待结单页面
+			uni.navigateTo({
+			    url: `/pages/order/detail/suspendIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
+			})
+		}  else if(currentStatus.value === 'to_approve') {
+			// 跳转到待审批页面
+			uni.navigateTo({
+			    url: `/pages/order/detail/approveIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
+			})
 		}
 
     }
@@ -532,8 +510,7 @@ import { getDictDataByType } from '../../api/dict/index'
 			color: #fff;
 		}
 	}
-
-
+	
     .list-item {
         margin: 24rpx 30rpx;
         background-color: #ffffff;
@@ -574,48 +551,51 @@ import { getDictDataByType } from '../../api/dict/index'
         margin-bottom: 20rpx;
         line-height: 40rpx;
     }
-
-    .item-info {
-        padding: 20rpx;
-        background-color: #f8f9fa;
-        border-radius: 8rpx;
-
-        .info-row {
-            flex-direction: row;
-            margin-bottom: 16rpx;
-
-            &:last-child {
-                margin-bottom: 0;
-            }
-
-            .info-item {
-                flex: 1;
-                flex-direction: row;
-                align-items: center;
-
-                .info-label {
-                    font-size: 26rpx;
-                    color: #666666;
-                    margin-right: 8rpx;
-                    white-space: nowrap;
-                }
-
-                .info-value {
-                    flex: 1;
-                    font-size: 26rpx;
-                    color: #333333;
-                }
-            }
-        }
-    }
+	
 	.btn-primary {
 		font-size: 14px;
 	    background-color: #165DFF;
 	    color: #ffffff;
-	    // font-weight: 100;
-	    // padding-top: 0.1rem;
-	    // padding-bottom: 0.1rem;
-	    // padding-left: 1rem;
-	    // padding-right: 1rem;
 	}
+.item-header {
+  flex-direction: row;
+  align-items: flex-start;
+  margin-bottom: 16rpx;
+
+  .item-title {
+    font-size: 30rpx;
+    color: #333333;
+    font-weight: bold;
+    flex-wrap: wrap;
+    flex: 0 1 80%;
+    min-width: 0;
+  }
+
+  .info-value {
+    font-size: 28rpx;
+    color: #999999;
+    margin-left: auto;
+    flex: 0 0 auto;
+    white-space: nowrap;
+  }
+}
+.info-row {
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+  
+  .info-label {
+    font-size: 26rpx;
+    color: #666;
+  }
+  
+  .info-value {
+    font-size: 26rpx;
+    // color: #666;
+  }
+}
+.text-gray{
+  font-size: 26rpx;
+  color: #666;
+}
 </style>

+ 3 - 1
types/order.uts

@@ -66,4 +66,6 @@ export type acceptOrderInfo = {
     model: string | null
     createTime: string | null
     workOrderFlowList?: WorkOrderFlowList | null
-}
+	suspendReason: string | null
+	rejectionReason: string | null
+}