Jelajahi Sumber

维保结单

HD_wangm 3 bulan lalu
induk
melakukan
71a88b40d8

+ 11 - 2
api/order/detail.uts

@@ -59,7 +59,7 @@ export const approveOrder = (gxtWorkOrder: acceptOrderInfo2 | null): Promise<any
 	})
 }
 
-// 
+//
 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;
@@ -88,4 +88,13 @@ export const resetAndStart = (gxtWorkOrder: UTSJSONObject | null): Promise<any>
 		method: 'PUT',
 		data: gxtWorkOrder
 	})
-}
+}
+
+// 完成订单
+export const finishOrder = (gxtWorkOrder: UTSJSONObject | null): Promise<any> => {
+	return request({
+		url: `/mobile/order/finish`,
+		method: 'PUT',
+		data: gxtWorkOrder
+	})
+}

+ 60 - 1
api/order/list.uts

@@ -74,4 +74,63 @@ export const pendingList = (page: number, rows: number, keyword: string | null):
         url: url,
         method: 'GET'
     })
-}
+}
+
+/**
+ * 获取MIS工单列表
+ * @param page 页码
+ * @param rows 每页数量
+ * @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)}`
+    }
+    return request({
+        url: url,
+        method: 'GET'
+    })
+}
+
+/**
+ * 获取MIS工单列表
+ * @param page 页码
+ * @param rows 每页数量
+ * @param keyword 关键字(可选,支持工单编码和风机编号查询)
+ * @param status 工单状态(可选)
+ */
+export const listWorkPerson = (misNo: string | null): Promise<any> => {
+    let url = `/gxt/misInfo/listWorkPerson`
+    if (misNo != null) {
+        url += `?misNo=${encodeURIComponent(misNo)}`
+    }
+
+    // 添加状态筛选参数
+    // if (misNo != null && misNo.length > 0) {
+    //     url += `&misNo=${encodeURIComponent(misNo)}`
+    // }
+    return request({
+        url: url,
+        method: 'GET'
+    })
+}
+/**
+ * 获取MIS工单列表
+ * @param query 查询条件
+ */
+export const listAutoMisInfo = (query: UTSJSONObject | null): Promise<any> => {
+    let url = `/gxt/misInfo/autoList`
+
+    return request({
+        url: url,
+        method: 'GET',
+		data: query
+    })
+}

+ 1 - 1
api/user/list.uts

@@ -7,7 +7,7 @@ import type { UserInfo } from '../../types/user'
 /**
  * 获取用户列表
  */
-export const getUserList = (deptId: any): Promise<any> => {
+export const getUserList = (deptId?: any): Promise<any> => {
 	let url = `/system/user/listNoPermi?status=0`
 	if (deptId != null ) {
 	    // 支持工单编码和风机编号查询

+ 22 - 1
pages.json

@@ -233,6 +233,27 @@
 				"navigationBarTitleText": "工分复评",
 				"navigationStyle": "custom"
 			}
+		},
+		{
+			"path": "pages/order/detail/wbFinalize",
+			"style": {
+				"navigationBarTitleText": "结单",
+				"navigationStyle": "#custom"
+			}
+		},
+		{
+			"path": "pages/order/detail/wbBackfillFinalize",
+			"style": {
+				"navigationBarTitleText": "结单",
+				"navigationStyle": "#custom"
+			}
+		},
+		{
+			"path": "pages/order/detail/wxFinalize",
+			"style": {
+				"navigationBarTitleText": "结单",
+				"navigationStyle": "#custom"
+			}
 		}
 	],
 	"globalStyle": {
@@ -242,4 +263,4 @@
 		"backgroundColor": "#F8F8F8"
 	},
 	"uniIdRouter": {}
-}
+}

+ 1555 - 0
pages/order/detail/wbBackfillFinalize.uvue

