feat(表单): 将静态表单重构为动态可配置表单
重构添加计数对象表单,使用动态字段配置替代硬编码字段 添加表单校验逻辑和备注字段,提升表单可扩展性
Showing
1 changed file
with
55 additions
and
35 deletions
| ... | @@ -79,30 +79,27 @@ | ... | @@ -79,30 +79,27 @@ |
| 79 | </div> | 79 | </div> |
| 80 | 80 | ||
| 81 | <!-- 新增计数对象弹框 --> | 81 | <!-- 新增计数对象弹框 --> |
| 82 | - <van-dialog v-model:show="showAddTargetDialog" title="添加计数对象" show-cancel-button confirmButtonColor="#4caf50" @confirm="confirmAddTarget"> | 82 | + <van-dialog |
| 83 | + v-model:show="showAddTargetDialog" | ||
| 84 | + title="添加计数对象" | ||
| 85 | + show-cancel-button | ||
| 86 | + confirmButtonColor="#4caf50" | ||
| 87 | + :before-close="onBeforeClose" | ||
| 88 | + > | ||
| 83 | <div class="p-4"> | 89 | <div class="p-4"> |
| 90 | + <div v-for="field in dynamicFormFields" :key="field.id"> | ||
| 84 | <van-field | 91 | <van-field |
| 85 | - v-model="newTargetForm.name" | 92 | + v-model="field.value" |
| 86 | - label="姓名" | 93 | + :label="field.label" |
| 87 | - placeholder="请输入姓名" | 94 | + :placeholder="'请输入' + field.label" |
| 88 | - class="border-b border-gray-100" | 95 | + :type="field.type === 'textarea' ? 'textarea' : 'text'" |
| 89 | - /> | 96 | + :rows="field.type === 'textarea' ? 2 : 1" |
| 90 | - <van-field | 97 | + :autosize="field.type === 'textarea'" |
| 91 | - v-model="newTargetForm.city" | ||
| 92 | - label="城市" | ||
| 93 | - placeholder="请输入所在城市" | ||
| 94 | class="border-b border-gray-100" | 98 | class="border-b border-gray-100" |
| 95 | - /> | 99 | + :required="field.required" |
| 96 | - <van-field | ||
| 97 | - v-model="newTargetForm.school" | ||
| 98 | - label="单位" | ||
| 99 | - rows="2" | ||
| 100 | - autosize | ||
| 101 | - type="textarea" | ||
| 102 | - maxlength="50" | ||
| 103 | - placeholder="请输入所在单位" | ||
| 104 | /> | 100 | /> |
| 105 | </div> | 101 | </div> |
| 102 | + </div> | ||
| 106 | </van-dialog> | 103 | </van-dialog> |
| 107 | 104 | ||
| 108 | <!-- 文本输入区域 --> | 105 | <!-- 文本输入区域 --> |
| ... | @@ -279,11 +276,14 @@ const targetList = ref([ | ... | @@ -279,11 +276,14 @@ const targetList = ref([ |
| 279 | { name: '李老师', city: '上海', school: '复旦大学' } | 276 | { name: '李老师', city: '上海', school: '复旦大学' } |
| 280 | ]) | 277 | ]) |
| 281 | const showAddTargetDialog = ref(false) | 278 | const showAddTargetDialog = ref(false) |
| 282 | -const newTargetForm = reactive({ | 279 | + |
| 283 | - name: '', | 280 | +// 动态表单字段 Mock 数据 |
| 284 | - city: '', | 281 | +const dynamicFormFields = ref([ |
| 285 | - school: '' | 282 | + { id: 'name', label: '姓名', value: '', type: 'text', required: true }, |
| 286 | -}) | 283 | + { id: 'city', label: '城市', value: '', type: 'text', required: true }, |
| 284 | + { id: 'school', label: '单位', value: '', type: 'text', required: true }, | ||
| 285 | + { id: 'remark', label: '备注', value: '', type: 'textarea', required: true } // 新增字段 | ||
| 286 | +]) | ||
| 287 | 287 | ||
| 288 | const toggleTarget = (item) => { | 288 | const toggleTarget = (item) => { |
| 289 | const index = selectedTargets.value.findIndex(t => t.name === item.name) | 289 | const index = selectedTargets.value.findIndex(t => t.name === item.name) |
| ... | @@ -294,22 +294,42 @@ const toggleTarget = (item) => { | ... | @@ -294,22 +294,42 @@ const toggleTarget = (item) => { |
| 294 | } | 294 | } |
| 295 | } | 295 | } |
| 296 | 296 | ||
| 297 | -const confirmAddTarget = () => { | 297 | +const onBeforeClose = (action) => { |
| 298 | - if (!newTargetForm.name || !newTargetForm.city || !newTargetForm.school) { | 298 | + if (action === 'confirm') { |
| 299 | - showToast('请完整填写信息') | 299 | + // 校验必填项 |
| 300 | - return | 300 | + for (const field of dynamicFormFields.value) { |
| 301 | + if (field.required && !field.value.trim()) { | ||
| 302 | + showToast(`请填写${field.label}`) | ||
| 303 | + return false // 阻止关闭 | ||
| 304 | + } | ||
| 301 | } | 305 | } |
| 302 | 306 | ||
| 303 | - // 打印录入信息 | 307 | + // 校验通过,处理提交逻辑 |
| 304 | - console.log('新增计数对象信息:', { ...newTargetForm }) | 308 | + confirmAddTarget() |
| 309 | + return true // 允许关闭 | ||
| 310 | + } | ||
| 311 | + return true // 取消时允许关闭 | ||
| 312 | +} | ||
| 305 | 313 | ||
| 306 | - // 添加到列表 | 314 | +const confirmAddTarget = () => { |
| 307 | - targetList.value.push({ ...newTargetForm }) | 315 | + // 收集表单数据 |
| 316 | + const formData = dynamicFormFields.value.reduce((acc, field) => { | ||
| 317 | + acc[field.id] = field.value | ||
| 318 | + return acc | ||
| 319 | + }, {}) | ||
| 320 | + | ||
| 321 | + console.log('新增计数对象信息:', formData) | ||
| 322 | + | ||
| 323 | + // 添加到列表(适配原有的数据结构) | ||
| 324 | + targetList.value.push({ | ||
| 325 | + name: formData.name, | ||
| 326 | + city: formData.city, | ||
| 327 | + school: formData.school | ||
| 328 | + // 其他字段... | ||
| 329 | + }) | ||
| 308 | 330 | ||
| 309 | // 重置表单 | 331 | // 重置表单 |
| 310 | - newTargetForm.name = '' | 332 | + dynamicFormFields.value.forEach(field => field.value = '') |
| 311 | - newTargetForm.city = '' | ||
| 312 | - newTargetForm.school = '' | ||
| 313 | } | 333 | } |
| 314 | 334 | ||
| 315 | // 作品类型选项 | 335 | // 作品类型选项 | ... | ... |
-
Please register or login to post a comment