Explorar el Código

Merge remote-tracking branch 'origin/master'

ouyj hace 3 meses
padre
commit
b7123d19ed

+ 19 - 1
api/order/detail.uts

@@ -90,7 +90,7 @@ export const resetAndStart = (gxtWorkOrder: UTSJSONObject | null): Promise<any>
 	})
 }
 
-// 完成订
+// 维保工单结
 export const finishOrder = (gxtWorkOrder: UTSJSONObject | null): Promise<any> => {
 	return request({
 		url: `/mobile/order/finish`,
@@ -98,3 +98,21 @@ export const finishOrder = (gxtWorkOrder: UTSJSONObject | null): Promise<any> =>
 		data: gxtWorkOrder
 	})
 }
+
+// 维修工单结单
+export const repairFinishOrder = (gxtWorkOrder: UTSJSONObject | null): Promise<any> => {
+	return request({
+		url: `/mobile/order/repairFinish`,
+		method: 'PUT',
+		data: gxtWorkOrder
+	})
+}
+
+// 维保工单停机
+export const shutdownOrder = (gxtWorkOrder: UTSJSONObject | null): Promise<any> => {
+	return request({
+		url: `/mobile/order/shutdown`,
+		method: 'PUT',
+		data: gxtWorkOrder
+	})
+}

+ 6 - 12
api/order/list.uts

@@ -83,19 +83,13 @@ export const pendingList = (page: number, rows: number, keyword: string | null):
  * @param keyword 关键字(可选,支持工单编码和风机编号查询)
  * @param status 工单状态(可选)
  */
-export const getMisInfoList = (page: number, rows: number, keyword: string | null, status: string | null): Promise<any> => {
-    let url = `/gxt/misInfo/list?pageNum=${page}&pageSize=${rows}`
-    if (keyword != null && keyword.length > 0) {
-        // 支持工单编码和风机编号查询
-        url += `&keyword=${encodeURIComponent(keyword)}`
-    }
-    // 添加状态筛选参数
-    if (status != null && status.length > 0) {
-        url += `&workOrderStatus=${encodeURIComponent(status)}`
-    }
+export const getMisInfoList = (query: UTSJSONObject | null): Promise<any> => {
+    let url = `/gxt/misInfo/list`
     return request({
         url: url,
-        method: 'GET'
+        method: 'GET',
+		data: query
+
     })
 }
 
@@ -118,7 +112,7 @@ export const listWorkPerson = (misNo: string | null): Promise<any> => {
     // }
     return request({
         url: url,
-        method: 'GET'
+        method: 'GET',
     })
 }
 /**

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

@@ -80,7 +80,7 @@
 			<!-- 工作负责人选择 -->
 			<view class="info-section">
 			    <view class="section-title">
-			        <text class="section-title-text">工作负责人<text style="color: red;">*</text></text>
+			        <text class="section-title-text">工作负责人</text>
 			    </view>
 			    <view class="info-card">
 			        <view class="form-item">
@@ -328,13 +328,13 @@
 	const hasDealed = ref(false)
 	// 处理接单操作
 	const handleAcceptOrder = async (): Promise<void> => {
-		if (selectedTeamLeaderName.value.trim() === '') {
-			uni.showToast({
-				title: '请选择工作负责人',
-				icon: 'none'
-			})
-			return
-		}
+		// if (selectedTeamLeaderName.value.trim() === '') {
+		// 	uni.showToast({
+		// 		title: '请选择工作负责人',
+		// 		icon: 'none'
+		// 	})
+		// 	return
+		// }
 		if (isDealing.value || hasDealed.value) return // 双重保险
 		isDealing.value = true
 		// const subOrder = {

+ 105 - 14
pages/order/detail/index.uvue

@@ -44,7 +44,18 @@
 					    <text class="info-label">接单退回说明</text>
 					    <text class="info-value">{{ acceptReturnReason}}</text>
 					</view>
-					
+					<view class="info-item" v-if="detailData.pauseTime != null && detailData.orderType == 1">
+					    <text class="info-label">发生时间</text>
+					    <text class="info-value">{{ detailData.pauseTime ?? '' }}</text>
+					</view>
+					<view class="info-item" v-if="detailData.pauseTime != null && detailData.orderType == 2">
+					    <text class="info-label">停机时间</text>
+					    <text class="info-value">{{ detailData.pauseTime ?? '' }}</text>
+					</view>
+					<view class="info-item" v-if="detailData.restartTime != null">
+					    <text class="info-label">恢复运行时间</text>
+					    <text class="info-value">{{ detailData.restartTime ?? '' }}</text>
+					</view>
 					<view class="info-item">
 					    <text class="info-label">{{getLabel(detailData)}}</text>
 					    <text class="info-value">{{ getDisplayTime(detailData) }}</text>
@@ -65,6 +76,25 @@
                 </view>
             </view>
 
+            <!-- 附件信息 -->
+            <view class="info-section" v-if="attachmentList.length > 0">
+                <view class="section-title">
+                    <text class="section-title-text">附件</text>
+                </view>
+                <view class="info-card">
+                    <view class="image-container">
+                        <image 
+                            v-for="(attachment, index) in attachmentList" 
+                            :key="index"
+                            :src="attachment" 
+                            :alt="'附件图片' + (index + 1)"
+                            class="attachment-image"
+                            @click="previewImage(attachment)"
+                        />
+                    </view>
+                </view>
+            </view>
+
             <!-- 工单流转 -->
             <view class="info-section">
                 <view class="section-title">
@@ -103,6 +133,7 @@
     import { getOrderInfoById, getRepairOrderInfoById } from '../../../api/order/detail'
 	import type { SysDictData } from '../../../types/dict'
 	import { getDictDataByType } from '../../../api/dict/index'
+	import { getBaseUrl } from '../../../utils/request'
 	
 	type OrderInfoForDetail = {
 		orderType: Number
@@ -134,6 +165,9 @@
 		faultCode: string | null
 		faultBarcode: string | null
 		faultDesc: string | null
+		pauseTime: string | null,
+		restartTime: string | null,
+		attachmentUrls: string | null // 附件URLs(逗号分隔的字符串格式)
 	}
 	
     // 详情数据
@@ -166,7 +200,10 @@
         workEndTime: null,  // 新增字段
 		faultCode: null,
 		faultBarcode: null,
-		faultDesc: null
+		faultDesc: null,
+		pauseTime: null,
+		restartTime: null,
+		attachmentUrls: null
     })
 
 	const statusDictList = ref<SysDictData[]>([]) // 工单状态字典列表
@@ -192,9 +229,8 @@
 	}
 
 	// 根据状态显示不同的时间label
-	const getLabel = (item : OrderInfoForDetail): string|null => {
+	const getLabel = (item : OrderInfoForDetail | null): string|null => {
 		if (item == null) return null
-
 		// 如果是"待接单"状态,显示派单时间
 		if (item.workOrderStatus == 'assigned') {
 			return '下发时间'
@@ -220,7 +256,7 @@
 	}
 
 	// 根据状态显示不同的时间
-	const getDisplayTime = (item : OrderInfoForDetail): string|null => {
+	const getDisplayTime = (item : OrderInfoForDetail | null): string|null => {
 		if (item == null) return null
 		let showTime = ref<string|null>('')
 
@@ -315,14 +351,54 @@
         isFlowListExpanded.value = !isFlowListExpanded.value
     }
 
+    // 计算附件列表
+    const attachmentList = computed<string[]>(() => {
+        if (detailData.value.attachmentUrls != null && detailData.value.attachmentUrls != '') {
+            // 按逗号分割附件URL字符串,并加上基础URL
+            const arr = detailData.value.attachmentUrls.split(',')
+                .map((url: string) => {
+                    const trimmedUrl = url.trim();
+                    // 如果是相对路径,加上基础URL
+                    if (trimmedUrl.startsWith('/')) {
+                        return getBaseUrl() + trimmedUrl;
+                    }
+                    return trimmedUrl;
+                })
+                .filter((url: string) => url.length > 0);
+            return arr;
+        }
+        return []
+    })
+
+    // 预览图片
+    const previewImage = (url: string) => {
+        if (url == '') return
+        
+        // 检查是否为图片文件
+        const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp']
+        const isImage = imageExtensions.some(ext => url.toLowerCase().endsWith(ext))
+        
+        if (isImage) {
+            // 如果是图片,使用uni.previewImage预览
+            uni.previewImage({
+                urls: [url],
+                current: 0
+            })
+        } else {
+            // 对于非图片文件,显示提示
+            uni.showToast({
+                title: '不支持预览此文件类型',
+                icon: 'none',
+                duration: 2000
+            })
+        }
+    }
+
 	// 获取操作类型名称
 	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 == false) {
 			return rawStatus
@@ -338,8 +414,6 @@
 	    // const orderInfoItem = item as orderInfo
 	    const rawStatus = item
 	
-	    if (rawStatus==null) return ''
-	
 		// 如果字典尚未加载,返回原始值
 		if (dictLoaded.value == false) {
 			return rawStatus
@@ -354,8 +428,6 @@
 	    // const orderInfoItem = item as orderInfo
 	    const rawStatus = item
 	
-	    if (rawStatus==null) return ''
-	
 		// 如果字典尚未加载,返回原始值
 		if (dictLoaded.value == false) {
 			return rawStatus
@@ -440,7 +512,7 @@
 				    // 维保工单
 				    flowList = data['workOrderFlowList'] as UTSJSONObject[]
 				}
-                if (flowList != null) {
+                if (flowList.length > 0) {
                     workOrderFlowList = []
                     for (let i = 0; i < flowList.length; i++) {
                         const flowItem = flowList[i]
@@ -492,7 +564,10 @@
                     workEndTime: data['workEndTime'] as string | null,  // 新增字段
 					faultCode: data['faultCode'] as string | null,
 					faultBarcode: data['faultBarcode'] as string | null,
-					faultDesc: data['faultDesc'] as string | null
+					faultDesc: data['faultDesc'] as string | null,
+					pauseTime: data['pauseTime'] as string | null,
+					restartTime: data['restartTime'] as string | null,
+					attachmentUrls: data['attachmentUrls'] as string | null
                 }
                 detailData.value = orderDtail
 				await loadReturnDictList('gxt_return_type')
@@ -700,5 +775,21 @@
             border-radius: 12rpx;
         }
     }
+    
+    .image-container {
+		display: flex;
+		flex-direction: row;
+		flex-wrap: wrap;
+		justify-content: flex-start; // 或 space-around
+		// justify-content: space-around; /* 自动分配间距,避免挤压 */
+		align-items: center;
+		padding: 0 10rpx;
+    }
+    
+    .attachment-image {
+        width: 300rpx; /* 一行显示两个图片,减去间距的一半 */
+        height: 300rpx;
+		padding: 10rpx
+    }
 </style>
 

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

