Commit 4c54ad5d917083f7a2024f12b9f96f80337e5a95

Authored by 刘淇
1 parent 2f1e3176

转工单 选择是 传紧急程度和希望完成时间

api/regional-order-manage/regional-order-manage.js 0 → 100644
common/utils/common.js
... ... @@ -55,4 +55,111 @@ export const buzStatusMap = {
55 55 "230" : '养护组长验收不通过',
56 56 "140" : '巡查员验收通过',
57 57 "240" : '巡查员验收不通过',
58   -}
59 58 \ No newline at end of file
  59 +}
  60 +
  61 +
  62 +/**
  63 + * 计算两个时间的时间差,返回格式化字符串(天/小时/分钟/秒,按需显示,无无效单位)
  64 + * @param {string | Date | number} startTime - 开始时间(时间字符串/Date对象/10位/13位时间戳)
  65 + * @param {string | Date | number} endTime - 结束时间(时间字符串/Date对象/10位/13位时间戳)
  66 + * @returns {string} - 格式化时间差字符串(如:3天5小时2分钟30秒、3小时2分钟30秒、2分钟30秒、30秒)
  67 + */
  68 +export const calculateFormatTimeDiff = (startTime, endTime) => {
  69 + // 辅助函数:将任意合法时间格式转换为13位毫秒级时间戳
  70 + const to13BitTimestamp = (time) => {
  71 + let timestamp = 0;
  72 +
  73 + // 情况1:数字类型(时间戳)
  74 + if (typeof time === 'number') {
  75 + const timeStr = time.toString();
  76 + if (timeStr.length === 10) {
  77 + timestamp = time * 1000; // 10位秒级转13位毫秒级
  78 + } else if (timeStr.length === 13) {
  79 + timestamp = time; // 13位毫秒级直接使用
  80 + } else {
  81 + console.error('非法时间戳:仅支持10位/13位数字', time);
  82 + return 0;
  83 + }
  84 + return timestamp;
  85 + }
  86 +
  87 + // 情况2:Date对象
  88 + if (time instanceof Date) {
  89 + timestamp = time.getTime();
  90 + if (isNaN(timestamp)) {
  91 + console.error('无效的Date对象', time);
  92 + return 0;
  93 + }
  94 + return timestamp;
  95 + }
  96 +
  97 + // 情况3:字符串类型
  98 + if (typeof time === 'string') {
  99 + const timeStr = time.trim().replace(/\//g, '-'); // 统一分隔符,兼容YYYY/MM/DD
  100 + const date = new Date(timeStr);
  101 + timestamp = date.getTime();
  102 + if (isNaN(timestamp)) {
  103 + console.error('无效的时间字符串', time);
  104 + return 0;
  105 + }
  106 + return timestamp;
  107 + }
  108 +
  109 + // 非法类型
  110 + console.error('不支持的时间类型:仅支持string/Date/number', time);
  111 + return 0;
  112 + };
  113 +
  114 + // 1. 统一转换为13位时间戳
  115 + const startTimestamp = to13BitTimestamp(startTime);
  116 + const endTimestamp = to13BitTimestamp(endTime);
  117 +
  118 + // 2. 校验时间戳有效性
  119 + if (startTimestamp === 0 || endTimestamp === 0) {
  120 + return '0秒';
  121 + }
  122 +
  123 + // 3. 计算总毫秒差(取绝对值,确保时间差为正数,不影响单位计算)
  124 + const totalMsDiff = Math.abs(endTimestamp - startTimestamp);
  125 +
  126 + // 4. 定义时间单位换算(毫秒)
  127 + const oneDayMs = 24 * 60 * 60 * 1000;
  128 + const oneHourMs = 60 * 60 * 1000;
  129 + const oneMinuteMs = 60 * 1000;
  130 + const oneSecondMs = 1000;
  131 +
  132 + // 5. 计算各单位的差值(向下取整,获取整数单位)
  133 + const days = Math.floor(totalMsDiff / oneDayMs);
  134 + const remainingMsAfterDay = totalMsDiff % oneDayMs; // 扣除天数后剩余的毫秒数
  135 +
  136 + const hours = Math.floor(remainingMsAfterDay / oneHourMs);
  137 + const remainingMsAfterHour = remainingMsAfterDay % oneHourMs; // 扣除小时后剩余的毫秒数
  138 +
  139 + const minutes = Math.floor(remainingMsAfterHour / oneMinuteMs);
  140 + const remainingMsAfterMinute = remainingMsAfterHour % oneMinuteMs; // 扣除分钟后剩余的毫秒数
  141 +
  142 + const seconds = Math.floor(remainingMsAfterMinute / oneSecondMs);
  143 +
  144 + // 6. 组装格式化字符串(按需添加单位,无无效单位)
  145 + const timeParts = [];
  146 + if (days > 0) {
  147 + timeParts.push(`${days}天`);
  148 + }
  149 + if (hours > 0 || (days > 0 && hours === 0)) { // 有天数时,小时即使为0也可保留(可选:删除 || 后的条件则不显示0小时)
  150 + timeParts.push(`${hours}小时`);
  151 + }
  152 + if (minutes > 0 || (timeParts.length > 0 && minutes === 0)) { // 有天/小时时,分钟即使为0也可保留(可选:删除 || 后的条件则不显示0分钟)
  153 + timeParts.push(`${minutes}分钟`);
  154 + }
  155 + // 秒数始终保留(即使为0,保证最后有一个有效单位)
  156 + timeParts.push(`${seconds}秒`);
  157 +
  158 + // 7. 过滤掉可能存在的「0单位」(可选优化:避免出现“0小时”等无效字段)
  159 + const validTimeParts = timeParts.filter(part => {
  160 + const num = parseInt(part);
  161 + return num > 0 || (timeParts.length === 1 && num === 0); // 仅当只有秒数时,允许0秒
  162 + });
  163 +
  164 + // 8. 拼接并返回结果
  165 + return validTimeParts.join('');
  166 +};
60 167 \ No newline at end of file
... ...
common/utils/useUploadImgs.js
... ... @@ -17,6 +17,8 @@ export function useUploadImgs(config) {
17 17  
18 18 // 核心修复:初始化为纯数组,且格式适配u-upload
19 19 const imgList = ref([])
  20 + // 确保 rawImgList 响应式对象的初始值也是空数组
  21 + // const rawImgList = ref([]);
20 22  
21 23 /**
22 24 * 新增:清空所有图片
... ...
pages-sub/daily/patrol-manage/add-patrol-record.vue
1 1 <template>
2 2 <view class="u-page">
3   - <!-- 核心:将所有 up-form-item 包裹在同一个 up-form 内 -->
  3 + <!-- 原有模板内容不变,仅调整表单校验相关配置 -->
4 4 <view class="inspect-form-content commonPageLRpadding">
5 5 <up-form
6 6 label-position="left"
7 7 :model="inspectForm"
8 8 ref="inspectFormRef"
9   - labelWidth="140rpx"
  9 + labelWidth="190rpx"
10 10 >
11   - <!-- 1. 巡查描述(文本域) -->
  11 + <!-- 1. 巡查描述 -->
12 12 <up-form-item
13 13 label="巡查描述"
14 14 prop="content"
... ... @@ -41,11 +41,12 @@
41 41 upload-text="选择图片"
42 42 del-color="#ff4d4f"
43 43 class="upload-wrap"
  44 + width="70"
  45 + height="70"
44 46 ></up-upload>
45   - <!-- <view class="tips">(最少1张,最多3张)</view>-->
46 47 </up-form-item>
47 48  
48   - <!-- 3. 转为工单(单选框) -->
  49 + <!-- 3. 转为工单 -->
49 50 <up-form-item
50 51 label="转为工单"
51 52 prop="isWorkOrder"
... ... @@ -57,6 +58,7 @@
57 58 active-color="#1989fa"
58 59 direction="row"
59 60 class="radio-group"
  61 + @change="handleWorkOrderChange"
60 62 >
61 63 <up-radio
62 64 :custom-style="{marginRight: '40rpx'}"
... ... @@ -70,6 +72,51 @@
70 72 </up-radio-group>
71 73 </up-form-item>
72 74  
  75 + <!-- 紧急程度(仍为必填) -->
  76 +<!-- v-if="inspectForm.isWorkOrder === '2'"-->
  77 + <up-form-item
  78 + v-if="inspectForm.isWorkOrder === '2'"
  79 + label="紧急程度"
  80 + prop="pressingTypeName"
  81 + border-bottom
  82 + required
  83 + class="form-item"
  84 + @click="handleActionSheetOpen('pressingType')"
  85 + >
  86 + <up-input
  87 + v-model="inspectForm.pressingTypeName"
  88 + disabled
  89 + disabled-color="#ffffff"
  90 + placeholder="请选择紧急程度"
  91 + border="none"
  92 +
  93 + ></up-input>
  94 + <template #right>
  95 + <up-icon name="arrow-right" size="16"></up-icon>
  96 + </template>
  97 + </up-form-item>
  98 +
  99 + <!-- 希望完成时间(移除 required 属性,改为非必填) -->
  100 +<!-- v-if="inspectForm.isWorkOrder === '2'"-->
  101 + <up-form-item
  102 + v-if="inspectForm.isWorkOrder === '2'"
  103 + label="希望完成时间"
  104 + prop="expectedFinishDate"
  105 + class="form-item"
  106 + @click="show = true; uni.hideKeyboard()"
  107 + >
  108 + <up-input
  109 + v-model="inspectForm.expectedFinishDate"
  110 + border="none"
  111 + readonly
  112 + placeholder="点击选择时间"
  113 +
  114 + ></up-input>
  115 + <template #right>
  116 + <up-icon name="arrow-right" size="16"></up-icon>
  117 + </template>
  118 + </up-form-item>
  119 +
73 120 </up-form>
74 121 </view>
75 122  
... ... @@ -82,38 +129,59 @@
82 129 :style="{ width: '100%', height: '88rpx', fontSize: '32rpx', borderRadius: 0 }"
83 130 ></up-button>
84 131 </view>
  132 +
  133 + <!-- 紧急程度下拉弹窗 -->
  134 + <up-action-sheet
  135 + :show="showActionSheet"
  136 + :actions="pressingTypeList"
  137 + title="请选择紧急程度"
  138 + @close="handleActionSheetClose"
  139 + @select="handlePressingTypeSelect"
  140 + ></up-action-sheet>
  141 +
  142 + <!-- 完成时间选择器 -->
  143 + <up-datetime-picker
  144 + :show="show"
  145 + v-model="datetimeValue"
  146 + mode="datetime"
  147 + :min-date="new Date()"
  148 + @cancel="show = false"
  149 + @confirm="expectedFinishDateConfirm"
  150 + ></up-datetime-picker>
85 151 </view>
86 152 </template>
87 153  
88 154 <script setup lang="ts">
89 155 import { ref } from 'vue'
90 156 import type { UniFormRef } from '@/uni_modules/uview-plus/types'
91   -// 定义ref供选项式API使用
92 157 const inspectFormRef = ref<UniFormRef>(null)
93 158 </script>
94 159  
95 160 <script lang="ts">
96 161 import { uploadImages } from '@/common/utils/upload';
97 162 import { inspectionCreate } from "@/api/patrol-manage/patrol-plan";
98   -
  163 +import { timeFormat } from '@/uni_modules/uview-plus'
99 164  
100 165 export default {
101 166 data() {
102 167 return {
103   - // 图片列表
104 168 imagesList: [],
105   - // 单选列表
106 169 radioList: [
107 170 { label: '否', value: '1' },
108 171 { label: '是', value: '2' }
109 172 ],
110   - // 巡查表单数据
  173 + pressingTypeList: [],
111 174 inspectForm: {
112   - content: '', // 巡查描述
113   - isWorkOrder: '1' // 是否转为工单 1:否(默认) 2:是
  175 + content: '',
  176 + isWorkOrder: '1',
  177 + pressingTypeName: '',
  178 + pressingType: '',
  179 + expectedFinishDate: '' // 非必填,可空
114 180 },
115   - paramsOptins:{},//接受参数
116   - // 表单校验规则
  181 + paramsOptins: {},
  182 + showActionSheet: false,
  183 + show: false,
  184 + datetimeValue: Date.now(),
117 185 inspectFormRules: {
118 186 images: [
119 187 {
... ... @@ -121,7 +189,6 @@ export default {
121 189 message: '请上传图片',
122 190 trigger: 'change',
123 191 validator: (rule, value, callback) => {
124   - // 自定义校验规则:检查是否有成功上传的图片
125 192 const hasSuccessImg = this.imagesList.some(item => item.status === 'success')
126 193 const imgCount = this.imagesList.filter(item => item.status === 'success').length
127 194  
... ... @@ -135,42 +202,104 @@ export default {
135 202 }
136 203 }
137 204 ],
138   -
139 205 content: [
140 206 { type: 'string', required: true, message: '请输入工单描述', trigger: ['change'] }
141 207 ],
142 208 isWorkOrder: [
143 209 { type: 'string', required: true, message: '请选择是否转为工单', trigger: ['change'] }
  210 + ],
  211 + pressingTypeName: [
  212 + {
  213 + required: true,
  214 + message: '请选择紧急程度',
  215 + trigger: 'change',
  216 + validator: (rule, value, callback) => {
  217 + if (this.inspectForm.isWorkOrder === '2' && !value) {
  218 + callback(new Error('请选择紧急程度'))
  219 + } else {
  220 + callback()
  221 + }
  222 + }
  223 + }
  224 + ],
  225 + // 关键修改:希望完成时间 移除必填校验,或改为非必填
  226 + expectedFinishDate: [
  227 + {
  228 + // 移除 required: true,改为非必填
  229 + message: '请选择有效的希望完成时间', // 仅当有值时,校验格式(可选)
  230 + trigger: 'change',
  231 + validator: (rule, value, callback) => {
  232 + // 只有当字段有值时,才校验时间格式是否有效
  233 + if (value && !/^\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}$/.test(value)) {
  234 + callback(new Error('请选择有效的希望完成时间'))
  235 + } else {
  236 + callback() // 无值时直接通过校验
  237 + }
  238 + }
  239 + }
144 240 ]
145 241 }
146 242 }
147 243 },
148 244 onLoad(option){
149   - console.log(option)
150 245 this.paramsOptins = option
  246 + this.getPressingTypeDict()
151 247 },
152 248 onReady() {
153   - // 兼容微信小程序,通过setRules设置校验规则
154 249 this.$refs.inspectFormRef.setRules(this.inspectFormRules)
155   - console.log('巡查表单规则初始化完成')
156 250 },
157 251 methods: {
158   - /**
159   - * 删除图片
160   - */
  252 + getPressingTypeDict() {
  253 + const dictList = uni.$dict.getDictSimpleList('workorder_pressing_type')
  254 + this.pressingTypeList = uni.$dict.transformLabelValueToNameValue(dictList)
  255 + console.log(this.pressingTypeList)
  256 + },
  257 +
  258 + handleWorkOrderChange() {
  259 + if (this.inspectForm.isWorkOrder === '1') {
  260 + this.inspectForm.pressingTypeName = ''
  261 + this.inspectForm.pressingType = ''
  262 + this.inspectForm.expectedFinishDate = '' // 清空非必填字段
  263 + this.$refs.inspectFormRef.validateField(['pressingTypeName', 'expectedFinishDate'])
  264 + }
  265 + },
  266 +
  267 +
  268 + handleActionSheetOpen(type) {
  269 + uni.hideKeyboard()
  270 + console.log('showActionSheet')
  271 + if (type === 'pressingType') {
  272 + console.log('showActionSheet')
  273 + this.showActionSheet = true
  274 + }
  275 + uni.hideKeyboard()
  276 + },
  277 +
  278 + handleActionSheetClose() {
  279 + this.showActionSheet = false
  280 + },
  281 +
  282 + handlePressingTypeSelect(e) {
  283 + console.log(e)
  284 + this.inspectForm.pressingTypeName = e.name
  285 + this.inspectForm.pressingType = e.value
  286 + this.showActionSheet = false
  287 + this.$refs.inspectFormRef.validateField('pressingTypeName')
  288 + },
  289 +
  290 + expectedFinishDateConfirm(e) {
  291 + this.inspectForm.expectedFinishDate = timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss')
  292 + this.show = false
  293 + this.$refs.inspectFormRef.validateField('expectedFinishDate')
  294 + },
  295 +
161 296 deleteImg(event) {
162   - console.log('删除图片事件:', event)
163 297 this.imagesList.splice(event.index, 1)
164   - // 删除图片后重新校验图片字段
165 298 this.$refs.inspectFormRef.validateField('images')
166 299 uni.showToast({ title: '图片删除成功', icon: 'success' })
167 300 },
168 301  
169   - /**
170   - * 上传图片
171   - */
172 302 async uploadImgs(event) {
173   - console.log('上传图片事件:', event)
174 303 const fileList = Array.isArray(event.file) ? event.file : [event.file]
175 304 const targetImgList = this.imagesList
176 305  
... ... @@ -188,7 +317,6 @@ export default {
188 317 filePaths: filePaths,
189 318 ignoreError: true
190 319 })
191   - console.log('上传成功的URL列表:', uploadResultUrls)
192 320  
193 321 uploadResultUrls.forEach((url, index) => {
194 322 if (targetImgList[startIndex + index]) {
... ... @@ -203,21 +331,11 @@ export default {
203 331  
204 332 if (uploadResultUrls.length < fileList.length) {
205 333 const failCount = fileList.length - uploadResultUrls.length
206   - for (let i = uploadResultUrls.length; i < fileList.length; i++) {
207   - if (targetImgList[startIndex + i]) {
208   - targetImgList.splice(startIndex + i, 1, {
209   - ...fileList[i],
210   - status: 'failed',
211   - message: '上传失败'
212   - })
213   - }
214   - }
215 334 uni.showToast({ title: `成功上传${uploadResultUrls.length}张,失败${failCount}张`, icon: 'none' })
216 335 } else {
217 336 uni.showToast({ title: `成功上传${fileList.length}张图片`, icon: 'success' })
218 337 }
219 338  
220   - // 上传完成后重新校验图片字段
221 339 this.$refs.inspectFormRef.validateField('images')
222 340 } catch (err) {
223 341 console.error('图片上传失败:', err)
... ... @@ -231,55 +349,48 @@ export default {
231 349 }
232 350 }
233 351 uni.showToast({ title: '图片上传失败,请重试', icon: 'none' })
234   -
235   - // 上传失败后重新校验图片字段
236 352 this.$refs.inspectFormRef.validateField('images')
237 353 }
238 354 },
239 355  
240   - /**
241   - * 处理图片超出数量限制
242   - */
243 356 handleExceed() {
244 357 uni.showToast({ title: '最多只能上传3张图片', icon: 'none' })
245 358 },
246 359  
247   - /**
248   - * 提取图片URL数组
249   - */
250 360 getImgUrlList(imgList) {
251 361 return imgList.filter(item => item.status === 'success').map(item => item.url)
252 362 },
253 363  
254   - /**
255   - * 提交巡查表单
256   - */
257 364 async submitInspect() {
258 365 console.log('当前选择是否转为工单:', this.inspectForm.isWorkOrder)
259 366 try {
260   - // 先执行表单校验
261 367 await this.$refs.inspectFormRef.validate()
262 368 console.log(this.imagesList)
263   - // 构造提交数据
264   - const submitData = {
265   - // content: this.inspectForm.content,
266   - // images: this.getImgUrlList(this.imagesList),
267   - // isWorkOrder: this.inspectForm.isWorkOrder // 1=否,2=是
268   -
269 369  
  370 + // 构造基础提交数据
  371 + const baseSubmitData = {
270 372 "batchNo": this.paramsOptins.batchNo,
271   - "planNo":this.paramsOptins.planNo,
  373 + "planNo": this.paramsOptins.planNo,
272 374 "imgHost": "1",
273 375 "imgList": this.getImgUrlList(this.imagesList),
274 376 "inspectionState": this.inspectForm.isWorkOrder,
275   - "transState": this.inspectForm.isWorkOrder==1?'1':'2',
  377 + "transState": this.inspectForm.isWorkOrder === '1' ? '1' : '2',
276 378 "transWorkNo": "default'",
277 379 "remark": this.inspectForm.content.trim()
278 380 }
279 381  
280   - // 显示加载中
281   - uni.showLoading({ title: '提交中...' })
  382 + // 构造最终提交数据
  383 + let submitData = { ...baseSubmitData }
  384 + if (this.inspectForm.isWorkOrder === '2') {
  385 + // 紧急程度仍为必填,必传
  386 + submitData.pressingType = this.inspectForm.pressingType
  387 + // 关键修改:仅当希望完成时间有值时,才添加该参数
  388 + if (this.inspectForm.expectedFinishDate) {
  389 + submitData.expectedFinishDate = new Date(this.inspectForm.expectedFinishDate).getTime()
  390 + }
  391 + }
282 392  
  393 + uni.showLoading({ title: '提交中...' })
283 394 await inspectionCreate(submitData)
284 395  
285 396 uni.hideLoading()
... ... @@ -289,7 +400,6 @@ export default {
289 400 duration: 1000
290 401 })
291 402  
292   - // // 延迟跳转(等待提示框显示完成)
293 403 setTimeout(() => {
294 404 uni.reLaunch({
295 405 url: '/pages-sub/daily/patrol-manage/index'
... ... @@ -297,14 +407,8 @@ export default {
297 407 }, 1000)
298 408  
299 409 } catch (error) {
300   - // 隐藏加载框
301 410 uni.hideLoading()
302   -
303   - // 区分是表单校验失败还是接口调用失败
304   - if (Array.isArray(error)) {
305   - // 表单校验失败 - 静默处理(uView会自动提示)
306   - } else {
307   - // 接口调用失败
  411 + if (!Array.isArray(error)) {
308 412 console.error('巡查表单提交失败:', error)
309 413 uni.showToast({
310 414 title: '提交失败,请重试',
... ... @@ -319,14 +423,18 @@ export default {
319 423 </script>
320 424  
321 425 <style lang="scss" scoped>
322   -// 全局页面样式
323 426 .u-page {
  427 + min-height: 100vh;
324 428 }
325 429  
326   -// 巡查表单内容容器
327 430 .inspect-form-content {
328 431 background: #fff;
329 432 padding: 20rpx;
330 433 }
331 434  
  435 +.form-item {
  436 + margin-bottom: 20rpx;
  437 +}
  438 +
  439 +
332 440 </style>
333 441 \ No newline at end of file
... ...
pages-sub/daily/quick-order/add-order.vue
... ... @@ -89,6 +89,8 @@
89 89 @after-read="(event) => uploadImgs(event, 'problemImgsList')"
90 90 @delete="(event) => deleteImg(event, 'problemImgsList')"
91 91 multiple
  92 + width="70"
  93 + height="70"
92 94 :max-count="3"
93 95 upload-text="选择问题照片"
94 96 ></up-upload>
... ... @@ -101,6 +103,8 @@
101 103 @after-read="(event) => uploadImgs(event, 'completeImgsList')"
102 104 @delete="(event) => deleteImg(event, 'completeImgsList')"
103 105 multiple
  106 + width="70"
  107 + height="70"
104 108 :max-count="3"
105 109 :sizeType="['compressed']"
106 110 upload-text="选择完成照片"
... ...
pages-sub/daily/quick-order/order-detail.vue
... ... @@ -65,11 +65,11 @@
65 65  
66 66 <!-- 修复1:正确判断problemImgsList,补充空数组默认值 -->
67 67 <up-album
68   - v-if="!!orderDetail.problemImgsList?.length"
69   - :urls="orderDetail.problemImgsList || []"
  68 + v-if="!!orderDetail.problemsImgs?.length"
  69 + :urls="orderDetail.problemsImgs || []"
70 70 singleSize="70"
71 71 :preview-full-image="true"
72   -
  72 + multipleSize="70"
73 73 ></up-album>
74 74 <text v-else class="empty-text">暂无问题照片</text>
75 75 </view>
... ... @@ -81,9 +81,10 @@
81 81 <template #value>
82 82 <view class="cell-content-wrap">
83 83 <up-album
84   - v-if="!!orderDetail.completeImgsList?.length"
85   - :urls="orderDetail.completeImgsList || []"
  84 + v-if="!!orderDetail.endImgs?.length"
  85 + :urls="orderDetail.endImgs || []"
86 86 singleSize="70"
  87 + multipleSize="70"
87 88 :preview-full-image="true"
88 89  
89 90 ></up-album>
... ... @@ -131,8 +132,8 @@ const getOrderDetail = async (id: string) =&gt; {
131 132 // 优化:确保图片数组为数组类型,避免非数组导致渲染错误
132 133 orderDetail.value = {
133 134 ...res,
134   - problemImgsList: Array.isArray(res.problemImgsList) ? res.problemImgsList : [],
135   - completeImgsList: Array.isArray(res.completeImgsList) ? res.completeImgsList : []
  135 + problemsImgs: Array.isArray(res.problemsImgs) ? res.problemsImgs : [],
  136 + endImgs: Array.isArray(res.endImgs) ? res.endImgs : []
136 137 };
137 138 } catch (error) {
138 139 console.error('获取工单详情失败:', error);
... ...
pages-sub/problem/regional-order-manage/add-order.vue 0 → 100644
  1 +<script lang="ts">
  2 +import {defineComponent} from 'vue'
  3 +
  4 +export default defineComponent({
  5 + name: "add-order"
  6 +})
  7 +</script>
  8 +
  9 +<template>
  10 +
  11 +</template>
  12 +
  13 +<style scoped lang="scss">
  14 +
  15 +</style>
0 16 \ No newline at end of file
... ...
pages-sub/problem/regional-order-manage/index.vue 0 → 100644
  1 +<script lang="ts">
  2 +import {defineComponent} from 'vue'
  3 +
  4 +export default defineComponent({
  5 + name: "index"
  6 +})
  7 +</script>
  8 +
  9 +<template>
  10 +
  11 +</template>
  12 +
  13 +<style scoped lang="scss">
  14 +
  15 +</style>
0 16 \ No newline at end of file
... ...
pages-sub/problem/regional-order-manage/order-detail.vue 0 → 100644
  1 +<script lang="ts">
  2 +import {defineComponent} from 'vue'
  3 +
  4 +export default defineComponent({
  5 + name: "order-detail"
  6 +})
  7 +</script>
  8 +
  9 +<template>
  10 +
  11 +</template>
  12 +
  13 +<style scoped lang="scss">
  14 +
  15 +</style>
0 16 \ No newline at end of file
... ...
pages-sub/problem/work-order-manage/add-order.vue
... ... @@ -103,7 +103,7 @@
103 103 <!-- 问题照片(核心修复:绑定纯数组) -->
104 104 <up-form-item label="问题照片" prop="problemImgs" required>
105 105 <up-upload
106   - :file-list="problemImgs.imgList"
  106 + :file-list="problemImgs.imgList.value||[]"
107 107 @after-read="problemImgs.uploadImgs"
108 108 @delete="problemImgs.deleteImg"
109 109 multiple
... ... @@ -185,10 +185,11 @@ const problemImgs = useUploadImgs({
185 185 fieldName: 'problemImgs'
186 186 })
187 187  
188   -// 核心修复:监听响应式数组变化,同步更新纯数组(解决u-upload不刷新问题)
189   -watch(() => problemImgs.rawImgList.value, (newVal) => {
190   - problemImgs.imgList = newVal
191   -}, { deep: true })
  188 +// 无需再手动初始化普通数组,直接使用 ref 响应式数据
  189 +if (!Array.isArray(problemImgs.rawImgList.value)) {
  190 + problemImgs.rawImgList.value = [];
  191 +}
  192 +
192 193  
193 194 // ========== 页面状态 ==========
194 195 // 通用弹窗控制
... ... @@ -318,7 +319,7 @@ const echoOrderData = (orderItem) =&gt; {
318 319 workOrderForm.problemDesc = orderItem.remark || '';
319 320 workOrderForm.lat = orderItem.lat || 0;
320 321 workOrderForm.lon = orderItem.lon || 0;
321   - workOrderForm.expectedFinishDate = orderItem.expectedFinishDate || timeFormat(new Date(), 'yyyy-mm-dd hh:MM:ss');
  322 + workOrderForm.expectedFinishDate = timeFormat(orderItem.expectedFinishDate, 'yyyy-mm-dd hh:MM:ss') || timeFormat(new Date(), 'yyyy-mm-dd hh:MM:ss');
322 323  
323 324 // 2. 上传图片回显(兼容useUploadImgs格式)
324 325 if (orderItem.problemsImgs && Array.isArray(orderItem.problemsImgs) && orderItem.problemsImgs.length > 0) {
... ... @@ -327,7 +328,7 @@ const echoOrderData = (orderItem) =&gt; {
327 328 name: `renew_img_${index}`,
328 329 status: 'success' // 标记为已上传状态
329 330 }));
330   - problemImgs.imgList = imgList;
  331 + problemImgs.imgList.value = imgList;
331 332 problemImgs.rawImgList.value = imgList;
332 333 }
333 334  
... ... @@ -513,7 +514,8 @@ const submitWorkOrder = async () =&gt; {
513 514 lonLatAddress: workOrderForm.workLocation,
514 515 pressingType: workOrderForm.pressingType,
515 516 orderName: workOrderForm.orderName,
516   - expectedFinishDate: workOrderForm.expectedFinishDate,
  517 + // expectedFinishDate: workOrderForm.expectedFinishDate,
  518 + expectedFinishDate: new Date(workOrderForm.expectedFinishDate).getTime(),
517 519 sourceId: 1,
518 520 sourceName: '园林',
519 521 busiLine: 'yl'
... ...
pages-sub/problem/work-order-manage/order-detail.vue
... ... @@ -80,7 +80,7 @@
80 80 ></up-cell>
81 81  
82 82 <!-- 处理结果 -->
83   - <up-cell>
  83 + <up-cell v-if="orderDetail.handleResult">
84 84 <template #title>
85 85 <view style="min-width: 200rpx">处理结果</view>
86 86 </template>
... ... @@ -109,15 +109,17 @@
109 109  
110 110 <!-- 希望完成时间 -->
111 111 <up-cell
  112 + v-if="orderDetail.expectedFinishDate"
112 113 title="希望完成时间"
113   - :value="orderDetail.expectedFinishDate === 0 ? '未设置' : timeFormat(orderDetail.expectedFinishDate, 'yyyy-mm-dd hh:MM:ss')"
  114 + :value="timeFormat(orderDetail.expectedFinishDate, 'yyyy-mm-dd hh:MM:ss')"
114 115 align="middle"
115 116 :border="false"
116 117 ></up-cell>
117 118  
118 119 <up-cell
  120 + v-if="orderDetail.finishDate"
119 121 title="工单完结时间"
120   - :value="orderDetail.finishDate === 0 ? '暂无' : timeFormat(orderDetail.finishDate, 'yyyy-mm-dd hh:MM:ss')"
  122 + :value="timeFormat(orderDetail.finishDate, 'yyyy-mm-dd hh:MM:ss')"
121 123 align="middle"
122 124 :border="false"
123 125 ></up-cell>
... ... @@ -198,6 +200,11 @@
198 200 <text v-if="item.endTime"> 至 {{ timeFormat(item.endTime, 'yyyy-mm-dd hh:MM:ss') }}</text>
199 201 <text v-else class="processing-tag">(处理中)</text>
200 202 </view>
  203 +
  204 + <view class="reason-line up-line-1" v-if="index!==0&&item.endTime">
  205 + 总耗时:{{ calculateFormatTimeDiff(item.startTime , item.endTime) }}
  206 + </view>
  207 +
201 208 <!-- 原因行 -->
202 209 <view class="reason-line up-line-2" v-if="item.tasks && item.tasks[0]?.reason">
203 210 描述:{{ getLimitReason(item.tasks && item.tasks[0]?.reason) }}
... ... @@ -321,7 +328,7 @@ import {
321 328 getApprovalDetail,
322 329 universalApproval
323 330 } from '@/api/work-order-manage/work-order-manage';
324   -import { nextStepMap, buzStatusMap } from '@/common/utils/common'
  331 +import { nextStepMap, buzStatusMap, calculateFormatTimeDiff } from '@/common/utils/common'
325 332 // 引入图片上传组合式函数
326 333 import { useUploadImgs } from '@/common/utils/useUploadImgs'
327 334  
... ...
pages.json
... ... @@ -134,8 +134,6 @@
134 134 "style": { "navigationBarTitleText": "分配工单" }
135 135 },
136 136  
137   -
138   -
139 137 {
140 138 "path": "work-order-manage/order-detail",
141 139 "style": { "navigationBarTitleText": "工单详情" }
... ... @@ -145,11 +143,24 @@
145 143 "style": { "navigationBarTitleText": "养护任务" }
146 144 },
147 145  
148   -
149   -
150 146 {
151 147 "path": "problem-allot/index",
152 148 "style": { "navigationBarTitleText": "问题分配" }
  149 + },
  150 +
  151 + {
  152 + "path": "regional-order-manage/index",
  153 + "style": { "navigationBarTitleText": "工单管理" }
  154 + },
  155 +
  156 + {
  157 + "path": "regional-order-manage/add-order",
  158 + "style": { "navigationBarTitleText": "待派单" }
  159 + },
  160 +
  161 + {
  162 + "path": "regional-order-manage/order-detail",
  163 + "style": { "navigationBarTitleText": "工单详情" }
153 164 }
154 165 ]
155 166 },
... ...