- 添加 Lombok 配置支持 - 完善枚举类和常量定义 - 新增工具类(TraceId、限流、OSS 等) - 添加切面(日志、限流、TraceId) - 更新数据库索引规范(应用层防重) - 登录页面样式优化 - 前后端项目文档补充
22 KiB
22 KiB
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 |
完整依赖列表
{
"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 认证
- 用户信息获取
- 动态菜单加载
- 权限/角色判断
- 租户编码管理
核心代码示例:
// 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/) - 权限守卫
- 公众端与管理端分离
路由结构:
// 基础路由
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 添加
]
}
]
路由守卫逻辑:
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)
表单配置:
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 评审管理模块
功能:
- 评委分配(手动/批量/自动)
- 评审进度监控
- 作品评分界面
- 评审统计(评委进度/作品状态)
评审进度数据结构:
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 示例:
// 自动设置奖项
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
功能:
- 用户列表(分页 + 搜索)
- 用户类型筛选(平台/机构/评委/公共)
- 用户统计卡片
- 创建/编辑用户
- 用户状态切换(启用/禁用)
- 角色分配
查询参数:
interface UserQueryParams {
page?: number;
pageSize?: number;
keyword?: string; // 关键字搜索
userType?: "platform" | "org" | "judge" | "public";
filterTenantId?: number; // 按租户筛选
userSource?: "admin_created" | "self_registered";
status?: "enabled" | "disabled";
}
用户统计接口:
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 个不同角度)
- 模型下载
- 创作历史记录
任务状态:
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;
}
生成参数:
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
- 支持图文混排
- 支持文件上传
- 表单验证集成
使用示例:
<template>
<RichTextEditor v-model="content" :height="400" />
</template>
2. ModelViewer.vue - 3D 模型预览
功能:
- 基于 Three.js
- 支持 GLB/GLTF 格式
- 轨道控制器(旋转/缩放/平移)
- 自动加载/卸载
五、API 封装
Axios 封装 (utils/request.ts)
核心特性:
- 请求拦截器(自动添加 Token)
- 响应拦截器(统一错误处理)
- 多租户支持
- 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 类型定义
// 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:
{
user: User | null, // 用户信息
token: string, // JWT Token
menus: Menu[], // 用户菜单
loading: boolean // 加载状态
}
Getters:
{
isAuthenticated: boolean, // 是否已登录
tenantCode: string, // 租户编码
isSuperAdmin: () => boolean, // 是否超管
hasPermission: (p: string) => boolean, // 权限检查
hasAnyRole: (roles: string[]) => boolean // 角色检查
}
Actions:
{
login: (form: LoginForm) => Promise<LoginResponse>,
logout: () => Promise<void>,
fetchUserInfo: () => Promise<User>,
fetchUserMenus: () => Promise<Menu[]>,
updateToken: (newToken: string) => void,
initAuth: () => Promise<void>,
}
七、组合式函数 (Composables)
useListRequest
用途: 列表数据请求通用逻辑
使用示例:
const {
loading,
list,
total,
page,
pageSize,
fetchList,
handlePageChange,
handleSizeChange,
} = useListRequest(contestsApi.getList, initialParams)
useSimpleListRequest
用途: 简化版列表请求(无分页)
八、自定义指令
v-permission 权限指令
使用示例:
<template>
<button v-permission="['user:create']">创建用户</button>
<button v-permission="'admin'">超管功能</button>
</template>
实现:
// 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. 下载模型文件
十、总结
项目特点
- 完整的前后端分离架构 - Vue 3 + TypeScript + Vite
- 动态路由系统 - 基于菜单动态加载路由
- 多租户支持 - 租户编码路径前缀 + Token 隔离
- 细粒度权限控制 - 权限指令 + 路由守卫
- 丰富的竞赛管理功能 - 从创建到评审全流程
- AI 能力集成 - 腾讯混元 3D 模型生成
- 公众端独立入口 - /p 前缀区分
适用场景
- 📚 图书馆绘本创作比赛
- 🏫 学校各类竞赛活动
- 🎨 艺术创作比赛
- 📖 作文/阅读比赛
- 🤖 科技创新大赛
技术亮点
- Vue 3 Composition API
- TypeScript 类型安全
- Pinia 状态管理
- Ant Design Vue 组件库
- Tailwind CSS 原子化 CSS
- Three.js 3D 渲染
- WangEditor 富文本
文档生成时间:2026-03-28 分析人:AI Assistant