@@ -27,10 +27,6 @@
                         <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>

+ 594 - 0
pages/order/detail/shutdownIndex.uvue

@@ -0,0 +1,594 @@
+<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">{{ 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">{{ brand ?? '' }} {{ model ?? '' }}</text>
+                    </view>
+					<view class="info-item">
+					    <text class="info-label">下发时间</text>
+					    <text class="info-value">{{ assignTime ?? '' }}</text>
+					</view>
+                </view>
+            </view>
+			<view class="info-section">
+			    <view class="info-card">
+			        <view class="info-item">
+						<view class="info-label">
+							<text class="form-label required">停机时间<text style="color: red;">*</text></text>
+						</view>
+						
+						<view class="info-value">
+						    <view class="form-picker" @click="showshutdownTimePicker = true">
+								<input
+								    class="input-field"
+								    placeholder="请选择停机时间"
+								    v-model="pauseTime"
+								/>
+						    </view>
+						</view>
+			        </view>
+			    </view>
+			</view>
+			
+			<!-- 时间选择器弹窗 -->
+			<!-- Start Date Picker -->
+			<l-popup v-model="showshutdownTimePicker" position="bottom">
+				<l-date-time-picker
+					title="选择开始时间"
+					:mode="1 | 2 | 4 | 8 | 16"
+					format="YYYY-MM-DD HH:mm"
+					:modelValue="pauseTime"
+					confirm-btn="确定"
+					cancel-btn="取消"
+					@confirm="onStartDateConfirm"
+					@cancel="showshutdownTimePicker = false">
+				</l-date-time-picker>
+			</l-popup>
+        </scroll-view>
+
+        <!-- 接单按钮 -->
+        <view class="accept-button-container" v-if="checkPermi(orderType == '2' ? ['gxt:maintenance:order:suspend'] : ['gxt:repairOrder:suspend'])">
+            <button class="accept-button" @click="handleShutdownOrder">{{ 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, shutdownOrder } from '../../../api/order/detail'
+	import type { SysDictData } from '../../../types/dict'
+	import { getDictDataByType } from '../../../api/dict/index'
+	import type { UserInfo } from '../../../types/user'
+	import {checkPermi} from '../../../utils/storage'
+
+	const teamLeaderName = ref<string>("")
+	const statusDictList = ref<SysDictData[]>([]) // 工单状态字典列表
+	// 添加字典加载状态
+	const dictLoaded = ref<boolean>(false)
+	const pauseTime = ref<string>("")
+	
+	// 工单信息
+	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 assignTime = ref<string>('')
+
+	const showshutdownTimePicker = ref<boolean>(false)
+	
+	function onStartDateConfirm(value: string) {
+	  // 检查结束时间是否小于新的开始时间
+	  pauseTime.value = value
+	  showshutdownTimePicker.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 isDealing = ref(false)
+	const hasDealed = ref(false)
+	// 处理接单操作
+	const handleShutdownOrder = async (): Promise<void> => {
+		if (pauseTime.value.trim() === '') {
+			uni.showToast({
+				title: '请选择停机时间',
+				icon: 'none'
+			})
+			return
+		}
+		if (isDealing.value || hasDealed.value) return // 双重保险
+		isDealing.value = true
+		try {
+			const submitData = {
+			    id: orderId.value,
+				workOrderProjectNo: workOrderProjectNo.value,
+				workOrderStatus: workOrderStatus.value,
+			    pauseTime: pauseTime.value
+			} as UTSJSONObject;
+			const result = await shutdownOrder(submitData)
+			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')
+				uni.$emit('refreshApproveCount')
+				uni.$emit('refreshSuspendedCount')
+				// 接单成功后返回上一页
+				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 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) {
+				orderId.value = id
+				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) ?? ''
+				assignTime.value = (data['assignTime'] as string | null) ?? ''
+
+            } 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;
+	}
+.reject-reason-textarea {
+    width: 100%;
+    min-height: 100rpx;
+    line-height: 1.5;
+}
+</style>
+

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 150 - 526
pages/order/detail/wbBackfillFinalize.uvue


+ 175 - 174
pages/order/detail/wbFinalize.uvue

@@ -61,56 +61,44 @@
                             </radio-group>
                         </view>
                     </view>
-                    
+
                     <!-- MIS工单编码选择(当信息录入为1时显示) -->
                     <view class="info-item" v-if="infoEntry == '1'">
                         <view class="info-label">
                             <text class="form-label required">MIS工单编码<text style="color: red;">*</text></text>
                         </view>
                         <view class="info-value">
-                            <input 
-                                class="input-field" 
-                                placeholder="请输入或选择MIS工单编码" 
-                                v-model="misNo"
-                                @focus="handleMisNoInputFocus"
-                                @blur="handleMisNoInputBlur"
-                                @input="handleMisNoInput"
-                                :disabled="infoEntry == '1'"
-                            />
-                            <!-- 选择MIS工单按钮 -->
-                            <button class="select-mis-btn" @click="openMisListModal">选择MIS工单</button>
-                            <!-- 快速检索下拉框 -->
-                            <!-- <view class="quick-select-dropdown" v-show="showMisNoQuickSelect && quickMisNoList.length > 0">
-                                <view
-                                    v-for="(item, index) in quickMisNoList"
-                                    :key="index"
-                                    class="quick-select-item"
-                                    @click="handleMisNoQuickSelect(item)">
-                                    <text class="mis-no">{{ item['misNo'] }}</text>
-                                </view>
-                            </view>
-                            <view class="quick-select-dropdown no-data" v-show="showMisNoQuickSelect && quickMisNoList.length === 0 && misNo != ''">
-                                <view>未找到匹配的MIS工单</view>
-                            </view> -->
+                            <view class="input-with-select">
+								<input
+									class="input-field"
+									placeholder="请输入或选择MIS工单编码"
+									v-model="misNo"
+									@focus="handleMisNoInputFocus"
+									@blur="handleMisNoInputBlur"
+									@input="handleMisNoInput"
+									:readonly="infoEntry == '1'"
+									:style="{ paddingRight: '120rpx' }" />
+								<text class="select-mis-btn" @click="openMisListModal">选择</text>
+							</view>
                         </view>
                     </view>
-                    
+
                     <!-- 工作票编号(当信息录入为2时可编辑) -->
                     <view class="info-item">
                         <view class="info-label">
                             <text class="form-label required">工作票编号<text style="color: red;">*</text></text>
                         </view>
                         <view class="info-value">
-                            <input 
-                                class="input-field" 
-                                placeholder="请输入工作票编号" 
+                            <input
+                                class="input-field"
+                                placeholder="请输入工作票编号"
                                 v-model="workPermitNum"
                                 maxlength="20"
                                 :disabled="infoEntry == '1'"
                             />
                         </view>
                     </view>
-                    
+
                     <!-- 开始时间 -->
                     <view class="info-item">
                         <view class="info-label">
@@ -119,18 +107,14 @@
                         <view class="info-value">
                             <view class="form-picker" @click="showStartTimePicker = true">
 								<input
-								    class="input-field" 
-								    placeholder="请选择开始时间" 
+								    class="input-field"
+								    placeholder="请选择开始时间"
 								    v-model="realStartTime"
 								/>
-                                <!-- <view class="picker-display">
-                                    <text v-if="realStartTime" class="selected-value">{{ realStartTime }}</text>
-                                    <text v-else>请选择开始时间</text>
-                                </view> -->
                             </view>
                         </view>
                     </view>
-                    
+
                     <!-- 结束时间 -->
                     <view class="info-item">
                         <view class="info-label">
@@ -139,80 +123,79 @@
                         <view class="info-value">
                             <view class="form-picker" @click="showEndTimePicker = true">
 								<input
-								    class="input-field" 
-								    placeholder="请选择结束时间" 
+								    class="input-field"
+								    placeholder="请选择结束时间"
 								    v-model="realEndTime"
 								/>
-                                <!-- <view class="picker-display">
-                                    <text v-if="realEndTime" class="selected-value">{{ realEndTime }}</text>
-                                    <text v-else>请选择结束时间</text>
-                                </view> -->
                             </view>
                         </view>
                     </view>
-                    
+
                     <!-- 外委人员数 -->
                     <view class="info-item">
                         <view class="info-label">
                             <text class="form-label required">外委人员数(人)</text>
                         </view>
                         <view class="info-value">
-                            <input 
+                            <input
                                 type="number"
-                                class="input-field" 
-                                placeholder="请输入外委人员数" 
+                                class="input-field"
+                                placeholder="请输入外委人员数"
                                 v-model="wwryNum"
                             />
                         </view>
                     </view>
-                    
+
                     <!-- 外来人员数 -->
                     <view class="info-item">
                         <view class="info-label">
                             <text class="form-label required">外来人员数(人)</text>
                         </view>
                         <view class="info-value">
-                            <input 
+                            <input
                                 type="number"
-                                class="input-field" 
-                                placeholder="请输入外来人员数" 
+                                class="input-field"
+                                placeholder="请输入外来人员数"
                                 v-model="wlryNum"
                             />
                         </view>
                     </view>
-                    
+
                     <!-- 工作负责人 -->
                     <view class="info-item">
                         <view class="info-label">
                             <text class="form-label required">工作负责人</text>
                         </view>
                         <view class="info-value">
-                            <input 
-                                class="input-field" 
-                                placeholder="请输入工作负责人" 
+                            <input
+                                class="input-field"
+                                placeholder="请输入工作负责人"
                                 v-model="teamLeaderName"
                                 :disabled="true"
                             />
                         </view>
                     </view>
-                    
+
                     <!-- 检修人员选择(当信息录入为2时可编辑) -->
                     <view class="info-item">
                         <view class="info-label">
                             <text class="form-label required">检修人员</text>
                         </view>
                         <view class="info-value">
-                            <input 
-                                class="input-field" 
-                                placeholder="请选择检修人员" 
-                                v-model="workGroupMemberName"
-                                @click="showUserSelect = true"
-                                :disabled="infoEntry == '1'"
-                            />
-                            <text class="select-users-count" v-if="selectedUserIds.length > 0">({{ selectedUserIds.length }}人)</text>
+                            <view class="input-with-clear">
+								<input
+									class="input-field"
+									placeholder="请选择检修人员"
+									v-model="workGroupMemberName"
+									@click="showUserSelect = true"
+									:disabled="infoEntry == '1'"
+								/>
+								<text class="select-users-count" v-if="selectedUserIds.length > 0" :style="{ marginRight: selectedUserIds.length > 0 ? '60rpx' : '0' }">({{ selectedUserIds.length }}人)</text>
+								<text class="select-clear" v-if="selectedUserIds.length > 0" @click="clearSelectedUsers">×</text>
+							</view>
                         </view>
                     </view>
-                    
+
                     <!-- 维保内容 -->
                     <view class="info-item full-width">
                         <view class="info-label">
@@ -230,7 +213,7 @@
                             ></textarea>
                         </view>
                     </view>
-                    
+
                     <!-- 附件上传 -->
                     <view class="info-item full-width">
                         <view class="info-label">
@@ -248,7 +231,6 @@
                 </view>
             </view>
 
-            
             <!-- 时间选择器弹窗 -->
 			<!-- Start Date Picker -->
 			<l-popup v-model="showStartTimePicker" position="bottom">
@@ -263,7 +245,7 @@
 					@cancel="showStartTimePicker = false">
 				</l-date-time-picker>
 			</l-popup>
-			
+
 			<!-- End Date Picker -->
 			<l-popup v-model="showEndTimePicker" position="bottom">
 				<l-date-time-picker
@@ -277,7 +259,7 @@
 					@cancel="showEndTimePicker = false">
 				</l-date-time-picker>
 			</l-popup>
-            
+
             <!-- 人员选择弹窗 -->
             <view v-if="showUserSelect" class="picker-modal">
                 <view class="modal-mask" @click="showUserSelect = false"></view>
@@ -294,9 +276,9 @@
 						</view>
 					</view>
                     <scroll-view class="modal-body" scroll-y="true">
-                        <view 
-                            v-for="(user, index) in userList" 
-                            :key="index" 
+                        <view
+                            v-for="(user, index) in userList"
+                            :key="index"
                             class="picker-option"
                             @click="toggleUserSelection(user)"
                         >
@@ -307,7 +289,7 @@
                     </scroll-view>
                 </view>
             </view>
-            
+
             <!-- MIS工单列表弹窗 -->
             <view v-if="showMisListModal" class="picker-modal">
                 <view class="modal-mask" @click="closeMisListModal"></view>
@@ -324,24 +306,8 @@
                             <text v-if="misListKeyword.length > 0" class="clear-icon" @click="clearMisListSearch">✕</text>
                         </view>
                     </view>
-		
+
                     <!-- 列表内容 -->
-                    <!-- <scroll-view class="modal-body" scroll-y="true">
-                        <view v-if="misList.length > 0">
-                            <view 
-                                v-for="(item, index) in misList" 
-                                :key="index" 
-                                class="picker-option"
-                                @click="selectMisItem(item)"
-                            >
-                                <text class="option-text">{{ ((item['misNo'] as string | null) ?? '-') }}</text>
-                                <text class="option-text">{{ item['pcsDeviceName'] as string | null ?? '-' }}</text>
-                                <text class="option-text">{{ item['workPermitNum'] as string | null ?? '-' }}</text>
-                            </view>
-                        </view>
-                        <view v-if="misList.length === 0" class="empty-tip">未找到匹配的MIS工单</view>
-                    </scroll-view> -->
-					
 					<scroll-view class="modal-body" scroll-y="true">
 						<!-- 有数据时显示列表 -->
 						<view v-if="misList.length > 0">
@@ -360,7 +326,7 @@
 						</view>
 						<!-- 无数据时显示提示 -->
 						<view v-else class="empty-tip">
-						    <text>未找到匹配的人员</text>
+						    <text>未找到匹配的MIS工单</text>
 						</view>
 					</scroll-view>
                 </view>
@@ -391,8 +357,7 @@
     import type { UploadResponse } from '../../../types/workbench'
     import {checkPermi} from '../../../utils/storage'
 	import { getUserList, getLeaderList } from '../../../api/user/list'
-    // import uploadImage from '../../../components/upload-image/upload-image.uvue'
-	
+    import uploadImage from '../../../components/upload-image/upload-image.uvue'
 
 	// 工单信息
 	const orderId = ref<string>('')
@@ -431,11 +396,9 @@
     const attachmentUrls = ref<string>('') // 附件URLs(逗号分隔的字符串格式)
     const uploadedFiles = ref<UploadResponse[]>([]) // 上传的文件对象数组
 	const workOrderPersonList = ref<UTSJSONObject[]>([]) // 检修人员数组
-		const selectedUserIds = ref<string[]>([]) // 选中的用户ID数组
-		const selectedUsers = ref<UTSJSONObject[]>([]) // 选中的用户对象数组
-	
-	
-    
+	const selectedUserIds = ref<string[]>([]) // 选中的用户ID数组
+	const selectedUsers = ref<UTSJSONObject[]>([]) // 选中的用户对象数组
+
     // 时间选择器相关变量
     const showStartTimePicker = ref<boolean>(false)
     const showEndTimePicker = ref<boolean>(false)
@@ -443,7 +406,7 @@
     const startTimeTime = ref<string>('')
     const endTimeDate = ref<string>('')
     const endTimeTime = ref<string>('')
-    
+
     // MIS工单选择相关变量
     const showMisNoQuickSelect = ref<boolean>(false)
     const quickMisNoList = ref<UTSJSONObject[]>([])
@@ -459,16 +422,16 @@
     // 搜索关键词
     const misListKeyword = ref<string>('')
 	const userKeyword = ref<string>('')
-    
+
     // 人员选择相关变量
     const showUserSelect = ref<boolean>(false)
     const userList = ref<UTSJSONObject[]>([])
 	const userAllList = ref<UTSJSONObject[]>([])
-    
+
     // 信息录入选项
     const infoEntryOptions = ref<SysDictData[]>([])
 	const selectedMisInfoIndex = ref<number>(-1)
-    
+
     // 获取信息录入字典列表
     const loadInfoEntryDictList = async (): Promise<void> => {
         try {
@@ -512,7 +475,7 @@
             ];
         }
     }