@@ -0,0 +1,1555 @@
+<template>
+    <view class="detail-page">
+        <scroll-view class="detail-content" :scroll-y="true">
+            <!-- 工单信息 -->
+            <view class="info-section">
+                <view class="section-title">
+                    <text class="section-title-text">工单信息</text>
+                </view>
+                <view class="info-card">
+                    <view class="info-item">
+                        <text class="info-label">工单编码</text>
+                        <text class="info-value">{{ workOrderProjectNo ?? '' }}</text>
+                    </view>
+                    <view class="info-item">
+                        <text class="info-label">工单类型</text>
+                        <text class="info-value">{{ orderType == '1' ? '维修工单' : '维保工单' }}</text>
+                    </view>
+                    <view class="info-item">
+                        <text class="info-label">风机编号</text>
+                        <text class="info-value">{{ pcsDeviceName ?? '' }}</text>
+                    </view>
+					<view class="info-item">
+					    <text class="info-label">维保中心</text>
+					    <text class="info-value">{{ gxtCenter ?? '' }}</text>
+					</view>
+                    <view class="info-item">
+                        <text class="info-label">场站</text>
+                        <text class="info-value">{{ pcsStationName ?? '' }}</text>
+                    </view>
+					<!-- <view class="info-item">
+					    <text class="info-label">品牌</text>
+					    <text class="info-value">{{ detailData.model ?? '' }}</text>
+					</view> -->
+                    <view class="info-item">
+                        <text class="info-label">机型</text>
+                        <text class="info-value">{{ brand ?? '' }} {{ model ?? '' }}</text>
+                    </view>
+					<view class="info-item">
+					    <text class="info-label">MIS工单</text>
+					    <text class="info-value">{{ misNo ?? '' }}</text>
+					</view>
+					<view class="info-item">
+					    <text class="info-label">接单时间</text>
+					    <text class="info-value">{{ 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">
+                        <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="showStartTimePicker = true">
+								<input
+								    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">
+                            <text class="form-label required">结束时间<text style="color: red;">*</text></text>
+                        </view>
+                        <view class="info-value">
+                            <view class="form-picker" @click="showEndTimePicker = true">
+								<input
+								    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 
+                                type="number"
+                                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 
+                                type="number"
+                                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="请输入工作负责人" 
+                                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>
+                    </view>
+                    
+                    <!-- 维保内容 -->
+                    <view class="info-item full-width">
+                        <view class="info-label">
+                            <text class="form-label required">维保内容<text style="color: red;">*</text></text>
+                        </view>
+                        <view class="info-value">
+                            <textarea
+                                class="textarea-field"
+                                placeholder="请输入维保内容"
+                                v-model="content"
+                                maxlength="500"
+                                :disabled="infoEntry == '1'"
+                                :show-confirm-bar="false"
+                                auto-height
+                            ></textarea>
+                        </view>
+                    </view>
+                    
+                    <!-- 附件上传 -->
+                    <view class="info-item full-width">
+                        <view class="info-label">
+                            <text class="form-label">附件(可选)</text>
+                        </view>
+                        <view class="info-value">
+                            <upload-image
+                                :limit="8"
+                                :modelValue="uploadedFiles"
+                                :businessType="'workOrder'"
+                                @update:modelValue="uploadedFiles = $event as UTSArray<UploadResponse>"
+                            />
+                        </view>
+                    </view>
+                </view>
+            </view>
+
+            
+            <!-- 时间选择器弹窗 -->
+			<!-- Start Date Picker -->
+			<l-popup v-model="showStartTimePicker" position="bottom">
+				<l-date-time-picker
+					title="选择开始时间"
+					:mode="1 | 2 | 4 | 8 | 16"
+					format="YYYY-MM-DD HH:mm"
+					:modelValue="realStartTime"
+					confirm-btn="确定"
+					cancel-btn="取消"
+					@confirm="onStartDateConfirm"
+					@cancel="showStartTimePicker = false">
+				</l-date-time-picker>
+			</l-popup>
+			
+			<!-- End Date Picker -->
+			<l-popup v-model="showEndTimePicker" position="bottom">
+				<l-date-time-picker
+					title="选择结束时间"
+					:mode="31"
+					format="YYYY-MM-DD HH:mm"
+					:modelValue="realStartTime"
+					confirm-btn="确定"
+					cancel-btn="取消"
+					@confirm="onEndDateConfirm"
+					@cancel="showEndTimePicker = false">
+				</l-date-time-picker>
+			</l-popup>
+            
+            <!-- 人员选择弹窗 -->
+            <view v-if="showUserSelect" class="picker-modal">
+                <view class="modal-mask" @click="showUserSelect = false"></view>
+                <view class="modal-content">
+                    <view class="modal-header">
+                        <text class="modal-title">选择检修人员</text>
+                        <text class="modal-close" @click="confirmSelectedUsers">确定</text>
+                    </view>
+					<view class="search-bar">
+						<view class="search-box">
+							<image class="search-icon" src="/static/images/workbench/list/1.png" mode="aspectFit"></image>
+							<input class="search-input" type="text" placeholder="搜索姓名" v-model="userKeyword" @input="handleSearch" />
+							<text v-if="userKeyword.length > 0" class="clear-icon" @click="clearSearch">✕</text>
+						</view>
+					</view>
+                    <scroll-view class="modal-body" scroll-y="true">
+                        <view 
+                            v-for="(user, index) in userList" 
+                            :key="index" 
+                            class="picker-option"
+                            @click="toggleUserSelection(user)"
+                        >
+                            <text class="option-text">{{ (user['nickName'] as string | null) ?? '' }}</text>
+							<text class="option-text">{{ ((user['dept'] as UTSJSONObject | null)?.['deptName'] as string | null) ?? '' }}</text>
+                            <text class="option-check" v-if="isSelected(user)">✓</text>
+                        </view>
+                    </scroll-view>
+                </view>
+            </view>
+            
+            
+        </scroll-view>
+
+        <!-- 确认结单按钮 -->
+        <view class="accept-button-container">
+            <button class="accept-button" @click="handleSubmit" :loading="submitLoading">{{ submitLoading ? '提交中...' : '确认结单' }}</button>
+        </view>
+
+        <!-- 加载中状态 -->
+        <view v-if="loading" class="loading-mask">
+            <text class="loading-text">加载中...</text>
+        </view>
+    </view>
+</template>
+
+<script setup lang="uts">
+    import { ref } from 'vue'
+    import type { acceptOrderInfo } from '../../../types/order'
+    import type { WorkOrderFlow } from '../../../types/flow'
+    import { getOrderInfoById, getRepairOrderInfoById, returnRepairOrder, finishOrder } from '../../../api/order/detail'
+    import { getMisInfoList, listWorkPerson, getOrderList, listAutoMisInfo } from '../../../api/order/list'
+    import type { SysDictData } from '../../../types/dict'
+    import { getDictDataByType } from '../../../api/dict/index'
+    import type { UserInfo } from '../../../types/user'
+    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'
+	
+
+	// 工单信息
+	const orderId = ref<string>('')
+	const workOrderProjectNo = ref<string>('')
+	const workOrderStatus = ref<string>('')
+	const orderType = ref<string>('')
+	const pcsDeviceName = ref<string>('')
+	const gxtCenter = ref<string>('')
+	const pcsStationName = ref<string>('')
+	const brand = ref<string>('')
+	const model = ref<string>('')
+	const acceptTime = ref<string>('')
+	const returnType = ref<string>('')
+	const returnReason = ref<string>("")
+	const returnTypeLabel = ref<string>("")
+	const acceptReturnType = ref<string>('')
+	const acceptReturnReason = ref<string>("")
+	const teamLeaderId = ref<Number | null>(null)
+	const teamLeaderName = ref<string>('')
+	const pauseTime = ref<string>('')
+	const restartTime = ref<string>('')
+
+	// 添加字典加载状态
+	const dictLoaded = ref<boolean>(false)
+
+    // 结单表单相关变量
+    const infoEntry = ref<string>('') // 信息录入
+    const misNo = ref<string>('') // MIS工单编码
+    const workPermitNum = ref<string>('') // 工作票编号
+    const realStartTime = ref<string>('') // 开始时间
+    const realEndTime = ref<string>('') // 结束时间
+    const wwryNum = ref<string>('') // 外委人员数
+    const wlryNum = ref<string>('') // 外来人员数
+    const workGroupMemberName = ref<string>('') // 检修人员
+    const content = ref<string>('') // 维保内容
+    const attachmentUrls = ref<string>('') // 附件URLs(逗号分隔的字符串格式)
+    const uploadedFiles = ref<UploadResponse[]>([]) // 上传的文件对象数组
+	const workOrderPersonList = ref<UTSJSONObject[]>([]) // 检修人员数组
+		const selectedUserIds = ref<string[]>([]) // 选中的用户ID数组
+		const selectedUsers = ref<UTSJSONObject[]>([]) // 选中的用户对象数组
+	
+	
+    
+    // 时间选择器相关变量
+    const showStartTimePicker = ref<boolean>(false)
+    const showEndTimePicker = ref<boolean>(false)
+    const startTimeDate = ref<string>('')
+    const startTimeTime = ref<string>('')
+    const endTimeDate = ref<string>('')
+    const endTimeTime = ref<string>('')
+    
+    // MIS工单选择相关变量
+    const showMisNoQuickSelect = ref<boolean>(false)
+    const quickMisNoList = ref<UTSJSONObject[]>([])
+    // 添加MIS工单列表弹窗显示状态
+    const showMisListModal = ref<boolean>(false)
+    // MIS工单列表数据
+    const misList = ref<UTSJSONObject[]>([])
+	const allMisList = ref<UTSJSONObject[]>([])
+    // 分页信息
+    const misListPage = ref<number>(1)
+    const misListPageSize = ref<number>(999)
+    const misListTotal = ref<number>(0)
+    // 搜索关键词
+    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 {
+            const result = await getDictDataByType('gxt_info_entry') // 假设信息录入类型字典类型为gxt_info_entry
+            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)
+                    }
+                }
+
+                infoEntryOptions.value = dictData
+            }
+        } catch (e: any) {
+            console.error('获取信息录入类型字典失败:', e.message)
+            // 设置默认值
+            infoEntryOptions.value = [
+                { dictValue: '1', dictLabel: 'MIS工单', dictCode: null, dictSort: null, dictType: null, cssClass: null, listClass: null, isDefault: null, status: null, default: null, createTime: null, remark: null },
+                { dictValue: '2', dictLabel: '手工录入', dictCode: null, dictSort: null, dictType: null, cssClass: null, listClass: null, isDefault: null, status: null, default: null, createTime: null, remark: null }
+            ];
+        }
+    }
+    
+    // 获取用户列表
+    const getUserAllList = async (): Promise<void> => {
+        try {
+            // 这里应该调用获取用户列表的API
+            const result = await getLeaderList(-1); // 空参数调用
+			const resultObj = result as UTSJSONObject;
+			const code = resultObj['code'] as number
+			const users = resultObj['data'] as UTSJSONObject[] | null
+			if (code == 200 && users != null ) {
+			    // 解析列表数据
+				// const rows = resultObj['rows'] as UTSJSONObject[]
+			    userList.value = users;
+				userAllList.value = users
+            // userList.value = result.data || [];
+			}
+        } catch (error) {
+            console.error('获取用户列表失败:', error);
+            uni.showToast({
+                title: '获取用户列表失败',
+                icon: 'none'
+            });
+        }
+    };
+    
+    // 验证和提交
+    const submitLoading = ref<boolean>(false)
+    
+    // 信息录入禁用状态
+    const infoEntryDisabled = ref<boolean>(false)
+    
+    // 接受用户名
+    const acceptUserName = ref<string>('')
+
+	// 选择器选项类型
+	type PickerOption = {
+	    label: string
+	    value: string
+	}
+
+	// 选中的挂起原因
+
+	const selectedReasonIndex = ref<number>(-1)
+	const returnTypeOptions = ref<PickerOption[]>([])
+	const showReasonPicker = ref<boolean>(false)
+
+	// 获取负责人列表(使用用户列表接口)
+	const dictList = async (): Promise<void> => {
+	    try {
+			const dictString = ref("")
+			if(workOrderStatus.value != 'to_finish') {
+				dictString.value = "gxt_accept_return_type"
+			} else {
+				dictString.value = "gxt_return_type"
+			}
+
+	        const result = await getDictDataByType(dictString.value)
+	        const resultObj = result as UTSJSONObject
+
+	        if (resultObj['code'] == 200) {
+				const data = resultObj['data'] as any[]
+				const options: PickerOption[] = []
+	            if (data.length > 0) {
+	                for (let i = 0; i < data.length; i++) {
+	                    const item = data[i] as UTSJSONObject
+	                    let dictItem: SysDictData = {
+							dictValue: item['dictValue'] as string | null,
+							dictLabel: item['dictLabel'] as string | null,
+							dictCode: null,
+							dictSort: null,
+							dictType: null,
+							cssClass: null,
+							listClass: null,
+							isDefault: null,
+							status: null,
+							default: null,
+							createTime: null,
+							remark: null
+	                    }
+						// 构建选择器选项
+						options.push({
+							label: dictItem.dictLabel ?? '',
+							value: dictItem.dictValue ?? ''
+						})
+	                }
+	            }
+
+				returnTypeOptions.value = options
+	        }
+	    } catch (e: any) {
+	        console.error('获取挂起原因失败:', e.message)
+	    }
+	}
+
+	// 手动选择负责人
+	const selectLeaderManually = (index: number): void => {
+	    selectedReasonIndex.value = index
+	    if (index >= 0 && index < returnTypeOptions.value.length) {
+	        const selectedOption = returnTypeOptions.value[index]
+	        returnTypeLabel.value = selectedOption.label
+			returnType.value = selectedOption.value
+	    }
+	    showReasonPicker.value = false
+	}
+
+    // 信息录入变化处理
+    const handleInfoEntryChange = (e: UniRadioGroupChangeEvent): void => {
+        // 兼容 radio-group 事件:detail 可能不存在,直接取 e.value
+        const val = e.detail?.value as string | null
+		infoEntry.value = val ?? ''
+        if (infoEntry.value == '1') {
+            // 当选择MIS工单时,清空手工录入的字段
+            workPermitNum.value = '';
+            realStartTime.value = '';
+            realEndTime.value = '';
+            workGroupMemberName.value = '';
+        }
+    };
+
+    // MIS工单编码输入处理
+    const handleMisNoInputFocus = (): void => {
+        showMisNoQuickSelect.value = true;
+    };
+
+    const handleMisNoInputBlur = (): void => {
+        setTimeout(() => {
+            showMisNoQuickSelect.value = false;
+        }, 200);
+    };
+
+    const handleMisNoInput = (e: SysDictData): void => {
+        misNo.value = (e['detail'] as string | null) ?? '';
+        // 这里可以添加实时搜索MIS工单的逻辑
+    };
+
+    const handleMisNoClear = (): void => {
+        misNo.value = '';
+        showMisNoQuickSelect.value = false;
+    };
+
+    const handleMisNoQuickSelect = (item: UTSJSONObject): void => {
+        misNo.value = (item['misNo'] as string | null) ?? '';
+        showMisNoQuickSelect.value = false;
+    };
+    
+    // 获取MIS工单列表
+    const getMisList = async (): Promise<void> => {
+        try {
+            // 调用获取MIS工单列表的API
+            const result = await getMisInfoList(
+                misListPage.value,
+                misListPageSize.value,
+                misListKeyword.value,
+				'结束'
+                // null // 状态筛选,可根据需要添加
+            );
+            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 {
+				const msg = resultObj['msg'] as string | null
+				uni.showToast({
+				    title: msg ?? '获取MIS工单列表失败',
+				    icon: 'none'
+				})
+            }
+        } catch (error: any) {
+            console.error('获取MIS工单列表失败:', error);
+              uni.showToast({
+                  title: error.message ?? '获取MIS工单列表失败',
+                  icon: 'none'
+              });
+        }
+    };
+    
+    // 打开MIS工单选择弹窗
+    const openMisListModal = (): void => {
+        showMisListModal.value = true;
+        misListPage.value = 1; // 重置为第一页
+        getMisList(); // 获取列表数据
+    };
+    
+    // 选择MIS工单
+    const selectMisItem = async (item: UTSJSONObject, index: number): Promise<void> => {
+		selectedMisInfoIndex.value = index
+        // 回填MIS工单相关信息
+        misNo.value = item['misNo'] as string | '';
+        // 查询MIS工单是否已存在
+		const response = await getOrderList(1, 10, misNo.value, '')
+		const responseObj = response as UTSJSONObject
+		const rows = responseObj['rows'] as UTSJSONObject[] | null
+		if (rows != null && rows.length > 0) {
+			uni.showToast({ title: 'MIS工单:' + misNo.value + '已存在', icon: 'none' })
+			misNo.value = ''
+			return
+		}
+		// 查询相关检修人员
+		await listWorkPerson(misNo.value).then(response => {
+			const responseObj = response as UTSJSONObject
+			const rows = responseObj['rows'] as UTSJSONObject[] | null
+			workOrderPersonList.value = rows ?? []
+			if (rows != null && rows.length > 0) {
+				const nickNames = rows
+					.map((person: UTSJSONObject) => (person['nickName'] as string | null) ?? '')
+					.join(',');
+				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
+		userList.value = userAllList.value.filter(leader => {
+			const nickName = leader['nickName'] as string | null
+			return nickName != null && nickName.indexOf(keyword) >= 0
+		})
+	}
+    
+    // 关闭MIS工单选择弹窗
+    const closeMisListModal = (): void => {
+        showMisListModal.value = false;
+    };
+    
+	// 搜索
+	const searchMisList = (): void => {
+		const keyword = misListKeyword.value
+		misList.value = allMisList.value.filter(misInfo => {
+			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
+	}
+
+    // 检查用户是否已被选中
+    const isSelected = (user: UTSJSONObject): boolean => {
+        const userId = user['userId'] as string | number | null;
+        if (userId !== null) {
+            return selectedUserIds.value.includes(userId.toString());
+        }
+        // 如果没有userId,则比较nickName
+        const nickName = user['nickName'] as string | null;
+        if (nickName !== null) {
+            return selectedUsers.value.some(selected => 
+                (selected['nickName'] as string | null) === nickName
+            );
+        }
+        return false;
+    };
+
+    // 切换用户选择状态
+    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 => 
+                    (selected['userId'] as string | number | null)?.toString() !== userIdStr
+                );
+            } else {
+                // 添加选择
+                selectedUserIds.value.push(userIdStr);
+                selectedUsers.value.push(user);
+            }
+        } else if (nickName !== null) {
+            // 如果没有userId,通过nickName来识别
+            const index = selectedUsers.value.findIndex(selected => 
+                (selected['nickName'] as string | null) === nickName
+            );
+            if (index > -1) {
+                // 取消选择
+                selectedUsers.value.splice(index, 1);
+                // 同时移除对应的userId(如果有的话)
+                const userToRemoveId = user['userId'] as string | number | null;
+                if (userToRemoveId !== null) {
+                    const idIndex = selectedUserIds.value.indexOf(userToRemoveId.toString());
+                    if (idIndex > -1) {
+                        selectedUserIds.value.splice(idIndex, 1);
+                    }
+                }
+            } else {
+                // 添加选择
+                selectedUsers.value.push(user);
+                const userToAddId = user['userId'] as string | number | null;
+                if (userToAddId !== null) {
+                    selectedUserIds.value.push(userToAddId.toString());
+                }
+            }
+        }
+    };
+
+    // 确认选择的用户
+    const confirmSelectedUsers = (): void => {
+        // 将选中的用户姓名拼接成字符串
+        const nickNames = selectedUsers.value
+            .map(user => (user['nickName'] as string | null) ?? '')
+            .filter(name => name !== '')
+            .join(',');
+        
+        workGroupMemberName.value = nickNames;
+        
+        // 更新workOrderPersonList为选中的用户
+        workOrderPersonList.value = [...selectedUsers.value];
+        
+        showUserSelect.value = false;
+    };
+
+
+    // 表单验证
+    const validateForm = (): boolean => {
+        if (infoEntry.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;
+        }
+
+        if (infoEntry.value == '1' && (misNo.value == '')) {
+            uni.showToast({
+                title: '请输入MIS工单编码',
+                icon: 'none'
+            });
+            return false;
+        }
+
+        if (workPermitNum.value == '') {
+            uni.showToast({
+                title: '请输入工作票编号',
+                icon: 'none'
+            });
+            return false;
+        }
+
+        if (realStartTime.value == '') {
+            uni.showToast({
+                title: '请选择开始时间',
+                icon: 'none'
+            });
+            return false;
+        }
+
+        if (realEndTime.value == '') {
+            uni.showToast({
+                title: '请选择结束时间',
+                icon: 'none'
+            });
+            return false;
+        }
+
+        if (new Date(realEndTime.value) <= new Date(realStartTime.value)) {
+            uni.showToast({
+                title: '结束时间必须大于开始时间',
+                icon: 'none'
+            });
+            return false;
+        }
+
+        // if (infoEntry.value == '2' && (workGroupMemberName.value == '')) {
+        //     uni.showToast({
+        //         title: '请选择检修人员',
+        //         icon: 'none'
+        //     });
+        //     return false;
+        // }
+
+        return true;
+    };
+	
+	const isDealing = ref(false)
+	const hasDealed = ref(false)
+	// 提交表单
+	const handleSubmit = async (): Promise<void> => {
+	    if (!validateForm()) {
+	        return;
+	    }
+	
+	    submitLoading.value = true;
+	    try {
+			if (isDealing.value || hasDealed.value) return // 双重保险
+			isDealing.value = true
+	        // 确保附件URLs是最新的逗号分隔格式
+	        attachmentUrls.value = uploadedFiles.value.map(file => file.url).join(',');
+	        
+	        const finishData = {
+	            id: orderId.value,
+	            orderType: orderType.value,
+	            workOrderProjectNo: workOrderProjectNo.value,
+	            infoEntry: infoEntry.value,
+	            misNo: misNo.value,
+	            workPermitNum: workPermitNum.value,
+	            realStartTime: realStartTime.value,
+	            realEndTime: realEndTime.value,
+	            wwryNum: wwryNum.value,
+	            wlryNum: wlryNum.value,
+	            workGroupMemberName: workGroupMemberName.value,
+	            content: content.value,
+	            attachmentUrls: attachmentUrls.value,
+				workOrderPersonList: workOrderPersonList.value,
+				teamLeaderId: teamLeaderId.value,
+				teamLeaderName: teamLeaderName.value,
+				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: '结单成功',
+	                icon: 'success'
+	            });
+				hasDealed.value = true
+	            // 使用事件总线通知列表页面刷新
+	            uni.$emit('refreshOrderList', {});
+	            uni.$emit('refreshAssignedCount');
+	            uni.$emit('refreshOverdueCount');
+	
+	            setTimeout(() => {
+	                uni.navigateBack();
+	            }, 800);
+	        } else {
+	            const msg = resultObj['msg'] as string;
+	            uni.showToast({
+	                title: msg.length > 0 ? msg : '结单失败',
+	                icon: 'none'
+	            });
+	        }
+	    } catch (error: any) {
+	        console.error('结单失败:', error);
+	        uni.showToast({
+	            title: '结单失败',
+	            icon: 'none'
+	        });
+	    } finally {
+	        submitLoading.value = false;
+			isDealing.value = false // 无论成功失败都解锁
+	    }
+	};
+
+
+    const loading = ref<boolean>(false)
+
+    // 加载详情数据
+    const loadDetail = async (id: string, orderType?: string): 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) {
+				workOrderStatus.value = (data['workOrderStatus'] as string | null) ?? ''
+				workOrderProjectNo.value = (data['workOrderProjectNo'] as string | null) ?? ''
+				pcsDeviceName.value = (data['pcsDeviceName'] as string | null) ?? ''
+				gxtCenter.value = (data['gxtCenter'] as string | null) ?? ''
+				pcsStationName.value = (data['pcsStationName'] as string | null) ?? ''
+				brand.value = (data['brand'] as string | null) ?? ''
+				model.value = (data['model'] as string | null) ?? ''
+				acceptTime.value = (data['acceptTime'] as string | null) ?? ''
+				acceptUserName.value = (data['acceptUserName'] as string | null) ?? ''
+				// 初始化结单表单默认值
+				infoEntry.value = '1' // 默认为手工录入
+				teamLeaderId.value = (data['teamLeaderId'] as Number | null) ?? null
+				teamLeaderName.value = (data['teamLeaderName'] as string | null) ?? ''
+				returnType.value = workOrderStatus.value == 'to_finish' ? '1' : ''
+				content.value = (data['content'] as string | null) ?? ''
+				// 初始化附件数据
+				const attachmentUrlsFromServer = (data['attachmentUrls'] as string | null) ?? ''
+				if (attachmentUrlsFromServer.length > 0) {
+					attachmentUrls.value = attachmentUrlsFromServer
+					// 将逗号分隔的URL字符串转换为UploadResponse对象数组
+					const urls = attachmentUrlsFromServer.split(',')
+					const fileArr : UploadResponse[] = []
+					for (let i = 0; i < urls.length; i++) {
+						const url = urls[i]
+						const item : UploadResponse = {
+							url: url,
+							fileId: '',
+							fileName: url.substring(url.lastIndexOf('/') + 1),
+							filePath: url,
+							fileSize: 0,
+							fileExt: url.substring(url.lastIndexOf('.') + 1),
+							businessType: 'workOrder'
+						}
+						fileArr.push(item)
+					}
+					uploadedFiles.value = fileArr
+				}
+				pauseTime.value = (data['pauseTime'] as string | null) ?? ''
+				restartTime.value = (data['restartTime'] as string | null) ?? ''
+				
+				if(pauseTime.value != '' && restartTime.value != '') {	
+					const queryParams = {
+						pauseTime: pauseTime.value,
+						restartTime: restartTime.value,
+						pcsDeviceName: pcsDeviceName.value,
+						pcsStationName: pcsStationName.value,
+						workOrderStatus: '结束'
+					} as UTSJSONObject;
+					const result =  await listAutoMisInfo(queryParams)
+					// 提取响应数据
+					const resultObj = result as UTSJSONObject
+					const code = resultObj['code'] as number
+					const misInfo = resultObj['rows'] as UTSJSONObject[] | null
+					if (code == 200 && misInfo != null) {
+						if(misInfo.length > 0 && misInfo.length == 1) {
+							// 有工作票号提示
+							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
+								if (rows != null && rows.length > 0) {
+									misNo.value = ''
+									infoEntry.value = '2'
+									uni.showToast({
+										title: '未找到匹配的MIS工单,请确认风机停复机时间是否已录入工效通系统或请进入工作票录入方式',
+										icon: 'none'
+									});
+									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) ?? ''
+									workPermitNum.value = (misInfo[0]['workPermitNum'] as string | null) ?? ''
+									// 查询相关检修人员
+									await listWorkPerson(misNo.value).then(response => {
+										const responseObj = response as UTSJSONObject
+										const rows = responseObj['rows'] as UTSJSONObject[] | null
+										workOrderPersonList.value = rows ?? []
+										if (rows != null && rows.length > 0) {
+											// 查询负责人信息并回填
+											for (const person of workOrderPersonList.value) {
+											  // 严格判断isLeader为1(兼容数字/字符串类型)
+											  if (person.isLeader == 1) {
+												teamLeaderName.value = (person.nickName as string | null) ?? '';
+												break; // 找到后立即停止循环
+											  }
+											}
+											const nickNames = rows
+												.map((person: UTSJSONObject) => (person['nickName'] as string | null) ?? '')
+												.join(',');
+											workGroupMemberName.value = nickNames;
+										}
+									})
+								}
+								
+							} else {
+								misNo.value = ''
+								infoEntry.value = '2'
+								uni.showToast({
+									title: '已匹配到MIS工单,但未关联工作票号,系统无法自动结单,请进入工作票录入方式。',
+									icon: 'none'
+								});
+								return
+							}
+						} else if(misInfo.length == 0) {
+							misNo.value = ''
+							infoEntry.value = '2'
+							uni.showToast({
+								title: '未找到匹配的MIS工单,请确认风机停复机时间是否已录入工效通系统或请进入工作票录入方式',
+								icon: 'none'
+							});
+							return
+						} else if(misInfo.length > 1) {
+							infoEntryDisabled.value = false
+						}
+					}
+				} else {
+					infoEntryDisabled.value = true
+					misNo.value = ''
+					infoEntry.value = '2'
+					uni.showToast({
+						title: '未找到匹配的MIS工单,请确认风机停复机时间是否已录入工效通系统或请进入工作票录入方式',
+						icon: 'none'
+					});
+				}
+				
+				
+				// await dictList()
+				if (returnTypeOptions.value.length > 0 && workOrderStatus.value == 'to_finish') {
+					// returnTypeLabel.value = returnTypeOptions.value[0].label
+					// 循环匹配
+				    for (const option of returnTypeOptions.value) {
+						// 严格匹配value
+						if (returnType.value == option.value) {
+						  returnTypeLabel.value = option.label;
+						  break; // 匹配成功后跳出循环,提升性能
+						}
+					}
+				}
+
+            } else {
+                const msg = resultObj['msg'] as string | null
+                uni.showToast({
+                    title: msg ?? '加载失败',
+                    icon: 'none'
+                })
+            }
+
+        } catch (e: any) {
+            uni.showToast({
+                title: e.message ?? '加载失败',
+                icon: 'none'
+            })
+        } finally {
+            loading.value = false
+        }
+    }
+
+    // 页面加载
+    onLoad((options: any) => {
+        const params = options as UTSJSONObject
+        const id = params['id'] as string | null
+		const orderTypeParam = params['orderType'] as string | null
+        if (id != null && orderTypeParam != null) {
+            // 先尝试从参数中获取orderType
+            // const orderTypeNumber = parseInt(orderTypeParam)
+			orderType.value = orderTypeParam
+			orderId.value = id
+            loadDetail(id, orderTypeParam)
+        }
+    })
+	// 初始化
+	onMounted(() => {
+        getUserAllList();
+        loadInfoEntryDictList();
+    })
+</script>
+
+<style lang="scss">
+    .detail-page {
+        flex: 1;
+        background-color: #e8f0f9;
+    }
+
+    .detail-content {
+        flex: 1;
+        padding: 20rpx 0;
+    }
+
+    .info-section {
+        margin: 0 30rpx 24rpx;
+
+        .section-title {
+            position: relative;
+            padding-left: 20rpx;
+            margin-bottom: 20rpx;
+
+            &::before {
+                // content: '';
+                position: absolute;
+                left: 0;
+                top: 50%;
+                transform: translateY(-50%);
+                width: 8rpx;
+                height: 32rpx;
+                background-color: #007aff;
+                border-radius: 4rpx;
+            }
+
+            &-text {
+                font-size: 32rpx;
+                font-weight: bold;
+                color: #333333;
+            }
+        }
+
+        .info-card {
+            background-color: #ffffff;
+            border-radius: 16rpx;
+            padding: 30rpx;
+
+            .info-item {
+                flex-direction: row;
+                padding: 20rpx 0;
+                border-bottom: 1rpx solid #f0f0f0;
+
+                &:last-child {
+                    border-bottom: none;
+                }
+
+                &.full-width {
+                    flex-direction: column;
+
+                    .info-label {
+                        margin-bottom: 12rpx;
+                    }
+
+                    .info-value {
+                        line-height: 44rpx;
+                    }
+                }
+
+                .info-label {
+                    width: 240rpx;
+                    font-size: 28rpx;
+                    color: #666666;
+                    white-space: nowrap;
+                }
+
+                .info-value {
+                    flex: 1;
+                    font-size: 28rpx;
+                    color: #333333;
+                    text-align: right;
+
+                    &.highlight {
+                        color: #007aff;
+                        font-weight: bold;
+                    }
+
+                    &.input {
+                        text-align: left;
+                        border: 1rpx solid #e0e0e0;
+                        border-radius: 8rpx;
+                        padding: 10rpx;
+                    }
+                }
+            }
+
+            .flow-item {
+                padding: 20rpx 0;
+                border-bottom: 1rpx solid #f0f0f0;
+
+                &:last-child {
+                    border-bottom: none;
+                }
+
+                .flow-header {
+                    flex-direction: row;
+                    justify-content: space-between;
+                    margin-bottom: 10rpx;
+
+                    .flow-operator {
+                        font-size: 28rpx;
+                        color: #333333;
+                        font-weight: bold;
+                    }
+
+                    .flow-time {
+                        font-size: 24rpx;
+                        color: #999999;
+                    }
+                }
+
+                .flow-content {
+                    flex-direction: column;
+
+                    .flow-action {
+                        font-size: 26rpx;
+                        color: #666666;
+                        margin-bottom: 8rpx;
+                    }
+
+                    .flow-remark {
+                        font-size: 24rpx;
+                        color: #999999;
+                        background-color: #f5f5f5;
+                        padding: 10rpx;
+                        border-radius: 8rpx;
+                    }
+                }
+            }
+
+            .no-data {
+                text-align: center;
+                padding: 40rpx 0;
+                font-size: 28rpx;
+                color: #999999;
+            }
+        }
+    }
+
+    .accept-button-container {
+        padding: 30rpx 30rpx 50rpx;
+        background-color: #ffffff;
+
+        .accept-button {
+            width: 100%;
+            height: 80rpx;
+            background-color: #007aff;
+            color: #ffffff;
+            font-size: 32rpx;
+            border-radius: 16rpx;
+            border: none;
+
+            &:active {
+                background-color: #0062cc;
+            }
+        }
+    }
+
+    .loading-mask {
+        position: absolute;
+        top: 0;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        justify-content: center;
+        align-items: center;
+        background-color: rgba(0, 0, 0, 0.3);
+
+        .loading-text {
+            padding: 30rpx 60rpx;
+            background-color: rgba(0, 0, 0, 0.7);
+            color: #ffffff;
+            font-size: 28rpx;
+            border-radius: 12rpx;
+        }
+    }
+	.picker-modal {
+	    position: fixed;
+	    top: 0;
+	    left: 0;
+	    right: 0;
+	    bottom: 0;
+	    z-index: 1000;
+	}
+
+	.modal-mask {
+	    position: absolute;
+	    top: 0;
+	    left: 0;
+	    right: 0;
+	    bottom: 0;
+	    background-color: rgba(0, 0, 0, 0.5);
+	}
+
+	.modal-content {
+	    position: absolute;
+	    bottom: 0;
+	    left: 0;
+	    right: 0;
+	    background-color: #ffffff;
+	    border-top-left-radius: 16rpx;
+	    border-top-right-radius: 16rpx;
+	    min-height: 700rpx;
+	}
+
+	.modal-header {
+	    flex-direction: row;
+	    justify-content: space-between;
+	    align-items: center;
+	    padding: 30rpx;
+	    border-bottom: 1rpx solid #f0f0f0;
+	}
+
+	.modal-title {
+	    font-size: 32rpx;
+	    font-weight: bold;
+	    color: #333333;
+	}
+
+	.modal-close {
+	    font-size: 28rpx;
+	    color: #007aff;
+	}
+
+	.modal-body {
+	    max-height: 800rpx;
+		min-height: 800rpx;
+	}
+
+	.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;
+	}
+
+	.picker-option:last-child {
+	    border-bottom: none;
+	}
+
+
+	.option-text {
+	    font-size: 28rpx;
+	    color: #333333;
+	    margin-bottom: 10rpx;
+	}
+
+	.option-text:last-child {
+	    margin-bottom: 0;
+	}
+
+	.option-check {
+	    font-size: 28rpx;
+	    color: #007aff;
+	}
+	
+	.empty-tip {
+		justify-content: space-between;
+		padding: 24rpx 30rpx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		color: #999;
+	}
+
+	.picker-option {
+	    flex-direction: row;
+	    justify-content: space-between;
+	    align-items: center;
+	    padding: 24rpx 30rpx;
+	    border-bottom: 1rpx solid #f0f0f0;
+	}
+
+	.picker-option:last-child {
+	    border-bottom: none;
+	}
+
+	.picker-option.selected {
+	    background-color: #f8f9fa;
+	}
+
+	.option-text {
+	    font-size: 28rpx;
+	    color: #333333;
+	}
+
+	.mis-list {
+    flex: 1;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+}
+
+	.empty-tip {
+	    text-align: center;
+	    padding: 40rpx;
+	    color: #999;
+	    font-size: 28rpx;
+	}
+
+
+
+
+
+.form-item {
+	flex-direction: row;
+	padding: 20rpx 0;
+	border-bottom: 1rpx solid #f0f0f0;
+}
+
+.reject-reason-textarea {
+    width: 100%;
+    min-height: 100rpx;
+    line-height: 1.5;
+}
+
+.input-field {
+    width: 100%;
+    height: 60rpx;
+    padding: 0 20rpx;
+    border: 1rpx solid #e0e0e0;
+    border-radius: 8rpx;
+    font-size: 28rpx;
+    background-color: #f8f9fa;
+}
+
+.select-mis-btn {
+    width: 150rpx;
+    height: 60rpx;
+    margin-left: 10rpx;
+    background-color: #007aff;
+    color: #fff;
+    border: none;
+    border-radius: 8rpx;
+    font-size: 24rpx;
+}
+
+.textarea-field {
+    width: 100%;
+    min-height: 120rpx;
+    padding: 20rpx;
+    border: 1rpx solid #e0e0e0;
+    border-radius: 8rpx;
+    font-size: 28rpx;
+    background-color: #f8f9fa;
+}
+
+.radio-label {
+    display: flex;
+    align-items: center;
+    margin-right: 30rpx;
+}
+
+.quick-select-dropdown {
+    position: absolute;
+    top: 100%;
+    left: 0;
+    right: 0;
+    background: #fff;
+    border: 1rpx solid #ddd;
+    border-top: none;
+    z-index: 1000;
+    max-height: 300rpx;
+}
+
+.quick-select-item {
+    padding: 20rpx;
+    border-bottom: 1rpx solid #eee;
+}
+
+.mis-no {
+    font-size: 28rpx;
+    color: #333;
+}
+
+.search-bar {
+		padding: 20rpx 30rpx;
+		background-color: #d7eafe;
+	}
+
+	.search-box {
+		flex-direction: row;
+		align-items: center;
+		height: 72rpx;
+		padding: 0 24rpx;
+		background-color: #f5f5f5;
+		border-radius: 36rpx;
+
+		.search-icon {
+			width: 32rpx;
+			height: 32rpx;
+			margin-right: 12rpx;
+		}
+
+		.search-input {
+			flex: 1;
+			font-size: 28rpx;
+			color: #333333;
+		}
+
+		.clear-icon {
+			margin-left: 12rpx;
+			font-size: 28rpx;
+			color: #999999;
+		}
+	}
+
+.mis-list {
+    flex: 1;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+}
+
+.select-users-count {
+    margin-left: 10rpx;
+    font-size: 24rpx;
+    color: #666;
+}
+
+
+</style>
+
+
+
+
+

