library-picturebook-activity/java-frontend/项目分析文档.md
En 48fc71b41d fix: 前后端接口对齐修复
- 修复 sys-config 接口参数对齐(configKey/configValue)
- 添加 dict 字典项管理 API
- 修复 logs 接口参数格式(批量删除/清理日志)
- 添加 request.ts postForm/putForm 方法支持

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 18:53:24 +08:00

898 lines
22 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.

# Vue 3 前端项目分析报告
> 项目路径:`frontend/`
> 分析日期2026-03-28
> 项目类型:多租户竞赛/活动管理系统前端
---
## 一、技术栈概览
| 组件 | 技术选型 | 版本 |
|------|----------|------|
| **框架** | Vue 3 | 3.4.21 |
| **构建工具** | Vite | 5.1.6 |
| **语言** | TypeScript | 5.4.3 |
| **状态管理** | Pinia | 2.1.7 |
| **路由** | Vue Router | 4.3.0 |
| **UI 组件库** | Ant Design Vue | 4.1.1 |
| **图标** | @ant-design/icons-vue | 7.0.1 |
| **HTTP 客户端** | Axios | 1.6.7 |
| **表单验证** | Vee Validate + Zod | 4.12.4 / 3.22.4 |
| **富文本编辑器** | WangEditor | 5.1.12 |
| **3D 渲染** | Three.js | 0.182.0 |
| **样式** | Tailwind CSS + SCSS | 3.4.1 |
| **日期处理** | Day.js | 1.11.10 |
### 完整依赖列表
```json
{
"dependencies": {
"@ant-design/icons-vue": "^7.0.1",
"@vee-validate/zod": "^4.12.4",
"@wangeditor/editor": "^5.1.23",
"@wangeditor-editor-for-vue": "^5.1.12",
"ant-design-vue": "^4.1.1",
"axios": "^1.6.7",
"dayjs": "^1.11.10",
"pinia": "^2.1.7",
"three": "^0.182.0",
"vee-validate": "^4.12.4",
"vue": "^3.4.21",
"vue-router": "^4.3.0",
"zod": "^3.22.4"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.0.4",
"autoprefixer": "^10.4.18",
"eslint": "^8.57.0",
"eslint-plugin-vue": "^9.22.0",
"postcss": "^8.4.35",
"sass": "^1.71.1",
"tailwindcss": "^3.4.1",
"typescript": "^5.4.3",
"vite": "^5.1.6",
"vue-tsc": "^3.2.2"
}
}
```
---
## 二、项目架构
### 目录结构
```
frontend/
├── src/
│ ├── api/ # API 接口层
│ │ ├── ai-3d.ts # AI 3D 任务接口
│ │ ├── auth.ts # 认证接口
│ │ ├── classes.ts # 班级管理接口
│ │ ├── config.ts # 系统配置接口
│ │ ├── contests.ts # 竞赛管理接口(核心)
│ │ ├── departments.ts # 部门管理接口
│ │ ├── dict.ts # 数据字典接口
│ │ ├── grades.ts # 年级管理接口
│ │ ├── homework.ts # 作业管理接口
│ │ ├── judges-management.ts # 评委管理接口
│ │ ├── logs.ts # 日志管理接口
│ │ ├── menus.ts # 菜单管理接口
│ │ ├── permissions.ts # 权限管理接口
│ │ ├── preset-comments.ts # 预设评语接口
│ │ ├── public.ts # 公共接口
│ │ ├── roles.ts # 角色管理接口
│ │ ├── schools.ts # 学校管理接口
│ │ ├── students.ts # 学生管理接口
│ │ ├── teachers.ts # 教师管理接口
│ │ ├── tenants.ts # 租户管理接口
│ │ ├── upload.ts # 文件上传接口
│ │ └── users.ts # 用户管理接口
│ │
│ ├── components/ # 公共组件
│ │ ├── ModelViewer.vue # 3D 模型预览组件
│ │ └── RichTextEditor.vue # 富文本编辑器组件
│ │
│ ├── composables/ # 组合式函数
│ │ ├── useListRequest.ts # 列表请求 Hook
│ │ └── useSimpleListRequest.ts # 简单列表请求 Hook
│ │
│ ├── directives/ # 自定义指令
│ │ └── permission.ts # 权限指令
│ │
│ ├── layouts/ # 布局组件
│ │ ├── BasicLayout.vue # 管理端基础布局
│ │ ├── EmptyLayout.vue # 空白布局
│ │ └── PublicLayout.vue # 公众端布局
│ │
│ ├── router/ # 路由配置
│ │ └── index.ts # 路由主文件(含动态路由)
│ │
│ ├── stores/ # Pinia 状态管理
│ │ └── auth.ts # 认证状态
│ │
│ ├── types/ # TypeScript 类型定义
│ │ ├── api.ts # API 通用类型
│ │ ├── auth.ts # 认证相关类型
│ │ └── router.ts # 路由扩展类型
│ │
│ ├── utils/ # 工具函数
│ │ ├── auth.ts # 认证工具
│ │ ├── avatar.ts # 头像工具
│ │ ├── menu.ts # 菜单工具
│ │ └── request.ts # Axios 封装
│ │
│ └── views/ # 页面组件
│ ├── activities/ # 活动评审页面
│ ├── auth/ # 认证页面
│ ├── content/ # 内容管理页面
│ ├── contests/ # 竞赛管理页面(核心)
│ ├── error/ # 错误页面
│ ├── homework/ # 作业管理页面
│ ├── model/ # 3D 模型页面
│ ├── public/ # 公众端页面
│ ├── school/ # 学校管理页面
│ ├── system/ # 系统管理页面
│ └── workbench/ # 工作台页面
├── scripts/ # 构建脚本
└── package.json
```
---
## 三、核心功能模块详解
### 1. 认证授权模块 (`auth/`)
**文件结构:**
```
src/stores/auth.ts # Pinia Store
src/api/auth.ts # API 接口
src/views/auth/Login.vue # 登录页面
src/utils/auth.ts # 认证工具
```
**核心功能:**
- JWT Token 认证
- 用户信息获取
- 动态菜单加载
- 权限/角色判断
- 租户编码管理
**核心代码示例:**
```typescript
// src/stores/auth.ts
export const useAuthStore = defineStore("auth", () => {
const user = ref<User | null>(null)
const token = ref<string>(getToken() || "")
const menus = ref<Menu[]>([])
const isAuthenticated = computed(() => !!token.value)
// 检查是否为超级管理员
const isSuperAdmin = (): boolean => {
return user.value?.roles?.includes('super_admin') ?? false
}
// 检查是否有指定权限(超管自动拥有所有权限)
const hasPermission = (permission: string): boolean => {
if (isSuperAdmin()) return true
return user.value?.permissions?.includes(permission) ?? false
}
const login = async (form: LoginForm) => {
const response = await authApi.login(form)
token.value = response.token
user.value = response.user
await fetchUserMenus() // 获取用户菜单
return response
}
// ...
})
```
---
### 2. 路由系统
**核心特性:**
- 基于动态菜单的路由加载
- 租户编码路径前缀(`/:tenantCode/`
- 权限守卫
- 公众端与管理端分离
**路由结构:**
```typescript
// 基础路由
const baseRoutes = [
// 管理端登录
{ path: "/:tenantCode/login", component: Login },
// 公众端路由(/p 前缀)
{
path: "/p",
children: [
{ path: "gallery", name: "PublicGallery" }, // 作品广场
{ path: "activities", name: "PublicActivities" }, // 活动大厅
{ path: "mine", name: "PublicMine" }, // 个人中心
{ path: "create", name: "PublicCreate" }, // 绘本创作
]
},
// 管理端路由(动态加载)
{
path: "/:tenantCode",
name: "Main",
component: BasicLayout,
children: [
// 动态路由将通过菜单 API 添加
]
}
]
```
**路由守卫逻辑:**
```typescript
router.beforeEach(async (to, _from, next) => {
// 公众端路由直接放行
if (to.path.startsWith("/p/")) {
next()
return
}
const authStore = useAuthStore()
// 未登录跳转登录页
if (!authStore.token && to.meta.requiresAuth !== false) {
next({ name: "Login", query: { redirect: to.fullPath } })
return
}
// 已登录自动获取用户信息和菜单
if (authStore.token && !authStore.user) {
await authStore.fetchUserInfo()
await addDynamicRoutes() // 添加动态路由
}
// 权限检查
const requiredPermissions = to.meta.permissions
if (requiredPermissions && !authStore.hasAnyPermission(requiredPermissions)) {
next({ name: "Forbidden" })
return
}
next()
})
```
---
### 3. 竞赛管理模块 (`contests/`) ⭐核心业务
**页面结构:**
```
contests/
├── Index.vue # 活动列表页
├── Create.vue # 创建/编辑活动
├── Detail.vue # 活动详情页
├── SuperDetail.vue # 超管活动详情页
├── RegisterIndividual.vue # 个人报名页
├── RegisterTeam.vue # 团队报名页
├── components/
│ ├── AddJudgeDrawer.vue # 添加评委抽屉
│ ├── AddParticipantDrawer.vue # 添加参与者抽屉
│ ├── AddTeacherDrawer.vue # 添加指导老师抽屉
│ ├── SubmitWorkDrawer.vue # 提交作品抽屉
│ ├── ViewWorkDrawer.vue # 查看作品抽屉
│ └── WorkDetailModal.vue # 作品详情弹窗
├── judges/
│ └── Index.vue # 评委管理
├── notices/
│ └── Index.vue # 公告管理
├── registrations/
│ ├── Index.vue # 报名管理列表
│ └── Records.vue # 报名记录
├── reviews/
│ ├── Index.vue # 评审管理
│ ├── Progress.vue # 评审进度
│ ├── ProgressDetail.vue # 评审进度详情
│ └── Tasks.vue # 评审任务
├── results/
│ ├── Index.vue # 成果管理列表
│ └── Detail.vue # 成果发布详情
├── works/
│ ├── Index.vue # 作品管理列表
│ └── WorksDetail.vue # 参赛作品详情
└── Guidance.vue # 我的指导(教师视角)
```
#### 3.1 活动列表页 (`Index.vue`)
**功能:**
- 活动列表展示(分页)
- 活动阶段筛选(未发布/报名中/提交中/评审中/已完结)
- 活动统计卡片
- 创建活动入口
- 活动状态管理(发布/完结/重新开启)
#### 3.2 创建活动页 (`Create.vue`)
**表单配置:**
```typescript
interface CreateContestForm {
contestName: string; // 活动名称
contestType: "individual" | "team"; // 活动类型
startTime: string; // 活动开始时间
endTime: string; // 活动结束时间
// 报名配置
registerStartTime: string; // 报名开始时间
registerEndTime: string; // 报名结束时间
requireAudit: boolean; // 是否需要审核
teamMinMembers?: number; // 团队最少人数
teamMaxMembers?: number; // 团队最多人数
// 作品配置
submitStartTime: string; // 作品提交开始时间
submitEndTime: string; // 作品提交结束时间
submitRule: "once" | "resubmit"; // 提交规则
workType: "image" | "video" | "document" | "code" | "other";
// 评审配置
reviewStartTime: string; // 评审开始时间
reviewEndTime: string; // 评审结束时间
reviewRuleId?: number; // 评审规则 ID
// 成果配置
resultPublishTime?: string; // 结果发布时间
}
```
#### 3.3 报名管理模块
**功能:**
- 报名列表(支持按状态筛选)
- 报名审核(通过/拒绝)
- 报名统计(待审核/已通过/已拒绝)
- 添加指导老师
- 报名记录查看
#### 3.4 评审管理模块
**功能:**
- 评委分配(手动/批量/自动)
- 评审进度监控
- 作品评分界面
- 评审统计(评委进度/作品状态)
**评审进度数据结构:**
```typescript
interface ReviewProgress {
contest: { /* 活动信息 */ };
summary: {
totalWorks: number; // 总作品数
assignedWorksCount: number; // 已分配作品数
scoredWorksCount: number; // 已评分作品数
totalJudges: number; // 评委总数
};
progress: {
assignmentProgress: number; // 分配进度百分比
scoringProgress: number; // 评分进度百分比
overallProgress: number; // 整体进度百分比
};
judgeProgress: JudgeProgressItem[]; // 评委进度列表
unassignedWorks: UnassignedWork[]; // 未分配作品列表
}
```
#### 3.5 成果管理模块
**功能:**
- 计算最终得分(支持多种计算规则)
- 自动排名
- 设置奖项(单个/批量/自动)
- 成果发布/撤回
**API 示例:**
```typescript
// 自动设置奖项
resultsApi.autoSetAwards(contestId, {
first: 3, // 一等奖 3 名
second: 6, // 二等奖 6 名
third: 10, // 三等奖 10 名
excellent: 20 // 优秀奖 20 名
})
// 批量设置奖项
resultsApi.batchSetAwards(contestId, {
awards: [
{ workId: 1, awardLevel: 'first' },
{ workId: 2, awardLevel: 'second' },
// ...
]
})
```
---
### 4. 用户管理模块 (`system/users/`)
**页面:** `src/views/system/users/Index.vue`
**功能:**
- 用户列表(分页 + 搜索)
- 用户类型筛选(平台/机构/评委/公共)
- 用户统计卡片
- 创建/编辑用户
- 用户状态切换(启用/禁用)
- 角色分配
**查询参数:**
```typescript
interface UserQueryParams {
page?: number;
pageSize?: number;
keyword?: string; // 关键字搜索
userType?: "platform" | "org" | "judge" | "public";
filterTenantId?: number; // 按租户筛选
userSource?: "admin_created" | "self_registered";
status?: "enabled" | "disabled";
}
```
**用户统计接口:**
```typescript
interface UserStats {
total: number; // 总用户数
platform: number; // 平台用户
org: number; // 机构用户
judge: number; // 评委用户
public: number; // 公共用户
}
```
---
### 5. AI 3D 创作模块 (`workbench/ai-3d/`) ⭐特色功能
**文件结构:**
```
workbench/ai-3d/
├── Index.vue # 3D 建模实验室首页
├── Generate.vue # 模型生成页面
└── History.vue # 创作历史
```
**功能:**
- AI 文生 3D 模型(腾讯混元 API
- 生成类型选择Normal/LowPoly/Geometry/Sketch
- 任务状态轮询
- 多结果展示4 个不同角度)
- 模型下载
- 创作历史记录
**任务状态:**
```typescript
type AI3DTaskStatus = "pending" | "processing" | "completed" | "failed" | "timeout";
interface AI3DTask {
id: number;
inputType: "text" | "image";
inputContent: string;
status: AI3DTaskStatus;
resultUrls?: string[]; // 多结果 URL
previewUrls?: string[]; // 预览图 URL
queuePosition?: number; // 队列位置
createTime: string;
completeTime?: string;
}
```
**生成参数:**
```typescript
interface CreateAI3DTaskParams {
inputType: "text" | "image";
inputContent: string;
generateType?: "Normal" | "LowPoly" | "Geometry" | "Sketch";
faceCount?: number; // 模型面数 (10000-1500000)
}
```
---
### 6. 学校管理模块 (`school/`)
**子模块:**
```
school/
├── schools/ # 学校信息
├── grades/ # 年级管理
├── classes/ # 班级管理
├── teachers/ # 教师管理
└── students/ # 学生管理
```
**功能:**
- 学校信息 CRUD
- 年级管理(支持排序)
- 班级管理(关联年级)
- 教师列表(支持搜索)
- 学生列表(支持按班级筛选)
---
### 7. 系统管理模块 (`system/`)
**子模块:**
| 页面 | 功能 |
|------|------|
| `users/` | 用户管理 |
| `roles/` | 角色管理 |
| `permissions/` | 权限管理 |
| `menus/` | 菜单管理 |
| `tenants/` | 租户管理 |
| `dict/` | 数据字典 |
| `config/` | 系统配置 |
| `logs/` | 系统日志 |
---
### 8. 公众端模块 (`public/`)
**页面结构:**
```
public/
├── Login.vue # 公众端登录
├── Gallery.vue # 作品广场
├── Activities.vue # 活动大厅
├── ActivityDetail.vue # 活动详情
├── mine/
│ ├── Index.vue # 个人中心
│ ├── Registrations.vue # 我的报名
│ ├── Works.vue # 我的作品
│ └── Children.vue # 子女账号
├── create/
│ ├── Index.vue # 绘本创作首页
│ └── Generating.vue # 生成中页面
├── works/
│ ├── Index.vue # 我的作品库
│ ├── Detail.vue # 作品详情
│ └── Publish.vue # 发布作品
└── components/
└── WorkSelector.vue # 作品选择器
```
**核心功能:**
- 公众端独立登录
- 作品广场展示
- 活动大厅浏览
- 个人中心(报名/作品/子女管理)
- AI 绘本创作
---
### 9. 作业管理模块 (`homework/`)
**页面:**
- `Index.vue` - 作业列表
- `ReviewRules.vue` - 评审规则
- `Submissions.vue` - 提交记录
- `StudentDetail.vue` - 学生作业详情
- `StudentList.vue` - 学生列表
**功能:**
- 作业发布与查看
- 作业提交记录
- 作业评审
- 成绩查看
---
## 四、公共组件
### 1. RichTextEditor.vue - 富文本编辑器
**功能:**
- 基于 WangEditor
- 支持图文混排
- 支持文件上传
- 表单验证集成
**使用示例:**
```vue
<template>
<RichTextEditor v-model="content" :height="400" />
</template>
```
### 2. ModelViewer.vue - 3D 模型预览
**功能:**
- 基于 Three.js
- 支持 GLB/GLTF 格式
- 轨道控制器(旋转/缩放/平移)
- 自动加载/卸载
---
## 五、API 封装
### Axios 封装 (`utils/request.ts`)
**核心特性:**
- 请求拦截器(自动添加 Token
- 响应拦截器(统一错误处理)
- 多租户支持
- TypeScript 泛型支持
**请求配置:**
```typescript
const request = axios.create({
baseURL: '/api',
timeout: 30000,
})
// 请求拦截器
request.interceptors.request.use(config => {
const token = getToken()
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
})
// 响应拦截器
request.interceptors.response.use(
response => response.data,
error => {
if (error.response?.status === 401) {
// Token 过期,跳转登录
}
return Promise.reject(error)
}
)
```
### API 类型定义
```typescript
// types/api.ts
export interface PaginationParams {
page?: number
pageSize?: number
}
export interface PaginationResponse<T> {
list: T[]
total: number
page: number
pageSize: number
}
```
---
## 六、状态管理
### Auth Store (`stores/auth.ts`)
**State**
```typescript
{
user: User | null, // 用户信息
token: string, // JWT Token
menus: Menu[], // 用户菜单
loading: boolean // 加载状态
}
```
**Getters**
```typescript
{
isAuthenticated: boolean, // 是否已登录
tenantCode: string, // 租户编码
isSuperAdmin: () => boolean, // 是否超管
hasPermission: (p: string) => boolean, // 权限检查
hasAnyRole: (roles: string[]) => boolean // 角色检查
}
```
**Actions**
```typescript
{
login: (form: LoginForm) => Promise<LoginResponse>,
logout: () => Promise<void>,
fetchUserInfo: () => Promise<User>,
fetchUserMenus: () => Promise<Menu[]>,
updateToken: (newToken: string) => void,
initAuth: () => Promise<void>,
}
```
---
## 七、组合式函数 (Composables)
### useListRequest
**用途:** 列表数据请求通用逻辑
**使用示例:**
```typescript
const {
loading,
list,
total,
page,
pageSize,
fetchList,
handlePageChange,
handleSizeChange,
} = useListRequest(contestsApi.getList, initialParams)
```
### useSimpleListRequest
**用途:** 简化版列表请求(无分页)
---
## 八、自定义指令
### v-permission 权限指令
**使用示例:**
```vue
<template>
<button v-permission="['user:create']">创建用户</button>
<button v-permission="'admin'">超管功能</button>
</template>
```
**实现:**
```typescript
// directives/permission.ts
export const permission = {
mounted(el, binding) {
const { hasPermission } = useAuthStore()
const value = binding.value
const required = Array.isArray(value) ? value : [value]
if (!hasPermission(required)) {
el.parentNode?.removeChild(el)
}
}
}
```
---
## 九、核心业务流程
### 1. 用户登录流程
```
1. 输入用户名密码 →
2. 调用 login API →
3. 存储 Token按租户隔离
4. 获取用户信息 →
5. 获取用户菜单 →
6. 添加动态路由 →
7. 跳转到首页
```
### 2. 活动创建流程
```
1. 填写活动基本信息 →
2. 配置报名参数 →
3. 配置作品参数 →
4. 配置评审规则 →
5. 提交创建 →
6. 跳转到活动详情页
```
### 3. 作品提交流程
```
1. 选择活动 →
2. 点击提交作品 →
3. 填写作品信息(标题/描述) →
4. 上传作品文件 →
5. 上传预览图 →
6. 提交成功 →
7. 可查看/编辑(在截止时间前)
```
### 4. 评审工作流程
```
1. 管理员分配作品给评委 →
2. 评委登录后查看待评审作品 →
3. 查看作品详情 →
4. 按维度评分 →
5. 填写评语 →
6. 提交评分
```
### 5. AI 3D 模型生成流程
```
1. 输入提示词 →
2. 选择生成类型 →
3. 提交任务 →
4. 轮询任务状态 →
5. 生成完成后展示 4 个角度模型 →
6. 下载模型文件
```
---
## 十、总结
### 项目特点
1. **完整的前后端分离架构** - Vue 3 + TypeScript + Vite
2. **动态路由系统** - 基于菜单动态加载路由
3. **多租户支持** - 租户编码路径前缀 + Token 隔离
4. **细粒度权限控制** - 权限指令 + 路由守卫
5. **丰富的竞赛管理功能** - 从创建到评审全流程
6. **AI 能力集成** - 腾讯混元 3D 模型生成
7. **公众端独立入口** - /p 前缀区分
### 适用场景
- 📚 图书馆绘本创作比赛
- 🏫 学校各类竞赛活动
- 🎨 艺术创作比赛
- 📖 作文/阅读比赛
- 🤖 科技创新大赛
### 技术亮点
- Vue 3 Composition API
- TypeScript 类型安全
- Pinia 状态管理
- Ant Design Vue 组件库
- Tailwind CSS 原子化 CSS
- Three.js 3D 渲染
- WangEditor 富文本
---
> 文档生成时间2026-03-28
> 分析人AI Assistant