-    
+
     // 获取用户列表
     const getUserAllList = async (): Promise<void> => {
         try {
@@ -536,13 +499,13 @@
             });
         }
     };
-    
+
     // 验证和提交
     const submitLoading = ref<boolean>(false)
-    
+
     // 信息录入禁用状态
     const infoEntryDisabled = ref<boolean>(false)
-    
+
     // 接受用户名
     const acceptUserName = ref<string>('')
 
@@ -643,7 +606,7 @@
     };
 
     const handleMisNoInput = (e: SysDictData): void => {
-        misNo.value = (e['detail'] as string | null) ?? '';
+        // misNo.value = (e['detail'] as string | null) ?? '';
         // 这里可以添加实时搜索MIS工单的逻辑
     };
 
@@ -656,25 +619,26 @@
         misNo.value = (item['misNo'] as string | null) ?? '';
         showMisNoQuickSelect.value = false;
     };
-    
+
     // 获取MIS工单列表
     const getMisList = async (): Promise<void> => {
         try {
+			const queryParams = {
+				pauseTime: pauseTime.value,
+				restartTime: restartTime.value,
+				pcsDeviceName: pcsDeviceName.value,
+				pcsStationName: pcsStationName.value,
+				workOrderStatus: '结束'
+			} as UTSJSONObject;
             // 调用获取MIS工单列表的API
-            const result = await getMisInfoList(
-                misListPage.value,
-                misListPageSize.value,
-                misListKeyword.value,
-				'结束'
-                // null // 状态筛选,可根据需要添加
-            );
+            const result = await listAutoMisInfo(queryParams);
             const resultObj = result as UTSJSONObject;
             if (resultObj['code'] == 200) {
                 // 解析列表数据
 				const rows = resultObj['rows'] as UTSJSONObject[]
                 misList.value = rows;
 				allMisList.value = rows
-                
+
                 // 解析总数
                 misListTotal.value = resultObj['total'] as number;
             } else {
@@ -692,14 +656,14 @@
               });
         }
     };