+ 1670 - 0
pages/order/detail/wbFinalize.uvue

@@ -0,0 +1,1670 @@
+<template>
+    <view class="detail-page">
+        <scroll-view class="detail-content" :scroll-y="true">
+            <!-- 工单信息 -->
+            <view class="info-section">
+                <view class="section-title">
+                    <text class="section-title-text">工单信息</text>
+                </view>
+                <view class="info-card">
+                    <view class="info-item">
+                        <text class="info-label">工单编码</text>
+                        <text class="info-value">{{ workOrderProjectNo ?? '' }}</text>
+                    </view>
+                    <view class="info-item">
+                        <text class="info-label">工单类型</text>
+                        <text class="info-value">{{ orderType == '1' ? '维修工单' : '维保工单' }}</text>
+                    </view>
+                    <view class="info-item">
+                        <text class="info-label">风机编号</text>
+                        <text class="info-value">{{ pcsDeviceName ?? '' }}</text>
+                    </view>
+					<view class="info-item">
+					    <text class="info-label">维保中心</text>
+					    <text class="info-value">{{ gxtCenter ?? '' }}</text>
+					</view>
+                    <view class="info-item">
+                        <text class="info-label">场站</text>
+                        <text class="info-value">{{ pcsStationName ?? '' }}</text>
+                    </view>
+					<!-- <view class="info-item">
+					    <text class="info-label">品牌</text>
+					    <text class="info-value">{{ detailData.model ?? '' }}</text>
+					</view> -->
+                    <view class="info-item">
+                        <text class="info-label">机型</text>
+                        <text class="info-value">{{ brand ?? '' }} {{ model ?? '' }}</text>
+                    </view>
+					<view class="info-item">
+					    <text class="info-label">接单时间</text>
+					    <text class="info-value">{{ acceptTime ?? '' }}</text>
+					</view>
+                </view>
+            </view>
+            <!-- 结单表单 -->
+            <view class="info-section">
+                <view class="section-title">
+                    <text class="section-title-text">结单信息</text>
+                </view>
+                <view class="info-card">
+                    <!-- 信息录入 -->
+                    <view class="info-item">
+                        <view class="info-label">
+                            <text class="form-label required">信息录入<text style="color: red;">*</text></text>
+                        </view>
+                        <view class="info-value">
+                            <radio-group @change="handleInfoEntryChange" :disabled="infoEntryDisabled" class="uni-flex uni-row radio-group">
+                                <view v-for="(option, index) in infoEntryOptions" :key="index" class="radio-label">
+                                    <radio :value="option.dictValue" :checked="infoEntry == option.dictValue">{{ option.dictLabel }}</radio>
+                                    <!-- <text></text> -->
+                                </view>
+                            </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>
+                    </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="请输入工作票编号" 
+                                v-model="workPermitNum"
+                                maxlength="20"
+                                :disabled="infoEntry == '1'"
+                            />
+                        </view>
+                    </view>
+                    
+                    <!-- 开始时间 -->
+                    <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="showStartTimePicker = true">
+								<input
+								    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">
+                            <text class="form-label required">结束时间<text style="color: red;">*</text></text>
+                        </view>
+                        <view class="info-value">
+                            <view class="form-picker" @click="showEndTimePicker = true">
+								<input
+								    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 
+                                type="number"
+                                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 
+                                type="number"
+                                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="请输入工作负责人" 
+                                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>
+                    </view>
+                    
+                    <!-- 维保内容 -->
+                    <view class="info-item full-width">
+                        <view class="info-label">
+                            <text class="form-label required">维保内容<text style="color: red;">*</text></text>
+                        </view>
+                        <view class="info-value">
+                            <textarea
+                                class="textarea-field"
+                                placeholder="请输入维保内容"
+                                v-model="content"
+                                maxlength="500"
+                                :disabled="infoEntry == '1'"
+                                :show-confirm-bar="false"
+                                auto-height
+                            ></textarea>
+                        </view>
+                    </view>
+                    
+                    <!-- 附件上传 -->
+                    <view class="info-item full-width">
+                        <view class="info-label">
+                            <text class="form-label">附件(可选)</text>
+                        </view>
+                        <view class="info-value">
+                            <upload-image
+                                :limit="8"
+                                :modelValue="uploadedFiles"
+                                :businessType="'workOrder'"
+                                @update:modelValue="uploadedFiles = $event as UTSArray<UploadResponse>"
+                            />
+                        </view>
+                    </view>
+                </view>
+            </view>
+
+            
+            <!-- 时间选择器弹窗 -->
+			<!-- Start Date Picker -->
+			<l-popup v-model="showStartTimePicker" position="bottom">
+				<l-date-time-picker
+					title="选择开始时间"
+					:mode="1 | 2 | 4 | 8 | 16"
+					format="YYYY-MM-DD HH:mm"
+					:modelValue="realStartTime"
+					confirm-btn="确定"
+					cancel-btn="取消"
+					@confirm="onStartDateConfirm"
+					@cancel="showStartTimePicker = false">
+				</l-date-time-picker>
+			</l-popup>
+			
+			<!-- End Date Picker -->
+			<l-popup v-model="showEndTimePicker" position="bottom">
+				<l-date-time-picker
+					title="选择结束时间"
+					:mode="31"
+					format="YYYY-MM-DD HH:mm"
+					:modelValue="realStartTime"
+					confirm-btn="确定"
+					cancel-btn="取消"
+					@confirm="onEndDateConfirm"
+					@cancel="showEndTimePicker = false">
+				</l-date-time-picker>
+			</l-popup>
+            
+            <!-- 人员选择弹窗 -->
+            <view v-if="showUserSelect" class="picker-modal">
+                <view class="modal-mask" @click="showUserSelect = false"></view>
+                <view class="modal-content">
+                    <view class="modal-header">
+                        <text class="modal-title">选择检修人员</text>
+                        <text class="modal-close" @click="confirmSelectedUsers">确定</text>
+                    </view>
+					<view class="search-bar">
+						<view class="search-box">
+							<image class="search-icon" src="/static/images/workbench/list/1.png" mode="aspectFit"></image>
+							<input class="search-input" type="text" placeholder="搜索姓名" v-model="userKeyword" @input="handleSearch" />
+							<text v-if="userKeyword.length > 0" class="clear-icon" @click="clearSearch">✕</text>
+						</view>
+					</view>
+                    <scroll-view class="modal-body" scroll-y="true">
+                        <view 
+                            v-for="(user, index) in userList" 
+                            :key="index" 
+                            class="picker-option"
+                            @click="toggleUserSelection(user)"
+                        >
+                            <text class="option-text">{{ (user['nickName'] as string | null) ?? '' }}</text>
+							<text class="option-text">{{ ((user['dept'] as UTSJSONObject | null)?.['deptName'] as string | null) ?? '' }}</text>
+                            <text class="option-check" v-if="isSelected(user)">✓</text>
+                        </view>
+                    </scroll-view>
+                </view>
+            </view>
+            
+            <!-- MIS工单列表弹窗 -->
+            <view v-if="showMisListModal" class="picker-modal">
+                <view class="modal-mask" @click="closeMisListModal"></view>
+                <view class="modal-content">
+                    <view class="modal-header">
+                        <text class="modal-title">选择MIS工单</text>
+                        <text class="modal-close" @click="closeMisListModal">取消</text>
+                    </view>
+                    <!-- 搜索栏 -->
+                    <view class="search-bar">
+                        <view class="search-box">
+                            <image class="search-icon" src="/static/images/workbench/list/1.png" mode="aspectFit"></image>
+                            <input class="search-input" type="text" placeholder="搜索 MIS工单编码" v-model="misListKeyword" @input="searchMisList" />
+                            <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">
+							<view
+								v-for="(item, index) in misList"
+								:key="index"
+								class="picker-option"
+								@click="selectMisItem(item, index)"
+							>
+								<!-- <text class="option-text">{{ option.label }}</text>
+								<text class="option-text">{{ option.value }}</text> -->
+								<text class="option-text">{{ ((item['misNo'] as string | null) ?? '-')}}</text>
+								<text class="option-text">{{ item['workPermitNum'] as string | null ?? '-' }}</text>
+								<text v-if="index === selectedMisInfoIndex" class="option-check">✓</text>
+							</view>
+						</view>
+						<!-- 无数据时显示提示 -->
+						<view v-else class="empty-tip">
+						    <text>未找到匹配的人员</text>
+						</view>
+					</scroll-view>
+                </view>
+            </view>
+        </scroll-view>
+
+        <!-- 确认结单按钮 -->
+        <view class="accept-button-container">
+            <button class="accept-button" @click="handleSubmit" :loading="submitLoading">{{ submitLoading ? '提交中...' : '确认结单' }}</button>
+        </view>
+
+        <!-- 加载中状态 -->
+        <view v-if="loading" class="loading-mask">
+            <text class="loading-text">加载中...</text>
+        </view>
+    </view>
+</template>
+
+<script setup lang="uts">
+    import { ref } from 'vue'
+    import type { acceptOrderInfo } from '../../../types/order'
+    import type { WorkOrderFlow } from '../../../types/flow'
+    import { getOrderInfoById, getRepairOrderInfoById, returnRepairOrder, finishOrder } from '../../../api/order/detail'
+    import { getMisInfoList, listWorkPerson, getOrderList, listAutoMisInfo } from '../../../api/order/list'
+    import type { SysDictData } from '../../../types/dict'
+    import { getDictDataByType } from '../../../api/dict/index'
+    import type { UserInfo } from '../../../types/user'
+    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'
+	
+
+	// 工单信息
+	const orderId = ref<string>('')
+	const workOrderProjectNo = ref<string>('')
+	const workOrderStatus = ref<string>('')
+	const orderType = ref<string>('')
+	const pcsDeviceName = ref<string>('')
+	const gxtCenter = ref<string>('')
+	const pcsStationName = ref<string>('')
+	const brand = ref<string>('')
+	const model = ref<string>('')
+	const acceptTime = ref<string>('')
+	const returnType = ref<string>('')
+	const returnReason = ref<string>("")
+	const returnTypeLabel = ref<string>("")
+	const acceptReturnType = ref<string>('')
+	const acceptReturnReason = ref<string>("")
+	const teamLeaderId = ref<Number | null>(null)
+	const teamLeaderName = ref<string>('')
+	const pauseTime = ref<string>('')
+	const restartTime = ref<string>('')
+
+	// 添加字典加载状态
+	const dictLoaded = ref<boolean>(false)
+
+    // 结单表单相关变量
+    const infoEntry = ref<string>('') // 信息录入
+    const misNo = ref<string>('') // MIS工单编码
+    const workPermitNum = ref<string>('') // 工作票编号
+    const realStartTime = ref<string>('') // 开始时间
+    const realEndTime = ref<string>('') // 结束时间
+    const wwryNum = ref<string>('') // 外委人员数
+    const wlryNum = ref<string>('') // 外来人员数
+    const workGroupMemberName = ref<string>('') // 检修人员
+    const content = ref<string>('') // 维保内容
+    const attachmentUrls = ref<string>('') // 附件URLs(逗号分隔的字符串格式)
+    const uploadedFiles = ref<UploadResponse[]>([]) // 上传的文件对象数组
+	const workOrderPersonList = ref<UTSJSONObject[]>([]) // 检修人员数组
+		const selectedUserIds = ref<string[]>([]) // 选中的用户ID数组
+		const selectedUsers = ref<UTSJSONObject[]>([]) // 选中的用户对象数组
+	
+	
+    
+    // 时间选择器相关变量
+    const showStartTimePicker = ref<boolean>(false)
+    const showEndTimePicker = ref<boolean>(false)
+    const startTimeDate = ref<string>('')
+    const startTimeTime = ref<string>('')
+    const endTimeDate = ref<string>('')
+    const endTimeTime = ref<string>('')
+    
+    // MIS工单选择相关变量
+    const showMisNoQuickSelect = ref<boolean>(false)
+    const quickMisNoList = ref<UTSJSONObject[]>([])
+    // 添加MIS工单列表弹窗显示状态
+    const showMisListModal = ref<boolean>(false)
+    // MIS工单列表数据
+    const misList = ref<UTSJSONObject[]>([])
+	const allMisList = ref<UTSJSONObject[]>([])
+    // 分页信息
+    const misListPage = ref<number>(1)
+    const misListPageSize = ref<number>(999)
+    const misListTotal = ref<number>(0)
+    // 搜索关键词
+    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 {
+            const result = await getDictDataByType('gxt_info_entry') // 假设信息录入类型字典类型为gxt_info_entry
+            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)
+                    }
+                }
+
+                infoEntryOptions.value = dictData
+            }
+        } catch (e: any) {
+            console.error('获取信息录入类型字典失败:', e.message)
+            // 设置默认值
+            infoEntryOptions.value = [
+                { dictValue: '1', dictLabel: 'MIS工单', dictCode: null, dictSort: null, dictType: null, cssClass: null, listClass: null, isDefault: null, status: null, default: null, createTime: null, remark: null },
+                { dictValue: '2', dictLabel: '手工录入', dictCode: null, dictSort: null, dictType: null, cssClass: null, listClass: null, isDefault: null, status: null, default: null, createTime: null, remark: null }
+            ];
+        }
+    }
+    
+    // 获取用户列表
+    const getUserAllList = async (): Promise<void> => {
+        try {
+            // 这里应该调用获取用户列表的API
+            const result = await getLeaderList(-1); // 空参数调用
+			const resultObj = result as UTSJSONObject;
+			const code = resultObj['code'] as number
+			const users = resultObj['data'] as UTSJSONObject[] | null
+			if (code == 200 && users != null ) {
+			    // 解析列表数据
+				// const rows = resultObj['rows'] as UTSJSONObject[]
+			    userList.value = users;
+				userAllList.value = users
+            // userList.value = result.data || [];
+			}
+        } catch (error) {
+            console.error('获取用户列表失败:', error);
+            uni.showToast({
+                title: '获取用户列表失败',
+                icon: 'none'
+            });
+        }
+    };
+    
+    // 验证和提交
+    const submitLoading = ref<boolean>(false)
+    
+    // 信息录入禁用状态
+    const infoEntryDisabled = ref<boolean>(false)
+    
+    // 接受用户名
+    const acceptUserName = ref<string>('')
+
+	// 选择器选项类型
+	type PickerOption = {
+	    label: string
+	    value: string
+	}
+
+	// 选中的挂起原因
+
+	const selectedReasonIndex = ref<number>(-1)
+	const returnTypeOptions = ref<PickerOption[]>([])
+	const showReasonPicker = ref<boolean>(false)
+
+	// 获取负责人列表(使用用户列表接口)
+	const dictList = async (): Promise<void> => {
+	    try {
+			const dictString = ref("")
+			if(workOrderStatus.value != 'to_finish') {
+				dictString.value = "gxt_accept_return_type"
+			} else {
+				dictString.value = "gxt_return_type"
+			}
+
+	        const result = await getDictDataByType(dictString.value)
+	        const resultObj = result as UTSJSONObject
+
+	        if (resultObj['code'] == 200) {
+				const data = resultObj['data'] as any[]
+				const options: PickerOption[] = []
+	            if (data.length > 0) {
+	                for (let i = 0; i < data.length; i++) {
+	                    const item = data[i] as UTSJSONObject
+	                    let dictItem: SysDictData = {
+							dictValue: item['dictValue'] as string | null,
+							dictLabel: item['dictLabel'] as string | null,
+							dictCode: null,
+							dictSort: null,
+							dictType: null,
+							cssClass: null,
+							listClass: null,
+							isDefault: null,
+							status: null,
+							default: null,
+							createTime: null,
+							remark: null
+	                    }
+						// 构建选择器选项
+						options.push({
+							label: dictItem.dictLabel ?? '',
+							value: dictItem.dictValue ?? ''
+						})
+	                }
+	            }
+
+				returnTypeOptions.value = options
+	        }
+	    } catch (e: any) {
+	        console.error('获取挂起原因失败:', e.message)
+	    }
+	}
+
+	// 手动选择负责人
+	const selectLeaderManually = (index: number): void => {
+	    selectedReasonIndex.value = index
+	    if (index >= 0 && index < returnTypeOptions.value.length) {
+	        const selectedOption = returnTypeOptions.value[index]
+	        returnTypeLabel.value = selectedOption.label
+			returnType.value = selectedOption.value
+	    }
+	    showReasonPicker.value = false
+	}
+
+    // 信息录入变化处理
+    const handleInfoEntryChange = (e: UniRadioGroupChangeEvent): void => {
+        // 兼容 radio-group 事件:detail 可能不存在,直接取 e.value
+        const val = e.detail?.value as string | null
+		infoEntry.value = val ?? ''
+        if (infoEntry.value == '1') {
+            // 当选择MIS工单时,清空手工录入的字段
+            workPermitNum.value = '';
+            realStartTime.value = '';
+            realEndTime.value = '';
+            workGroupMemberName.value = '';
+        }
+    };
+
+    // MIS工单编码输入处理
+    const handleMisNoInputFocus = (): void => {
+        showMisNoQuickSelect.value = true;
+    };
+
+    const handleMisNoInputBlur = (): void => {
+        setTimeout(() => {
+            showMisNoQuickSelect.value = false;
+        }, 200);
+    };
+
+    const handleMisNoInput = (e: SysDictData): void => {
+        misNo.value = (e['detail'] as string | null) ?? '';
+        // 这里可以添加实时搜索MIS工单的逻辑
+    };
+
+    const handleMisNoClear = (): void => {
+        misNo.value = '';
+        showMisNoQuickSelect.value = false;
+    };
+
+    const handleMisNoQuickSelect = (item: UTSJSONObject): void => {
+        misNo.value = (item['misNo'] as string | null) ?? '';
+        showMisNoQuickSelect.value = false;
+    };
+    
+    // 获取MIS工单列表
+    const getMisList = async (): Promise<void> => {
+        try {
+            // 调用获取MIS工单列表的API
+            const result = await getMisInfoList(
+                misListPage.value,
+                misListPageSize.value,
+                misListKeyword.value,
+				'结束'
+                // null // 状态筛选,可根据需要添加
+            );
+            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 {
+				const msg = resultObj['msg'] as string | null
+				uni.showToast({
+				    title: msg ?? '获取MIS工单列表失败',
+				    icon: 'none'
+				})
+            }
+        } catch (error: any) {
+            console.error('获取MIS工单列表失败:', error);
+              uni.showToast({
+                  title: error.message ?? '获取MIS工单列表失败',
+                  icon: 'none'
+              });
+        }
+    };
+    
+    // 打开MIS工单选择弹窗
+    const openMisListModal = (): void => {
+        showMisListModal.value = true;
+        misListPage.value = 1; // 重置为第一页
+        getMisList(); // 获取列表数据
+    };
+    
+    // 选择MIS工单
+    const selectMisItem = async (item: UTSJSONObject, index: number): Promise<void> => {
+		selectedMisInfoIndex.value = index
+        // 回填MIS工单相关信息
+        misNo.value = item['misNo'] as string | '';
+        // 查询MIS工单是否已存在
+		const response = await getOrderList(1, 10, misNo.value, '')
+		const responseObj = response as UTSJSONObject
+		const rows = responseObj['rows'] as UTSJSONObject[] | null
+		if (rows != null && rows.length > 0) {
+			uni.showToast({ title: 'MIS工单:' + misNo.value + '已存在', icon: 'none' })
+			misNo.value = ''
+			return
+		}
+		// 查询相关检修人员
+		await listWorkPerson(misNo.value).then(response => {
+			const responseObj = response as UTSJSONObject
+			const rows = responseObj['rows'] as UTSJSONObject[] | null
+			workOrderPersonList.value = rows ?? []
+			if (rows != null && rows.length > 0) {
+				const nickNames = rows
+					.map((person: UTSJSONObject) => (person['nickName'] as string | null) ?? '')
+					.join(',');
+				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
+		userList.value = userAllList.value.filter(leader => {
+			const nickName = leader['nickName'] as string | null
+			return nickName != null && nickName.indexOf(keyword) >= 0
+		})
+	}
+    
+    // 关闭MIS工单选择弹窗
+    const closeMisListModal = (): void => {
+        showMisListModal.value = false;
+    };
+    
+	// 搜索
+	const searchMisList = (): void => {
+		const keyword = misListKeyword.value
+		misList.value = allMisList.value.filter(misInfo => {
+			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
+	}
+
+    // 检查用户是否已被选中
+    const isSelected = (user: UTSJSONObject): boolean => {
+        const userId = user['userId'] as string | number | null;
+        if (userId !== null) {
+            return selectedUserIds.value.includes(userId.toString());
+        }
+        // 如果没有userId,则比较nickName
+        const nickName = user['nickName'] as string | null;
+        if (nickName !== null) {
+            return selectedUsers.value.some(selected => 
+                (selected['nickName'] as string | null) === nickName
+            );
+        }
+        return false;
+    };
+
+    // 切换用户选择状态
+    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 => 
+                    (selected['userId'] as string | number | null)?.toString() !== userIdStr
+                );
+            } else {
+                // 添加选择
+                selectedUserIds.value.push(userIdStr);
+                selectedUsers.value.push(user);
+            }
+        } else if (nickName !== null) {
+            // 如果没有userId,通过nickName来识别
+            const index = selectedUsers.value.findIndex(selected => 
+                (selected['nickName'] as string | null) === nickName
+            );
+            if (index > -1) {
+                // 取消选择
+                selectedUsers.value.splice(index, 1);
+                // 同时移除对应的userId(如果有的话)
+                const userToRemoveId = user['userId'] as string | number | null;
+                if (userToRemoveId !== null) {
+                    const idIndex = selectedUserIds.value.indexOf(userToRemoveId.toString());
+                    if (idIndex > -1) {
+                        selectedUserIds.value.splice(idIndex, 1);
+                    }
+                }
+            } else {
+                // 添加选择
+                selectedUsers.value.push(user);
+                const userToAddId = user['userId'] as string | number | null;
+                if (userToAddId !== null) {
+                    selectedUserIds.value.push(userToAddId.toString());
+                }
+            }
+        }
+    };
+
+    // 确认选择的用户
+    const confirmSelectedUsers = (): void => {
+        // 将选中的用户姓名拼接成字符串
+        const nickNames = selectedUsers.value
+            .map(user => (user['nickName'] as string | null) ?? '')
+            .filter(name => name !== '')
+            .join(',');
+        
+        workGroupMemberName.value = nickNames;
+        
+        // 更新workOrderPersonList为选中的用户
+        workOrderPersonList.value = [...selectedUsers.value];
+        
+        showUserSelect.value = false;
+    };
+
+
+    // 表单验证
+    const validateForm = (): boolean => {
+        if (infoEntry.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;
+        }
+
+        if (infoEntry.value == '1' && (misNo.value == '')) {
+            uni.showToast({
+                title: '请输入MIS工单编码',
+                icon: 'none'
+            });
+            return false;
+        }
+
+        if (workPermitNum.value == '') {
+            uni.showToast({
+                title: '请输入工作票编号',
+                icon: 'none'
+            });
+            return false;
+        }
+
+        if (realStartTime.value == '') {
+            uni.showToast({
+                title: '请选择开始时间',
+                icon: 'none'
+            });
+            return false;
+        }
+
+        if (realEndTime.value == '') {
+            uni.showToast({
+                title: '请选择结束时间',
+                icon: 'none'
+            });
+            return false;
+        }
+
+        if (new Date(realEndTime.value) <= new Date(realStartTime.value)) {
+            uni.showToast({
+                title: '结束时间必须大于开始时间',
+                icon: 'none'
+            });
+            return false;
+        }
+
+        // if (infoEntry.value == '2' && (workGroupMemberName.value == '')) {
+        //     uni.showToast({
+        //         title: '请选择检修人员',
+        //         icon: 'none'
+        //     });
+        //     return false;
+        // }
+
+        return true;
+    };
+	
+	const isDealing = ref(false)
+	const hasDealed = ref(false)
+	// 提交表单
+	const handleSubmit = async (): Promise<void> => {
+	    if (!validateForm()) {
+	        return;
+	    }
+	
+	    submitLoading.value = true;
+	    try {
+			if (isDealing.value || hasDealed.value) return // 双重保险
+			isDealing.value = true
+	        // 确保附件URLs是最新的逗号分隔格式
+	        attachmentUrls.value = uploadedFiles.value.map(file => file.url).join(',');
+	        
+	        const finishData = {
+	            id: orderId.value,
+	            orderType: orderType.value,
+	            workOrderProjectNo: workOrderProjectNo.value,
+	            infoEntry: infoEntry.value,
+	            misNo: infoEntry.value == '1' ? misNo.value : null,
+	            workPermitNum: workPermitNum.value,
+	            realStartTime: realStartTime.value,
+	            realEndTime: realEndTime.value,
+	            wwryNum: wwryNum.value,
+	            wlryNum: wlryNum.value,
+	            workGroupMemberName: workGroupMemberName.value,
+	            content: content.value,
+	            attachmentUrls: attachmentUrls.value,
+				workOrderPersonList: workOrderPersonList.value,
+				teamLeaderId: teamLeaderId.value,
+				teamLeaderName: teamLeaderName.value,
+				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: '结单成功',
+	                icon: 'success'
+	            });
+				hasDealed.value = true
+	            // 使用事件总线通知列表页面刷新
+	            uni.$emit('refreshOrderList', {});
+	            uni.$emit('refreshAssignedCount');
+	            uni.$emit('refreshOverdueCount');
+	
+	            setTimeout(() => {
+	                uni.navigateBack();
+	            }, 800);
+	        } else {
+	            const msg = resultObj['msg'] as string;
+	            uni.showToast({
+	                title: msg.length > 0 ? msg : '结单失败',
+	                icon: 'none'
+	            });
+	        }
+	    } catch (error: any) {
+	        console.error('结单失败:', error);
+	        uni.showToast({
+	            title: '结单失败',
+	            icon: 'none'
+	        });
+	    } finally {
+	        submitLoading.value = false;
+			isDealing.value = false // 无论成功失败都解锁
+	    }
+	};
+
+
+    const loading = ref<boolean>(false)
+
+    // 加载详情数据
+    const loadDetail = async (id: string, orderType?: string): 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) {
+				workOrderStatus.value = (data['workOrderStatus'] as string | null) ?? ''
+				workOrderProjectNo.value = (data['workOrderProjectNo'] as string | null) ?? ''
+				pcsDeviceName.value = (data['pcsDeviceName'] as string | null) ?? ''
+				gxtCenter.value = (data['gxtCenter'] as string | null) ?? ''
+				pcsStationName.value = (data['pcsStationName'] as string | null) ?? ''
+				brand.value = (data['brand'] as string | null) ?? ''
+				model.value = (data['model'] as string | null) ?? ''
+				acceptTime.value = (data['acceptTime'] as string | null) ?? ''
+				acceptUserName.value = (data['acceptUserName'] as string | null) ?? ''
+				// 初始化结单表单默认值
+				infoEntry.value = '1' // 默认为手工录入
+				teamLeaderId.value = (data['teamLeaderId'] as Number | null) ?? null
+				teamLeaderName.value = (data['teamLeaderName'] as string | null) ?? ''
+				returnType.value = workOrderStatus.value == 'to_finish' ? '1' : ''
+				content.value = (data['content'] as string | null) ?? ''
+				// 初始化附件数据
+				const attachmentUrlsFromServer = (data['attachmentUrls'] as string | null) ?? ''
+				if (attachmentUrlsFromServer.length > 0) {
+					attachmentUrls.value = attachmentUrlsFromServer
+					// 将逗号分隔的URL字符串转换为UploadResponse对象数组
+					const urls = attachmentUrlsFromServer.split(',')
+					const fileArr : UploadResponse[] = []
+					for (let i = 0; i < urls.length; i++) {
+						const url = urls[i]
+						const item : UploadResponse = {
+							url: url,
+							fileId: '',
+							fileName: url.substring(url.lastIndexOf('/') + 1),
+							filePath: url,
+							fileSize: 0,
+							fileExt: url.substring(url.lastIndexOf('.') + 1),
+							businessType: 'workOrder'
+						}
+						fileArr.push(item)
+					}
+					uploadedFiles.value = fileArr
+				}
+				pauseTime.value = (data['pauseTime'] as string | null) ?? ''
+				restartTime.value = (data['restartTime'] as string | null) ?? ''
+				
+				if(pauseTime.value != '' && restartTime.value != '') {	
+					const queryParams = {
+						pauseTime: pauseTime.value,
+						restartTime: restartTime.value,
+						pcsDeviceName: pcsDeviceName.value,
+						pcsStationName: pcsStationName.value,
+						workOrderStatus: '结束'
+					} as UTSJSONObject;
+					const result =  await listAutoMisInfo(queryParams)
+					// 提取响应数据
+					const resultObj = result as UTSJSONObject
+					const code = resultObj['code'] as number
+					const misInfo = resultObj['rows'] as UTSJSONObject[] | null
+					if (code == 200 && misInfo != null) {
+						if(misInfo.length > 0 && misInfo.length == 1) {
+							// 有工作票号提示
+							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
+								if (rows != null && rows.length > 0) {
+									misNo.value = ''
+									infoEntry.value = '2'
+									uni.showToast({
+										title: '未找到匹配的MIS工单,请确认风机停复机时间是否已录入工效通系统或请进入工作票录入方式',
+										icon: 'none'
+									});
+									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) ?? ''
+									workPermitNum.value = (misInfo[0]['workPermitNum'] as string | null) ?? ''
+									// 查询相关检修人员
+									await listWorkPerson(misNo.value).then(response => {
+										const responseObj = response as UTSJSONObject
+										const rows = responseObj['rows'] as UTSJSONObject[] | null
+										workOrderPersonList.value = rows ?? []
+										if (rows != null && rows.length > 0) {
+											// 查询负责人信息并回填
+											for (const person of workOrderPersonList.value) {
+											  // 严格判断isLeader为1(兼容数字/字符串类型)
+											  if (person.isLeader == 1) {
+												teamLeaderName.value = (person.nickName as string | null) ?? '';
+												break; // 找到后立即停止循环
+											  }
+											}
+											const nickNames = rows
+												.map((person: UTSJSONObject) => (person['nickName'] as string | null) ?? '')
+												.join(',');
+											workGroupMemberName.value = nickNames;
+										}
+									})
+								}
+								
+							} else {
+								misNo.value = ''
+								infoEntry.value = '2'
+								uni.showToast({
+									title: '已匹配到MIS工单,但未关联工作票号,系统无法自动结单,请进入工作票录入方式。',
+									icon: 'none'
+								});
+								return
+							}
+						} else if(misInfo.length == 0) {
+							misNo.value = ''
+							infoEntry.value = '2'
+							uni.showToast({
+								title: '未找到匹配的MIS工单,请确认风机停复机时间是否已录入工效通系统或请进入工作票录入方式',
+								icon: 'none'
+							});
+							return
+						} else if(misInfo.length > 1) {
+							infoEntryDisabled.value = false
+						}
+					}
+				} else {
+					infoEntryDisabled.value = true
+					misNo.value = ''
+					infoEntry.value = '2'
+					uni.showToast({
+						title: '未找到匹配的MIS工单,请确认风机停复机时间是否已录入工效通系统或请进入工作票录入方式',
+						icon: 'none'
+					});
+				}
+				
+				
+				// await dictList()
+				if (returnTypeOptions.value.length > 0 && workOrderStatus.value == 'to_finish') {
+					// returnTypeLabel.value = returnTypeOptions.value[0].label
+					// 循环匹配
+				    for (const option of returnTypeOptions.value) {
+						// 严格匹配value
+						if (returnType.value == option.value) {
+						  returnTypeLabel.value = option.label;
+						  break; // 匹配成功后跳出循环,提升性能
+						}
+					}
+				}
+
+            } else {
+                const msg = resultObj['msg'] as string | null
+                uni.showToast({
+                    title: msg ?? '加载失败',
+                    icon: 'none'
+                })
+            }
+
+        } catch (e: any) {
+            uni.showToast({
+                title: e.message ?? '加载失败',
+                icon: 'none'
+            })
+        } finally {
+            loading.value = false
+        }
+    }
+
+    // 页面加载
+    onLoad((options: any) => {
+        const params = options as UTSJSONObject
+        const id = params['id'] as string | null
+		const orderTypeParam = params['orderType'] as string | null
+        if (id != null && orderTypeParam != null) {
+            // 先尝试从参数中获取orderType
+            // const orderTypeNumber = parseInt(orderTypeParam)
+			orderType.value = orderTypeParam
+			orderId.value = id
+            loadDetail(id, orderTypeParam)
+        }
+    })
+	// 初始化
+	onMounted(() => {
+        getUserAllList();
+        loadInfoEntryDictList();
+    })
+</script>
+
+<style lang="scss">
+    .detail-page {
+        flex: 1;
+        background-color: #e8f0f9;
+    }
+
+    .detail-content {
+        flex: 1;
+        padding: 20rpx 0;
+    }
+
+    .info-section {
+        margin: 0 30rpx 24rpx;
+
+        .section-title {
+            position: relative;
+            padding-left: 20rpx;
+            margin-bottom: 20rpx;
+
+            &::before {
+                // content: '';
+                position: absolute;
+                left: 0;
+                top: 50%;
+                transform: translateY(-50%);
+                width: 8rpx;
+                height: 32rpx;
+                background-color: #007aff;
+                border-radius: 4rpx;
+            }
+
+            &-text {
+                font-size: 32rpx;
+                font-weight: bold;
+                color: #333333;
+            }
+        }
+
+        .info-card {
+            background-color: #ffffff;
+            border-radius: 16rpx;
+            padding: 30rpx;
+
+            .info-item {
+                flex-direction: row;
+                padding: 20rpx 0;
+                border-bottom: 1rpx solid #f0f0f0;
+
+                &:last-child {
+                    border-bottom: none;
+                }
+
+                &.full-width {
+                    flex-direction: column;
+
+                    .info-label {
+                        margin-bottom: 12rpx;
+                    }
+
+                    .info-value {
+                        line-height: 44rpx;
+                    }
+                }
+
+                .info-label {
+                    width: 240rpx;
+                    font-size: 28rpx;
+                    color: #666666;
+                    white-space: nowrap;
+                }
+
+                .info-value {
+                    flex: 1;
+                    font-size: 28rpx;
+                    color: #333333;
+                    text-align: right;
+
+                    &.highlight {
+                        color: #007aff;
+                        font-weight: bold;
+                    }
+
+                    &.input {
+                        text-align: left;
+                        border: 1rpx solid #e0e0e0;
+                        border-radius: 8rpx;
+                        padding: 10rpx;
+                    }
+                }
+            }
+
+            .flow-item {
+                padding: 20rpx 0;
+                border-bottom: 1rpx solid #f0f0f0;
+
+                &:last-child {
+                    border-bottom: none;
+                }
+
+                .flow-header {
+                    flex-direction: row;
+                    justify-content: space-between;
+                    margin-bottom: 10rpx;
+
+                    .flow-operator {
+                        font-size: 28rpx;
+                        color: #333333;
+                        font-weight: bold;
+                    }
+
+                    .flow-time {
+                        font-size: 24rpx;
+                        color: #999999;
+                    }
+                }
+
+                .flow-content {
+                    flex-direction: column;
+
+                    .flow-action {
+                        font-size: 26rpx;
+                        color: #666666;
+                        margin-bottom: 8rpx;
+                    }
+
+                    .flow-remark {
+                        font-size: 24rpx;
+                        color: #999999;
+                        background-color: #f5f5f5;
+                        padding: 10rpx;
+                        border-radius: 8rpx;
+                    }
+                }
+            }
+
+            .no-data {
+                text-align: center;
+                padding: 40rpx 0;
+                font-size: 28rpx;
+                color: #999999;
+            }
+        }
+    }
+
+    .accept-button-container {
+        padding: 30rpx 30rpx 50rpx;
+        background-color: #ffffff;
+
+        .accept-button {
+            width: 100%;
+            height: 80rpx;
+            background-color: #007aff;
+            color: #ffffff;
+            font-size: 32rpx;
+            border-radius: 16rpx;
+            border: none;
+
+            &:active {
+                background-color: #0062cc;
+            }
+        }
+    }
+
+    .loading-mask {
+        position: absolute;
+        top: 0;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        justify-content: center;
+        align-items: center;
+        background-color: rgba(0, 0, 0, 0.3);
+
+        .loading-text {
+            padding: 30rpx 60rpx;
+            background-color: rgba(0, 0, 0, 0.7);
+            color: #ffffff;
+            font-size: 28rpx;
+            border-radius: 12rpx;
+        }
+    }
+	.picker-modal {
+	    position: fixed;
+	    top: 0;
+	    left: 0;
+	    right: 0;
+	    bottom: 0;
+	    z-index: 1000;
+	}
+
+	.modal-mask {
+	    position: absolute;
+	    top: 0;
+	    left: 0;
+	    right: 0;
+	    bottom: 0;
+	    background-color: rgba(0, 0, 0, 0.5);
+	}
+
+	.modal-content {
+	    position: absolute;
+	    bottom: 0;
+	    left: 0;
+	    right: 0;
+	    background-color: #ffffff;
+	    border-top-left-radius: 16rpx;
+	    border-top-right-radius: 16rpx;
+	    min-height: 700rpx;
+	}
+
+	.modal-header {
+	    flex-direction: row;
+	    justify-content: space-between;
+	    align-items: center;
+	    padding: 30rpx;
+	    border-bottom: 1rpx solid #f0f0f0;
+	}
+
+	.modal-title {
+	    font-size: 32rpx;
+	    font-weight: bold;
+	    color: #333333;
+	}
+
+	.modal-close {
+	    font-size: 28rpx;
+	    color: #007aff;
+	}
+
+	.modal-body {
+	    max-height: 800rpx;
+		min-height: 800rpx;
+	}
+
+	.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;
+	}
+
+	.picker-option:last-child {
+	    border-bottom: none;
+	}
+
+
+	.option-text {
+	    font-size: 28rpx;
+	    color: #333333;
+	    margin-bottom: 10rpx;
+	}
+
+	.option-text:last-child {
+	    margin-bottom: 0;
+	}
+
+	.option-check {
+	    font-size: 28rpx;
+	    color: #007aff;
+	}
+	
+	.empty-tip {
+		justify-content: space-between;
+		padding: 24rpx 30rpx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		color: #999;
+	}
+
+	.picker-option {
+	    flex-direction: row;
+	    justify-content: space-between;
+	    align-items: center;
+	    padding: 24rpx 30rpx;
+	    border-bottom: 1rpx solid #f0f0f0;
+	}
+
+	.picker-option:last-child {
+	    border-bottom: none;
+	}
+
+	.picker-option.selected {
+	    background-color: #f8f9fa;
+	}
+
+	.option-text {
+	    font-size: 28rpx;
+	    color: #333333;
+	}
+
+	.mis-list {
+    flex: 1;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+}
+
+	.empty-tip {
+	    text-align: center;
+	    padding: 40rpx;
+	    color: #999;
+	    font-size: 28rpx;
+	}
+
+
+
+
+
+.form-item {
+	flex-direction: row;
+	padding: 20rpx 0;
+	border-bottom: 1rpx solid #f0f0f0;
+}
+
+.reject-reason-textarea {
+    width: 100%;
+    min-height: 100rpx;
+    line-height: 1.5;
+}
+
+.input-field {
+    width: 100%;
+    height: 60rpx;
+    padding: 0 20rpx;
+    border: 1rpx solid #e0e0e0;
+    border-radius: 8rpx;
+    font-size: 28rpx;
+    background-color: #f8f9fa;
+}
+
+.select-mis-btn {
+    width: 150rpx;
+    height: 60rpx;
+    margin-left: 10rpx;
+    background-color: #007aff;
+    color: #fff;
+    border: none;
+    border-radius: 8rpx;
+    font-size: 24rpx;
+}
+
+.textarea-field {
+    width: 100%;
+    min-height: 120rpx;
+    padding: 20rpx;
+    border: 1rpx solid #e0e0e0;
+    border-radius: 8rpx;
+    font-size: 28rpx;
+    background-color: #f8f9fa;
+}
+
+.radio-label {
+    display: flex;
+    align-items: center;
+    margin-right: 30rpx;
+}
+
+.quick-select-dropdown {
+    position: absolute;
+    top: 100%;
+    left: 0;
+    right: 0;
+    background: #fff;
+    border: 1rpx solid #ddd;
+    border-top: none;
+    z-index: 1000;
+    max-height: 300rpx;
+}
+
+.quick-select-item {
+    padding: 20rpx;
+    border-bottom: 1rpx solid #eee;
+}
+
+.mis-no {
+    font-size: 28rpx;
+    color: #333;
+}
+
+.search-bar {
+		padding: 20rpx 30rpx;
+		background-color: #d7eafe;
+	}
+
+	.search-box {
+		flex-direction: row;
+		align-items: center;
+		height: 72rpx;
+		padding: 0 24rpx;
+		background-color: #f5f5f5;
+		border-radius: 36rpx;
+
+		.search-icon {
+			width: 32rpx;
+			height: 32rpx;
+			margin-right: 12rpx;
+		}
+
+		.search-input {
+			flex: 1;
+			font-size: 28rpx;
+			color: #333333;
+		}
+
+		.clear-icon {
+			margin-left: 12rpx;
+			font-size: 28rpx;
+			color: #999999;
+		}
+	}
+
+.mis-list {
+    flex: 1;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+}
+
+.select-users-count {
+    margin-left: 10rpx;
+    font-size: 24rpx;
+    color: #666;
+}
+
+
+</style>
+
+
+
+
+

