From 8ee2a9233280f0fdab1ab5722f5071728e9d33bb Mon Sep 17 00:00:00 2001 From: liugongyu <290219706@qq.com> Date: Thu, 11 Dec 2025 20:18:00 +0800 Subject: [PATCH] 新增快速工单,原版 --- pages-sub/daily/quick-order/add-order.vue | 331 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 1 file changed, 151 insertions(+), 180 deletions(-) diff --git a/pages-sub/daily/quick-order/add-order.vue b/pages-sub/daily/quick-order/add-order.vue index 2cf5b58..89cc1d6 100644 --- a/pages-sub/daily/quick-order/add-order.vue +++ b/pages-sub/daily/quick-order/add-order.vue @@ -1,15 +1,17 @@ @@ -172,19 +175,12 @@ import { getRoadListByLatLng } from '@/api/common' import { uploadImages } from '@/common/utils/upload'; import { createQuick } from '@/api/quick-order/quick-order' -// ========== 基础变量定义(语义化命名) ========== -// 图片分类标签列表 -const imgTabList = ref([ - { name: '问题照片', id: '1' }, - { name: '完成照片', id: '2' } -]) -// 激活的图片标签(默认选中问题照片) -const activeImgTab = ref('1') +// ========== 基础变量定义 ========== // 问题照片列表 const problemImgsList = ref([]) // 完成照片列表 const completeImgsList = ref([]) -// 表单Ref(语义化:工单表单) +// 表单Ref const workOrderFormRef = ref(null) // 提交加载状态 const isSubmitting = ref(false) @@ -199,7 +195,7 @@ const orderNameList = ref([ { name: '垃圾清理', code: 'ORDER003' } ]) -// ========== 工单表单数据(语义化字段名) ========== +// ========== 工单表单数据 ========== const workOrderForm = reactive({ roadId: 0, // 道路ID roadName: '', // 道路名称 @@ -211,20 +207,20 @@ const workOrderForm = reactive({ lon: 0 // 经度 }) -// ========== 表单校验规则(修复trigger + 语义化) ========== +// ========== 表单校验规则 ========== const workOrderFormRules = reactive({ workLocation: [ - { type: 'string', required: true, message: '请选择工单位置', trigger: 'change' } + { type: 'string', required: true, message: '请选择工单位置', trigger: ['change', 'blur'] } ], roadName: [ - { type: 'string', required: true, message: '请选择道路名称', trigger: 'change' } + { type: 'string', required: true, message: '请选择道路名称', trigger: ['change', 'blur'] } ], orderName: [ - { type: 'string', required: true, message: '请选择工单名称', trigger: 'change' } + { type: 'string', required: true, message: '请选择工单名称', trigger: ['change', 'blur'] } ], problemDesc: [ - { type: 'string', required: true, message: '请输入情况描述', trigger: 'change' }, - { type: 'string', min: 3, max: 150, message: '情况描述需3-150字', trigger: 'change' } + { type: 'string', required: true, message: '请输入情况描述', trigger: ['change', 'blur'] }, + { type: 'string', min: 3, max: 150, message: '情况描述需3-150字', trigger: ['change', 'blur'] } ], problemImgs: [ { required: true, message: '请上传问题照片', trigger: 'change' } @@ -233,16 +229,14 @@ const workOrderFormRules = reactive({ { required: true, message: '请上传完成照片', trigger: 'change' } ], handleResultDesc: [ - { type: 'string', required: true, message: '请输入处理结果描述', trigger: 'change' }, - { type: 'string', min: 3, max: 200, message: '处理结果需3-200字', trigger: 'change' } + { type: 'string', required: true, message: '请输入处理结果描述', trigger: ['change', 'blur'] }, + { type: 'string', min: 3, max: 200, message: '处理结果需3-200字', trigger: ['change', 'blur'] } ] }) -// ========== 方法定义(语义化命名 + 修复逻辑) ========== +// ========== 方法定义 ========== /** * 删除图片 - * @param event 删除事件 - * @param type 图片类型(problemImgsList/completeImgsList) */ const deleteImg = (event: UploadDeleteEvent, type: string) => { console.log('删除图片事件:', event, '类型:', type) @@ -255,19 +249,14 @@ const deleteImg = (event: UploadDeleteEvent, type: string) => { } /** - * 上传图片(单/多图统一逻辑) - * @param event 上传事件 - * @param type 图片类型(problemImgsList/completeImgsList) + * 上传图片 */ const uploadImgs = async (event: { file: UploadFile | UploadFile[] }, type: string) => { console.log('上传图片事件:', event, '类型:', type) - // 统一处理为数组格式 const fileList = Array.isArray(event.file) ? event.file : [event.file] const targetImgList = type === 'problemImgsList' ? problemImgsList : completeImgsList - // 1. 提取文件路径 const filePaths = fileList.map(item => item.url) - // 2. 添加上传中临时项 const tempItems: UploadFile[] = fileList.map(item => ({ ...item, status: 'uploading' as const, @@ -277,14 +266,12 @@ const uploadImgs = async (event: { file: UploadFile | UploadFile[] }, type: stri targetImgList.value.push(...tempItems) try { - // 3. 调用统一上传方法 const uploadResultUrls = await uploadImages({ filePaths: filePaths, ignoreError: true }) console.log('上传成功的URL列表:', uploadResultUrls) - // 4. 更新成功状态 uploadResultUrls.forEach((url, index) => { if (targetImgList.value[startIndex + index]) { targetImgList.value.splice(startIndex + index, 1, { @@ -296,7 +283,6 @@ const uploadImgs = async (event: { file: UploadFile | UploadFile[] }, type: stri } }) - // 5. 处理失败项 if (uploadResultUrls.length < fileList.length) { const failCount = fileList.length - uploadResultUrls.length for (let i = uploadResultUrls.length; i < fileList.length; i++) { @@ -314,7 +300,6 @@ const uploadImgs = async (event: { file: UploadFile | UploadFile[] }, type: stri } } catch (err) { console.error('图片上传失败:', err) - // 标记所有为失败 for (let i = 0; i < fileList.length; i++) { if (targetImgList.value[startIndex + i]) { targetImgList.value.splice(startIndex + i, 1, { @@ -329,16 +314,7 @@ const uploadImgs = async (event: { file: UploadFile | UploadFile[] }, type: stri } /** - * 切换图片标签 - * @param item 标签项 - */ -const switchImgTab = (item: { name: string; id: string }) => { - console.log('切换图片标签:', item) - activeImgTab.value = item.id -} - -/** - * 选择工单位置(地图)- 核心修改:清空道路名称 + * 选择工单位置 */ const chooseWorkLocation = () => { if (isSubmitting.value) return @@ -348,17 +324,14 @@ const chooseWorkLocation = () => { success: () => { uni.chooseLocation({ success: async (res) => { - // ========== 核心新增:清空道路名称相关数据 ========== - workOrderForm.roadName = '' // 清空道路名称 - workOrderForm.roadId = 0 // 清空道路ID - roadNameList.value = [] // 清空道路名称列表 + workOrderForm.roadName = '' + workOrderForm.roadId = 0 + roadNameList.value = [] - // 更新工单位置 workOrderForm.workLocation = res.name workOrderForm.lat = res.latitude workOrderForm.lon = res.longitude - // 触发工单位置和道路名称的表单校验更新 workOrderFormRef.value?.validateField('workLocation') workOrderFormRef.value?.validateField('roadName') @@ -419,7 +392,6 @@ const chooseWorkLocation = () => { /** * 选择道路名称 - * @param e 选择事件 */ const handleRoadNameSelect = (e: UniActionSheetSelectEvent) => { console.log('选择道路名称:', e) @@ -431,7 +403,6 @@ const handleRoadNameSelect = (e: UniActionSheetSelectEvent) => { /** * 选择工单名称 - * @param e 选择事件 */ const handleOrderNameSelect = (e: UniActionSheetSelectEvent) => { workOrderForm.orderName = e.name @@ -448,8 +419,6 @@ const hideKeyboard = () => { /** * 提取图片URL数组 - * @param imgList 图片列表 - * @returns URL数组 */ const getImgUrlList = (imgList: UploadFile[]) => { console.log('提取图片URL:', imgList) @@ -457,29 +426,28 @@ const getImgUrlList = (imgList: UploadFile[]) => { } /** - * 校验上传图片(兜底校验) - * @returns 是否校验通过 + * 校验上传图片 */ const validateUploadImgs = () => { - // 修复:补充返回值,避免函数无返回 - if (activeImgTab.value === '1') { - const hasValidImgs = problemImgsList.value.some(item => item.status === 'success') - if (!hasValidImgs) { - uni.showToast({ title: '请上传至少1张问题照片', icon: 'none' }) - return false - } - } else { - const hasValidcompleteImgs = completeImgsList.value.some(item => item.status === 'success') - if (!hasValidcompleteImgs) { - uni.showToast({ title: '请上传至少1张完成照片', icon: 'none' }) - return false - } + const hasValidProblemImgs = problemImgsList.value.some(item => item.status === 'success') + if (!hasValidProblemImgs) { + uni.showToast({ title: '请上传至少1张问题照片', icon: 'none' }) + workOrderFormRef.value?.validateField('problemImgs') + return false } + + const hasValidCompleteImgs = completeImgsList.value.some(item => item.status === 'success') + if (!hasValidCompleteImgs) { + uni.showToast({ title: '请上传至少1张完成照片', icon: 'none' }) + workOrderFormRef.value?.validateField('completeImgs') + return false + } + return true } /** - * 提交工单(修复核心:await位置 + 表单Ref名称错误) + * 提交工单 */ const submitWorkOrder = async () => { if (isSubmitting.value) { @@ -490,33 +458,36 @@ const submitWorkOrder = async () => { try { isSubmitting.value = true - // 修复1:兜底校验图片 if (!validateUploadImgs()) { isSubmitting.value = false return } - // 修复2:使用正确的表单Ref名称(workOrderFormRef 而非 uFormRef) - // 修复3:将validate转为Promise形式,配合async/await - const valid = await new Promise((resolve) => { - workOrderFormRef.value?.validate((isValid) => { + const valid = await new Promise((resolve) => { + workOrderFormRef.value?.validate((isValid, invalidFields) => { + console.log('校验失败的字段:', invalidFields) resolve(isValid) }) }) if (!valid) { - uni.showToast({ title: '表单校验失败,请检查必填项', icon: 'none' }) + const firstInvalidField = Object.keys(workOrderFormRef.value?.invalidFields || {})[0] + if (firstInvalidField) { + const el = document.querySelector(`[prop="${firstInvalidField}"]`) + el?.scrollIntoView({ behavior: 'smooth', block: 'center' }) + } + uni.showToast({ title: '表单填写不完整,请检查', icon: 'none' }) isSubmitting.value = false return } - // 构造提交数据 const submitData = { roadId: workOrderForm.roadId, roadName: workOrderForm.roadName, - imgs: getImgUrlList(problemImgsList.value), // 问题照片URL数组 - longRangeImgList: getImgUrlList(completeImgsList.value), // 完成照片URL数组 - remark: activeImgTab.value === '2' ? workOrderForm.handleResultDesc : workOrderForm.problemDesc, + imgs: getImgUrlList(problemImgsList.value), + longRangeImgList: getImgUrlList(completeImgsList.value), + remark: workOrderForm.problemDesc, + handleResultDesc: workOrderForm.handleResultDesc, latLonType: 2, lat: workOrderForm.lat, lon: workOrderForm.lon, @@ -529,19 +500,9 @@ const submitWorkOrder = async () => { } console.log('提交工单数据:', submitData) - // 修复4:await 现在在async函数中,可正常使用 await createQuick(submitData) uni.showToast({ title: '工单提交成功', icon: 'success' }) - // 可选:提交成功后重置表单 - // problemImgsList.value = [] - // completeImgsList.value = [] - // Object.assign(workOrderForm, { - // roadId: 0, roadName: '', workLocation: '', orderName: '', - // problemDesc: '', handleResultDesc: '', lat: 0, lon: 0 - // }) - // workOrderFormRef.value?.clearValidate() - } catch (error) { console.error('提交工单失败:', error) uni.showToast({ title: '提交失败,请重试', icon: 'none' }) @@ -552,12 +513,10 @@ const submitWorkOrder = async () => { // ========== 页面挂载初始化 ========== onMounted(() => { - setTimeout(() => { - if (workOrderFormRef.value && !workOrderFormRef.value.rules) { - workOrderFormRef.value.setRules(workOrderFormRules) - console.log('工单表单规则初始化完成') - } - }, 200) + if (workOrderFormRef.value && !workOrderFormRef.value.rules) { + workOrderFormRef.value.setRules(workOrderFormRules) + console.log('工单表单规则初始化完成') + } }) @@ -566,10 +525,15 @@ onMounted(() => { .u-page { background-color: #f5f5f5; min-height: 100vh; - padding-bottom: 100rpx; // 给底部按钮留空间 + padding-bottom: 100rpx; +} + +// 表单容器(新增:包裹整个表单) +.work-order-form-container { + width: 100%; } -// 工单表单容器 +// 工单表单内容容器 .work-order-form-content { background: #fff; padding: 20rpx; @@ -612,7 +576,7 @@ onMounted(() => { } // 提交按钮区域 -.fixed-bottom-btn-wrap { // 修复:原样式类名是submit-btn-wrap,与模板不一致 +.fixed-bottom-btn-wrap { position: fixed; bottom: 0; left: 0; @@ -630,15 +594,15 @@ onMounted(() => { } } -// ========== 修复Label折行样式 ========== +// Label样式 :deep(.u-form-item__label) { - white-space: nowrap; // 强制不换行 - text-overflow: ellipsis; // 超出省略 - overflow: hidden; // 隐藏超出部分 - line-height: 1.4; // 行高适配 + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + line-height: 1.4; } -// 表单基础样式适配 +// 表单基础样式 :deep(.u-form-item) { --u-form-item-label-font-size: 28rpx; --u-form-item-content-font-size: 28rpx; @@ -658,7 +622,14 @@ onMounted(() => { z-index: 9999 !important; } -:deep(.u-tabs) { - background: #fff; +// 错误提示样式 +:deep(.u-form-item__error-message) { + font-size: 24rpx !important; + color: #f56c6c !important; + margin-top: 5rpx !important; +} + +:deep(.u-form-item--error .u-input__wrap) { + border-color: #f56c6c !important; } \ No newline at end of file -- libgit2 0.21.4