-    
+
     // 打开MIS工单选择弹窗
     const openMisListModal = (): void => {
         showMisListModal.value = true;
         misListPage.value = 1; // 重置为第一页
         getMisList(); // 获取列表数据
     };
-    
+
     // 选择MIS工单
     const selectMisItem = async (item: UTSJSONObject, index: number): Promise<void> => {
 		selectedMisInfoIndex.value = index
@@ -726,14 +690,14 @@
 				workGroupMemberName.value = nickNames;
 			}
 		})
-		
+
         workPermitNum.value = item['workPermitNum'] as string | '';
         realStartTime.value = item['realStartTime'] as string | '';
         realEndTime.value = item['realEndTime'] as string | '';
         // 关闭弹窗
         showMisListModal.value = false;
     };
-	
+
 	// 搜索
 	const handleSearch = (): void => {
 		const keyword = userKeyword.value
@@ -742,12 +706,12 @@
 			return nickName != null && nickName.indexOf(keyword) >= 0
 		})
 	}
-    
+
     // 关闭MIS工单选择弹窗
     const closeMisListModal = (): void => {
         showMisListModal.value = false;
     };
-    
+
 	// 搜索
 	const searchMisList = (): void => {
 		const keyword = misListKeyword.value
@@ -755,47 +719,46 @@
 			const misNo = misInfo['misNo'] as string | null
 			// return misNo != null && misNo.indexOf(keyword) >= 0
 			const workPermitNum = misInfo['workPermitNum'] as string | null
-			        
+
 			// 逻辑或(||)连接两个条件,满足其一即可
 			const misNoMatch = misNo != null && misNo.indexOf(keyword) >= 0
 			const workPermitNumMatch = workPermitNum != null && workPermitNum.indexOf(keyword) >= 0
-			
+
 			return misNoMatch || workPermitNumMatch
 		})
 	}
 
