Commit 8ee2a9233280f0fdab1ab5722f5071728e9d33bb
1 parent
9b30ab8c
新增快速工单,原版
Showing
1 changed file
with
151 additions
and
180 deletions
pages-sub/daily/quick-order/add-order.vue
| 1 | <template> | 1 | <template> |
| 2 | <view class="u-page"> | 2 | <view class="u-page"> |
| 3 | - <!-- 工单表单容器 --> | ||
| 4 | - <view class="work-order-form-content commonPageLRpadding"> | ||
| 5 | - <!-- uview-plus表单(Vue3 适配) --> | ||
| 6 | - <up-form | ||
| 7 | - label-position="left" | ||
| 8 | - :model="workOrderForm" | ||
| 9 | - ref="workOrderFormRef" | ||
| 10 | - labelWidth="220rpx" | ||
| 11 | - :rules="workOrderFormRules" | ||
| 12 | - > | 3 | + <!-- 核心:将所有 up-form-item 包裹在同一个 up-form 内 --> |
| 4 | + <up-form | ||
| 5 | + label-position="left" | ||
| 6 | + :model="workOrderForm" | ||
| 7 | + ref="workOrderFormRef" | ||
| 8 | + labelWidth="220rpx" | ||
| 9 | + :rules="workOrderFormRules" | ||
| 10 | + :error-type="['message', 'border']" | ||
| 11 | + class="work-order-form-container" | ||
| 12 | + > | ||
| 13 | + <!-- 工单表单容器 --> | ||
| 14 | + <view class="work-order-form-content commonPageLRpadding"> | ||
| 13 | <!-- 1. 工单位置(地图选择) --> | 15 | <!-- 1. 工单位置(地图选择) --> |
| 14 | <up-form-item | 16 | <up-form-item |
| 15 | label="工单位置" | 17 | label="工单位置" |
| @@ -80,75 +82,58 @@ | @@ -80,75 +82,58 @@ | ||
| 80 | count | 82 | count |
| 81 | maxlength="150" | 83 | maxlength="150" |
| 82 | rows="4" | 84 | rows="4" |
| 85 | + @blur="() => workOrderFormRef.value?.validateField('problemDesc')" | ||
| 83 | ></up-textarea> | 86 | ></up-textarea> |
| 84 | </up-form-item> | 87 | </up-form-item> |
| 85 | - </up-form> | ||
| 86 | - | ||
| 87 | - <!-- 道路名称下拉弹窗 --> | ||
| 88 | - <up-action-sheet | ||
| 89 | - :show="showRoadName" | ||
| 90 | - :actions="roadNameList" | ||
| 91 | - title="请选择道路名称" | ||
| 92 | - @close="showRoadName = false" | ||
| 93 | - @select="handleRoadNameSelect" | ||
| 94 | - ></up-action-sheet> | ||
| 95 | - | ||
| 96 | - <!-- 工单名称下拉弹窗 --> | ||
| 97 | - <up-action-sheet | ||
| 98 | - :show="showOrderName" | ||
| 99 | - :actions="orderNameList" | ||
| 100 | - title="请选择工单名称" | ||
| 101 | - @close="showOrderName = false" | ||
| 102 | - @select="handleOrderNameSelect" | ||
| 103 | - ></up-action-sheet> | ||
| 104 | - </view> | ||
| 105 | - | ||
| 106 | - <!-- 图片分类标签 --> | ||
| 107 | - <up-tabs :list="imgTabList" @click="switchImgTab"></up-tabs> | ||
| 108 | - | ||
| 109 | - <!-- 图片上传组件(根据选中标签显示对应列表) --> | ||
| 110 | - <view class="img-upload-wrap" v-if="activeImgTab === '1'"> | ||
| 111 | - <up-form-item label="问题照片" prop="problemImgs" required> | ||
| 112 | - <up-upload | ||
| 113 | - :file-list="problemImgsList" | ||
| 114 | - @after-read="(event) => uploadImgs(event, 'problemImgsList')" | ||
| 115 | - @delete="(event) => deleteImg(event, 'problemImgsList')" | ||
| 116 | - multiple | ||
| 117 | - :max-count="3" | ||
| 118 | - upload-text="选择问题照片" | ||
| 119 | - ></up-upload> | ||
| 120 | - </up-form-item> | ||
| 121 | - </view> | ||
| 122 | - <view class="img-upload-wrap" v-else> | ||
| 123 | - <up-form-item label="完成照片" prop="completeImgs" required> | ||
| 124 | - <up-upload | ||
| 125 | - :file-list="completeImgsList" | ||
| 126 | - @after-read="(event) => uploadImgs(event, 'completeImgsList')" | ||
| 127 | - @delete="(event) => deleteImg(event, 'completeImgsList')" | ||
| 128 | - multiple | ||
| 129 | - :max-count="3" | ||
| 130 | - :sizeType="['compressed']" | ||
| 131 | - upload-text="选择完成照片" | ||
| 132 | - ></up-upload> | ||
| 133 | - </up-form-item> | ||
| 134 | - </view> | 88 | + </view> |
| 89 | + | ||
| 90 | + <!-- 问题照片:独立一行显示(移入 up-form 内) --> | ||
| 91 | + <view class="img-upload-wrap"> | ||
| 92 | + <up-form-item label="问题照片" prop="problemImgs" required> | ||
| 93 | + <up-upload | ||
| 94 | + :file-list="problemImgsList" | ||
| 95 | + @after-read="(event) => uploadImgs(event, 'problemImgsList')" | ||
| 96 | + @delete="(event) => deleteImg(event, 'problemImgsList')" | ||
| 97 | + multiple | ||
| 98 | + :max-count="3" | ||
| 99 | + upload-text="选择问题照片" | ||
| 100 | + ></up-upload> | ||
| 101 | + </up-form-item> | ||
| 102 | + </view> | ||
| 103 | + | ||
| 104 | + <!-- 完成照片:独立一行显示(移入 up-form 内) --> | ||
| 105 | + <view class="img-upload-wrap"> | ||
| 106 | + <up-form-item label="完成照片" prop="completeImgs" required> | ||
| 107 | + <up-upload | ||
| 108 | + :file-list="completeImgsList" | ||
| 109 | + @after-read="(event) => uploadImgs(event, 'completeImgsList')" | ||
| 110 | + @delete="(event) => deleteImg(event, 'completeImgsList')" | ||
| 111 | + multiple | ||
| 112 | + :max-count="3" | ||
| 113 | + :sizeType="['compressed']" | ||
| 114 | + upload-text="选择完成照片" | ||
| 115 | + ></up-upload> | ||
| 116 | + </up-form-item> | ||
| 117 | + </view> | ||
| 135 | 118 | ||
| 136 | - <!-- 处理结果描述(独立显示) --> | ||
| 137 | - <view class="handle-result-wrap"> | ||
| 138 | - <up-form-item | ||
| 139 | - label="处理结果" | ||
| 140 | - prop="handleResultDesc" | ||
| 141 | - required | ||
| 142 | - > | ||
| 143 | - <up-textarea | ||
| 144 | - placeholder="请输入处理结果描述(最多200字)" | ||
| 145 | - v-model="workOrderForm.handleResultDesc" | ||
| 146 | - count | ||
| 147 | - maxlength="200" | ||
| 148 | - rows="4" | ||
| 149 | - ></up-textarea> | ||
| 150 | - </up-form-item> | ||
| 151 | - </view> | 119 | + <!-- 处理结果描述(独立显示,移入 up-form 内) --> |
| 120 | + <view class="handle-result-wrap"> | ||
| 121 | + <up-form-item | ||
| 122 | + label="处理结果" | ||
| 123 | + prop="handleResultDesc" | ||
| 124 | + required | ||
| 125 | + > | ||
| 126 | + <up-textarea | ||
| 127 | + placeholder="请输入处理结果描述(最多200字)" | ||
| 128 | + v-model="workOrderForm.handleResultDesc" | ||
| 129 | + count | ||
| 130 | + maxlength="200" | ||
| 131 | + rows="4" | ||
| 132 | + @blur="() => workOrderFormRef.value?.validateField('handleResultDesc')" | ||
| 133 | + ></up-textarea> | ||
| 134 | + </up-form-item> | ||
| 135 | + </view> | ||
| 136 | + </up-form> | ||
| 152 | 137 | ||
| 153 | <!-- 底部提交按钮 --> | 138 | <!-- 底部提交按钮 --> |
| 154 | <view class="fixed-bottom-btn-wrap"> | 139 | <view class="fixed-bottom-btn-wrap"> |
| @@ -160,6 +145,24 @@ | @@ -160,6 +145,24 @@ | ||
| 160 | :disabled="isSubmitting" | 145 | :disabled="isSubmitting" |
| 161 | ></up-button> | 146 | ></up-button> |
| 162 | </view> | 147 | </view> |
| 148 | + | ||
| 149 | + <!-- 道路名称下拉弹窗 --> | ||
| 150 | + <up-action-sheet | ||
| 151 | + :show="showRoadName" | ||
| 152 | + :actions="roadNameList" | ||
| 153 | + title="请选择道路名称" | ||
| 154 | + @close="showRoadName = false" | ||
| 155 | + @select="handleRoadNameSelect" | ||
| 156 | + ></up-action-sheet> | ||
| 157 | + | ||
| 158 | + <!-- 工单名称下拉弹窗 --> | ||
| 159 | + <up-action-sheet | ||
| 160 | + :show="showOrderName" | ||
| 161 | + :actions="orderNameList" | ||
| 162 | + title="请选择工单名称" | ||
| 163 | + @close="showOrderName = false" | ||
| 164 | + @select="handleOrderNameSelect" | ||
| 165 | + ></up-action-sheet> | ||
| 163 | </view> | 166 | </view> |
| 164 | </template> | 167 | </template> |
| 165 | 168 | ||
| @@ -172,19 +175,12 @@ import { getRoadListByLatLng } from '@/api/common' | @@ -172,19 +175,12 @@ import { getRoadListByLatLng } from '@/api/common' | ||
| 172 | import { uploadImages } from '@/common/utils/upload'; | 175 | import { uploadImages } from '@/common/utils/upload'; |
| 173 | import { createQuick } from '@/api/quick-order/quick-order' | 176 | import { createQuick } from '@/api/quick-order/quick-order' |
| 174 | 177 | ||
| 175 | -// ========== 基础变量定义(语义化命名) ========== | ||
| 176 | -// 图片分类标签列表 | ||
| 177 | -const imgTabList = ref([ | ||
| 178 | - { name: '问题照片', id: '1' }, | ||
| 179 | - { name: '完成照片', id: '2' } | ||
| 180 | -]) | ||
| 181 | -// 激活的图片标签(默认选中问题照片) | ||
| 182 | -const activeImgTab = ref('1') | 178 | +// ========== 基础变量定义 ========== |
| 183 | // 问题照片列表 | 179 | // 问题照片列表 |
| 184 | const problemImgsList = ref<UploadFile[]>([]) | 180 | const problemImgsList = ref<UploadFile[]>([]) |
| 185 | // 完成照片列表 | 181 | // 完成照片列表 |
| 186 | const completeImgsList = ref<UploadFile[]>([]) | 182 | const completeImgsList = ref<UploadFile[]>([]) |
| 187 | -// 表单Ref(语义化:工单表单) | 183 | +// 表单Ref |
| 188 | const workOrderFormRef = ref<UniFormRef>(null) | 184 | const workOrderFormRef = ref<UniFormRef>(null) |
| 189 | // 提交加载状态 | 185 | // 提交加载状态 |
| 190 | const isSubmitting = ref(false) | 186 | const isSubmitting = ref(false) |
| @@ -199,7 +195,7 @@ const orderNameList = ref([ | @@ -199,7 +195,7 @@ const orderNameList = ref([ | ||
| 199 | { name: '垃圾清理', code: 'ORDER003' } | 195 | { name: '垃圾清理', code: 'ORDER003' } |
| 200 | ]) | 196 | ]) |
| 201 | 197 | ||
| 202 | -// ========== 工单表单数据(语义化字段名) ========== | 198 | +// ========== 工单表单数据 ========== |
| 203 | const workOrderForm = reactive({ | 199 | const workOrderForm = reactive({ |
| 204 | roadId: 0, // 道路ID | 200 | roadId: 0, // 道路ID |
| 205 | roadName: '', // 道路名称 | 201 | roadName: '', // 道路名称 |
| @@ -211,20 +207,20 @@ const workOrderForm = reactive({ | @@ -211,20 +207,20 @@ const workOrderForm = reactive({ | ||
| 211 | lon: 0 // 经度 | 207 | lon: 0 // 经度 |
| 212 | }) | 208 | }) |
| 213 | 209 | ||
| 214 | -// ========== 表单校验规则(修复trigger + 语义化) ========== | 210 | +// ========== 表单校验规则 ========== |
| 215 | const workOrderFormRules = reactive({ | 211 | const workOrderFormRules = reactive({ |
| 216 | workLocation: [ | 212 | workLocation: [ |
| 217 | - { type: 'string', required: true, message: '请选择工单位置', trigger: 'change' } | 213 | + { type: 'string', required: true, message: '请选择工单位置', trigger: ['change', 'blur'] } |
| 218 | ], | 214 | ], |
| 219 | roadName: [ | 215 | roadName: [ |
| 220 | - { type: 'string', required: true, message: '请选择道路名称', trigger: 'change' } | 216 | + { type: 'string', required: true, message: '请选择道路名称', trigger: ['change', 'blur'] } |
| 221 | ], | 217 | ], |
| 222 | orderName: [ | 218 | orderName: [ |
| 223 | - { type: 'string', required: true, message: '请选择工单名称', trigger: 'change' } | 219 | + { type: 'string', required: true, message: '请选择工单名称', trigger: ['change', 'blur'] } |
| 224 | ], | 220 | ], |
| 225 | problemDesc: [ | 221 | problemDesc: [ |
| 226 | - { type: 'string', required: true, message: '请输入情况描述', trigger: 'change' }, | ||
| 227 | - { type: 'string', min: 3, max: 150, message: '情况描述需3-150字', trigger: 'change' } | 222 | + { type: 'string', required: true, message: '请输入情况描述', trigger: ['change', 'blur'] }, |
| 223 | + { type: 'string', min: 3, max: 150, message: '情况描述需3-150字', trigger: ['change', 'blur'] } | ||
| 228 | ], | 224 | ], |
| 229 | problemImgs: [ | 225 | problemImgs: [ |
| 230 | { required: true, message: '请上传问题照片', trigger: 'change' } | 226 | { required: true, message: '请上传问题照片', trigger: 'change' } |
| @@ -233,16 +229,14 @@ const workOrderFormRules = reactive({ | @@ -233,16 +229,14 @@ const workOrderFormRules = reactive({ | ||
| 233 | { required: true, message: '请上传完成照片', trigger: 'change' } | 229 | { required: true, message: '请上传完成照片', trigger: 'change' } |
| 234 | ], | 230 | ], |
| 235 | handleResultDesc: [ | 231 | handleResultDesc: [ |
| 236 | - { type: 'string', required: true, message: '请输入处理结果描述', trigger: 'change' }, | ||
| 237 | - { type: 'string', min: 3, max: 200, message: '处理结果需3-200字', trigger: 'change' } | 232 | + { type: 'string', required: true, message: '请输入处理结果描述', trigger: ['change', 'blur'] }, |
| 233 | + { type: 'string', min: 3, max: 200, message: '处理结果需3-200字', trigger: ['change', 'blur'] } | ||
| 238 | ] | 234 | ] |
| 239 | }) | 235 | }) |
| 240 | 236 | ||
| 241 | -// ========== 方法定义(语义化命名 + 修复逻辑) ========== | 237 | +// ========== 方法定义 ========== |
| 242 | /** | 238 | /** |
| 243 | * 删除图片 | 239 | * 删除图片 |
| 244 | - * @param event 删除事件 | ||
| 245 | - * @param type 图片类型(problemImgsList/completeImgsList) | ||
| 246 | */ | 240 | */ |
| 247 | const deleteImg = (event: UploadDeleteEvent, type: string) => { | 241 | const deleteImg = (event: UploadDeleteEvent, type: string) => { |
| 248 | console.log('删除图片事件:', event, '类型:', type) | 242 | console.log('删除图片事件:', event, '类型:', type) |
| @@ -255,19 +249,14 @@ const deleteImg = (event: UploadDeleteEvent, type: string) => { | @@ -255,19 +249,14 @@ const deleteImg = (event: UploadDeleteEvent, type: string) => { | ||
| 255 | } | 249 | } |
| 256 | 250 | ||
| 257 | /** | 251 | /** |
| 258 | - * 上传图片(单/多图统一逻辑) | ||
| 259 | - * @param event 上传事件 | ||
| 260 | - * @param type 图片类型(problemImgsList/completeImgsList) | 252 | + * 上传图片 |
| 261 | */ | 253 | */ |
| 262 | const uploadImgs = async (event: { file: UploadFile | UploadFile[] }, type: string) => { | 254 | const uploadImgs = async (event: { file: UploadFile | UploadFile[] }, type: string) => { |
| 263 | console.log('上传图片事件:', event, '类型:', type) | 255 | console.log('上传图片事件:', event, '类型:', type) |
| 264 | - // 统一处理为数组格式 | ||
| 265 | const fileList = Array.isArray(event.file) ? event.file : [event.file] | 256 | const fileList = Array.isArray(event.file) ? event.file : [event.file] |
| 266 | const targetImgList = type === 'problemImgsList' ? problemImgsList : completeImgsList | 257 | const targetImgList = type === 'problemImgsList' ? problemImgsList : completeImgsList |
| 267 | 258 | ||
| 268 | - // 1. 提取文件路径 | ||
| 269 | const filePaths = fileList.map(item => item.url) | 259 | const filePaths = fileList.map(item => item.url) |
| 270 | - // 2. 添加上传中临时项 | ||
| 271 | const tempItems: UploadFile[] = fileList.map(item => ({ | 260 | const tempItems: UploadFile[] = fileList.map(item => ({ |
| 272 | ...item, | 261 | ...item, |
| 273 | status: 'uploading' as const, | 262 | status: 'uploading' as const, |
| @@ -277,14 +266,12 @@ const uploadImgs = async (event: { file: UploadFile | UploadFile[] }, type: stri | @@ -277,14 +266,12 @@ const uploadImgs = async (event: { file: UploadFile | UploadFile[] }, type: stri | ||
| 277 | targetImgList.value.push(...tempItems) | 266 | targetImgList.value.push(...tempItems) |
| 278 | 267 | ||
| 279 | try { | 268 | try { |
| 280 | - // 3. 调用统一上传方法 | ||
| 281 | const uploadResultUrls = await uploadImages({ | 269 | const uploadResultUrls = await uploadImages({ |
| 282 | filePaths: filePaths, | 270 | filePaths: filePaths, |
| 283 | ignoreError: true | 271 | ignoreError: true |
| 284 | }) | 272 | }) |
| 285 | console.log('上传成功的URL列表:', uploadResultUrls) | 273 | console.log('上传成功的URL列表:', uploadResultUrls) |
| 286 | 274 | ||
| 287 | - // 4. 更新成功状态 | ||
| 288 | uploadResultUrls.forEach((url, index) => { | 275 | uploadResultUrls.forEach((url, index) => { |
| 289 | if (targetImgList.value[startIndex + index]) { | 276 | if (targetImgList.value[startIndex + index]) { |
| 290 | targetImgList.value.splice(startIndex + index, 1, { | 277 | targetImgList.value.splice(startIndex + index, 1, { |
| @@ -296,7 +283,6 @@ const uploadImgs = async (event: { file: UploadFile | UploadFile[] }, type: stri | @@ -296,7 +283,6 @@ const uploadImgs = async (event: { file: UploadFile | UploadFile[] }, type: stri | ||
| 296 | } | 283 | } |
| 297 | }) | 284 | }) |
| 298 | 285 | ||
| 299 | - // 5. 处理失败项 | ||
| 300 | if (uploadResultUrls.length < fileList.length) { | 286 | if (uploadResultUrls.length < fileList.length) { |
| 301 | const failCount = fileList.length - uploadResultUrls.length | 287 | const failCount = fileList.length - uploadResultUrls.length |
| 302 | for (let i = uploadResultUrls.length; i < fileList.length; i++) { | 288 | for (let i = uploadResultUrls.length; i < fileList.length; i++) { |
| @@ -314,7 +300,6 @@ const uploadImgs = async (event: { file: UploadFile | UploadFile[] }, type: stri | @@ -314,7 +300,6 @@ const uploadImgs = async (event: { file: UploadFile | UploadFile[] }, type: stri | ||
| 314 | } | 300 | } |
| 315 | } catch (err) { | 301 | } catch (err) { |
| 316 | console.error('图片上传失败:', err) | 302 | console.error('图片上传失败:', err) |
| 317 | - // 标记所有为失败 | ||
| 318 | for (let i = 0; i < fileList.length; i++) { | 303 | for (let i = 0; i < fileList.length; i++) { |
| 319 | if (targetImgList.value[startIndex + i]) { | 304 | if (targetImgList.value[startIndex + i]) { |
| 320 | targetImgList.value.splice(startIndex + i, 1, { | 305 | targetImgList.value.splice(startIndex + i, 1, { |
| @@ -329,16 +314,7 @@ const uploadImgs = async (event: { file: UploadFile | UploadFile[] }, type: stri | @@ -329,16 +314,7 @@ const uploadImgs = async (event: { file: UploadFile | UploadFile[] }, type: stri | ||
| 329 | } | 314 | } |
| 330 | 315 | ||
| 331 | /** | 316 | /** |
| 332 | - * 切换图片标签 | ||
| 333 | - * @param item 标签项 | ||
| 334 | - */ | ||
| 335 | -const switchImgTab = (item: { name: string; id: string }) => { | ||
| 336 | - console.log('切换图片标签:', item) | ||
| 337 | - activeImgTab.value = item.id | ||
| 338 | -} | ||
| 339 | - | ||
| 340 | -/** | ||
| 341 | - * 选择工单位置(地图)- 核心修改:清空道路名称 | 317 | + * 选择工单位置 |
| 342 | */ | 318 | */ |
| 343 | const chooseWorkLocation = () => { | 319 | const chooseWorkLocation = () => { |
| 344 | if (isSubmitting.value) return | 320 | if (isSubmitting.value) return |
| @@ -348,17 +324,14 @@ const chooseWorkLocation = () => { | @@ -348,17 +324,14 @@ const chooseWorkLocation = () => { | ||
| 348 | success: () => { | 324 | success: () => { |
| 349 | uni.chooseLocation({ | 325 | uni.chooseLocation({ |
| 350 | success: async (res) => { | 326 | success: async (res) => { |
| 351 | - // ========== 核心新增:清空道路名称相关数据 ========== | ||
| 352 | - workOrderForm.roadName = '' // 清空道路名称 | ||
| 353 | - workOrderForm.roadId = 0 // 清空道路ID | ||
| 354 | - roadNameList.value = [] // 清空道路名称列表 | 327 | + workOrderForm.roadName = '' |
| 328 | + workOrderForm.roadId = 0 | ||
| 329 | + roadNameList.value = [] | ||
| 355 | 330 | ||
| 356 | - // 更新工单位置 | ||
| 357 | workOrderForm.workLocation = res.name | 331 | workOrderForm.workLocation = res.name |
| 358 | workOrderForm.lat = res.latitude | 332 | workOrderForm.lat = res.latitude |
| 359 | workOrderForm.lon = res.longitude | 333 | workOrderForm.lon = res.longitude |
| 360 | 334 | ||
| 361 | - // 触发工单位置和道路名称的表单校验更新 | ||
| 362 | workOrderFormRef.value?.validateField('workLocation') | 335 | workOrderFormRef.value?.validateField('workLocation') |
| 363 | workOrderFormRef.value?.validateField('roadName') | 336 | workOrderFormRef.value?.validateField('roadName') |
| 364 | 337 | ||
| @@ -419,7 +392,6 @@ const chooseWorkLocation = () => { | @@ -419,7 +392,6 @@ const chooseWorkLocation = () => { | ||
| 419 | 392 | ||
| 420 | /** | 393 | /** |
| 421 | * 选择道路名称 | 394 | * 选择道路名称 |
| 422 | - * @param e 选择事件 | ||
| 423 | */ | 395 | */ |
| 424 | const handleRoadNameSelect = (e: UniActionSheetSelectEvent) => { | 396 | const handleRoadNameSelect = (e: UniActionSheetSelectEvent) => { |
| 425 | console.log('选择道路名称:', e) | 397 | console.log('选择道路名称:', e) |
| @@ -431,7 +403,6 @@ const handleRoadNameSelect = (e: UniActionSheetSelectEvent) => { | @@ -431,7 +403,6 @@ const handleRoadNameSelect = (e: UniActionSheetSelectEvent) => { | ||
| 431 | 403 | ||
| 432 | /** | 404 | /** |
| 433 | * 选择工单名称 | 405 | * 选择工单名称 |
| 434 | - * @param e 选择事件 | ||
| 435 | */ | 406 | */ |
| 436 | const handleOrderNameSelect = (e: UniActionSheetSelectEvent) => { | 407 | const handleOrderNameSelect = (e: UniActionSheetSelectEvent) => { |
| 437 | workOrderForm.orderName = e.name | 408 | workOrderForm.orderName = e.name |
| @@ -448,8 +419,6 @@ const hideKeyboard = () => { | @@ -448,8 +419,6 @@ const hideKeyboard = () => { | ||
| 448 | 419 | ||
| 449 | /** | 420 | /** |
| 450 | * 提取图片URL数组 | 421 | * 提取图片URL数组 |
| 451 | - * @param imgList 图片列表 | ||
| 452 | - * @returns URL数组 | ||
| 453 | */ | 422 | */ |
| 454 | const getImgUrlList = (imgList: UploadFile[]) => { | 423 | const getImgUrlList = (imgList: UploadFile[]) => { |
| 455 | console.log('提取图片URL:', imgList) | 424 | console.log('提取图片URL:', imgList) |
| @@ -457,29 +426,28 @@ const getImgUrlList = (imgList: UploadFile[]) => { | @@ -457,29 +426,28 @@ const getImgUrlList = (imgList: UploadFile[]) => { | ||
| 457 | } | 426 | } |
| 458 | 427 | ||
| 459 | /** | 428 | /** |
| 460 | - * 校验上传图片(兜底校验) | ||
| 461 | - * @returns 是否校验通过 | 429 | + * 校验上传图片 |
| 462 | */ | 430 | */ |
| 463 | const validateUploadImgs = () => { | 431 | const validateUploadImgs = () => { |
| 464 | - // 修复:补充返回值,避免函数无返回 | ||
| 465 | - if (activeImgTab.value === '1') { | ||
| 466 | - const hasValidImgs = problemImgsList.value.some(item => item.status === 'success') | ||
| 467 | - if (!hasValidImgs) { | ||
| 468 | - uni.showToast({ title: '请上传至少1张问题照片', icon: 'none' }) | ||
| 469 | - return false | ||
| 470 | - } | ||
| 471 | - } else { | ||
| 472 | - const hasValidcompleteImgs = completeImgsList.value.some(item => item.status === 'success') | ||
| 473 | - if (!hasValidcompleteImgs) { | ||
| 474 | - uni.showToast({ title: '请上传至少1张完成照片', icon: 'none' }) | ||
| 475 | - return false | ||
| 476 | - } | 432 | + const hasValidProblemImgs = problemImgsList.value.some(item => item.status === 'success') |
| 433 | + if (!hasValidProblemImgs) { | ||
| 434 | + uni.showToast({ title: '请上传至少1张问题照片', icon: 'none' }) | ||
| 435 | + workOrderFormRef.value?.validateField('problemImgs') | ||
| 436 | + return false | ||
| 477 | } | 437 | } |
| 438 | + | ||
| 439 | + const hasValidCompleteImgs = completeImgsList.value.some(item => item.status === 'success') | ||
| 440 | + if (!hasValidCompleteImgs) { | ||
| 441 | + uni.showToast({ title: '请上传至少1张完成照片', icon: 'none' }) | ||
| 442 | + workOrderFormRef.value?.validateField('completeImgs') | ||
| 443 | + return false | ||
| 444 | + } | ||
| 445 | + | ||
| 478 | return true | 446 | return true |
| 479 | } | 447 | } |
| 480 | 448 | ||
| 481 | /** | 449 | /** |
| 482 | - * 提交工单(修复核心:await位置 + 表单Ref名称错误) | 450 | + * 提交工单 |
| 483 | */ | 451 | */ |
| 484 | const submitWorkOrder = async () => { | 452 | const submitWorkOrder = async () => { |
| 485 | if (isSubmitting.value) { | 453 | if (isSubmitting.value) { |
| @@ -490,33 +458,36 @@ const submitWorkOrder = async () => { | @@ -490,33 +458,36 @@ const submitWorkOrder = async () => { | ||
| 490 | try { | 458 | try { |
| 491 | isSubmitting.value = true | 459 | isSubmitting.value = true |
| 492 | 460 | ||
| 493 | - // 修复1:兜底校验图片 | ||
| 494 | if (!validateUploadImgs()) { | 461 | if (!validateUploadImgs()) { |
| 495 | isSubmitting.value = false | 462 | isSubmitting.value = false |
| 496 | return | 463 | return |
| 497 | } | 464 | } |
| 498 | 465 | ||
| 499 | - // 修复2:使用正确的表单Ref名称(workOrderFormRef 而非 uFormRef) | ||
| 500 | - // 修复3:将validate转为Promise形式,配合async/await | ||
| 501 | - const valid = await new Promise((resolve) => { | ||
| 502 | - workOrderFormRef.value?.validate((isValid) => { | 466 | + const valid = await new Promise<boolean>((resolve) => { |
| 467 | + workOrderFormRef.value?.validate((isValid, invalidFields) => { | ||
| 468 | + console.log('校验失败的字段:', invalidFields) | ||
| 503 | resolve(isValid) | 469 | resolve(isValid) |
| 504 | }) | 470 | }) |
| 505 | }) | 471 | }) |
| 506 | 472 | ||
| 507 | if (!valid) { | 473 | if (!valid) { |
| 508 | - uni.showToast({ title: '表单校验失败,请检查必填项', icon: 'none' }) | 474 | + const firstInvalidField = Object.keys(workOrderFormRef.value?.invalidFields || {})[0] |
| 475 | + if (firstInvalidField) { | ||
| 476 | + const el = document.querySelector(`[prop="${firstInvalidField}"]`) | ||
| 477 | + el?.scrollIntoView({ behavior: 'smooth', block: 'center' }) | ||
| 478 | + } | ||
| 479 | + uni.showToast({ title: '表单填写不完整,请检查', icon: 'none' }) | ||
| 509 | isSubmitting.value = false | 480 | isSubmitting.value = false |
| 510 | return | 481 | return |
| 511 | } | 482 | } |
| 512 | 483 | ||
| 513 | - // 构造提交数据 | ||
| 514 | const submitData = { | 484 | const submitData = { |
| 515 | roadId: workOrderForm.roadId, | 485 | roadId: workOrderForm.roadId, |
| 516 | roadName: workOrderForm.roadName, | 486 | roadName: workOrderForm.roadName, |
| 517 | - imgs: getImgUrlList(problemImgsList.value), // 问题照片URL数组 | ||
| 518 | - longRangeImgList: getImgUrlList(completeImgsList.value), // 完成照片URL数组 | ||
| 519 | - remark: activeImgTab.value === '2' ? workOrderForm.handleResultDesc : workOrderForm.problemDesc, | 487 | + imgs: getImgUrlList(problemImgsList.value), |
| 488 | + longRangeImgList: getImgUrlList(completeImgsList.value), | ||
| 489 | + remark: workOrderForm.problemDesc, | ||
| 490 | + handleResultDesc: workOrderForm.handleResultDesc, | ||
| 520 | latLonType: 2, | 491 | latLonType: 2, |
| 521 | lat: workOrderForm.lat, | 492 | lat: workOrderForm.lat, |
| 522 | lon: workOrderForm.lon, | 493 | lon: workOrderForm.lon, |
| @@ -529,19 +500,9 @@ const submitWorkOrder = async () => { | @@ -529,19 +500,9 @@ const submitWorkOrder = async () => { | ||
| 529 | } | 500 | } |
| 530 | 501 | ||
| 531 | console.log('提交工单数据:', submitData) | 502 | console.log('提交工单数据:', submitData) |
| 532 | - // 修复4:await 现在在async函数中,可正常使用 | ||
| 533 | await createQuick(submitData) | 503 | await createQuick(submitData) |
| 534 | uni.showToast({ title: '工单提交成功', icon: 'success' }) | 504 | uni.showToast({ title: '工单提交成功', icon: 'success' }) |
| 535 | 505 | ||
| 536 | - // 可选:提交成功后重置表单 | ||
| 537 | - // problemImgsList.value = [] | ||
| 538 | - // completeImgsList.value = [] | ||
| 539 | - // Object.assign(workOrderForm, { | ||
| 540 | - // roadId: 0, roadName: '', workLocation: '', orderName: '', | ||
| 541 | - // problemDesc: '', handleResultDesc: '', lat: 0, lon: 0 | ||
| 542 | - // }) | ||
| 543 | - // workOrderFormRef.value?.clearValidate() | ||
| 544 | - | ||
| 545 | } catch (error) { | 506 | } catch (error) { |
| 546 | console.error('提交工单失败:', error) | 507 | console.error('提交工单失败:', error) |
| 547 | uni.showToast({ title: '提交失败,请重试', icon: 'none' }) | 508 | uni.showToast({ title: '提交失败,请重试', icon: 'none' }) |
| @@ -552,12 +513,10 @@ const submitWorkOrder = async () => { | @@ -552,12 +513,10 @@ const submitWorkOrder = async () => { | ||
| 552 | 513 | ||
| 553 | // ========== 页面挂载初始化 ========== | 514 | // ========== 页面挂载初始化 ========== |
| 554 | onMounted(() => { | 515 | onMounted(() => { |
| 555 | - setTimeout(() => { | ||
| 556 | - if (workOrderFormRef.value && !workOrderFormRef.value.rules) { | ||
| 557 | - workOrderFormRef.value.setRules(workOrderFormRules) | ||
| 558 | - console.log('工单表单规则初始化完成') | ||
| 559 | - } | ||
| 560 | - }, 200) | 516 | + if (workOrderFormRef.value && !workOrderFormRef.value.rules) { |
| 517 | + workOrderFormRef.value.setRules(workOrderFormRules) | ||
| 518 | + console.log('工单表单规则初始化完成') | ||
| 519 | + } | ||
| 561 | }) | 520 | }) |
| 562 | </script> | 521 | </script> |
| 563 | 522 | ||
| @@ -566,10 +525,15 @@ onMounted(() => { | @@ -566,10 +525,15 @@ onMounted(() => { | ||
| 566 | .u-page { | 525 | .u-page { |
| 567 | background-color: #f5f5f5; | 526 | background-color: #f5f5f5; |
| 568 | min-height: 100vh; | 527 | min-height: 100vh; |
| 569 | - padding-bottom: 100rpx; // 给底部按钮留空间 | 528 | + padding-bottom: 100rpx; |
| 529 | +} | ||
| 530 | + | ||
| 531 | +// 表单容器(新增:包裹整个表单) | ||
| 532 | +.work-order-form-container { | ||
| 533 | + width: 100%; | ||
| 570 | } | 534 | } |
| 571 | 535 | ||
| 572 | -// 工单表单容器 | 536 | +// 工单表单内容容器 |
| 573 | .work-order-form-content { | 537 | .work-order-form-content { |
| 574 | background: #fff; | 538 | background: #fff; |
| 575 | padding: 20rpx; | 539 | padding: 20rpx; |
| @@ -612,7 +576,7 @@ onMounted(() => { | @@ -612,7 +576,7 @@ onMounted(() => { | ||
| 612 | } | 576 | } |
| 613 | 577 | ||
| 614 | // 提交按钮区域 | 578 | // 提交按钮区域 |
| 615 | -.fixed-bottom-btn-wrap { // 修复:原样式类名是submit-btn-wrap,与模板不一致 | 579 | +.fixed-bottom-btn-wrap { |
| 616 | position: fixed; | 580 | position: fixed; |
| 617 | bottom: 0; | 581 | bottom: 0; |
| 618 | left: 0; | 582 | left: 0; |
| @@ -630,15 +594,15 @@ onMounted(() => { | @@ -630,15 +594,15 @@ onMounted(() => { | ||
| 630 | } | 594 | } |
| 631 | } | 595 | } |
| 632 | 596 | ||
| 633 | -// ========== 修复Label折行样式 ========== | 597 | +// Label样式 |
| 634 | :deep(.u-form-item__label) { | 598 | :deep(.u-form-item__label) { |
| 635 | - white-space: nowrap; // 强制不换行 | ||
| 636 | - text-overflow: ellipsis; // 超出省略 | ||
| 637 | - overflow: hidden; // 隐藏超出部分 | ||
| 638 | - line-height: 1.4; // 行高适配 | 599 | + white-space: nowrap; |
| 600 | + text-overflow: ellipsis; | ||
| 601 | + overflow: hidden; | ||
| 602 | + line-height: 1.4; | ||
| 639 | } | 603 | } |
| 640 | 604 | ||
| 641 | -// 表单基础样式适配 | 605 | +// 表单基础样式 |
| 642 | :deep(.u-form-item) { | 606 | :deep(.u-form-item) { |
| 643 | --u-form-item-label-font-size: 28rpx; | 607 | --u-form-item-label-font-size: 28rpx; |
| 644 | --u-form-item-content-font-size: 28rpx; | 608 | --u-form-item-content-font-size: 28rpx; |
| @@ -658,7 +622,14 @@ onMounted(() => { | @@ -658,7 +622,14 @@ onMounted(() => { | ||
| 658 | z-index: 9999 !important; | 622 | z-index: 9999 !important; |
| 659 | } | 623 | } |
| 660 | 624 | ||
| 661 | -:deep(.u-tabs) { | ||
| 662 | - background: #fff; | 625 | +// 错误提示样式 |
| 626 | +:deep(.u-form-item__error-message) { | ||
| 627 | + font-size: 24rpx !important; | ||
| 628 | + color: #f56c6c !important; | ||
| 629 | + margin-top: 5rpx !important; | ||
| 630 | +} | ||
| 631 | + | ||
| 632 | +:deep(.u-form-item--error .u-input__wrap) { | ||
| 633 | + border-color: #f56c6c !important; | ||
| 663 | } | 634 | } |
| 664 | </style> | 635 | </style> |
| 665 | \ No newline at end of file | 636 | \ No newline at end of file |