hookehuyr

feat(表单): 将静态表单重构为动态可配置表单

重构添加计数对象表单,使用动态字段配置替代硬编码字段
添加表单校验逻辑和备注字段,提升表单可扩展性
...@@ -79,29 +79,26 @@ ...@@ -79,29 +79,26 @@
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">
84 - <van-field 90 + <div v-for="field in dynamicFormFields" :key="field.id">
85 - v-model="newTargetForm.name" 91 + <van-field
86 - label="姓名" 92 + v-model="field.value"
87 - placeholder="请输入姓名" 93 + :label="field.label"
88 - class="border-b border-gray-100" 94 + :placeholder="'请输入' + field.label"
89 - /> 95 + :type="field.type === 'textarea' ? 'textarea' : 'text'"
90 - <van-field 96 + :rows="field.type === 'textarea' ? 2 : 1"
91 - v-model="newTargetForm.city" 97 + :autosize="field.type === 'textarea'"
92 - label="城市" 98 + class="border-b border-gray-100"
93 - placeholder="请输入所在城市" 99 + :required="field.required"
94 - class="border-b border-gray-100" 100 + />
95 - /> 101 + </div>
96 - <van-field
97 - v-model="newTargetForm.school"
98 - label="单位"
99 - rows="2"
100 - autosize
101 - type="textarea"
102 - maxlength="50"
103 - placeholder="请输入所在单位"
104 - />
105 </div> 102 </div>
106 </van-dialog> 103 </van-dialog>
107 104
...@@ -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 - } 301 + if (field.required && !field.value.trim()) {
302 + showToast(`请填写${field.label}`)
303 + return false // 阻止关闭
304 + }
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 // 作品类型选项
......