-    
     // 清除MIS工单搜索
     const clearMisListSearch = (): void => {
         misListKeyword.value = "";
 		misList.value = allMisList.value
     };
-	
+
 	// 清除用户搜索
 	const clearSearch = (): void => {
 	    userKeyword.value = "";
 		userList.value = userAllList.value
 	};
-    
-	
+
+
 	function onStartDateConfirm(value: string) {
 	  // 检查结束时间是否小于新的开始时间
 	  if (realEndTime.value != '' && new Date(value) > new Date(realEndTime.value as string)) {
 	    uni.showToast({ title: '开始时间不能大于结束时间', icon: 'none' })
 	    return
 	  }
-	
+
 	  realStartTime.value = value
 	  showStartTimePicker.value = false
 	}
-	
+
 	function onEndDateConfirm(value: string) {
 	  // 检查新的结束时间是否小于开始时间
 	  if (realStartTime.value != '' && new Date(realStartTime.value as string) > new Date(value)) {
 	    uni.showToast({ title: '结束时间不能小于开始时间', icon: 'none' })
 	    return
 	  }
-	
+
 	  realEndTime.value = value
 	  showEndTimePicker.value = false
 	}
@@ -809,7 +772,7 @@
         // 如果没有userId,则比较nickName
         const nickName = user['nickName'] as string | null;
         if (nickName !== null) {
-            return selectedUsers.value.some(selected => 
+            return selectedUsers.value.some(selected =>
                 (selected['nickName'] as string | null) === nickName
             );
         }
@@ -820,14 +783,14 @@
     const toggleUserSelection = (user: UTSJSONObject): void => {
         const userId = user['userId'] as string | number | null;
         const nickName = user['nickName'] as string | null;
-        
+
         if (userId !== null) {
             const userIdStr = userId.toString();
             const index = selectedUserIds.value.indexOf(userIdStr);
             if (index > -1) {
                 // 取消选择
                 selectedUserIds.value.splice(index, 1);
-                selectedUsers.value = selectedUsers.value.filter(selected => 
+                selectedUsers.value = selectedUsers.value.filter(selected =>
                     (selected['userId'] as string | number | null)?.toString() !== userIdStr
                 );
             } else {
@@ -837,7 +800,7 @@
             }
         } else if (nickName !== null) {
             // 如果没有userId,通过nickName来识别
-            const index = selectedUsers.value.findIndex(selected => 
+            const index = selectedUsers.value.findIndex(selected =>
                 (selected['nickName'] as string | null) === nickName
             );
             if (index > -1) {
@@ -869,14 +832,27 @@
             .map(user => (user['nickName'] as string | null) ?? '')
             .filter(name => name !== '')
             .join(',');
-        
+
         workGroupMemberName.value = nickNames;
-        
+
         // 更新workOrderPersonList为选中的用户
         workOrderPersonList.value = [...selectedUsers.value];
-        
+
         showUserSelect.value = false;
     };
+	
+	// 清空已选择的用户
+	const clearSelectedUsers = (): void => {
+		// 清空选中的用户数组
+		selectedUsers.value = [];
+		selectedUserIds.value = [];
+		
+		// 清空显示的用户名
+		workGroupMemberName.value = '';
+		
+		// 清空检修人员列表
+		workOrderPersonList.value = [];
+	};
 
 
     // 表单验证
@@ -889,14 +865,6 @@
             return false;
         }
 
-        if (infoEntry.value == '2' && (workGroupMemberName.value == '' || selectedUsers.value.length == 0)) {
-            uni.showToast({
-                title: '请选择检修人员',
-                icon: 'none'
-            });
-            return false;
-        }
-
         if (infoEntry.value == '1' && (misNo.value == '')) {
             uni.showToast({
                 title: '请输入MIS工单编码',
@@ -936,18 +904,18 @@
             });
             return false;
         }
-
-        // if (infoEntry.value == '2' && (workGroupMemberName.value == '')) {
-        //     uni.showToast({
-        //         title: '请选择检修人员',
-        //         icon: 'none'
-        //     });
-        //     return false;
-        // }
+		
+		// if (infoEntry.value == '2' && (workGroupMemberName.value == '' || selectedUsers.value.length == 0)) {
+		//     uni.showToast({
+		//         title: '请选择检修人员',
+		//         icon: 'none'
+		//     });
+		//     return false;
+		// }
 
         return true;
     };
-	
+
 	const isDealing = ref(false)
 	const hasDealed = ref(false)
 	// 提交表单
@@ -955,14 +923,14 @@
 	    if (!validateForm()) {
 	        return;
 	    }
-	
+
 	    submitLoading.value = true;
 	    try {
 			if (isDealing.value || hasDealed.value) return // 双重保险
 			isDealing.value = true
 	        // 确保附件URLs是最新的逗号分隔格式
 	        attachmentUrls.value = uploadedFiles.value.map(file => file.fileName).join(',');
-	        
+
 	        const finishData = {
 	            id: orderId.value,
 	            orderType: orderType.value,
@@ -983,11 +951,11 @@
 				finalizeMethod: '2',
 				workOrderStatus: 'completed'
 	        } as UTSJSONObject;
-	
+
 	        const result = await finishOrder(finishData);
 	        const resultObj = result as UTSJSONObject;
 	        const code = resultObj['code'] as number;
-	
+
 	        if (code == 200) {
 	            uni.showToast({
 	                title: '结单成功',
@@ -998,7 +966,7 @@
 	            uni.$emit('refreshOrderList', {});
 	            uni.$emit('refreshAssignedCount');
 	            uni.$emit('refreshOverdueCount');
-	
+
 	            setTimeout(() => {
 	                uni.navigateBack();
 	            }, 800);
@@ -1028,11 +996,7 @@
     const loadDetail = async (id: string, orderType?: string): Promise<void> => {
         try {
             loading.value = true
-
-
-
             let result: any;
-
             // 根据orderType决定调用哪个API
             if (orderType == '1') {
                 // 维修工单
@@ -1087,8 +1051,8 @@
 				}
 				pauseTime.value = (data['pauseTime'] as string | null) ?? ''
 				restartTime.value = (data['restartTime'] as string | null) ?? ''
-				
-				if(pauseTime.value != '' && restartTime.value != '') {	
+
+				if(pauseTime.value != '' && restartTime.value != '') {
 					const queryParams = {
 						pauseTime: pauseTime.value,
 						restartTime: restartTime.value,
@@ -1106,9 +1070,9 @@
 							// 有工作票号提示
 							const workPermitNum2 = misInfo[0]['workPermitNum'] as string | null
 							const misNo2 = misInfo[0]['misNo'] as string | null
-							
+
 							if (workPermitNum2 != null && workPermitNum2.length > 0) {
-								
+
 								const response = await getOrderList(1, 10, misNo2 ?? '', '')
 								const responseObj = response as UTSJSONObject
 								const rows = responseObj['rows'] as UTSJSONObject[] | null
@@ -1121,7 +1085,7 @@
 									});
 									return
 								} else {
-									
+
 									misNo.value = (misInfo[0]['misNo'] as string | null) ?? ''
 									realStartTime.value = (misInfo[0]['realStartTime'] as string | null) ?? ''
 									realEndTime.value = (misInfo[0]['realEndTime'] as string | null) ?? ''
@@ -1147,7 +1111,7 @@
 										}
 									})
 								}
-								
+
 							} else {
 								misNo.value = ''
 								infoEntry.value = '2'
@@ -1178,8 +1142,7 @@
 						icon: 'none'
 					});
 				}
-				
-				
+
 				// await dictList()
 				if (returnTypeOptions.value.length > 0 && workOrderStatus.value == 'to_finish') {
 					// returnTypeLabel.value = returnTypeOptions.value[0].label
@@ -1319,6 +1282,44 @@
                         border-radius: 8rpx;
                         padding: 10rpx;
                     }
+					.input-with-clear {
+						position: relative;
+						display: flex;
+						align-items: center;
+					}
+					
+					.select-clear {
+						position: absolute;
+						right: 20rpx;
+						color: #ccc;
+						text-align: center;
+						font-size: 40rpx;
+						font-weight: bold;
+						z-index: 1;
+					}
+					
+					.input-with-select {
+						position: relative;
+						display: flex;
+						align-items: center;
+					}
+					
+					.select-mis-btn {
+						line-height: 50rpx;
+						text-align: center;
+						position: absolute;
+						right: 0rpx;
+						padding: 6rpx 12rpx;
+						background-color: #007aff;
+						color: #fff;
+						border-radius: 6rpx;
+						font-size: 26rpx;
+						z-index: 1;
+						max-width: 100rpx;
+						overflow: hidden;
+						text-overflow: ellipsis;
+						white-space: nowrap;
+					}
                 }
             }
 
@@ -1472,7 +1473,7 @@
 	    padding: 24rpx 30rpx;
 	    border-bottom: 1rpx solid #f0f0f0;
 	}
-	
+
 	.picker-option.selected {
 	    background-color: #f8f9fa;
 	}
@@ -1496,7 +1497,7 @@
 	    font-size: 28rpx;
 	    color: #007aff;
 	}