+ 1670 - 0
pages/order/detail/wxFinalize.uvue

@@ -0,0 +1,1670 @@
+<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">工单信息123</text>
+                </view>
+                <view class="info-card">
+                    <view class="info-item">
+                        <text class="info-label">工单编码</text>
+                        <text class="info-value">{{ workOrderProjectNo ?? '' }}</text>
+                    </view>
+                    <view class="info-item">
+                        <text class="info-label">工单类型</text>
+                        <text class="info-value">{{ orderType == '1' ? '维修工单' : '维保工单' }}</text>
+                    </view>
+                    <view class="info-item">
+                        <text class="info-label">风机编号</text>
+                        <text class="info-value">{{ pcsDeviceName ?? '' }}</text>
+                    </view>
+					<view class="info-item">
+					    <text class="info-label">维保中心</text>
+					    <text class="info-value">{{ gxtCenter ?? '' }}</text>
+					</view>
+                    <view class="info-item">
+                        <text class="info-label">场站</text>
+                        <text class="info-value">{{ pcsStationName ?? '' }}</text>
+                    </view>
+					<!-- <view class="info-item">
+					    <text class="info-label">品牌</text>
+					    <text class="info-value">{{ detailData.model ?? '' }}</text>
+					</view> -->
+                    <view class="info-item">
+                        <text class="info-label">机型</text>
+                        <text class="info-value">{{ brand ?? '' }} {{ model ?? '' }}</text>
+                    </view>
+					<view class="info-item">
+					    <text class="info-label">接单时间</text>
+					    <text class="info-value">{{ acceptTime ?? '' }}</text>
+					</view>
+                </view>
+            </view>
+            <!-- 结单表单 -->
+            <view class="info-section">
+                <view class="section-title">
+                    <text class="section-title-text">结单信息</text>
+                </view>
+                <view class="info-card">
+                    <!-- 信息录入 -->
+                    <view class="info-item">
+                        <view class="info-label">
+                            <text class="form-label required">信息录入<text style="color: red;">*</text></text>
+                        </view>
+                        <view class="info-value">
+                            <radio-group @change="handleInfoEntryChange" :disabled="infoEntryDisabled" class="uni-flex uni-row radio-group">
+                                <view v-for="(option, index) in infoEntryOptions" :key="index" class="radio-label">
+                                    <radio :value="option.dictValue" :checked="infoEntry == option.dictValue">{{ option.dictLabel }}</radio>
+                                    <!-- <text></text> -->
+                                </view>
+                            </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>
+                    </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="请输入工作票编号" 
+                                v-model="workPermitNum"
+                                maxlength="20"
+                                :disabled="infoEntry == '1'"
+                            />
+                        </view>
+                    </view>
+                    
+                    <!-- 开始时间 -->
+                    <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="showStartTimePicker = true">
+								<input
+								    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">
+                            <text class="form-label required">结束时间<text style="color: red;">*</text></text>
+                        </view>
+                        <view class="info-value">
+                            <view class="form-picker" @click="showEndTimePicker = true">
+								<input
+								    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 
+                                type="number"
+                                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 
+                                type="number"
+                                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="请输入工作负责人" 
+                                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>
+                    </view>
+                    
+                    <!-- 维保内容 -->
+                    <view class="info-item full-width">
+                        <view class="info-label">
+                            <text class="form-label required">维保内容<text style="color: red;">*</text></text>
+                        </view>
+                        <view class="info-value">
+                            <textarea
+                                class="textarea-field"
+                                placeholder="请输入维保内容"
+                                v-model="content"
+                                maxlength="500"
+                                :disabled="infoEntry == '1'"
+                                :show-confirm-bar="false"
+                                auto-height
+                            ></textarea>
+                        </view>
+                    </view>
+                    
+                    <!-- 附件上传 -->
+                    <view class="info-item full-width">
+                        <view class="info-label">
+                            <text class="form-label">附件(可选)</text>
+                        </view>
+                        <view class="info-value">
+                            <upload-image
+                                :limit="8"
+                                :modelValue="uploadedFiles"
+                                :businessType="'workOrder'"
+                                @update:modelValue="uploadedFiles = $event as UTSArray<UploadResponse>"
+                            />
+                        </view>
+                    </view>
+                </view>
+            </view>
+
+            
+            <!-- 时间选择器弹窗 -->
+			<!-- Start Date Picker -->
+			<l-popup v-model="showStartTimePicker" position="bottom">
+				<l-date-time-picker
+					title="选择开始时间"
+					:mode="1 | 2 | 4 | 8 | 16"
+					format="YYYY-MM-DD HH:mm"
+					:modelValue="realStartTime"
+					confirm-btn="确定"
+					cancel-btn="取消"
+					@confirm="onStartDateConfirm"
+					@cancel="showStartTimePicker = false">
+				</l-date-time-picker>
+			</l-popup>
+			
+			<!-- End Date Picker -->
+			<l-popup v-model="showEndTimePicker" position="bottom">
+				<l-date-time-picker
+					title="选择结束时间"
+					:mode="31"
+					format="YYYY-MM-DD HH:mm"
+					:modelValue="realStartTime"
+					confirm-btn="确定"
+					cancel-btn="取消"
+					@confirm="onEndDateConfirm"
+					@cancel="showEndTimePicker = false">
+				</l-date-time-picker>
+			</l-popup>
+            
+            <!-- 人员选择弹窗 -->
+            <view v-if="showUserSelect" class="picker-modal">
+                <view class="modal-mask" @click="showUserSelect = false"></view>
+                <view class="modal-content">
+                    <view class="modal-header">
+                        <text class="modal-title">选择检修人员</text>
+                        <text class="modal-close" @click="confirmSelectedUsers">确定</text>
+                    </view>
+					<view class="search-bar">
+						<view class="search-box">
+							<image class="search-icon" src="/static/images/workbench/list/1.png" mode="aspectFit"></image>
+							<input class="search-input" type="text" placeholder="搜索姓名" v-model="userKeyword" @input="handleSearch" />
+							<text v-if="userKeyword.length > 0" class="clear-icon" @click="clearSearch">✕</text>
+						</view>
+					</view>
+                    <scroll-view class="modal-body" scroll-y="true">
+                        <view 
+                            v-for="(user, index) in userList" 
+                            :key="index" 
+                            class="picker-option"
+                            @click="toggleUserSelection(user)"
+                        >
+                            <text class="option-text">{{ (user['nickName'] as string | null) ?? '' }}</text>
+							<text class="option-text">{{ ((user['dept'] as UTSJSONObject | null)?.['deptName'] as string | null) ?? '' }}</text>
+                            <text class="option-check" v-if="isSelected(user)">✓</text>
+                        </view>
+                    </scroll-view>
+                </view>
+            </view>
+            
+            <!-- MIS工单列表弹窗 -->
+            <view v-if="showMisListModal" class="picker-modal">
+                <view class="modal-mask" @click="closeMisListModal"></view>
+                <view class="modal-content">
+                    <view class="modal-header">
+                        <text class="modal-title">选择MIS工单</text>
+                        <text class="modal-close" @click="closeMisListModal">取消</text>
+                    </view>
+                    <!-- 搜索栏 -->
+                    <view class="search-bar">
+                        <view class="search-box">
+                            <image class="search-icon" src="/static/images/workbench/list/1.png" mode="aspectFit"></image>
+                            <input class="search-input" type="text" placeholder="搜索 MIS工单编码" v-model="misListKeyword" @input="searchMisList" />
+                            <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">
+							<view
+								v-for="(item, index) in misList"
+								:key="index"
+								class="picker-option"
+								@click="selectMisItem(item, index)"
+							>
+								<!-- <text class="option-text">{{ option.label }}</text>
+								<text class="option-text">{{ option.value }}</text> -->
+								<text class="option-text">{{ ((item['misNo'] as string | null) ?? '-')}}</text>
+								<text class="option-text">{{ item['workPermitNum'] as string | null ?? '-' }}</text>
+								<text v-if="index === selectedMisInfoIndex" class="option-check">✓</text>
+							</view>
+						</view>
+						<!-- 无数据时显示提示 -->
+						<view v-else class="empty-tip">
+						    <text>未找到匹配的人员</text>
+						</view>
+					</scroll-view>
+                </view>
+            </view>
+        </scroll-view>
+
+        <!-- 确认结单按钮 -->
+        <view class="accept-button-container">
+            <button class="accept-button" @click="handleSubmit" :loading="submitLoading">{{ submitLoading ? '提交中...' : '确认结单' }}</button>
+        </view>
+
+        <!-- 加载中状态 -->
+        <view v-if="loading" class="loading-mask">
+            <text class="loading-text">加载中...</text>
+        </view>
+    </view>
+</template>
+
+<script setup lang="uts">
+    import { ref } from 'vue'
+    import type { acceptOrderInfo } from '../../../types/order'
+    import type { WorkOrderFlow } from '../../../types/flow'
+    import { getOrderInfoById, getRepairOrderInfoById, returnRepairOrder, finishOrder } from '../../../api/order/detail'
+    import { getMisInfoList, listWorkPerson, getOrderList, listAutoMisInfo } from '../../../api/order/list'
+    import type { SysDictData } from '../../../types/dict'
+    import { getDictDataByType } from '../../../api/dict/index'
+    import type { UserInfo } from '../../../types/user'
+    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'
+	
+
+	// 工单信息
+	const orderId = ref<string>('')
+	const workOrderProjectNo = ref<string>('')
+	const workOrderStatus = ref<string>('')
+	const orderType = ref<string>('')
+	const pcsDeviceName = ref<string>('')
+	const gxtCenter = ref<string>('')
+	const pcsStationName = ref<string>('')
+	const brand = ref<string>('')
+	const model = ref<string>('')
+	const acceptTime = ref<string>('')
+	const returnType = ref<string>('')
+	const returnReason = ref<string>("")
+	const returnTypeLabel = ref<string>("")
+	const acceptReturnType = ref<string>('')
+	const acceptReturnReason = ref<string>("")
+	const teamLeaderId = ref<Number | null>(null)
+	const teamLeaderName = ref<string>('')
+	const pauseTime = ref<string>('')
+	const restartTime = ref<string>('')
+
+	// 添加字典加载状态
+	const dictLoaded = ref<boolean>(false)
+
+    // 结单表单相关变量
+    const infoEntry = ref<string>('') // 信息录入
+    const misNo = ref<string>('') // MIS工单编码
+    const workPermitNum = ref<string>('') // 工作票编号
+    const realStartTime = ref<string>('') // 开始时间
+    const realEndTime = ref<string>('') // 结束时间
+    const wwryNum = ref<string>('') // 外委人员数
+    const wlryNum = ref<string>('') // 外来人员数
+    const workGroupMemberName = ref<string>('') // 检修人员
+    const content = ref<string>('') // 维保内容
+    const attachmentUrls = ref<string>('') // 附件URLs(逗号分隔的字符串格式)
+    const uploadedFiles = ref<UploadResponse[]>([]) // 上传的文件对象数组
+	const workOrderPersonList = ref<UTSJSONObject[]>([]) // 检修人员数组
+		const selectedUserIds = ref<string[]>([]) // 选中的用户ID数组
+		const selectedUsers = ref<UTSJSONObject[]>([]) // 选中的用户对象数组
+	
+	
+    
+    // 时间选择器相关变量
+    const showStartTimePicker = ref<boolean>(false)
+    const showEndTimePicker = ref<boolean>(false)
+    const startTimeDate = ref<string>('')
+    const startTimeTime = ref<string>('')
+    const endTimeDate = ref<string>('')
+    const endTimeTime = ref<string>('')
+    
+    // MIS工单选择相关变量
+    const showMisNoQuickSelect = ref<boolean>(false)
+    const quickMisNoList = ref<UTSJSONObject[]>([])
+    // 添加MIS工单列表弹窗显示状态
+    const showMisListModal = ref<boolean>(false)
+    // MIS工单列表数据
+    const misList = ref<UTSJSONObject[]>([])
+	const allMisList = ref<UTSJSONObject[]>([])
+    // 分页信息
+    const misListPage = ref<number>(1)
+    const misListPageSize = ref<number>(999)
+    const misListTotal = ref<number>(0)
+    // 搜索关键词
+    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 {
+            const result = await getDictDataByType('gxt_info_entry') // 假设信息录入类型字典类型为gxt_info_entry
+            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)
+                    }
+                }
+
+                infoEntryOptions.value = dictData
+            }
+        } catch (e: any) {
+            console.error('获取信息录入类型字典失败:', e.message)
+            // 设置默认值
+            infoEntryOptions.value = [
+                { dictValue: '1', dictLabel: 'MIS工单', dictCode: null, dictSort: null, dictType: null, cssClass: null, listClass: null, isDefault: null, status: null, default: null, createTime: null, remark: null },
+                { dictValue: '2', dictLabel: '手工录入', dictCode: null, dictSort: null, dictType: null, cssClass: null, listClass: null, isDefault: null, status: null, default: null, createTime: null, remark: null }
+            ];
+        }
+    }
+    
+    // 获取用户列表
+    const getUserAllList = async (): Promise<void> => {
+        try {
+            // 这里应该调用获取用户列表的API
+            const result = await getLeaderList(-1); // 空参数调用
+			const resultObj = result as UTSJSONObject;
+			const code = resultObj['code'] as number
+			const users = resultObj['data'] as UTSJSONObject[] | null
+			if (code == 200 && users != null ) {
+			    // 解析列表数据
+				// const rows = resultObj['rows'] as UTSJSONObject[]
+			    userList.value = users;
+				userAllList.value = users
+            // userList.value = result.data || [];
+			}
+        } catch (error) {
+            console.error('获取用户列表失败:', error);
+            uni.showToast({
+                title: '获取用户列表失败',
+                icon: 'none'
+            });
+        }
+    };
+    
+    // 验证和提交
+    const submitLoading = ref<boolean>(false)
+    
+    // 信息录入禁用状态
+    const infoEntryDisabled = ref<boolean>(false)
+    
+    // 接受用户名
+    const acceptUserName = ref<string>('')
+
+	// 选择器选项类型
+	type PickerOption = {
+	    label: string
+	    value: string
+	}
+
+	// 选中的挂起原因
+
+	const selectedReasonIndex = ref<number>(-1)
+	const returnTypeOptions = ref<PickerOption[]>([])
+	const showReasonPicker = ref<boolean>(false)
+
+	// 获取负责人列表(使用用户列表接口)
+	const dictList = async (): Promise<void> => {
+	    try {
+			const dictString = ref("")
+			if(workOrderStatus.value != 'to_finish') {
+				dictString.value = "gxt_accept_return_type"
+			} else {
+				dictString.value = "gxt_return_type"
+			}
+
+	        const result = await getDictDataByType(dictString.value)
+	        const resultObj = result as UTSJSONObject
+
+	        if (resultObj['code'] == 200) {
+				const data = resultObj['data'] as any[]
+				const options: PickerOption[] = []
+	            if (data.length > 0) {
+	                for (let i = 0; i < data.length; i++) {
+	                    const item = data[i] as UTSJSONObject
+	                    let dictItem: SysDictData = {
+							dictValue: item['dictValue'] as string | null,
+							dictLabel: item['dictLabel'] as string | null,
+							dictCode: null,
+							dictSort: null,
+							dictType: null,
+							cssClass: null,
+							listClass: null,
+							isDefault: null,
+							status: null,
+							default: null,
+							createTime: null,
+							remark: null
+	                    }
+						// 构建选择器选项
+						options.push({
+							label: dictItem.dictLabel ?? '',
+							value: dictItem.dictValue ?? ''
+						})
+	                }
+	            }
+
+				returnTypeOptions.value = options
+	        }
+	    } catch (e: any) {
+	        console.error('获取挂起原因失败:', e.message)
+	    }
+	}
+
+	// 手动选择负责人
+	const selectLeaderManually = (index: number): void => {
+	    selectedReasonIndex.value = index
+	    if (index >= 0 && index < returnTypeOptions.value.length) {
+	        const selectedOption = returnTypeOptions.value[index]
+	        returnTypeLabel.value = selectedOption.label
+			returnType.value = selectedOption.value
+	    }
+	    showReasonPicker.value = false
+	}
+
+    // 信息录入变化处理
+    const handleInfoEntryChange = (e: UniRadioGroupChangeEvent): void => {
+        // 兼容 radio-group 事件:detail 可能不存在,直接取 e.value
+        const val = e.detail?.value as string | null
+		infoEntry.value = val ?? ''
+        if (infoEntry.value == '1') {
+            // 当选择MIS工单时,清空手工录入的字段
+            workPermitNum.value = '';
+            realStartTime.value = '';
+            realEndTime.value = '';
+            workGroupMemberName.value = '';
+        }
+    };
+
+    // MIS工单编码输入处理
+    const handleMisNoInputFocus = (): void => {
+        showMisNoQuickSelect.value = true;
+    };
+
+    const handleMisNoInputBlur = (): void => {
+        setTimeout(() => {
+            showMisNoQuickSelect.value = false;
+        }, 200);
+    };
+
+    const handleMisNoInput = (e: SysDictData): void => {
+        misNo.value = (e['detail'] as string | null) ?? '';
+        // 这里可以添加实时搜索MIS工单的逻辑
+    };
+
+    const handleMisNoClear = (): void => {
+        misNo.value = '';
+        showMisNoQuickSelect.value = false;
+    };
+
+    const handleMisNoQuickSelect = (item: UTSJSONObject): void => {
+        misNo.value = (item['misNo'] as string | null) ?? '';
+        showMisNoQuickSelect.value = false;
+    };
+    
+    // 获取MIS工单列表
+    const getMisList = async (): Promise<void> => {
+        try {
+            // 调用获取MIS工单列表的API
+            const result = await getMisInfoList(
+                misListPage.value,
+                misListPageSize.value,
+                misListKeyword.value,
+				'结束'
+                // null // 状态筛选,可根据需要添加
+            );
+            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 {
+				const msg = resultObj['msg'] as string | null
+				uni.showToast({
+				    title: msg ?? '获取MIS工单列表失败',
+				    icon: 'none'
+				})
+            }
+        } catch (error: any) {
+            console.error('获取MIS工单列表失败:', error);
+              uni.showToast({
+                  title: error.message ?? '获取MIS工单列表失败',
+                  icon: 'none'
+              });
+        }
+    };
+    
+    // 打开MIS工单选择弹窗
+    const openMisListModal = (): void => {
+        showMisListModal.value = true;
+        misListPage.value = 1; // 重置为第一页
+        getMisList(); // 获取列表数据
+    };
+    
+    // 选择MIS工单
+    const selectMisItem = async (item: UTSJSONObject, index: number): Promise<void> => {
+		selectedMisInfoIndex.value = index
+        // 回填MIS工单相关信息
+        misNo.value = item['misNo'] as string | '';
+        // 查询MIS工单是否已存在
+		const response = await getOrderList(1, 10, misNo.value, '')
+		const responseObj = response as UTSJSONObject
+		const rows = responseObj['rows'] as UTSJSONObject[] | null
+		if (rows != null && rows.length > 0) {
+			uni.showToast({ title: 'MIS工单:' + misNo.value + '已存在', icon: 'none' })
+			misNo.value = ''
+			return
+		}
+		// 查询相关检修人员
+		await listWorkPerson(misNo.value).then(response => {
+			const responseObj = response as UTSJSONObject
+			const rows = responseObj['rows'] as UTSJSONObject[] | null
+			workOrderPersonList.value = rows ?? []
+			if (rows != null && rows.length > 0) {
+				const nickNames = rows
+					.map((person: UTSJSONObject) => (person['nickName'] as string | null) ?? '')
+					.join(',');
+				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
+		userList.value = userAllList.value.filter(leader => {
+			const nickName = leader['nickName'] as string | null
+			return nickName != null && nickName.indexOf(keyword) >= 0
+		})
+	}
+    
+    // 关闭MIS工单选择弹窗
+    const closeMisListModal = (): void => {
+        showMisListModal.value = false;
+    };
+    
+	// 搜索
+	const searchMisList = (): void => {
+		const keyword = misListKeyword.value
+		misList.value = allMisList.value.filter(misInfo => {
+			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
+	}
+
+    // 检查用户是否已被选中
+    const isSelected = (user: UTSJSONObject): boolean => {
+        const userId = user['userId'] as string | number | null;
+        if (userId !== null) {
+            return selectedUserIds.value.includes(userId.toString());
+        }
+        // 如果没有userId,则比较nickName
+        const nickName = user['nickName'] as string | null;
+        if (nickName !== null) {
+            return selectedUsers.value.some(selected => 
+                (selected['nickName'] as string | null) === nickName
+            );
+        }
+        return false;
+    };
+
+    // 切换用户选择状态
+    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 => 
+                    (selected['userId'] as string | number | null)?.toString() !== userIdStr
+                );
+            } else {
+                // 添加选择
+                selectedUserIds.value.push(userIdStr);
+                selectedUsers.value.push(user);
+            }
+        } else if (nickName !== null) {
+            // 如果没有userId,通过nickName来识别
+            const index = selectedUsers.value.findIndex(selected => 
+                (selected['nickName'] as string | null) === nickName
+            );
+            if (index > -1) {
+                // 取消选择
+                selectedUsers.value.splice(index, 1);
+                // 同时移除对应的userId(如果有的话)
+                const userToRemoveId = user['userId'] as string | number | null;
+                if (userToRemoveId !== null) {
+                    const idIndex = selectedUserIds.value.indexOf(userToRemoveId.toString());
+                    if (idIndex > -1) {
+                        selectedUserIds.value.splice(idIndex, 1);
+                    }
+                }
+            } else {
+                // 添加选择
+                selectedUsers.value.push(user);
+                const userToAddId = user['userId'] as string | number | null;
+                if (userToAddId !== null) {
+                    selectedUserIds.value.push(userToAddId.toString());
+                }
+            }
+        }
+    };
+
+    // 确认选择的用户
+    const confirmSelectedUsers = (): void => {
+        // 将选中的用户姓名拼接成字符串
+        const nickNames = selectedUsers.value
+            .map(user => (user['nickName'] as string | null) ?? '')
+            .filter(name => name !== '')
+            .join(',');
+        
+        workGroupMemberName.value = nickNames;
+        
+        // 更新workOrderPersonList为选中的用户
+        workOrderPersonList.value = [...selectedUsers.value];
+        
+        showUserSelect.value = false;
+    };
+
+
+    // 表单验证
+    const validateForm = (): boolean => {
+        if (infoEntry.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;
+        }
+
+        if (infoEntry.value == '1' && (misNo.value == '')) {
+            uni.showToast({
+                title: '请输入MIS工单编码',
+                icon: 'none'
+            });
+            return false;
+        }
+
+        if (workPermitNum.value == '') {
+            uni.showToast({
+                title: '请输入工作票编号',
+                icon: 'none'
+            });
+            return false;
+        }
+
+        if (realStartTime.value == '') {
+            uni.showToast({
+                title: '请选择开始时间',
+                icon: 'none'
+            });
+            return false;
+        }
+
+        if (realEndTime.value == '') {
+            uni.showToast({
+                title: '请选择结束时间',
+                icon: 'none'
+            });
+            return false;
+        }
+
+        if (new Date(realEndTime.value) <= new Date(realStartTime.value)) {
+            uni.showToast({
+                title: '结束时间必须大于开始时间',
+                icon: 'none'
+            });
+            return false;
+        }
+
+        // if (infoEntry.value == '2' && (workGroupMemberName.value == '')) {
+        //     uni.showToast({
+        //         title: '请选择检修人员',
+        //         icon: 'none'
+        //     });
+        //     return false;
+        // }
+
+        return true;
+    };
+	
+	const isDealing = ref(false)
+	const hasDealed = ref(false)
+	// 提交表单
+	const handleSubmit = async (): Promise<void> => {
+	    if (!validateForm()) {
+	        return;
+	    }
+	
+	    submitLoading.value = true;
+	    try {
+			if (isDealing.value || hasDealed.value) return // 双重保险
+			isDealing.value = true
+	        // 确保附件URLs是最新的逗号分隔格式
+	        attachmentUrls.value = uploadedFiles.value.map(file => file.url).join(',');
+	        
+	        const finishData = {
+	            id: orderId.value,
+	            orderType: orderType.value,
+	            workOrderProjectNo: workOrderProjectNo.value,
+	            infoEntry: infoEntry.value,
+	            misNo: infoEntry.value == '1' ? misNo.value : null,
+	            workPermitNum: workPermitNum.value,
+	            realStartTime: realStartTime.value,
+	            realEndTime: realEndTime.value,
+	            wwryNum: wwryNum.value,
+	            wlryNum: wlryNum.value,
+	            workGroupMemberName: workGroupMemberName.value,
+	            content: content.value,
+	            attachmentUrls: attachmentUrls.value,
+				workOrderPersonList: workOrderPersonList.value,
+				teamLeaderId: teamLeaderId.value,
+				teamLeaderName: teamLeaderName.value,
+				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: '结单成功',
+	                icon: 'success'
+	            });
+				hasDealed.value = true
+	            // 使用事件总线通知列表页面刷新
+	            uni.$emit('refreshOrderList', {});
+	            uni.$emit('refreshAssignedCount');
+	            uni.$emit('refreshOverdueCount');
+	
+	            setTimeout(() => {
+	                uni.navigateBack();
+	            }, 800);
+	        } else {
+	            const msg = resultObj['msg'] as string;
+	            uni.showToast({
+	                title: msg.length > 0 ? msg : '结单失败',
+	                icon: 'none'
+	            });
+	        }
+	    } catch (error: any) {
+	        console.error('结单失败:', error);
+	        uni.showToast({
+	            title: '结单失败',
+	            icon: 'none'
+	        });
+	    } finally {
+	        submitLoading.value = false;
+			isDealing.value = false // 无论成功失败都解锁
+	    }
+	};
+
+
+    const loading = ref<boolean>(false)
+
+    // 加载详情数据
+    const loadDetail = async (id: string, orderType?: string): 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) {
+				workOrderStatus.value = (data['workOrderStatus'] as string | null) ?? ''
+				workOrderProjectNo.value = (data['workOrderProjectNo'] as string | null) ?? ''
+				pcsDeviceName.value = (data['pcsDeviceName'] as string | null) ?? ''
+				gxtCenter.value = (data['gxtCenter'] as string | null) ?? ''
+				pcsStationName.value = (data['pcsStationName'] as string | null) ?? ''
+				brand.value = (data['brand'] as string | null) ?? ''
+				model.value = (data['model'] as string | null) ?? ''
+				acceptTime.value = (data['acceptTime'] as string | null) ?? ''
+				acceptUserName.value = (data['acceptUserName'] as string | null) ?? ''
+				// 初始化结单表单默认值
+				infoEntry.value = '1' // 默认为手工录入
+				teamLeaderId.value = (data['teamLeaderId'] as Number | null) ?? null
+				teamLeaderName.value = (data['teamLeaderName'] as string | null) ?? ''
+				returnType.value = workOrderStatus.value == 'to_finish' ? '1' : ''
+				content.value = (data['content'] as string | null) ?? ''
+				// 初始化附件数据
+				const attachmentUrlsFromServer = (data['attachmentUrls'] as string | null) ?? ''
+				if (attachmentUrlsFromServer.length > 0) {
+					attachmentUrls.value = attachmentUrlsFromServer
+					// 将逗号分隔的URL字符串转换为UploadResponse对象数组
+					const urls = attachmentUrlsFromServer.split(',')
+					const fileArr : UploadResponse[] = []
+					for (let i = 0; i < urls.length; i++) {
+						const url = urls[i]
+						const item : UploadResponse = {
+							url: url,
+							fileId: '',
+							fileName: url.substring(url.lastIndexOf('/') + 1),
+							filePath: url,
+							fileSize: 0,
+							fileExt: url.substring(url.lastIndexOf('.') + 1),
+							businessType: 'workOrder'
+						}
+						fileArr.push(item)
+					}
+					uploadedFiles.value = fileArr
+				}
+				pauseTime.value = (data['pauseTime'] as string | null) ?? ''
+				restartTime.value = (data['restartTime'] as string | null) ?? ''
+				
+				if(pauseTime.value != '' && restartTime.value != '') {	
+					const queryParams = {
+						pauseTime: pauseTime.value,
+						restartTime: restartTime.value,
+						pcsDeviceName: pcsDeviceName.value,
+						pcsStationName: pcsStationName.value,
+						workOrderStatus: '结束'
+					} as UTSJSONObject;
+					const result =  await listAutoMisInfo(queryParams)
+					// 提取响应数据
+					const resultObj = result as UTSJSONObject
+					const code = resultObj['code'] as number
+					const misInfo = resultObj['rows'] as UTSJSONObject[] | null
+					if (code == 200 && misInfo != null) {
+						if(misInfo.length > 0 && misInfo.length == 1) {
+							// 有工作票号提示
+							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
+								if (rows != null && rows.length > 0) {
+									misNo.value = ''
+									infoEntry.value = '2'
+									uni.showToast({
+										title: '未找到匹配的MIS工单,请确认风机停复机时间是否已录入工效通系统或请进入工作票录入方式',
+										icon: 'none'
+									});
+									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) ?? ''
+									workPermitNum.value = (misInfo[0]['workPermitNum'] as string | null) ?? ''
+									// 查询相关检修人员
+									await listWorkPerson(misNo.value).then(response => {
+										const responseObj = response as UTSJSONObject
+										const rows = responseObj['rows'] as UTSJSONObject[] | null
+										workOrderPersonList.value = rows ?? []
+										if (rows != null && rows.length > 0) {
+											// 查询负责人信息并回填
+											for (const person of workOrderPersonList.value) {
+											  // 严格判断isLeader为1(兼容数字/字符串类型)
+											  if (person.isLeader == 1) {
+												teamLeaderName.value = (person.nickName as string | null) ?? '';
+												break; // 找到后立即停止循环
+											  }
+											}
+											const nickNames = rows
+												.map((person: UTSJSONObject) => (person['nickName'] as string | null) ?? '')
+												.join(',');
+											workGroupMemberName.value = nickNames;
+										}
+									})
+								}
+								
+							} else {
+								misNo.value = ''
+								infoEntry.value = '2'
+								uni.showToast({
+									title: '已匹配到MIS工单,但未关联工作票号,系统无法自动结单,请进入工作票录入方式。',
+									icon: 'none'
+								});
+								return
+							}
+						} else if(misInfo.length == 0) {
+							misNo.value = ''
+							infoEntry.value = '2'
+							uni.showToast({
+								title: '未找到匹配的MIS工单,请确认风机停复机时间是否已录入工效通系统或请进入工作票录入方式',
+								icon: 'none'
+							});
+							return
+						} else if(misInfo.length > 1) {
+							infoEntryDisabled.value = false
+						}
+					}
+				} else {
+					infoEntryDisabled.value = true
+					misNo.value = ''
+					infoEntry.value = '2'
+					uni.showToast({
+						title: '未找到匹配的MIS工单,请确认风机停复机时间是否已录入工效通系统或请进入工作票录入方式',
+						icon: 'none'
+					});
+				}
+				
+				
+				// await dictList()
+				if (returnTypeOptions.value.length > 0 && workOrderStatus.value == 'to_finish') {
+					// returnTypeLabel.value = returnTypeOptions.value[0].label
+					// 循环匹配
+				    for (const option of returnTypeOptions.value) {
+						// 严格匹配value
+						if (returnType.value == option.value) {
+						  returnTypeLabel.value = option.label;
+						  break; // 匹配成功后跳出循环,提升性能
+						}
+					}
+				}
+
+            } else {
+                const msg = resultObj['msg'] as string | null
+                uni.showToast({
+                    title: msg ?? '加载失败',
+                    icon: 'none'
+                })
+            }
+
+        } catch (e: any) {
+            uni.showToast({
+                title: e.message ?? '加载失败',
+                icon: 'none'
+            })
+        } finally {
+            loading.value = false
+        }
+    }
+
+    // 页面加载
+    onLoad((options: any) => {
+        const params = options as UTSJSONObject
+        const id = params['id'] as string | null
+		const orderTypeParam = params['orderType'] as string | null
+        if (id != null && orderTypeParam != null) {
+            // 先尝试从参数中获取orderType
+            // const orderTypeNumber = parseInt(orderTypeParam)
+			orderType.value = orderTypeParam
+			orderId.value = id
+            loadDetail(id, orderTypeParam)
+        }
+    })
+	// 初始化
+	onMounted(() => {
+        getUserAllList();
+        loadInfoEntryDictList();
+    })
+</script>
+
+<style lang="scss">
+    .detail-page {
+        flex: 1;
+        background-color: #e8f0f9;
+    }
+
+    .detail-content {
+        flex: 1;
+        padding: 20rpx 0;
+    }
+
+    .info-section {
+        margin: 0 30rpx 24rpx;
+
+        .section-title {
+            position: relative;
+            padding-left: 20rpx;
+            margin-bottom: 20rpx;
+
+            &::before {
+                // content: '';
+                position: absolute;
+                left: 0;
+                top: 50%;
+                transform: translateY(-50%);
+                width: 8rpx;
+                height: 32rpx;
+                background-color: #007aff;
+                border-radius: 4rpx;
+            }
+
+            &-text {
+                font-size: 32rpx;
+                font-weight: bold;
+                color: #333333;
+            }
+        }
+
+        .info-card {
+            background-color: #ffffff;
+            border-radius: 16rpx;
+            padding: 30rpx;
+
+            .info-item {
+                flex-direction: row;
+                padding: 20rpx 0;
+                border-bottom: 1rpx solid #f0f0f0;
+
+                &:last-child {
+                    border-bottom: none;
+                }
+
+                &.full-width {
+                    flex-direction: column;
+
+                    .info-label {
+                        margin-bottom: 12rpx;
+                    }
+
+                    .info-value {
+                        line-height: 44rpx;
+                    }
+                }
+
+                .info-label {
+                    width: 240rpx;
+                    font-size: 28rpx;
+                    color: #666666;
+                    white-space: nowrap;
+                }
+
+                .info-value {
+                    flex: 1;
+                    font-size: 28rpx;
+                    color: #333333;
+                    text-align: right;
+
+                    &.highlight {
+                        color: #007aff;
+                        font-weight: bold;
+                    }
+
+                    &.input {
+                        text-align: left;
+                        border: 1rpx solid #e0e0e0;
+                        border-radius: 8rpx;
+                        padding: 10rpx;
+                    }
+                }
+            }
+
+            .flow-item {
+                padding: 20rpx 0;
+                border-bottom: 1rpx solid #f0f0f0;
+
+                &:last-child {
+                    border-bottom: none;
+                }
+
+                .flow-header {
+                    flex-direction: row;
+                    justify-content: space-between;
+                    margin-bottom: 10rpx;
+
+                    .flow-operator {
+                        font-size: 28rpx;
+                        color: #333333;
+                        font-weight: bold;
+                    }
+
+                    .flow-time {
+                        font-size: 24rpx;
+                        color: #999999;
+                    }
+                }
+
+                .flow-content {
+                    flex-direction: column;
+
+                    .flow-action {
+                        font-size: 26rpx;
+                        color: #666666;
+                        margin-bottom: 8rpx;
+                    }
+
+                    .flow-remark {
+                        font-size: 24rpx;
+                        color: #999999;
+                        background-color: #f5f5f5;
+                        padding: 10rpx;
+                        border-radius: 8rpx;
+                    }
+                }
+            }
+
+            .no-data {
+                text-align: center;
+                padding: 40rpx 0;
+                font-size: 28rpx;
+                color: #999999;
+            }
+        }
+    }
+
+    .accept-button-container {
+        padding: 30rpx 30rpx 50rpx;
+        background-color: #ffffff;
+
+        .accept-button {
+            width: 100%;
+            height: 80rpx;
+            background-color: #007aff;
+            color: #ffffff;
+            font-size: 32rpx;
+            border-radius: 16rpx;
+            border: none;
+
+            &:active {
+                background-color: #0062cc;
+            }
+        }
+    }
+
+    .loading-mask {
+        position: absolute;
+        top: 0;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        justify-content: center;
+        align-items: center;
+        background-color: rgba(0, 0, 0, 0.3);
+
+        .loading-text {
+            padding: 30rpx 60rpx;
+            background-color: rgba(0, 0, 0, 0.7);
+            color: #ffffff;
+            font-size: 28rpx;
+            border-radius: 12rpx;
+        }
+    }
+	.picker-modal {
+	    position: fixed;
+	    top: 0;
+	    left: 0;
+	    right: 0;
+	    bottom: 0;
+	    z-index: 1000;
+	}
+
+	.modal-mask {
+	    position: absolute;
+	    top: 0;
+	    left: 0;
+	    right: 0;
+	    bottom: 0;
+	    background-color: rgba(0, 0, 0, 0.5);
+	}
+
+	.modal-content {
+	    position: absolute;
+	    bottom: 0;
+	    left: 0;
+	    right: 0;
+	    background-color: #ffffff;
+	    border-top-left-radius: 16rpx;
+	    border-top-right-radius: 16rpx;
+	    min-height: 700rpx;
+	}
+
+	.modal-header {
+	    flex-direction: row;
+	    justify-content: space-between;
+	    align-items: center;
+	    padding: 30rpx;
+	    border-bottom: 1rpx solid #f0f0f0;
+	}
+
+	.modal-title {
+	    font-size: 32rpx;
+	    font-weight: bold;
+	    color: #333333;
+	}
+
+	.modal-close {
+	    font-size: 28rpx;
+	    color: #007aff;
+	}
+
+	.modal-body {
+	    max-height: 800rpx;
+		min-height: 800rpx;
+	}
+
+	.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;
+	}
+
+	.picker-option:last-child {
+	    border-bottom: none;
+	}
+
+
+	.option-text {
+	    font-size: 28rpx;
+	    color: #333333;
+	    margin-bottom: 10rpx;
+	}
+
+	.option-text:last-child {
+	    margin-bottom: 0;
+	}
+
+	.option-check {
+	    font-size: 28rpx;
+	    color: #007aff;
+	}
+	
+	.empty-tip {
+		justify-content: space-between;
+		padding: 24rpx 30rpx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		color: #999;
+	}
+
+	.picker-option {
+	    flex-direction: row;
+	    justify-content: space-between;
+	    align-items: center;
+	    padding: 24rpx 30rpx;
+	    border-bottom: 1rpx solid #f0f0f0;
+	}
+
+	.picker-option:last-child {
+	    border-bottom: none;
+	}
+
+	.picker-option.selected {
+	    background-color: #f8f9fa;
+	}
+
+	.option-text {
+	    font-size: 28rpx;
+	    color: #333333;
+	}
+
+	.mis-list {
+    flex: 1;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+}
+
+	.empty-tip {
+	    text-align: center;
+	    padding: 40rpx;
+	    color: #999;
+	    font-size: 28rpx;
+	}
+
+
+
+
+
+.form-item {
+	flex-direction: row;
+	padding: 20rpx 0;
+	border-bottom: 1rpx solid #f0f0f0;
+}
+
+.reject-reason-textarea {
+    width: 100%;
+    min-height: 100rpx;
+    line-height: 1.5;
+}
+
+.input-field {
+    width: 100%;
+    height: 60rpx;
+    padding: 0 20rpx;
+    border: 1rpx solid #e0e0e0;
+    border-radius: 8rpx;
+    font-size: 28rpx;
+    background-color: #f8f9fa;
+}
+
+.select-mis-btn {
+    width: 150rpx;
+    height: 60rpx;
+    margin-left: 10rpx;
+    background-color: #007aff;
+    color: #fff;
+    border: none;
+    border-radius: 8rpx;
+    font-size: 24rpx;
+}
+
+.textarea-field {
+    width: 100%;
+    min-height: 120rpx;
+    padding: 20rpx;
+    border: 1rpx solid #e0e0e0;
+    border-radius: 8rpx;
+    font-size: 28rpx;
+    background-color: #f8f9fa;
+}
+
+.radio-label {
+    display: flex;
+    align-items: center;
+    margin-right: 30rpx;
+}
+
+.quick-select-dropdown {
+    position: absolute;
+    top: 100%;
+    left: 0;
+    right: 0;
+    background: #fff;
+    border: 1rpx solid #ddd;
+    border-top: none;
+    z-index: 1000;
+    max-height: 300rpx;
+}
+
+.quick-select-item {
+    padding: 20rpx;
+    border-bottom: 1rpx solid #eee;
+}
+
+.mis-no {
+    font-size: 28rpx;
+    color: #333;
+}
+
+.search-bar {
+		padding: 20rpx 30rpx;
+		background-color: #d7eafe;
+	}
+
+	.search-box {
+		flex-direction: row;
+		align-items: center;
+		height: 72rpx;
+		padding: 0 24rpx;
+		background-color: #f5f5f5;
+		border-radius: 36rpx;
+
+		.search-icon {
+			width: 32rpx;
+			height: 32rpx;
+			margin-right: 12rpx;
+		}
+
+		.search-input {
+			flex: 1;
+			font-size: 28rpx;
+			color: #333333;
+		}
+
+		.clear-icon {
+			margin-left: 12rpx;
+			font-size: 28rpx;
+			color: #999999;
+		}
+	}
+
+.mis-list {
+    flex: 1;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+}
+
+.select-users-count {
+    margin-left: 10rpx;
+    font-size: 24rpx;
+    color: #666;
+}
+
+
+</style>
+
+
+
+
+

