Commit 4c54ad5d917083f7a2024f12b9f96f80337e5a95
1 parent
2f1e3176
转工单 选择是 传紧急程度和希望完成时间
Showing
12 changed files
with
382 additions
and
95 deletions
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
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) => { |
| 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
pages-sub/problem/regional-order-manage/index.vue
0 → 100644
pages-sub/problem/regional-order-manage/order-detail.vue
0 → 100644
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) => { |
| 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) => { |
| 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 () => { |
| 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 | }, | ... | ... |