-	
+
 	.empty-tip {
 		justify-content: space-between;
 		padding: 24rpx 30rpx;

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 328 - 186
pages/order/detail/wxFinalize.uvue


+ 37 - 7
pages/order/index.uvue

@@ -72,6 +72,14 @@
 								>
 								<text class="btn-text">接单</text>
 							</view>
+							<view
+								v-if="(getOrderStatus(item) == 'assigned' || getOrderStatus(item) == 'to_finish') 
+								&& canHandleOrder(item,'shutdown') && (item as acceptOrderInfoExtend).pauseTime == null"
+								class="btn-primary info-value"
+								@click.stop="handleItemClick(item,'shutdown')"
+								>
+								<text class="btn-text">停机</text>
+							</view>
 							<view
 								v-if="getOrderStatus(item) == 'to_approve' && canHandleOrder(item,'')"
 								class="btn-primary info-value"
@@ -179,6 +187,7 @@ type acceptOrderInfoExtend = {
   updateTime: string | null
   workEndTime: string | null
   orderEntryType: string | null
+  pauseTime: string | null
 }
 
 	const userId = ref<string>("")
@@ -359,6 +368,7 @@ const statusConfig: StatusItem[] = [
 						updateTime: item['updateTime'] as string | null,  // 新增字段
 						workEndTime: item['workEndTime'] as string | null,// 新增字段
 						orderEntryType: item['orderEntryType'] as string | null,
+						pauseTime: item['pauseTime'] as string | null
                     }
                     newData.push(orderItem)
                 }
