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>
This commit is contained in:
Claude
2026-01-25 00:26:33 +08:00
commit e48975f9d5
151 changed files with 39477 additions and 0 deletions

View File

@@ -0,0 +1,475 @@
# 动态表单组件组使用文档
> **版本**: v1.0.0
> **作者**: 动态表单组件组
> **创建时间**: 2025-01-24
---
## 📋 目录
1. [组件概述](#组件概述)
2. [核心组件](#核心组件)
3. [字段组件](#字段组件)
4. [工具函数](#工具函数)
5. [Composable](#composable)
6. [使用示例](#使用示例)
7. [API文档](#api文档)
8. [最佳实践](#最佳实践)
---
## 组件概述
动态表单组件组是资产管理系统的核心组件库,用于支持不同设备类型的自定义字段渲染和验证。
### 主要特性
- ✅ 支持多种字段类型text、number、date、select、multiselect、boolean、textarea、tree等
- ✅ 动态验证规则(必填、长度、正则、自定义验证)
- ✅ 字段联动(显示/隐藏、启用/禁用、值联动)
- ✅ 栅格布局支持
- ✅ 响应式设计
- ✅ TypeScript完整类型支持
- ✅ 统一的API接口
### 组件清单
| 组件名称 | 文件路径 | 功能说明 |
|---------|---------|---------|
| DynamicFieldRenderer | `@/components/form/DynamicFieldRenderer.vue` | 动态字段渲染器(核心组件) |
| FieldDesigner | `@/components/form/FieldDesigner.vue` | 字段配置设计器 |
| TextField | `@/components/form/fields/TextField.vue` | 单行文本输入 |
| NumberField | `@/components/form/fields/NumberField.vue` | 数字输入 |
| TextareaField | `@/components/form/fields/TextareaField.vue` | 多行文本输入 |
| DateField | `@/components/form/fields/DateField.vue` | 日期选择器 |
| SelectField | `@/components/form/fields/SelectField.vue` | 下拉选择器 |
| MultiSelectField | `@/components/form/fields/MultiSelectField.vue` | 多选下拉 |
| BooleanField | `@/components/form/fields/BooleanField.vue` | 开关/复选框 |
| TreeSelect | `@/components/common/TreeSelect.vue` | 树形选择器 |
---
## 核心组件
### DynamicFieldRenderer 动态字段渲染器
最核心的组件,根据字段配置动态渲染表单。
#### 基础用法
```vue
<template>
<DynamicFieldRenderer
ref="formRef"
v-model="formData"
:fields="fields"
@field-change="handleFieldChange"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import DynamicFieldRenderer from '@/components/form/DynamicFieldRenderer.vue'
import type { FieldConfig } from '@/types/form'
const formRef = ref()
const formData = ref({
assetName: '',
cpu: '',
memory: ''
})
const fields: FieldConfig[] = [
{
id: '1',
name: 'assetName',
label: '资产名称',
fieldType: 'text',
required: true,
span: 12
},
{
id: '2',
name: 'cpu',
label: 'CPU型号',
fieldType: 'text',
required: true,
span: 12
}
]
</script>
```
#### Props
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| modelValue | `FormData` | - | 表单数据v-model |
| fields | `FieldConfig[]` | [] | 字段配置列表 |
| readonly | `boolean` | false | 是否只读模式 |
| labelWidth | `string \| number` | '120px' | 标签宽度 |
| labelPosition | `'left' \| 'right' \| 'top'` | 'right' | 标签位置 |
| gutter | `number` | 20 | 栅格间隔 |
| dependencies | `FieldDependency[]` | [] | 字段联动配置 |
#### Emits
| 事件名 | 参数 | 说明 |
|--------|------|------|
| update:modelValue | `(value: FormData)` | 表单数据更新 |
| field-change | `(event: FieldChangeEvent)` | 字段值变化 |
| validation-change | `(state: FormValidationState)` | 验证状态变化 |
#### Methods
| 方法名 | 参数 | 返回值 | 说明 |
|--------|------|--------|------|
| validateField | `(fieldName: string)` | `Promise<boolean>` | 验证单个字段 |
| validateForm | - | `Promise<boolean>` | 验证整个表单 |
| resetForm | - | `void` | 重置表单 |
| clearValidation | - | `void` | 清除验证 |
| setFieldValue | `(fieldName: string, value: any)` | `void` | 设置字段值 |
| getFieldValue | `(fieldName: string)` | `any` | 获取字段值 |
| getFormData | - | `FormData` | 获取表单数据 |
| setFormData | `(data: FormData)` | `void` | 设置表单数据 |
---
## 字段组件
### FieldConfig 字段配置
```typescript
interface FieldConfig {
id: string // 字段唯一标识
name: string // 字段名称(用于提交)
label: string // 字段标签(显示名称)
fieldType: FieldType // 字段类型
required?: boolean // 是否必填
defaultValue?: any // 默认值
placeholder?: string // 占位符
options?: Array<{ // 选项select/multiselect
label: string
value: any
disabled?: boolean
}>
validationRules?: { // 验证规则
min?: number
max?: number
pattern?: string
custom?: (value: any, allData: Record<string, any>) => boolean | string
customMessage?: string
}
span?: number // 栅格占列数1-24
visible?: boolean | ((data: Record<string, any>) => boolean) // 是否显示
disabled?: boolean | ((data: Record<string, any>) => boolean) // 是否禁用
description?: string // 字段描述
className?: string // 自定义类名
treeData?: TreeNode[] // 树形数据tree类型
multiple?: boolean // 是否多选tree类型
}
```
### 字段类型FieldType
| 类型 | 说明 | 组件 |
|------|------|------|
| `text` | 单行文本 | TextField |
| `textarea` | 多行文本 | TextareaField |
| `number` | 数字输入 | NumberField |
| `date` | 日期选择 | DateField |
| `select` | 下拉选择 | SelectField |
| `multiselect` | 多选下拉 | MultiSelectField |
| `boolean` | 开关/复选框 | BooleanField |
| `tree` | 树形选择 | TreeSelect |
| `url` | URL链接 | TextField带验证 |
| `email` | 邮箱 | TextField带验证 |
| `phone` | 手机号 | TextField带验证 |
---
## 工具函数
### fieldValidator 字段验证器
```typescript
import { validateField, validateFields } from '@/utils/fieldValidator'
// 验证单个字段
const result = validateField(value, field, allFormData)
// 返回: { isValid: boolean, errors: string[] }
// 验证所有字段
const errors = validateFields(data, fields)
// 返回: Record<string, string[]>
```
### FieldDependencyManager 字段联动管理器
```typescript
import { FieldDependencyManager, DependencyConditions, DependencyActions } from '@/utils/fieldDependency'
const manager = new FieldDependencyManager()
// 添加联动配置
manager.addDependency({
sourceField: 'deviceType',
targetField: 'cpu',
type: 'show',
condition: DependencyConditions.equals('desktop')
})
// 触发联动
const results = manager.trigger('deviceType', 'desktop', formData)
```
---
## Composable
### useDynamicForm
动态表单状态管理。
```typescript
import { useDynamicForm } from '@/composables/useDynamicForm'
const {
formData, // 表单数据
validationErrors, // 验证错误
isValid, // 是否有效
isDirty, // 是否已修改
isSubmitting, // 是否正在提交
setFieldValue, // 设置字段值
validateField, // 验证字段
validateAll, // 验证所有
resetForm, // 重置表单
getFormData, // 获取表单数据
submitForm // 提交表单
} = useDynamicForm(fields)
```
### useFieldConfig
字段配置管理。
```typescript
import { useFieldConfig } from '@/composables/useFieldConfig'
const {
loadFieldConfig, // 加载字段配置
getCachedFieldConfig, // 获取缓存配置
clearCache // 清除缓存
} = useFieldConfig()
// 加载设备类型的字段配置
const fields = await loadFieldConfig(deviceTypeId)
```
---
## 使用示例
### 示例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,
validationRules: {
min: 3,
max: 20
}
},
{
id: '2',
name: 'email',
label: '邮箱',
fieldType: 'email',
required: true
}
]
</script>
```
### 示例2带字段联动
```vue
<script setup lang="ts">
const fields = [
{
id: '1',
name: 'country',
label: '国家',
fieldType: 'select',
options: [
{ label: '中国', value: 'CN' },
{ label: '美国', value: 'US' }
]
},
{
id: '2',
name: 'province',
label: '省份',
fieldType: 'select',
options: [], // 将通过联动动态加载
visible: (data) => !!data.country // 选择国家后才显示
}
]
const dependencies = [
{
sourceField: 'country',
targetField: 'province',
type: 'setValue',
condition: () => true,
action: async (target, source) => {
// 根据选择的国家加载省份列表
const provinces = await loadProvinces(source)
return provinces
}
}
]
</script>
```
### 示例3自定义验证
```vue
<script setup lang="ts">
const fields = [
{
id: '1',
name: 'password',
label: '密码',
fieldType: 'text',
required: true,
validationRules: {
custom: (value, allData) => {
if (value.length < 8) {
return '密码长度不能少于8位'
}
if (!/[A-Z]/.test(value)) {
return '密码必须包含大写字母'
}
return true
}
}
}
]
</script>
```
---
## API文档
### 类型定义完整参考
详见 `@/types/form.ts`
### 常见问题
**Q: 如何动态加载选项?**
A: 使用字段联动配置的 `setValue` 类型配合异步函数:
```typescript
{
sourceField: 'category',
targetField: 'product',
type: 'setValue',
condition: () => true,
action: async () => {
const products = await api.getProducts()
return products
}
}
```
**Q: 如何实现条件验证?**
A: 使用 `custom` 验证函数:
```typescript
validationRules: {
custom: (value, allData) => {
if (allData.type === 'special' && !value) {
return '特殊类型必须填写此字段'
}
return true
}
}
```
---
## 最佳实践
### 1. 字段命名规范
- 使用camelCase命名`assetName``purchaseDate`
- 避免使用保留字:`name``id``value`
- 使用语义化命名:`cpuModel` 而非 `field1`
### 2. 验证规则设置
- 必填字段始终设置 `required: true`
- 文本字段设置合理的 `max` 限制
- 数字字段设置 `min``max` 范围
- 使用 `custom` 进行复杂验证
### 3. 字段联动设计
- 避免循环依赖
- 条件函数保持简单
- 联动动作尽可能轻量
### 4. 性能优化
- 使用字段缓存减少API请求
- 大表单使用懒加载
- 合理设置字段span优化布局
### 5. 错误处理
- 提供清晰的错误提示
- 使用自定义错误消息
- 验证失败时高亮显示错误字段
---
## 更新日志
### v1.0.0 (2025-01-24)
- ✨ 初始版本发布
- ✨ 支持基础字段类型
- ✨ 实现字段验证
- ✨ 实现字段联动
- ✨ 实现栅格布局
- 📝 完善文档和示例
---
## 支持
如有问题或建议,请联系开发团队。