Files
zcglxt/DYNAMIC_FORM_QUICKSTART.md
Claude e48975f9d5 fix: 修复前端登录体验和API调用问题
- 修复路由守卫:未登录时直接跳转,不显示提示信息
- 修复API拦截器:401错误直接跳转,无需确认
- 移除不必要的ElMessageBox确认框
- 优化Token过期处理逻辑
- 修复文件管理API引入路径和URL前缀
- 修复调拨/回收管理API端点不匹配问题
- 修复通知管理API方法不匹配问题
- 统一系统配置API路径为单数形式

影响文件:
- src/router/index.ts
- src/api/request.ts
- src/api/file.ts
- src/api/index.ts

测试状态:
- 前端构建通过
- 所有API路径已验证
- 登录流程测试通过

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-25 00:26:33 +08:00

400 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 动态表单组件 - 快速开始
## 1. 基础使用
### 最简单的例子
```vue
<template>
<DynamicFieldRenderer
v-model="formData"
:fields="fields"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import DynamicFieldRenderer from '@/components/form/DynamicFieldRenderer.vue'
const formData = ref({})
const fields = [
{
id: '1',
name: 'username',
label: '用户名',
fieldType: 'text',
required: true
}
]
</script>
```
## 2. 添加验证
```vue
<script setup lang="ts">
const fields = [
{
id: '1',
name: 'email',
label: '邮箱',
fieldType: 'email',
required: true,
validationRules: {
pattern: '^[^@]+@[^@]+\\\\.[^@]+$',
customMessage: '请输入有效的邮箱地址'
}
},
{
id: '2',
name: 'age',
label: '年龄',
fieldType: 'number',
validationRules: {
min: 18,
max: 65
}
}
]
</script>
```
## 3. 字段联动
```vue
<template>
<DynamicFieldRenderer
v-model="formData"
:fields="fields"
:dependencies="dependencies"
/>
</template>
<script setup lang="ts">
const fields = [
{
id: '1',
name: 'hasDiscount',
label: '是否有优惠',
fieldType: 'boolean'
},
{
id: '2',
name: 'discountCode',
label: '优惠码',
fieldType: 'text',
// 只有选择有优惠时才显示
visible: (data) => data.hasDiscount === true
}
]
</script>
```
## 4. 处理表单提交
```vue
<template>
<DynamicFieldRenderer
ref="formRef"
v-model="formData"
:fields="fields"
/>
<el-button @click="handleSubmit">提交</el-button>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
const formRef = ref()
const formData = ref({})
const handleSubmit = async () => {
const valid = await formRef.value?.validateForm()
if (valid) {
console.log('表单数据:', formData.value)
ElMessage.success('提交成功')
}
}
</script>
```
## 5. 使用Composable
```vue
<script setup lang="ts">
import { useDynamicForm } from '@/composables/useDynamicForm'
const fields = [
// ... 字段配置
]
const {
formData, // 表单数据
isValid, // 是否验证通过
setFieldValue, // 设置字段值
validateAll, // 验证所有字段
submitForm // 提交表单
} = useDynamicForm(fields)
const handleSubmit = async () => {
await submitForm(async (data) => {
console.log('提交数据:', data)
})
}
</script>
```
## 6. 加载设备类型字段
```vue
<script setup lang="ts">
import { onMounted } from 'vue'
import { useFieldConfig } from '@/composables/useFieldConfig'
const { loadFieldConfig } = useFieldConfig()
const fields = ref([])
onMounted(async () => {
// 从API加载设备类型的字段配置
fields.value = await loadFieldConfig(1) // 1是设备类型ID
})
</script>
```
## 7. 常用字段类型示例
```typescript
const fields = [
// 单行文本
{
id: '1',
name: 'title',
label: '标题',
fieldType: 'text',
required: true
},
// 多行文本
{
id: '2',
name: 'description',
label: '描述',
fieldType: 'textarea',
rows: 4
},
// 数字
{
id: '3',
name: 'price',
label: '价格',
fieldType: 'number',
validationRules: {
min: 0,
max: 999999
}
},
// 日期
{
id: '4',
name: 'birthday',
label: '生日',
fieldType: 'date'
},
// 下拉选择
{
id: '5',
name: 'gender',
label: '性别',
fieldType: 'select',
options: [
{ label: '男', value: 'male' },
{ label: '女', value: 'female' }
]
},
// 多选
{
id: '6',
name: 'hobbies',
label: '爱好',
fieldType: 'multiselect',
options: [
{ label: '读书', value: 'reading' },
{ label: '运动', value: 'sports' },
{ label: '音乐', value: 'music' }
]
},
// 开关
{
id: '7',
name: 'isActive',
label: '是否激活',
fieldType: 'boolean',
defaultValue: false
}
]
```
## 8. 布局控制
```typescript
const fields = [
// 半行
{
id: '1',
name: 'firstName',
label: '名',
fieldType: 'text',
span: 12 // 占12列半行
},
// 半行
{
id: '2',
name: 'lastName',
label: '姓',
fieldType: 'text',
span: 12 // 占12列半行
},
// 整行
{
id: '3',
name: 'address',
label: '地址',
fieldType: 'text',
span: 24 // 占24列整行
}
]
```
## 9. 自定义验证
```typescript
const fields = [
{
id: '1',
name: 'password',
label: '密码',
fieldType: 'text',
required: true,
validationRules: {
custom: (value) => {
if (value.length < 8) {
return '密码长度不能少于8位'
}
if (!/[A-Z]/.test(value)) {
return '密码必须包含大写字母'
}
if (!/[0-9]/.test(value)) {
return '密码必须包含数字'
}
return true
}
}
}
]
```
## 10. 完整示例
```vue
<template>
<el-card>
<DynamicFieldRenderer
ref="formRef"
v-model="formData"
:fields="fields"
label-width="100px"
@field-change="handleChange"
/>
<el-button type="primary" @click="handleSubmit">提交</el-button>
<el-button @click="handleReset">重置</el-button>
</el-card>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import DynamicFieldRenderer from '@/components/form/DynamicFieldRenderer.vue'
const formRef = ref()
const formData = ref({
username: '',
email: '',
role: 'user'
})
const fields = [
{
id: '1',
name: 'username',
label: '用户名',
fieldType: 'text',
required: true,
span: 12,
validationRules: {
min: 3,
max: 20
}
},
{
id: '2',
name: 'email',
label: '邮箱',
fieldType: 'email',
required: true,
span: 12
},
{
id: '3',
name: 'role',
label: '角色',
fieldType: 'select',
required: true,
span: 12,
options: [
{ label: '管理员', value: 'admin' },
{ label: '普通用户', value: 'user' }
]
},
{
id: '4',
name: 'isActive',
label: '激活状态',
fieldType: 'boolean',
span: 12,
defaultValue: true
}
]
const handleChange = (event) => {
console.log('字段变化:', event)
}
const handleSubmit = async () => {
const valid = await formRef.value?.validateForm()
if (valid) {
console.log('提交数据:', formData.value)
ElMessage.success('提交成功')
}
}
const handleReset = () => {
formRef.value?.resetForm()
}
</script>
```
## 更多资源
- [完整文档](./DYNAMIC_FORM_COMPONENTS_README.md)
- [开发总结](./DYNAMIC_FORM_DEVELOPMENT_SUMMARY.md)
- [示例代码](./src/views/examples/DynamicFormExample.vue)