@@ -607,12 +617,16 @@ const statusConfig: StatusItem[] = [
 	  if (item == null) return false
 	  let permit: string[] = []
 	  const orderItem = item as acceptOrderInfoExtend
-	  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']
+	  if(orderItem.workOrderStatus == 'assigned') {
+			if(buttonType != '' && buttonType == "acceptReturn" && orderItem.orderType == 1) {
+				// 接单退回
+				permit = ['gxt:repairOrder:acceptReturn']
+			} else if(buttonType != '' && buttonType == "accept") {
+				// 接单
+				permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:accept'] : ['gxt:repairOrder:accept']
+			}  else if(buttonType != '' && buttonType == "shutdown" && orderItem.orderType == 2) {
+				permit = ['gxt:maintenance:order:shutdown']
+			} 
 	  } else if(orderItem.workOrderStatus == 'to_finish') {
 		  if(buttonType != '' && buttonType == "suspend" && (orderItem.teamLeaderId == parseInt(userId.value) || roles.value.includes("管理员"))) {
 			  // 挂起
@@ -623,9 +637,12 @@ const statusConfig: StatusItem[] = [
 		  } else if(buttonType != '' && buttonType == "finalize" && orderItem.orderType == 1 && (orderItem.teamLeaderId == parseInt(userId.value) || roles.value.includes("管理员"))) {
 			  // 复启
 			  permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:finalize'] : ['gxt:repairOrder:finalize']
-		  } else if(buttonType != '' && buttonType == "complete" && (orderItem.teamLeaderId == parseInt(userId.value) || roles.value.includes("管理员"))) {
+		  // } else if(buttonType != '' && buttonType == "complete" && (orderItem.teamLeaderId == parseInt(userId.value) || roles.value.includes("管理员"))) {
+			} else if(buttonType != '' && buttonType == "complete") {
 			  // 结单
 			  permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:complete'] : ['gxt:repairOrder:finalize']
+		  } else if(buttonType != '' && buttonType == "shutdown" && orderItem.orderType == 2) {
+			  permit = ['gxt:maintenance:order:shutdown']
 		  }
 	  } else if(orderItem.workOrderStatus == 'to_approve') {
 	  	// 审批
@@ -639,6 +656,9 @@ const statusConfig: StatusItem[] = [
 	  } else if(orderItem.workOrderStatus == 'auto_suspend') {
 		  // 自动挂起恢复
 		  permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:autoResume'] : ['gxt:repairOrder:autoResume']
+	  } else if(orderItem.workOrderStatus == 'shutdown' && orderItem.orderType == 2) {
+		  // 自动挂起恢复
+		  permit = ['gxt:maintenance:order:shutdown']
 	  }
 	   else {
 		  return false
@@ -666,6 +686,11 @@ const statusConfig: StatusItem[] = [
 				uni.navigateTo({
 					url: `/pages/order/detail/returnIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
 				})
+			} else if(buttonType != '' && buttonType == "shutdown") {
+				// 跳转到停机页面
+				uni.navigateTo({
+					url: `/pages/order/detail/shutdownIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
+				})
 			} else {
 				// 跳转到接单页面
 				uni.navigateTo({
@@ -703,6 +728,11 @@ const statusConfig: StatusItem[] = [
 				uni.navigateTo({
 					url: `/pages/order/detail/wbBackfillFinalize?id=${orderItem.id}&orderType=${orderItem.orderType}`
 				})
+			} else if(buttonType != '' && buttonType == "shutdown") {
+				// 跳转到停机页面
+				uni.navigateTo({
+					url: `/pages/order/detail/shutdownIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
+				})
 			}
 		} else if(orderItem.workOrderStatus == 'to_approve') {
 			// 跳转到待审批页面

+ 88 - 34
pages/order/pendingOrder.uvue

@@ -24,7 +24,7 @@
                 <view class="list-item">
                     <view class="item-container">
 						<view class="item-header">
-							<text class="item-title">{{ getWorkOrderProjectNo(item) }}-{{ (item as acceptOrderInfo).pcsStationName }}{{ getPcsDeviceName(item) }}{{ getOrderType(item) }}</text>
+							<text class="item-title">{{ getWorkOrderProjectNo(item) }}-{{ (item as acceptOrderInfoExtend).pcsStationName }}{{ getPcsDeviceName(item) }}{{ getOrderType(item) }}</text>
 							<text class="status-tag" :class="getStatusClass(item)">{{ getWorkOrderStatus(item) }}</text>
 						</view>
 						<view class="info-row">
@@ -40,6 +40,14 @@
 								>
 								<text class="btn-text">接单</text>
 							</view>
+							<view
+								v-if="(getOrderStatus(item) == 'assigned' || getOrderStatus(item) == 'to_finish') 
+								&& canHandleOrder(item,'shutdown') && (item as acceptOrderInfoExtend).pauseTime == null"
+								class="btn-primary info-value"
+								@click.stop="handleItemClick(item,'shutdown')"
+								>
+								<text class="btn-text">停机</text>
+							</view>
 							<view
 								v-if="getOrderStatus(item) == 'to_approve' && canHandleOrder(item,'')"
 								class="btn-primary info-value"
@@ -99,17 +107,46 @@
 
 <script setup lang="uts">
 import { ref, onBeforeUnmount, onMounted } from 'vue'
-import type { acceptOrderInfo } from '../../types/order'
 import type { SysDictData } from '../../types/dict'
 import { pendingList } from '../../api/order/list'
 import { getDictDataByType } from '../../api/dict/index'
 import {checkPermi, getUserInfo} from '../../utils/storage'
 
+type acceptOrderInfoExtend = {
+  orderType: Number
+  id: Number
+  teamLeaderId: Number
+  acceptUserId: Number
+  teamLeaderName: string | null
+  acceptUserName: string | null
+  acceptTime: string | null
+  assignTime: string | null
+  assignUserName: string | null
+  status: Number
+  workOrderProjectNo: string | null
+  workOrderStatus: string | null
+  gxtCenterId: Number
+  gxtCenter: string | null
+  pcsStationId: Number
+  pcsStationName: string | null
+  pcsDeviceId: Number
+  pcsDeviceName: string | null
+  brand: string | null
+  model: string | null
+  createTime: string | null
+  suspendReason: string | null
+  rejectionReason: string | null
+  updateTime: string | null
+  workEndTime: string | null
+  orderEntryType: string | null
+  pauseTime: string | null
+}
+
 	const userId = ref<string>("")
 	const roles = ref<string>('')
 
     // 列表数据
-    const dataList = ref<acceptOrderInfo[]>([])
+    const dataList = ref<acceptOrderInfoExtend[]>([])
     let keyword = ref<string>("")
     const page = ref<number>(1)
     const pageSize: number = 10
@@ -131,7 +168,7 @@ import {checkPermi, getUserInfo} from '../../utils/storage'
 
 	const getOrderStatus = (item: any | null): string => {
 		if (item == null) return ''
-		const orderItem = item as acceptOrderInfo
+		const orderItem = item as acceptOrderInfoExtend
 		return orderItem.workOrderStatus ?? ''
 	}
 
@@ -139,24 +176,30 @@ import {checkPermi, getUserInfo} from '../../utils/storage'
 	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' && 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']
+	  const orderItem = item as acceptOrderInfoExtend
+	  if(orderItem.workOrderStatus == 'assigned') {
+			if(buttonType != '' && buttonType == "acceptReturn" && orderItem.orderType == 1) {
+				// 接单退回
+				permit = ['gxt:repairOrder:acceptReturn']
+			} else if(buttonType != '' && buttonType == "accept") {
+				// 接单
+				permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:accept'] : ['gxt:repairOrder:accept']
+			}  else if(buttonType != '' && buttonType == "shutdown" && orderItem.orderType == 2) {
+				permit = ['gxt:maintenance:order:shutdown']
+			} 
 	  } else if(orderItem.workOrderStatus == 'to_finish') {
-	  		  if(buttonType != '' && buttonType == "suspend" && (orderItem.teamLeaderId == parseInt(userId.value) || roles.value.includes("管理员"))) {
-	  			  // 挂起
-	  			  permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:suspend'] : ['gxt:repairOrder:suspend']
-	  		  } else if(buttonType != '' && buttonType == "return" && orderItem.orderType == 1 && (orderItem.teamLeaderId == parseInt(userId.value) || roles.value.includes("管理员"))) {
-	  			  // 退回
-	  			  permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:return'] : ['gxt:repairOrder:return']
-	  		  } else if(buttonType != '' && buttonType == "finalize" && orderItem.orderType == 1 && (orderItem.teamLeaderId == parseInt(userId.value) || roles.value.includes("管理员"))) {
-	  			  // 复启
-	  			  permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:finalize'] : ['gxt:repairOrder:finalize']
-	  		  }
+	  		if(buttonType != '' && buttonType == "suspend" && (orderItem.teamLeaderId == parseInt(userId.value) || roles.value.includes("管理员"))) {
+	  			// 挂起
+	  			permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:suspend'] : ['gxt:repairOrder:suspend']
+	  		} else if(buttonType != '' && buttonType == "return" && orderItem.orderType == 1 && (orderItem.teamLeaderId == parseInt(userId.value) || roles.value.includes("管理员"))) {
+	  			// 退回
+	  			permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:return'] : ['gxt:repairOrder:return']
+	  		} else if(buttonType != '' && buttonType == "finalize" && orderItem.orderType == 1 && (orderItem.teamLeaderId == parseInt(userId.value) || roles.value.includes("管理员"))) {
+	  			// 复启
+	  			permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:finalize'] : ['gxt:repairOrder:finalize']
+	  		} else if(buttonType != '' && buttonType == "shutdown" && orderItem.orderType == 2) {
+			    permit = ['gxt:maintenance:order:shutdown']
+			}
 	  } else if(orderItem.workOrderStatus == 'to_approve') {
 	  	// 审批
 	  	permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:approve'] : ['gxt:repairOrder:approve']
@@ -170,7 +213,7 @@ import {checkPermi, getUserInfo} from '../../utils/storage'
 	   else {
 	  		  return false
 	  }
-	  // const orderType = (item as acceptOrderInfo).orderType
+	  // const orderType = (item as acceptOrderInfoExtend).orderType
 	  return checkPermi(permit)
 	}
 
@@ -271,11 +314,11 @@ import {checkPermi, getUserInfo} from '../../utils/storage'
             const responseTotal = resultObj['total'] as number
 
             if (code == 200) {
-                // 将 any[] 转换为 acceptOrderInfo[]
-                const newData: acceptOrderInfo[] = []
+                // 将 any[] 转换为 acceptOrderInfoExtend[]
+                const newData: acceptOrderInfoExtend[] = []
                 for (let i = 0; i < responseData.length; i++) {
                     const item = responseData[i] as UTSJSONObject
-                    const orderItem: acceptOrderInfo = {
+                    const orderItem: acceptOrderInfoExtend = {
 						orderType: item['orderType'] as Number,
                         id: item['id'] as Number,
 						teamLeaderId: item['teamLeaderId'] != null ? (item['teamLeaderId'] as Number) : 0,
@@ -300,7 +343,8 @@ import {checkPermi, getUserInfo} from '../../utils/storage'
 						suspendReason: item['suspendReason'] as string | null,
 						rejectionReason: item['rejectionReason'] as string | null,
 						updateTime: item['updateTime'] as string | null,  // 新增字段
-						workEndTime: item['workEndTime'] as string | null  // 新增字段
+						workEndTime: item['workEndTime'] as string | null,  // 新增字段
+						pauseTime: item['pauseTime'] as string | null
                     }
                     newData.push(orderItem)
                 }
@@ -347,26 +391,26 @@ import {checkPermi, getUserInfo} from '../../utils/storage'
     // 辅助函数:从 any 类型提取属性
     const getOrderType = (item: any | null): string => {
         if (item == null) return ''
-        const orderInfoItem = item as acceptOrderInfo
+        const orderInfoItem = item as acceptOrderInfoExtend
         return orderInfoItem.orderType == 1?"维修工单":"维保工单";
     }
 
     const getWorkOrderProjectNo = (item: any | null): string | null => {
         if (item == null) return ''
-        const orderInfoItem = item as acceptOrderInfo
+        const orderInfoItem = item as acceptOrderInfoExtend
         return orderInfoItem.workOrderProjectNo
     }
 
     const getPcsDeviceName = (item: any | null): string | null=> {
         if (item == null) return ''
-        const orderInfoItem = item as acceptOrderInfo
+        const orderInfoItem = item as acceptOrderInfoExtend
         return orderInfoItem.pcsDeviceName
     }
 
 	// 根据状态显示不同的时间
 	const getDisplayTime = (item: any | null): string|null => {
 		if (item == null) return null
-		const orderInfoItem = item as acceptOrderInfo
+		const orderInfoItem = item as acceptOrderInfoExtend
 
 		// 如果是"待接单"状态,显示派单时间
 		if (orderInfoItem.workOrderStatus == 'assigned') {
@@ -393,7 +437,7 @@ import {checkPermi, getUserInfo} from '../../utils/storage'
 
 	const getWorkOrderStatus = (item: any | null): string | null => {
 	    if (item == null) return ''
-	    const orderInfoItem = item as acceptOrderInfo
+	    const orderInfoItem = item as acceptOrderInfoExtend
 	    const rawStatus = orderInfoItem.workOrderStatus
 
 	    if (rawStatus==null) return ''
@@ -410,7 +454,7 @@ import {checkPermi, getUserInfo} from '../../utils/storage'
 
 	const getStatusClass = (item: any | null): string => {
 		if (item == null) return ''
-		const orderInfoItem = item as acceptOrderInfo
+		const orderInfoItem = item as acceptOrderInfoExtend
 		const rawStatus = orderInfoItem.workOrderStatus
 		if (rawStatus==null) return ''
 		// const status = rawStatus
@@ -513,7 +557,7 @@ import {checkPermi, getUserInfo} from '../../utils/storage'
 	// 点击列表查看
 	const handleView = (item: any | null): void => {
 	    if (item == null) return
-	    const orderItem = item as acceptOrderInfo
+	    const orderItem = item as acceptOrderInfoExtend
 		uni.navigateTo({
 			url: `/pages/order/detail/index?id=${orderItem.id}&orderType=${orderItem.orderType}`
 		})
@@ -523,13 +567,18 @@ import {checkPermi, getUserInfo} from '../../utils/storage'
     // 点击列表项
     const handleItemClick = (item: any | null, buttonType: string | ''): void => {
         if (item == null) return
-        const orderItem = item as acceptOrderInfo
+        const orderItem = item as acceptOrderInfoExtend
 		if(orderItem.workOrderStatus == 'assigned') {
 			if(buttonType != '' && buttonType == "acceptReturn") {
 				// 跳转到退回页面
 				uni.navigateTo({
 					url: `/pages/order/detail/returnIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
 				})
+			} else if(buttonType != '' && buttonType == "shutdown") {
+				// 跳转到停机页面
+				uni.navigateTo({
+					url: `/pages/order/detail/shutdownIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
+				})
 			} else {
 				// 跳转到接单页面
 				uni.navigateTo({
@@ -552,6 +601,11 @@ import {checkPermi, getUserInfo} from '../../utils/storage'
 				uni.navigateTo({
 					url: `/pages/order/detail/resetIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
 				})
+			} else if(buttonType != '' && buttonType == "shutdown") {
+				// 跳转到停机页面
+				uni.navigateTo({
+					url: `/pages/order/detail/shutdownIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
+				})
 			}
 		} else if(orderItem.workOrderStatus == 'to_approve') {
 			// 跳转到待审批页面

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio