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

22 KiB
Raw Blame History

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. 下载模型文件

十、总结

项目特点

  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