Commit c7df828a939478c246d15dd8583e078840820353
1 parent
8d0834be
快速工单 样式优化
Showing
7 changed files
with
367 additions
and
451 deletions
App.vue
common/utils/useUploadImgs.ts renamed to common/utils/useUploadImgs.js
| 1 | -import { ref, type Ref } from 'vue' | |
| 1 | +import { ref } from 'vue' | |
| 2 | 2 | import { uploadImages } from '@/common/utils/upload' |
| 3 | -import type { UniFormRef } from '@/uni_modules/uview-plus/types' | |
| 4 | - | |
| 5 | -// 定义上传配置类型 | |
| 6 | -export interface UploadImgConfig { | |
| 7 | - maxCount?: number // 最大上传数量,默认3 | |
| 8 | - uploadText?: string // 上传按钮文案 | |
| 9 | - sizeType?: UniApp.UploadFileOption['sizeType'] // 图片压缩类型 | |
| 10 | - formRef: Ref<UniFormRef | null> // 表单ref,用于校验 | |
| 11 | - fieldName: string // 表单校验字段名(如problemImgs) | |
| 12 | -} | |
| 13 | - | |
| 14 | -// 定义图片项类型 | |
| 15 | -export interface UploadImgItem { | |
| 16 | - url: string | |
| 17 | - status: 'uploading' | 'success' | 'failed' | |
| 18 | - message: string | |
| 19 | - [key: string]: any // 兼容其他字段 | |
| 20 | -} | |
| 21 | 3 | |
| 22 | 4 | /** |
| 23 | - * 图片上传组合式函数(支持多实例复用) | |
| 5 | + * 图片上传组合式函数(兼容非TS环境,纯数组格式) | |
| 24 | 6 | * @param config 上传配置 |
| 25 | 7 | * @returns 上传相关方法和状态 |
| 26 | 8 | */ |
| 27 | -export function useUploadImgs(config: UploadImgConfig) { | |
| 9 | +export function useUploadImgs(config) { | |
| 28 | 10 | // 默认配置 |
| 29 | 11 | const defaultConfig = { |
| 30 | 12 | maxCount: 3, |
| 31 | 13 | uploadText: '选择图片', |
| 32 | - sizeType: ['compressed'] as UniApp.UploadFileOption['sizeType'], | |
| 14 | + sizeType: ['compressed'], | |
| 33 | 15 | ...config |
| 34 | 16 | } |
| 35 | 17 | |
| 36 | - // 图片列表 | |
| 37 | - const imgList = ref<UploadImgItem[]>([]) | |
| 18 | + // 核心修复:初始化为纯数组,且格式适配u-upload | |
| 19 | + const imgList = ref([]) | |
| 38 | 20 | |
| 39 | 21 | /** |
| 40 | 22 | * 删除图片 |
| 41 | 23 | */ |
| 42 | - const deleteImg = (event: { index: number }) => { | |
| 43 | - imgList.value.splice(event.index, 1) | |
| 24 | + const deleteImg = (event) => { | |
| 25 | + // 确保index是有效数字 | |
| 26 | + const index = Number(event.index) | |
| 27 | + if (isNaN(index) || index < 0 || index >= imgList.value.length) return | |
| 28 | + | |
| 29 | + imgList.value.splice(index, 1) | |
| 44 | 30 | // 删除后重新校验 |
| 45 | 31 | defaultConfig.formRef.value?.validateField(defaultConfig.fieldName) |
| 46 | 32 | uni.showToast({ title: '图片删除成功', icon: 'success' }) |
| 47 | 33 | } |
| 48 | 34 | |
| 49 | 35 | /** |
| 50 | - * 上传图片 | |
| 36 | + * 上传图片(适配u-upload的file格式) | |
| 51 | 37 | */ |
| 52 | - const uploadImgs = async (event: { file: UniApp.ChooseImageSuccessCallbackResult | UniApp.ChooseImageSuccessCallbackResult[] }) => { | |
| 53 | - const fileList = Array.isArray(event.file) ? event.file : [event.file] | |
| 38 | + const uploadImgs = async (event) => { | |
| 39 | + // 核心修复:标准化file数据格式 | |
| 40 | + const rawFile = event.file || {} | |
| 41 | + const fileList = Array.isArray(rawFile) ? rawFile : [rawFile] | |
| 42 | + | |
| 43 | + // 过滤无效文件 | |
| 44 | + const validFiles = fileList.filter(file => file && file.url) | |
| 45 | + if (validFiles.length === 0) { | |
| 46 | + uni.showToast({ title: '请选择有效图片', icon: 'none' }) | |
| 47 | + return | |
| 48 | + } | |
| 49 | + | |
| 54 | 50 | const targetImgList = imgList.value |
| 55 | 51 | |
| 56 | - // 过滤超出最大数量的图片 | |
| 57 | - if (targetImgList.length + fileList.length > defaultConfig.maxCount) { | |
| 52 | + // 校验最大数量 | |
| 53 | + if (targetImgList.length + validFiles.length > defaultConfig.maxCount) { | |
| 58 | 54 | uni.showToast({ title: `最多只能上传${defaultConfig.maxCount}张图片`, icon: 'none' }) |
| 59 | 55 | return |
| 60 | 56 | } |
| 61 | 57 | |
| 62 | - const filePaths = fileList.map(item => item.url) | |
| 63 | - const tempItems = fileList.map(item => ({ | |
| 64 | - ...item, | |
| 65 | - status: 'uploading' as const, | |
| 66 | - message: '上传中' | |
| 58 | + // 核心修复:转换为u-upload兼容的格式 | |
| 59 | + const filePaths = validFiles.map(item => item.url) | |
| 60 | + const tempItems = validFiles.map(item => ({ | |
| 61 | + url: item.url, | |
| 62 | + status: 'uploading', | |
| 63 | + message: '上传中', | |
| 64 | + name: item.name || '', | |
| 65 | + size: item.size || 0 | |
| 67 | 66 | })) |
| 68 | 67 | const startIndex = targetImgList.length |
| 69 | 68 | targetImgList.push(...tempItems) |
| ... | ... | @@ -78,29 +77,32 @@ export function useUploadImgs(config: UploadImgConfig) { |
| 78 | 77 | uploadResultUrls.forEach((url, index) => { |
| 79 | 78 | if (targetImgList[startIndex + index]) { |
| 80 | 79 | targetImgList.splice(startIndex + index, 1, { |
| 81 | - ...fileList[index], | |
| 82 | - status: 'success' as const, | |
| 80 | + url: url, | |
| 81 | + status: 'success', | |
| 83 | 82 | message: '', |
| 84 | - url: url | |
| 83 | + name: validFiles[index].name || '', | |
| 84 | + size: validFiles[index].size || 0 | |
| 85 | 85 | }) |
| 86 | 86 | } |
| 87 | 87 | }) |
| 88 | 88 | |
| 89 | 89 | // 处理上传失败的图片 |
| 90 | - if (uploadResultUrls.length < fileList.length) { | |
| 91 | - const failCount = fileList.length - uploadResultUrls.length | |
| 92 | - for (let i = uploadResultUrls.length; i < fileList.length; i++) { | |
| 90 | + if (uploadResultUrls.length < validFiles.length) { | |
| 91 | + const failCount = validFiles.length - uploadResultUrls.length | |
| 92 | + for (let i = uploadResultUrls.length; i < validFiles.length; i++) { | |
| 93 | 93 | if (targetImgList[startIndex + i]) { |
| 94 | 94 | targetImgList.splice(startIndex + i, 1, { |
| 95 | - ...fileList[i], | |
| 96 | - status: 'failed' as const, | |
| 97 | - message: '上传失败' | |
| 95 | + url: validFiles[i].url, | |
| 96 | + status: 'failed', | |
| 97 | + message: '上传失败', | |
| 98 | + name: validFiles[i].name || '', | |
| 99 | + size: validFiles[i].size || 0 | |
| 98 | 100 | }) |
| 99 | 101 | } |
| 100 | 102 | } |
| 101 | 103 | uni.showToast({ title: `成功上传${uploadResultUrls.length}张,失败${failCount}张`, icon: 'none' }) |
| 102 | 104 | } else { |
| 103 | - uni.showToast({ title: `成功上传${fileList.length}张图片`, icon: 'success' }) | |
| 105 | + uni.showToast({ title: `成功上传${validFiles.length}张图片`, icon: 'success' }) | |
| 104 | 106 | } |
| 105 | 107 | |
| 106 | 108 | // 上传完成后校验 |
| ... | ... | @@ -108,12 +110,14 @@ export function useUploadImgs(config: UploadImgConfig) { |
| 108 | 110 | } catch (err) { |
| 109 | 111 | console.error(`【${defaultConfig.fieldName}】图片上传失败:`, err) |
| 110 | 112 | // 标记所有上传失败 |
| 111 | - for (let i = 0; i < fileList.length; i++) { | |
| 113 | + for (let i = 0; i < validFiles.length; i++) { | |
| 112 | 114 | if (targetImgList[startIndex + i]) { |
| 113 | 115 | targetImgList.splice(startIndex + i, 1, { |
| 114 | - ...fileList[i], | |
| 115 | - status: 'failed' as const, | |
| 116 | - message: '上传失败' | |
| 116 | + url: validFiles[i].url, | |
| 117 | + status: 'failed', | |
| 118 | + message: '上传失败', | |
| 119 | + name: validFiles[i].name || '', | |
| 120 | + size: validFiles[i].size || 0 | |
| 117 | 121 | }) |
| 118 | 122 | } |
| 119 | 123 | } |
| ... | ... | @@ -137,14 +141,15 @@ export function useUploadImgs(config: UploadImgConfig) { |
| 137 | 141 | required: true, |
| 138 | 142 | message: `请上传${defaultConfig.uploadText.replace('选择', '')}`, |
| 139 | 143 | trigger: 'change', |
| 140 | - validator: (rule: any, value: any, callback: (error?: Error) => void) => { | |
| 144 | + validator: (rule, value, callback) => { | |
| 141 | 145 | const hasSuccessImg = imgList.value.some(item => item.status === 'success') |
| 142 | 146 | hasSuccessImg ? callback() : callback(new Error(`请上传至少1张${defaultConfig.uploadText.replace('选择', '')}`)) |
| 143 | 147 | } |
| 144 | 148 | } |
| 145 | 149 | |
| 146 | 150 | return { |
| 147 | - imgList, | |
| 151 | + imgList: imgList.value, // 核心修复:返回纯数组(解除响应式代理) | |
| 152 | + rawImgList: imgList, // 保留响应式引用(内部使用) | |
| 148 | 153 | uploadImgs, |
| 149 | 154 | deleteImg, |
| 150 | 155 | getSuccessImgUrls, | ... | ... |
pages-sub/daily/maintain-manage/finish-plan-detail.vue
| ... | ... | @@ -71,7 +71,7 @@ |
| 71 | 71 | <view style="min-width: 200rpx">巡查描述</view> |
| 72 | 72 | </template> |
| 73 | 73 | <template #value> |
| 74 | - <view class="up-line-1" style="color: #606266">{{i.remark || '--'}}</view> | |
| 74 | + <view class="up-line-1 common-text-color" >{{i.remark || '--'}}</view> | |
| 75 | 75 | </template> |
| 76 | 76 | </up-cell> |
| 77 | 77 | ... | ... |
pages-sub/daily/patrol-manage/finish-plan-detail.vue
| ... | ... | @@ -72,7 +72,7 @@ |
| 72 | 72 | <view style="min-width: 200rpx">巡查描述</view> |
| 73 | 73 | </template> |
| 74 | 74 | <template #value> |
| 75 | - <view class="up-line-1" style="color: #606266">{{i.remark || '--'}}</view> | |
| 75 | + <view class="up-line-1 common-text-color">{{i.remark || '--'}}</view> | |
| 76 | 76 | </template> |
| 77 | 77 | </up-cell> |
| 78 | 78 | ... | ... |
pages-sub/daily/quick-order/add-order.vue
| 1 | 1 | <template> |
| 2 | - <view class="u-page"> | |
| 2 | + <view class="page-container"> | |
| 3 | 3 | <!-- 核心:将所有 up-form-item 包裹在同一个 up-form 内 --> |
| 4 | 4 | <view class="work-order-form-content commonPageLRpadding"> |
| 5 | 5 | <up-form |
| ... | ... | @@ -35,14 +35,14 @@ |
| 35 | 35 | > |
| 36 | 36 | <up-input |
| 37 | 37 | v-model="workOrderForm.roadName" |
| 38 | - disabled | |
| 38 | + readonly | |
| 39 | 39 | disabled-color="#ffffff" |
| 40 | 40 | placeholder="请先选择工单位置" |
| 41 | 41 | border="none" |
| 42 | - :placeholder-style="workOrderForm.workLocation ? '' : 'color:#999;'" | |
| 42 | + | |
| 43 | 43 | ></up-input> |
| 44 | 44 | <template #right> |
| 45 | - <up-icon name="arrow-right" size="16" :color="workOrderForm.workLocation ? '#333' : '#999'"></up-icon> | |
| 45 | + <up-icon name="arrow-right" size="16" ></up-icon> | |
| 46 | 46 | </template> |
| 47 | 47 | </up-form-item> |
| 48 | 48 | |
| ... | ... | @@ -74,7 +74,7 @@ |
| 74 | 74 | > |
| 75 | 75 | <up-textarea |
| 76 | 76 | placeholder="请输入情况描述(最多200字)" |
| 77 | - v-model="workOrderForm.problemDesc" | |
| 77 | + v-model.trim="workOrderForm.problemDesc" | |
| 78 | 78 | count |
| 79 | 79 | maxlength="200" |
| 80 | 80 | rows="4" |
| ... | ... | @@ -111,7 +111,7 @@ |
| 111 | 111 | <up-form-item label="处理结果" prop="handleResult" class="mt-20"> |
| 112 | 112 | <up-textarea |
| 113 | 113 | placeholder="请输入处理结果描述(最多200字,选填)" |
| 114 | - v-model="workOrderForm.handleResult" | |
| 114 | + v-model.trim="workOrderForm.handleResult" | |
| 115 | 115 | count |
| 116 | 116 | maxlength="200" |
| 117 | 117 | rows="4" |
| ... | ... | @@ -206,7 +206,7 @@ export default { |
| 206 | 206 | ], |
| 207 | 207 | problemDesc: [ |
| 208 | 208 | {type: 'string', required: true, message: '请输入情况描述', trigger: ['change', 'blur']}, |
| 209 | - {type: 'string', min: 3, max: 200, message: '情况描述需3-150字', trigger: ['change', 'blur']} | |
| 209 | + {type: 'string', min: 3, max: 200, message: '情况描述需3-200字', trigger: ['change', 'blur']} | |
| 210 | 210 | ], |
| 211 | 211 | problemImgs: [ |
| 212 | 212 | { |
| ... | ... | @@ -447,8 +447,8 @@ export default { |
| 447 | 447 | roadName: this.workOrderForm.roadName, |
| 448 | 448 | imgs: this.getImgUrlList(this.problemImgsList), |
| 449 | 449 | longRangeImgList: this.getImgUrlList(this.completeImgsList), |
| 450 | - remark: this.workOrderForm.problemDesc, | |
| 451 | - handleResult: this.workOrderForm.handleResult, | |
| 450 | + remark: this.workOrderForm.problemDesc.trim(), | |
| 451 | + handleResult: this.workOrderForm.handleResult.trim(), | |
| 452 | 452 | latLonType: 2, |
| 453 | 453 | lat: this.workOrderForm.lat, |
| 454 | 454 | lon: this.workOrderForm.lon, |
| ... | ... | @@ -509,13 +509,14 @@ export default { |
| 509 | 509 | |
| 510 | 510 | <style lang="scss" scoped> |
| 511 | 511 | // 全局页面样式 |
| 512 | -.u-page { | |
| 512 | +.page-container { | |
| 513 | 513 | min-height: 100vh; |
| 514 | 514 | } |
| 515 | 515 | |
| 516 | 516 | // 工单表单内容容器 |
| 517 | 517 | .work-order-form-content { |
| 518 | 518 | background: #fff; |
| 519 | + margin-bottom: 100rpx; | |
| 519 | 520 | } |
| 520 | 521 | |
| 521 | 522 | ... | ... |
pages-sub/daily/quick-order/order-detail.vue
| ... | ... | @@ -33,7 +33,7 @@ |
| 33 | 33 | <view style="min-width: 200rpx">工单位置</view> |
| 34 | 34 | </template> |
| 35 | 35 | <template #value> |
| 36 | - <view class="up-line-1">{{orderDetail.roadName || '--'}}</view> | |
| 36 | + <view class="up-line-1 common-text-color" >{{orderDetail.roadName || '--'}}</view> | |
| 37 | 37 | </template> |
| 38 | 38 | |
| 39 | 39 | </up-cell> |
| ... | ... | @@ -54,7 +54,7 @@ |
| 54 | 54 | <view style="min-width: 200rpx">情况描述</view> |
| 55 | 55 | </template> |
| 56 | 56 | <template #value> |
| 57 | - <view class="up-line-1">{{orderDetail.remark || '--'}}</view> | |
| 57 | + <view class="up-line-1 common-text-color" >{{orderDetail.remark || '--'}}</view> | |
| 58 | 58 | </template> |
| 59 | 59 | </up-cell> |
| 60 | 60 | |
| ... | ... | @@ -101,7 +101,7 @@ |
| 101 | 101 | <view style="min-width: 200rpx">处理结果</view> |
| 102 | 102 | </template> |
| 103 | 103 | <template #value> |
| 104 | - <view class="up-line-1">{{orderDetail.handleResult || '--'}}</view> | |
| 104 | + <view class="up-line-1 common-text-color" >{{orderDetail.handleResult || '--'}}</view> | |
| 105 | 105 | </template> |
| 106 | 106 | </up-cell> |
| 107 | 107 | </up-cell-group> | ... | ... |
pages-sub/problem/work-order-manage/add-order.vue
| 1 | 1 | <template> |
| 2 | - <view class="u-page"> | |
| 3 | - <!-- 核心:将所有 up-form-item 包裹在同一个 up-form 内 --> | |
| 2 | + <view class="page-container"> | |
| 4 | 3 | <view class="work-order-form-content commonPageLRpadding"> |
| 5 | 4 | <up-form |
| 6 | 5 | label-position="left" |
| ... | ... | @@ -25,7 +24,7 @@ |
| 25 | 24 | ></up-input> |
| 26 | 25 | </up-form-item> |
| 27 | 26 | |
| 28 | - <!-- 2. 道路名称(下拉框:位置选择后才可点击) --> | |
| 27 | + <!-- 2. 道路名称(下拉框) --> | |
| 29 | 28 | <up-form-item |
| 30 | 29 | label="道路名称" |
| 31 | 30 | prop="roadName" |
| ... | ... | @@ -98,25 +97,26 @@ |
| 98 | 97 | count |
| 99 | 98 | maxlength="200" |
| 100 | 99 | rows="4" |
| 101 | - @blur="() => $refs.workOrderFormRef.validateField('problemDesc')" | |
| 100 | + @blur="() => workOrderFormRef.validateField('problemDesc')" | |
| 102 | 101 | ></up-textarea> |
| 103 | 102 | </up-form-item> |
| 104 | 103 | |
| 105 | - <!-- 问题照片(移除完成照片相关代码) --> | |
| 104 | + <!-- 问题照片(核心修复:绑定纯数组) --> | |
| 106 | 105 | <up-form-item label="问题照片" prop="problemImgs" required> |
| 107 | 106 | <up-upload |
| 108 | - :file-list="problemImgsList" | |
| 109 | - @after-read="(event) => uploadImgs(event, 'problemImgsList')" | |
| 110 | - @delete="(event) => deleteImg(event, 'problemImgsList')" | |
| 107 | + :file-list="problemImgs.imgList" | |
| 108 | + @after-read="problemImgs.uploadImgs" | |
| 109 | + @delete="problemImgs.deleteImg" | |
| 111 | 110 | multiple |
| 112 | - :max-count="3" | |
| 113 | - upload-text="选择问题照片" | |
| 111 | + :max-count="problemImgs.uploadConfig.maxCount" | |
| 112 | + :upload-text="problemImgs.uploadConfig.uploadText" | |
| 113 | + :size-type="problemImgs.uploadConfig.sizeType" | |
| 114 | 114 | ></up-upload> |
| 115 | 115 | </up-form-item> |
| 116 | 116 | |
| 117 | 117 | <!-- 完成时间 --> |
| 118 | 118 | <up-form-item |
| 119 | - label="完成时间" | |
| 119 | + label="希望完成时间" | |
| 120 | 120 | prop="finishTime" |
| 121 | 121 | @click="show=true;hideKeyboard()" |
| 122 | 122 | > |
| ... | ... | @@ -163,402 +163,307 @@ |
| 163 | 163 | </view> |
| 164 | 164 | </template> |
| 165 | 165 | |
| 166 | -<script setup lang="ts"> | |
| 167 | -import {ref} from 'vue' | |
| 168 | -import type {UniFormRef} from '@/uni_modules/uview-plus/types' | |
| 169 | -// 定义ref供选项式API使用 | |
| 170 | -const workOrderFormRef = ref<UniFormRef>(null) | |
| 171 | -</script> | |
| 166 | +<script setup> | |
| 167 | +import { ref, reactive, watch } from 'vue' | |
| 168 | +import { onReady, onShow } from '@dcloudio/uni-app'; | |
| 169 | +import { useUploadImgs } from '@/common/utils/useUploadImgs' // 引入改造后的上传逻辑 | |
| 170 | +import { getRoadListByLatLng } from '@/api/common' | |
| 171 | +import { createQuick } from '@/api/quick-order/quick-order' | |
| 172 | +import { timeFormat } from '@/uni_modules/uview-plus' | |
| 173 | + | |
| 174 | +// ========== 表单Ref ========== | |
| 175 | +const workOrderFormRef = ref(null) | |
| 176 | + | |
| 177 | +// ========== 公共上传逻辑复用 ========== | |
| 178 | +const problemImgs = useUploadImgs({ | |
| 179 | + maxCount: 3, | |
| 180 | + uploadText: '选择问题照片', | |
| 181 | + sizeType: ['compressed'], | |
| 182 | + formRef: workOrderFormRef, | |
| 183 | + fieldName: 'problemImgs' | |
| 184 | +}) | |
| 185 | + | |
| 186 | +// 核心修复:监听响应式数组变化,同步更新纯数组(解决u-upload不刷新问题) | |
| 187 | +watch(() => problemImgs.rawImgList.value, (newVal) => { | |
| 188 | + problemImgs.imgList = newVal | |
| 189 | +}, { deep: true }) | |
| 190 | + | |
| 191 | +// ========== 页面状态 ========== | |
| 192 | +// 通用弹窗控制 | |
| 193 | +const showActionSheet = ref(false) | |
| 194 | +// 当前弹窗配置 | |
| 195 | +const currentActionSheetData = reactive({ | |
| 196 | + type: '', | |
| 197 | + list: [], | |
| 198 | + title: '' | |
| 199 | +}) | |
| 200 | +// 完成时间选择器控制 | |
| 201 | +const show = ref(false) | |
| 202 | +const finishTime = ref(Date.now()) | |
| 203 | + | |
| 204 | +// ========== 下拉列表数据 ========== | |
| 205 | +const roadNameList = ref([]) | |
| 206 | +const orderNameList = ref([]) | |
| 207 | +const pressingTypeList = ref([]) | |
| 208 | + | |
| 209 | +// ========== 工单表单数据 ========== | |
| 210 | +const workOrderForm = reactive({ | |
| 211 | + roadId: 0, // 道路ID | |
| 212 | + roadName: '', // 道路名称 | |
| 213 | + workLocation: '', // 工单位置 | |
| 214 | + orderName: '', // 工单名称 | |
| 215 | + pressingType: 0, // 紧急程度值(提交接口用) | |
| 216 | + pressingTypeName: '', // 紧急程度名称(显示用) | |
| 217 | + problemDesc: '', // 情况描述 | |
| 218 | + lat: 0, // 纬度 | |
| 219 | + lon: 0, // 经度 | |
| 220 | + finishTime: '', // 完成时间 | |
| 221 | +}) | |
| 222 | + | |
| 223 | +// ========== 表单校验规则 ========== | |
| 224 | +const workOrderFormRules = reactive({ | |
| 225 | + workLocation: [ | |
| 226 | + { type: 'string', required: true, message: '请选择工单位置', trigger: ['change', 'blur'] } | |
| 227 | + ], | |
| 228 | + roadName: [ | |
| 229 | + { type: 'string', required: true, message: '请选择道路名称', trigger: ['change', 'blur'] } | |
| 230 | + ], | |
| 231 | + orderName: [ | |
| 232 | + { type: 'string', required: true, message: '请选择工单名称', trigger: ['change', 'blur'] } | |
| 233 | + ], | |
| 234 | + pressingType: [ | |
| 235 | + { type: 'number', required: true, message: '请选择紧急程度', trigger: ['change'] } | |
| 236 | + ], | |
| 237 | + problemDesc: [ | |
| 238 | + { type: 'string', required: true, message: '请输入情况描述', trigger: ['change', 'blur'] }, | |
| 239 | + { type: 'string', min: 3, max: 200, message: '情况描述需3-200字', trigger: ['change', 'blur'] } | |
| 240 | + ], | |
| 241 | + problemImgs: [problemImgs.imgValidateRule] // 复用上传校验规则 | |
| 242 | +}) | |
| 243 | + | |
| 244 | +// ========== 生命周期 ========== | |
| 245 | +onReady(() => { | |
| 246 | + // 设置表单校验规则 | |
| 247 | + if (workOrderFormRef.value) { | |
| 248 | + workOrderFormRef.value.setRules(workOrderFormRules) | |
| 249 | + } | |
| 250 | + console.log('工单表单规则初始化完成') | |
| 251 | +}) | |
| 252 | + | |
| 253 | +onShow(() => { | |
| 254 | + console.log(uni.$dict.getDictLabel('ai_image_status', 20)) | |
| 255 | + console.log(uni.$dict.getDictSimpleList('work_name')) | |
| 256 | + | |
| 257 | + // 初始化工单名称列表 | |
| 258 | + orderNameList.value = uni.$dict.transformLabelValueToNameValue(uni.$dict.getDictSimpleList('work_name')) | |
| 259 | + console.log('工单名称列表:', orderNameList.value) | |
| 260 | + | |
| 261 | + // 初始化紧急程度列表 | |
| 262 | + pressingTypeList.value = uni.$dict.transformLabelValueToNameValue(uni.$dict.getDictSimpleList('workorder_pressing_type')) | |
| 263 | + console.log('紧急程度列表:', pressingTypeList.value) | |
| 264 | +}) | |
| 265 | + | |
| 266 | +// ========== 方法定义 ========== | |
| 267 | +/** | |
| 268 | + * 打开通用下拉弹窗 | |
| 269 | + */ | |
| 270 | +const handleActionSheetOpen = (type) => { | |
| 271 | + // 道路名称需先校验工单位置是否选择 | |
| 272 | + if (type === 'roadName' && !workOrderForm.workLocation) { | |
| 273 | + uni.showToast({ title: '请先选择工单位置', icon: 'none' }) | |
| 274 | + return | |
| 275 | + } | |
| 172 | 276 | |
| 173 | -<script lang="ts"> | |
| 174 | -import {getRoadListByLatLng} from '@/api/common' | |
| 175 | -import {uploadImages} from '@/common/utils/upload'; | |
| 176 | -import {createQuick} from '@/api/quick-order/quick-order' | |
| 177 | -import { timeFormat } from '@/uni_modules/uview-plus' // 引入时间格式化工具 | |
| 178 | - | |
| 179 | -export default { | |
| 180 | - data() { | |
| 181 | - return { | |
| 182 | - // 问题照片列表 | |
| 183 | - problemImgsList: [], | |
| 184 | - // 通用弹窗控制 | |
| 185 | - showActionSheet: false, | |
| 186 | - // 当前弹窗配置(类型 + 数据 + 标题) | |
| 187 | - currentActionSheetData: { | |
| 188 | - type: '', // roadName / orderName / pressingType | |
| 189 | - list: [], // 对应类型的选项列表 | |
| 190 | - title: '' // 弹窗标题 | |
| 191 | - }, | |
| 192 | - // 完成时间选择器控制 | |
| 193 | - show: false, | |
| 194 | - finishTime: Date.now(), | |
| 195 | - // 下拉列表数据 | |
| 196 | - roadNameList: [], | |
| 197 | - orderNameList: [], | |
| 198 | - pressingTypeList: [], | |
| 199 | - // 工单表单数据 | |
| 200 | - workOrderForm: { | |
| 201 | - roadId: 0, // 道路ID | |
| 202 | - roadName: '', // 道路名称 | |
| 203 | - workLocation: '', // 工单位置 | |
| 204 | - orderName: '', // 工单名称 | |
| 205 | - pressingType: 0, // 紧急程度值(提交接口用) | |
| 206 | - pressingTypeName: '', // 紧急程度名称(显示用) | |
| 207 | - problemDesc: '', // 情况描述 | |
| 208 | - lat: 0, // 纬度 | |
| 209 | - lon: 0, // 经度 | |
| 210 | - finishTime: '', // 完成时间 | |
| 211 | - }, | |
| 212 | - | |
| 213 | - // 表单校验规则 | |
| 214 | - workOrderFormRules: { | |
| 215 | - workLocation: [ | |
| 216 | - {type: 'string', required: true, message: '请选择工单位置', trigger: ['change', 'blur']} | |
| 217 | - ], | |
| 218 | - roadName: [ | |
| 219 | - {type: 'string', required: true, message: '请选择道路名称', trigger: ['change', 'blur']} | |
| 220 | - ], | |
| 221 | - orderName: [ | |
| 222 | - {type: 'string', required: true, message: '请选择工单名称', trigger: ['change', 'blur']} | |
| 223 | - ], | |
| 224 | - pressingType: [ | |
| 225 | - {type: 'number', required: true, message: '请选择紧急程度', trigger: ['change']} | |
| 226 | - ], | |
| 227 | - problemDesc: [ | |
| 228 | - {type: 'string', required: true, message: '请输入情况描述', trigger: ['change', 'blur']}, | |
| 229 | - {type: 'string', min: 3, max: 200, message: '情况描述需3-200字', trigger: ['change', 'blur']} | |
| 230 | - ], | |
| 231 | - problemImgs: [ | |
| 232 | - { | |
| 233 | - required: true, | |
| 234 | - message: '请上传问题照片', | |
| 235 | - trigger: 'change', | |
| 236 | - validator: (rule, value, callback) => { | |
| 237 | - const hasSuccessImg = this.problemImgsList.some(item => item.status === 'success') | |
| 238 | - hasSuccessImg ? callback() : callback(new Error('请上传至少1张问题照片')) | |
| 239 | - } | |
| 240 | - } | |
| 241 | - ] | |
| 242 | - } | |
| 277 | + // 配置当前弹窗参数 | |
| 278 | + const configMap = { | |
| 279 | + roadName: { | |
| 280 | + title: '请选择道路名称', | |
| 281 | + list: roadNameList.value | |
| 282 | + }, | |
| 283 | + orderName: { | |
| 284 | + title: '请选择工单名称', | |
| 285 | + list: orderNameList.value | |
| 286 | + }, | |
| 287 | + pressingType: { | |
| 288 | + title: '请选择紧急程度', | |
| 289 | + list: pressingTypeList.value | |
| 243 | 290 | } |
| 244 | - }, | |
| 245 | - | |
| 246 | - onReady() { | |
| 247 | - // 兼容微信小程序,通过setRules设置校验规则 | |
| 248 | - this.$refs.workOrderFormRef.setRules(this.workOrderFormRules) | |
| 249 | - console.log('工单表单规则初始化完成') | |
| 250 | - }, | |
| 251 | - | |
| 252 | - onShow(){ | |
| 253 | - console.log(uni.$dict.getDictLabel('ai_image_status', 20)) | |
| 254 | - console.log(uni.$dict.getDictSimpleList('work_name')) | |
| 255 | - | |
| 256 | - // 初始化工单名称列表 | |
| 257 | - this.orderNameList = uni.$dict.transformLabelValueToNameValue(uni.$dict.getDictSimpleList('work_name')) | |
| 258 | - console.log('工单名称列表:', this.orderNameList) | |
| 259 | - | |
| 260 | - // 初始化紧急程度列表 | |
| 261 | - this.pressingTypeList = uni.$dict.transformLabelValueToNameValue(uni.$dict.getDictSimpleList('workorder_pressing_type')) | |
| 262 | - console.log('紧急程度列表:', this.pressingTypeList) | |
| 263 | - }, | |
| 264 | - | |
| 265 | - methods: { | |
| 266 | - /** | |
| 267 | - * 打开通用下拉弹窗 | |
| 268 | - * @param type 弹窗类型:roadName / orderName / pressingType | |
| 269 | - */ | |
| 270 | - handleActionSheetOpen(type) { | |
| 271 | - // 道路名称需先校验工单位置是否选择 | |
| 272 | - if (type === 'roadName' && !this.workOrderForm.workLocation) { | |
| 273 | - uni.showToast({title: '请先选择工单位置', icon: 'none'}) | |
| 274 | - return | |
| 275 | - } | |
| 291 | + } | |
| 276 | 292 | |
| 277 | - // 配置当前弹窗参数 | |
| 278 | - const configMap = { | |
| 279 | - roadName: { | |
| 280 | - title: '请选择道路名称', | |
| 281 | - list: this.roadNameList | |
| 282 | - }, | |
| 283 | - orderName: { | |
| 284 | - title: '请选择工单名称', | |
| 285 | - list: this.orderNameList | |
| 286 | - }, | |
| 287 | - pressingType: { | |
| 288 | - title: '请选择紧急程度', | |
| 289 | - list: this.pressingTypeList | |
| 290 | - } | |
| 291 | - } | |
| 293 | + currentActionSheetData.type = type | |
| 294 | + currentActionSheetData.title = configMap[type].title | |
| 295 | + currentActionSheetData.list = configMap[type].list | |
| 296 | + showActionSheet.value = true | |
| 297 | +} | |
| 292 | 298 | |
| 293 | - this.currentActionSheetData = { | |
| 294 | - type, | |
| 295 | - title: configMap[type].title, | |
| 296 | - list: configMap[type].list | |
| 297 | - } | |
| 298 | - this.showActionSheet = true | |
| 299 | - }, | |
| 299 | +/** | |
| 300 | + * 关闭通用下拉弹窗 | |
| 301 | + */ | |
| 302 | +const handleActionSheetClose = () => { | |
| 303 | + showActionSheet.value = false | |
| 304 | + // 重置当前弹窗配置 | |
| 305 | + currentActionSheetData.type = '' | |
| 306 | + currentActionSheetData.list = [] | |
| 307 | + currentActionSheetData.title = '' | |
| 308 | +} | |
| 300 | 309 | |
| 301 | - /** | |
| 302 | - * 关闭通用下拉弹窗 | |
| 303 | - */ | |
| 304 | - handleActionSheetClose() { | |
| 305 | - this.showActionSheet = false | |
| 306 | - // 重置当前弹窗配置(可选,防止数据残留) | |
| 307 | - this.currentActionSheetData = { type: '', list: [], title: '' } | |
| 308 | - }, | |
| 310 | +/** | |
| 311 | + * 通用下拉弹窗选择事件 | |
| 312 | + */ | |
| 313 | +const handleActionSheetSelect = (e) => { | |
| 314 | + const { type } = currentActionSheetData | |
| 315 | + // 根据类型处理不同的选择逻辑 | |
| 316 | + switch (type) { | |
| 317 | + case 'roadName': | |
| 318 | + workOrderForm.roadName = e.name | |
| 319 | + workOrderForm.roadId = e.code | |
| 320 | + workOrderFormRef.value?.validateField('roadName') | |
| 321 | + break | |
| 322 | + case 'orderName': | |
| 323 | + workOrderForm.orderName = e.name | |
| 324 | + workOrderFormRef.value?.validateField('orderName') | |
| 325 | + break | |
| 326 | + case 'pressingType': | |
| 327 | + workOrderForm.pressingType = Number(e.value) | |
| 328 | + workOrderForm.pressingTypeName = e.name | |
| 329 | + workOrderFormRef.value?.validateField('pressingType') | |
| 330 | + break | |
| 331 | + } | |
| 332 | + // 关闭弹窗 | |
| 333 | + showActionSheet.value = false | |
| 334 | +} | |
| 309 | 335 | |
| 310 | - /** | |
| 311 | - * 通用下拉弹窗选择事件 | |
| 312 | - * @param e 选择的项 | |
| 313 | - */ | |
| 314 | - handleActionSheetSelect(e) { | |
| 315 | - const { type } = this.currentActionSheetData | |
| 316 | - // 根据类型处理不同的选择逻辑 | |
| 317 | - switch (type) { | |
| 318 | - case 'roadName': | |
| 319 | - this.workOrderForm.roadName = e.name | |
| 320 | - this.workOrderForm.roadId = e.code | |
| 321 | - this.$refs.workOrderFormRef.validateField('roadName') | |
| 322 | - break | |
| 323 | - case 'orderName': | |
| 324 | - this.workOrderForm.orderName = e.name | |
| 325 | - this.$refs.workOrderFormRef.validateField('orderName') | |
| 326 | - break | |
| 327 | - case 'pressingType': | |
| 328 | - this.workOrderForm.pressingType = Number(e.value) | |
| 329 | - this.workOrderForm.pressingTypeName = e.name | |
| 330 | - this.$refs.workOrderFormRef.validateField('pressingType') | |
| 331 | - break | |
| 332 | - } | |
| 333 | - // 关闭弹窗 | |
| 334 | - this.showActionSheet = false | |
| 335 | - }, | |
| 336 | +/** | |
| 337 | + * 返回上一页 | |
| 338 | + */ | |
| 339 | +const navigateBack = () => { | |
| 340 | + uni.navigateBack() | |
| 341 | +} | |
| 336 | 342 | |
| 337 | - /** | |
| 338 | - * 返回上一页 | |
| 339 | - */ | |
| 340 | - navigateBack() { | |
| 341 | - uni.navigateBack() | |
| 342 | - }, | |
| 343 | +/** | |
| 344 | + * 选择工单位置 | |
| 345 | + */ | |
| 346 | +const chooseWorkLocation = () => { | |
| 347 | + uni.chooseLocation({ | |
| 348 | + success: async (res) => { | |
| 349 | + workOrderForm.roadName = '' | |
| 350 | + workOrderForm.roadId = 0 | |
| 351 | + roadNameList.value = [] | |
| 343 | 352 | |
| 344 | - /** | |
| 345 | - * 删除图片 | |
| 346 | - */ | |
| 347 | - deleteImg(event, type) { | |
| 348 | - console.log('删除图片事件:', event, '类型:', type) | |
| 349 | - if (type === 'problemImgsList') { | |
| 350 | - this.problemImgsList.splice(event.index, 1) | |
| 351 | - this.$refs.workOrderFormRef.validateField('problemImgs') | |
| 352 | - } | |
| 353 | - uni.showToast({title: '图片删除成功', icon: 'success'}) | |
| 354 | - }, | |
| 353 | + workOrderForm.workLocation = res.name | |
| 354 | + workOrderForm.lat = res.latitude | |
| 355 | + workOrderForm.lon = res.longitude | |
| 355 | 356 | |
| 356 | - /** | |
| 357 | - * 上传图片 | |
| 358 | - */ | |
| 359 | - async uploadImgs(event, type) { | |
| 360 | - console.log('上传图片事件:', event, '类型:', type) | |
| 361 | - if (type !== 'problemImgsList') return | |
| 362 | - | |
| 363 | - const fileList = Array.isArray(event.file) ? event.file : [event.file] | |
| 364 | - const targetImgList = this.problemImgsList | |
| 365 | - | |
| 366 | - const filePaths = fileList.map(item => item.url) | |
| 367 | - const tempItems = fileList.map(item => ({ | |
| 368 | - ...item, | |
| 369 | - status: 'uploading', | |
| 370 | - message: '上传中' | |
| 371 | - })) | |
| 372 | - const startIndex = targetImgList.length | |
| 373 | - targetImgList.push(...tempItems) | |
| 357 | + workOrderFormRef.value?.validateField('workLocation') | |
| 358 | + workOrderFormRef.value?.validateField('roadName') | |
| 374 | 359 | |
| 375 | 360 | try { |
| 376 | - const uploadResultUrls = await uploadImages({ | |
| 377 | - filePaths: filePaths, | |
| 378 | - ignoreError: true | |
| 379 | - }) | |
| 380 | - console.log('上传成功的URL列表:', uploadResultUrls) | |
| 381 | - | |
| 382 | - uploadResultUrls.forEach((url, index) => { | |
| 383 | - if (targetImgList[startIndex + index]) { | |
| 384 | - targetImgList.splice(startIndex + index, 1, { | |
| 385 | - ...fileList[index], | |
| 386 | - status: 'success', | |
| 387 | - message: '', | |
| 388 | - url: url | |
| 389 | - }) | |
| 390 | - } | |
| 361 | + uni.showLoading({ title: '获取道路名称中...' }) | |
| 362 | + const roadRes = await getRoadListByLatLng({ | |
| 363 | + companyCode: 'sls', | |
| 364 | + latitude: res.latitude, | |
| 365 | + longitude: res.longitude | |
| 391 | 366 | }) |
| 367 | + uni.hideLoading() | |
| 392 | 368 | |
| 393 | - if (uploadResultUrls.length < fileList.length) { | |
| 394 | - const failCount = fileList.length - uploadResultUrls.length | |
| 395 | - for (let i = uploadResultUrls.length; i < fileList.length; i++) { | |
| 396 | - if (targetImgList[startIndex + i]) { | |
| 397 | - targetImgList.splice(startIndex + i, 1, { | |
| 398 | - ...fileList[i], | |
| 399 | - status: 'failed', | |
| 400 | - message: '上传失败' | |
| 401 | - }) | |
| 402 | - } | |
| 403 | - } | |
| 404 | - uni.showToast({title: `成功上传${uploadResultUrls.length}张,失败${failCount}张`, icon: 'none'}) | |
| 369 | + if (Array.isArray(roadRes)) { | |
| 370 | + roadNameList.value = roadRes.map((item) => ({ | |
| 371 | + name: item.roadName || '', | |
| 372 | + code: item.roadCode || '', | |
| 373 | + id: item.roadId || 0 | |
| 374 | + })) | |
| 405 | 375 | } else { |
| 406 | - uni.showToast({title: `成功上传${fileList.length}张图片`, icon: 'success'}) | |
| 376 | + roadNameList.value = [{ name: '未查询到道路名称', code: '', id: 0 }] | |
| 377 | + uni.showToast({ title: '未查询到该位置的道路信息', icon: 'none' }) | |
| 407 | 378 | } |
| 408 | - | |
| 409 | - this.$refs.workOrderFormRef.validateField('problemImgs') | |
| 410 | 379 | } catch (err) { |
| 411 | - console.error('图片上传失败:', err) | |
| 412 | - for (let i = 0; i < fileList.length; i++) { | |
| 413 | - if (targetImgList[startIndex + i]) { | |
| 414 | - targetImgList.splice(startIndex + i, 1, { | |
| 415 | - ...fileList[i], | |
| 416 | - status: 'failed', | |
| 417 | - message: '上传失败' | |
| 418 | - }) | |
| 419 | - } | |
| 420 | - } | |
| 421 | - uni.showToast({title: '图片上传失败,请重试', icon: 'none'}) | |
| 422 | - this.$refs.workOrderFormRef.validateField('problemImgs') | |
| 380 | + uni.hideLoading() | |
| 381 | + console.error('获取道路名称失败:', err) | |
| 382 | + uni.showToast({ title: '获取道路名称失败,请重试', icon: 'none' }) | |
| 383 | + roadNameList.value = [{ name: '获取失败,请重新选择位置', code: '', id: 0 }] | |
| 423 | 384 | } |
| 424 | 385 | }, |
| 386 | + fail: (err) => { | |
| 387 | + console.error('选择位置失败:', err) | |
| 388 | + uni.showToast({ title: '选择位置失败:' + err.errMsg, icon: 'none' }) | |
| 389 | + } | |
| 390 | + }) | |
| 391 | +} | |
| 425 | 392 | |
| 426 | - /** | |
| 427 | - * 选择工单位置 | |
| 428 | - */ | |
| 429 | - chooseWorkLocation() { | |
| 430 | - let that = this | |
| 431 | - uni.chooseLocation({ | |
| 432 | - success: async (res) => { | |
| 433 | - that.workOrderForm.roadName = '' | |
| 434 | - that.workOrderForm.roadId = 0 | |
| 435 | - that.roadNameList = [] | |
| 436 | - | |
| 437 | - that.workOrderForm.workLocation = res.name | |
| 438 | - that.workOrderForm.lat = res.latitude | |
| 439 | - that.workOrderForm.lon = res.longitude | |
| 440 | - | |
| 441 | - that.$refs.workOrderFormRef.validateField('workLocation') | |
| 442 | - that.$refs.workOrderFormRef.validateField('roadName') | |
| 443 | - | |
| 444 | - try { | |
| 445 | - uni.showLoading({title: '获取道路名称中...'}) | |
| 446 | - const roadRes = await getRoadListByLatLng({ | |
| 447 | - companyCode: 'sls', | |
| 448 | - latitude: res.latitude, | |
| 449 | - longitude: res.longitude | |
| 450 | - }) | |
| 451 | - uni.hideLoading() | |
| 452 | - | |
| 453 | - if (Array.isArray(roadRes)) { | |
| 454 | - that.roadNameList = roadRes.map((item) => ({ | |
| 455 | - name: item.roadName || '', | |
| 456 | - code: item.roadCode || '', | |
| 457 | - id: item.roadId || 0 | |
| 458 | - })) | |
| 459 | - } else { | |
| 460 | - that.roadNameList = [{name: '未查询到道路名称', code: '', id: 0}] | |
| 461 | - uni.showToast({title: '未查询到该位置的道路信息', icon: 'none'}) | |
| 462 | - } | |
| 463 | - } catch (err) { | |
| 464 | - uni.hideLoading() | |
| 465 | - console.error('获取道路名称失败:', err) | |
| 466 | - uni.showToast({title: '获取道路名称失败,请重试', icon: 'none'}) | |
| 467 | - that.roadNameList = [{name: '获取失败,请重新选择位置', code: '', id: 0}] | |
| 468 | - } | |
| 469 | - }, | |
| 470 | - fail: (err) => { | |
| 471 | - console.error('选择位置失败:', err) | |
| 472 | - uni.showToast({title: '选择位置失败:' + err.errMsg, icon: 'none'}) | |
| 473 | - } | |
| 474 | - }) | |
| 475 | - }, | |
| 476 | - | |
| 477 | - /** | |
| 478 | - * 完成时间确认 | |
| 479 | - */ | |
| 480 | - finishTimeConfirm(e) { | |
| 481 | - console.log('选择的完成时间:', e) | |
| 482 | - this.workOrderForm.finishTime = timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss') | |
| 483 | - this.show = false | |
| 484 | - }, | |
| 485 | - | |
| 486 | - /** | |
| 487 | - * 隐藏键盘 | |
| 488 | - */ | |
| 489 | - hideKeyboard() { | |
| 490 | - uni.hideKeyboard() | |
| 491 | - }, | |
| 492 | - | |
| 493 | - /** | |
| 494 | - * 提取图片URL数组 | |
| 495 | - */ | |
| 496 | - getImgUrlList(imgList) { | |
| 497 | - return imgList.filter(item => item.status === 'success').map(item => item.url) | |
| 498 | - }, | |
| 393 | +/** | |
| 394 | + * 完成时间确认 | |
| 395 | + */ | |
| 396 | +const finishTimeConfirm = (e) => { | |
| 397 | + console.log('选择的完成时间:', e) | |
| 398 | + workOrderForm.finishTime = timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss') | |
| 399 | + show.value = false | |
| 400 | +} | |
| 499 | 401 | |
| 500 | - /** | |
| 501 | - * 提交工单 | |
| 502 | - */ | |
| 503 | - async submitWorkOrder() { | |
| 504 | - try { | |
| 505 | - // 先执行表单校验 | |
| 506 | - await this.$refs.workOrderFormRef.validate() | |
| 507 | - | |
| 508 | - const submitData = { | |
| 509 | - roadId: this.workOrderForm.roadId, | |
| 510 | - roadName: this.workOrderForm.roadName, | |
| 511 | - imgs: this.getImgUrlList(this.problemImgsList), | |
| 512 | - remark: this.workOrderForm.problemDesc, | |
| 513 | - latLonType: 2, | |
| 514 | - lat: this.workOrderForm.lat, | |
| 515 | - lon: this.workOrderForm.lon, | |
| 516 | - lonLatAddress: this.workOrderForm.workLocation, | |
| 517 | - pressingType: this.workOrderForm.pressingType, | |
| 518 | - orderName: this.workOrderForm.orderName, | |
| 519 | - finishTime: this.workOrderForm.finishTime, | |
| 520 | - sourceId: 1, | |
| 521 | - sourceName: '园林', | |
| 522 | - thirdWorkNo: '', | |
| 523 | - busiLine: 'yl' | |
| 524 | - } | |
| 402 | +/** | |
| 403 | + * 隐藏键盘 | |
| 404 | + */ | |
| 405 | +const hideKeyboard = () => { | |
| 406 | + uni.hideKeyboard() | |
| 407 | +} | |
| 525 | 408 | |
| 526 | - // 显示加载中 | |
| 527 | - uni.showLoading({title: '提交中...'}) | |
| 409 | +/** | |
| 410 | + * 提交工单 | |
| 411 | + */ | |
| 412 | +const submitWorkOrder = async () => { | |
| 413 | + try { | |
| 414 | + // 先执行表单校验 | |
| 415 | + await workOrderFormRef.value.validate() | |
| 416 | + | |
| 417 | + const submitData = { | |
| 418 | + roadId: workOrderForm.roadId, | |
| 419 | + roadName: workOrderForm.roadName, | |
| 420 | + imgs: problemImgs.getSuccessImgUrls(), // 复用上传逻辑的URL获取方法 | |
| 421 | + remark: workOrderForm.problemDesc, | |
| 422 | + latLonType: 2, | |
| 423 | + lat: workOrderForm.lat, | |
| 424 | + lon: workOrderForm.lon, | |
| 425 | + lonLatAddress: workOrderForm.workLocation, | |
| 426 | + pressingType: workOrderForm.pressingType, | |
| 427 | + orderName: workOrderForm.orderName, | |
| 428 | + finishTime: workOrderForm.finishTime, | |
| 429 | + sourceId: 1, | |
| 430 | + sourceName: '园林', | |
| 431 | + thirdWorkNo: '', | |
| 432 | + busiLine: 'yl' | |
| 433 | + } | |
| 528 | 434 | |
| 529 | - // 调用提交接口 | |
| 530 | - const res = await createQuick(submitData) | |
| 435 | + // 显示加载中 | |
| 436 | + uni.showLoading({ title: '提交中...' }) | |
| 531 | 437 | |
| 532 | - uni.hideLoading() | |
| 533 | - uni.showToast({ | |
| 534 | - title: '工单提交成功', | |
| 535 | - icon: 'success', | |
| 536 | - duration: 1000 | |
| 537 | - }) | |
| 438 | + // 调用提交接口 | |
| 439 | + const res = await createQuick(submitData) | |
| 538 | 440 | |
| 539 | - // 延迟跳转 | |
| 540 | - setTimeout(() => { | |
| 541 | - uni.redirectTo({ | |
| 542 | - url: '/pages-sub/daily/quick-order/index' | |
| 543 | - }) | |
| 544 | - }, 1000) | |
| 545 | - } catch (error) { | |
| 546 | - // 隐藏加载框 | |
| 547 | - uni.hideLoading() | |
| 441 | + uni.hideLoading() | |
| 442 | + uni.showToast({ | |
| 443 | + title: '工单提交成功', | |
| 444 | + icon: 'success', | |
| 445 | + duration: 1000 | |
| 446 | + }) | |
| 548 | 447 | |
| 549 | - // 区分是表单校验失败还是接口调用失败 | |
| 550 | - if (Array.isArray(error)) { | |
| 551 | - // 表单校验失败(无需额外提示,uView会自动提示) | |
| 552 | - } else { | |
| 553 | - // 接口调用失败 | |
| 554 | - console.error('工单提交失败:', error) | |
| 555 | - uni.showToast({ | |
| 556 | - title: '提交失败,请重试', | |
| 557 | - icon: 'none', | |
| 558 | - duration: 2000 | |
| 559 | - }) | |
| 560 | - } | |
| 561 | - } | |
| 448 | + // 延迟跳转 | |
| 449 | + setTimeout(() => { | |
| 450 | + uni.redirectTo({ | |
| 451 | + url: '/pages-sub/daily/quick-order/index' | |
| 452 | + }) | |
| 453 | + }, 1000) | |
| 454 | + } catch (error) { | |
| 455 | + // 隐藏加载框 | |
| 456 | + uni.hideLoading() | |
| 457 | + | |
| 458 | + // 区分是表单校验失败还是接口调用失败 | |
| 459 | + if (!Array.isArray(error)) { | |
| 460 | + // 接口调用失败 | |
| 461 | + console.error('工单提交失败:', error) | |
| 462 | + uni.showToast({ | |
| 463 | + title: '提交失败,请重试', | |
| 464 | + icon: 'none', | |
| 465 | + duration: 2000 | |
| 466 | + }) | |
| 562 | 467 | } |
| 563 | 468 | } |
| 564 | 469 | } |
| ... | ... | @@ -566,8 +471,9 @@ export default { |
| 566 | 471 | |
| 567 | 472 | <style lang="scss" scoped> |
| 568 | 473 | // 全局页面样式 |
| 569 | -.u-page { | |
| 474 | +.page-container { | |
| 570 | 475 | min-height: 100vh; |
| 476 | + padding-bottom: 100rpx; // 给底部按钮留空间 | |
| 571 | 477 | } |
| 572 | 478 | |
| 573 | 479 | // 工单表单内容容器 |
| ... | ... | @@ -575,5 +481,4 @@ export default { |
| 575 | 481 | background: #fff; |
| 576 | 482 | } |
| 577 | 483 | |
| 578 | - | |
| 579 | 484 | </style> |
| 580 | 485 | \ No newline at end of file | ... | ... |