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

399
DYNAMIC_FORM_QUICKSTART.md Normal file
View File

@@ -0,0 +1,399 @@
# 动态表单组件 - 快速开始
## 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)