+ 80 - 23
pages/order/index.uvue

@@ -107,12 +107,19 @@
 								>
 								<text class="btn-text">退回</text>
 							</view>
-							<view
+							<!-- <view
 								v-if="getOrderStatus(item) == 'to_finish' && canHandleOrder(item, 'return')"
 								class="btn-primary info-value"
 								@click.stop="handleItemClick(item, 'return')"
 								>
 								<text class="btn-text">退回</text>
+							</view> -->
+							<view
+								v-if="getOrderStatus(item) == 'to_finish' && canHandleOrder(item, 'complete')"
+								class="btn-primary info-value"
+								@click.stop="handleItemClick(item, 'complete')"
+								>
+								<text class="btn-text">结单</text>
 							</view>
 							<view
 								v-if="getOrderStatus(item) == 'to_finish' && canHandleOrder(item, 'suspend')"
@@ -139,16 +146,45 @@
 
 <script setup lang="uts">
 import { ref, onBeforeUnmount, onMounted, reactive } from 'vue'
-import type { acceptOrderInfo } from '../../types/order'
+// import type { acceptOrderInfo } from '../../types/order'
 import type { SysDictData, DictDataResponse } from '../../types/dict'
 import { getOrderList } 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
+}
+
 	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
@@ -189,7 +225,7 @@ const statusConfig: StatusItem[] = [
 
 	const getOrderStatus = (item: any | null): string => {
 		if (item == null) return ''
-		const orderItem = item as acceptOrderInfo
+		const orderItem = item as acceptOrderInfoExtend
 		return orderItem.workOrderStatus ?? ''
 	}
 
@@ -291,11 +327,12 @@ const statusConfig: StatusItem[] = [
             const responseTotal = resultObj['total'] as number
 
             if (code == 200) {
-                // 将 any[] 转换为 acceptOrderInfo[]
-                const newData: acceptOrderInfo[] = []
+                // 将 any[] 转换为 acceptOrderInfoExtend[]
+                // const newData: 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,
@@ -320,7 +357,8 @@ const statusConfig: StatusItem[] = [
 						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,// 新增字段
+						orderEntryType: item['orderEntryType'] as string | null,
                     }
                     newData.push(orderItem)
                 }
@@ -367,43 +405,43 @@ const statusConfig: StatusItem[] = [
     // 辅助函数:从 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 getPcsStationName = (item: any | null): string | null=> {
         if (item == null) return ''
-        const orderInfoItem = item as acceptOrderInfo
+        const orderInfoItem = item as acceptOrderInfoExtend
         return orderInfoItem.pcsStationName
     }
 
     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 getAssignTime = (item: any | null): string|null => {
         if (item == null) return null
-        const orderInfoItem = item as acceptOrderInfo
+        const orderInfoItem = item as acceptOrderInfoExtend
         return orderInfoItem.assignTime
     }
 
 	const getAcceptTime = (item: any | null): string|null => {
 	    if (item == null) return null
-	    const orderInfoItem = item as acceptOrderInfo
+	    const orderInfoItem = item as acceptOrderInfoExtend
 	    return orderInfoItem.acceptTime
 	}
 
 	const getCreateTime = (item: any | null): string|null => {
 	    if (item == null) return null
-	    const orderInfoItem = item as acceptOrderInfo
+	    const orderInfoItem = item as acceptOrderInfoExtend
 	    return orderInfoItem.createTime
 	}
 
@@ -411,7 +449,7 @@ const statusConfig: StatusItem[] = [
 	// 根据状态显示不同的时间
 	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') {
@@ -441,7 +479,7 @@ const statusConfig: StatusItem[] = [
 
 	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 ''
@@ -458,7 +496,7 @@ const statusConfig: StatusItem[] = [
 
 	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
@@ -568,7 +606,7 @@ const statusConfig: StatusItem[] = [
 	const canHandleOrder = (item: any | null, buttonType: string | ''): boolean => {
 	  if (item == null) return false
 	  let permit: string[] = []
-	  const orderItem = item as acceptOrderInfo
+	  const orderItem = item as acceptOrderInfoExtend
 	  if(orderItem.workOrderStatus == 'assigned' && buttonType != '' && buttonType == "acceptReturn" && orderItem.orderType == 1) {
 			// 接单退回
 			permit = ['gxt:repairOrder:acceptReturn']
@@ -585,6 +623,9 @@ 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("管理员"))) {
+			  // 结单
+			  permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:complete'] : ['gxt:repairOrder:finalize']
 		  }
 	  } else if(orderItem.workOrderStatus == 'to_approve') {
 	  	// 审批
@@ -603,7 +644,7 @@ const statusConfig: StatusItem[] = [
 		  return false
 	  }
 
-	  // const orderType = (item as acceptOrderInfo).orderType
+	  // const orderType = (item as acceptOrderInfoExtend).orderType
 	  return checkPermi(permit)
 	}
 
@@ -611,13 +652,14 @@ const statusConfig: StatusItem[] = [
     // 点击列表项
     const handleItemClick = (item: any | null, buttonType: string | ''): void => {
         if (item == null) return
-        const orderItem = item as acceptOrderInfo
+        const orderItem = item as acceptOrderInfoExtend
 		// if(currentStatus.value === '' || currentStatus.value === 'completed' || currentStatus.value === 'all') {
 		// 	// 传递orderType参数以便详情页决定调用哪个API
 		// 	uni.navigateTo({
 		// 	    url: `/pages/order/detail/index?id=${orderItem.id}&orderType=${orderItem.orderType}`
 		// 	})
 		// } else
+
 		if(orderItem.workOrderStatus == 'assigned') {
 			if(buttonType != '' && buttonType == "acceptReturn") {
 				// 跳转到退回页面
@@ -646,6 +688,21 @@ const statusConfig: StatusItem[] = [
 				uni.navigateTo({
 					url: `/pages/order/detail/resetIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
 				})
+			} else if(buttonType != '' && buttonType == "complete" && orderItem.orderType == 2 && orderItem.orderEntryType == '1') {
+				// 跳转到复启页面
+				uni.navigateTo({
+					url: `/pages/order/detail/wbFinalize?id=${orderItem.id}&orderType=${orderItem.orderType}`
+				})
+			} else if(buttonType != '' && buttonType == "complete" && orderItem.orderType == 1) {
+				// 跳转到复启页面
+				uni.navigateTo({
+					url: `/pages/order/detail/wxFinalize?id=${orderItem.id}&orderType=${orderItem.orderType}`
+				})
+			} else if(buttonType != '' && buttonType == "complete" && orderItem.orderType == 2 && orderItem.orderEntryType == '2') {
+				// 跳转到复启页面
+				uni.navigateTo({
+					url: `/pages/order/detail/wbBackfillFinalize?id=${orderItem.id}&orderType=${orderItem.orderType}`
+				})
 			}
 		} else if(orderItem.workOrderStatus == 'to_approve') {
 			// 跳转到待审批页面
@@ -673,7 +730,7 @@ const statusConfig: StatusItem[] = [
 	// 点击列表项
 	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}`
 		})
@@ -683,7 +740,7 @@ const statusConfig: StatusItem[] = [
     // 查看工单详情
     const showWorkOrderDetail = (item: any | null): void => {
         if (item == null) return
-        const orderItem = item as acceptOrderInfo
+        const orderItem = item as acceptOrderInfoExtend
         uni.navigateTo({
             url: `/pages/workbench/detail/index?id=${orderItem.id}`
         })

+ 7 - 7
pages/order/pendingOrder.uvue

@@ -68,13 +68,13 @@
 								>
 								<text class="btn-text">退回</text>
 							</view>
-							<view
+							<!-- <view
 								v-if="getOrderStatus(item) == 'to_finish' && canHandleOrder(item, 'return')"
 								class="btn-primary info-value"
 								@click.stop="handleItemClick(item, 'return')"
 								>
 								<text class="btn-text">退回</text>
-							</view>
+							</view> -->
 							<view
 								v-if="getOrderStatus(item) == 'to_finish' && canHandleOrder(item, 'suspend')"
 								class="btn-primary info-value"
@@ -231,11 +231,11 @@ import {checkPermi, getUserInfo} from '../../utils/storage'
 
         loading.value = true
         let refreshTimeout: number | null = null;
-        
+
         if (shouldRefresh && !disablePull) {
             page.value = 1
             refreshing.value = true
-            
+
             // 添加超时机制,确保刷新动画不会一直显示
             refreshTimeout = setTimeout(() => {
                 if (refreshing.value) {
@@ -445,7 +445,7 @@ import {checkPermi, getUserInfo} from '../../utils/storage'
         // 设置刷新标志
         isRefreshing.value = true;
         refreshing.value = true; // 确保刷新状态被设置
-        
+
         // 添加超时机制,确保刷新动画不会一直显示
         const refreshTimeout = setTimeout(() => {
             if (refreshing.value || isRefreshing.value) {
@@ -509,7 +509,7 @@ import {checkPermi, getUserInfo} from '../../utils/storage'
             isSearching.value = false
         }, 100)
     }
-	
+
 	// 点击列表查看
 	const handleView = (item: any | null): void => {
 	    if (item == null) return
@@ -517,7 +517,7 @@ import {checkPermi, getUserInfo} from '../../utils/storage'
 		uni.navigateTo({
 			url: `/pages/order/detail/index?id=${orderItem.id}&orderType=${orderItem.orderType}`
 		})
-	
+
 	}
 
     // 点击列表项

+ 14 - 14
utils/upload.uts

@@ -6,7 +6,7 @@ import type { ApiResponse } from '../types/user'
 import type { UploadResponse, UploadFileInfo } from '../types/workbench'
 
 // 基础 URL
-const BASE_URL = "http://192.168.108.77:8092"
+const BASE_URL = "http://192.168.110.40:8080"
 
 /**
  * 处理 401 未授权错误
@@ -14,14 +14,14 @@ const BASE_URL = "http://192.168.108.77:8092"
 const handle401Error = (): void => {
     // 清除所有本地存储
     clearAll()
-    
+
     // 提示用户
     uni.showToast({
         title: '登录已过期,请重新登录',
         icon: 'none',
         duration: 2000
     })
-    
+
     // 延迟跳转到登录页
     setTimeout(() => {
         uni.reLaunch({
@@ -45,9 +45,9 @@ export const getFileViewUrl = (fileId: string): string => {
 export const uploadFile = (filePath: string, businessType: string): Promise<UploadResponse> => {
     return new Promise((resolve, reject) => {
         const token = getAccessToken()
-
         uni.uploadFile({
-            url: BASE_URL + `/file/uploads?businessType=${businessType}`,
+            //url: BASE_URL + `/file/uploads?businessType=${businessType}`,
+			url: BASE_URL + `/common/upload`,
             filePath: filePath,
             name: 'files',
             header: {
@@ -59,20 +59,20 @@ export const uploadFile = (filePath: string, businessType: string): Promise<Uplo
                 const resData = res.data as string
 
                 console.log('上传响应:', res)
-                
+
                 // 处理 401 未授权
                 if (statusCode == 401) {
                     try {
                         const errorResult = JSON.parse(resData) as UTSJSONObject
                         const message = errorResult['message'] as string | null
                         const error = errorResult['error'] as string | null
-                        
+
                         // 显示错误信息
                         const errorMsg = message ?? error ?? '登录已过期'
-                        
+
                         // 处理 401 错误
                         handle401Error()
-                        
+
                         reject(new Error(errorMsg))
                     } catch (e: any) {
                         handle401Error()
@@ -80,7 +80,7 @@ export const uploadFile = (filePath: string, businessType: string): Promise<Uplo
                     }
                     return
                 }
-                
+
                 // 处理成功响应
                 if (statusCode == 200) {
                     try {
@@ -89,7 +89,7 @@ export const uploadFile = (filePath: string, businessType: string): Promise<Uplo
                         const code = result['code'] as number | null
                         const msg = result['msg'] as string | null
                         const data = result['data'] as any[] | null
-                        
+
                         // 判断是否成功
                         if (success == true || code == 0) {
                             if (data != null && data.length > 0) {
@@ -101,10 +101,10 @@ export const uploadFile = (filePath: string, businessType: string): Promise<Uplo
                                 const fileSize = fileInfo['fileSize'] as number
                                 const fileExt = fileInfo['fileExt'] as string
                                 const businessType = fileInfo['businessType'] as string
-                                
+
                                 // 构建完整的 URL
                                 const url = getFileViewUrl(fileId)
-                                
+
                                 // 返回 UploadResponse
                                 const uploadResult: UploadResponse = {
                                     url: url,
@@ -115,7 +115,7 @@ export const uploadFile = (filePath: string, businessType: string): Promise<Uplo
                                     fileExt: fileExt,
                                     businessType: businessType
                                 }
-                                
+
                                 resolve(uploadResult)
                             } else {
                                 reject(new Error('上传成功但未返回文件信息'))