library-picturebook-activity/frontend/docs/add-new-route.md
aid 418aa57ea8 Day4: 超管端设计优化 + UGC绘本创作社区P0实现
一、超管端设计优化
- 文档管理SOP体系建立,docs目录重组
- 统一用户管理:跨租户全局视角,合并用户管理+公众用户
- 活动监管全模块重构:全部活动(统计卡片+阶段筛选+SuperDetail详情页)、报名数据/作品数据/评审进度(两层合一扁平列表)、成果发布(去Tab+统计+隐藏写操作)
- 菜单精简:移除评委管理/评审规则/通知管理
- Bug修复:租户编辑丢失隐藏菜单、pageSize限制、主色统一

二、UGC绘本创作社区P0
- 数据库:10张新表(user_works/user_work_pages/work_tags等)
- 子女账号独立化:Child升级为独立User,家长切换+独立登录
- 用户作品库:CRUD+发布审核,8个API
- AI创作流程:提交→生成→保存到作品库,4个API
- 作品广场:首页改造为推荐流,标签+搜索+排序
- 内容审核(超管端):作品审核+作品管理+标签管理
- 活动联动:WorkSelector作品选择器
- 布局改造:底部5Tab(发现/创作/活动/作品库/我的)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 22:20:25 +08:00

263 lines
8.3 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.

# 新增前端页面路由指南
本文档介绍如何在活动管理系统中新增前端页面路由。
## 概述
系统采用**动态路由**机制,路由配置存储在数据库中,前端根据用户权限动态加载。新增页面需要完成以下 4 个步骤:
```
┌──────────────────────────────────────────────────────────────┐
│ Step 1: 创建 Vue 组件文件 │
│ frontend/src/views/xxx/Index.vue │
├──────────────────────────────────────────────────────────────┤
│ Step 2: 在 componentMap 中注册组件 │
│ frontend/src/utils/menu.ts │
├──────────────────────────────────────────────────────────────┤
│ Step 3: 在数据库 menus 表中添加菜单记录 │
├──────────────────────────────────────────────────────────────┤
│ Step 4: 在数据库 tenant_menus 表中关联租户 │
└──────────────────────────────────────────────────────────────┘
```
## 详细步骤
### Step 1: 创建 Vue 组件文件
`frontend/src/views/` 目录下创建对应的 Vue 组件。
**目录结构规范:**
```
frontend/src/views/
├── workbench/ # 工作台模块
│ └── Index.vue
├── contests/ # 活动管理模块
│ ├── Index.vue # 活动列表
│ ├── Create.vue # 创建活动
│ ├── Detail.vue # 活动详情
│ ├── registrations/ # 报名管理
│ │ └── Index.vue
│ ├── works/ # 作品管理
│ │ └── Index.vue
│ └── ...
├── system/ # 系统管理模块
│ ├── users/
│ │ └── Index.vue
│ ├── roles/
│ │ └── Index.vue
│ └── ...
└── your-module/ # 你的新模块
└── Index.vue
```
**组件模板示例:**
```vue
<template>
<div class="page-container">
<h1>页面标题</h1>
<!-- 页面内容 -->
</div>
</template>
<script setup lang="ts">
// 组件逻辑
</script>
<style scoped lang="scss">
.page-container {
// 样式
}
</style>
```
### Step 2: 注册组件映射
`frontend/src/utils/menu.ts` 文件中的 `componentMap` 对象中添加组件映射。
**文件位置:** `frontend/src/utils/menu.ts`
```typescript
const componentMap: Record<string, () => Promise<any>> = {
// 工作台
"workbench/Index": () => import("@/views/workbench/Index.vue"),
// 活动管理模块
"contests/Index": () => import("@/views/contests/Index.vue"),
"contests/Create": () => import("@/views/contests/Create.vue"),
// ...
// 系统管理模块
"system/users/Index": () => import("@/views/system/users/Index.vue"),
// ...
// ========== 新增组件映射 ==========
"your-module/Index": () => import("@/views/your-module/Index.vue"),
"your-module/Detail": () => import("@/views/your-module/Detail.vue"),
};
```
**注意事项:**
- Key 格式:`模块名/组件名`,不需要 `@/views/` 前缀和 `.vue` 后缀
- Value 格式:使用动态 import 函数
- 如果未注册,控制台会输出警告信息
### Step 3: 添加数据库菜单记录
在数据库的 `menus` 表中插入菜单记录。
**menus 表结构:**
| 字段 | 类型 | 说明 |
|------|------|------|
| id | int | 主键,自增 |
| name | varchar | 菜单名称(显示文本) |
| path | varchar | 路由路径,如 `/contests` |
| component | varchar | 组件路径,对应 componentMap 的 key |
| icon | varchar | 图标名称,使用 Ant Design 图标 |
| parent_id | int | 父菜单ID顶级菜单为 NULL |
| sort | int | 排序序号 |
| permission | varchar | 权限标识,如 `contest:read` |
| tenant_id | int | 租户ID |
**SQL 示例:**
```sql
-- 添加顶级菜单
INSERT INTO menus (name, path, component, icon, parent_id, sort, tenant_id)
VALUES ('新模块', '/your-module', 'your-module/Index', 'AppstoreOutlined', NULL, 10, 1);
-- 获取刚插入的菜单ID
SET @parent_id = LAST_INSERT_ID();
-- 添加子菜单
INSERT INTO menus (name, path, component, icon, parent_id, sort, tenant_id)
VALUES ('子页面1', '/your-module/sub1', 'your-module/Sub1', NULL, @parent_id, 1, 1);
INSERT INTO menus (name, path, component, icon, parent_id, sort, tenant_id)
VALUES ('子页面2', '/your-module/sub2', 'your-module/Sub2', NULL, @parent_id, 2, 1);
```
**常用图标名称:**
- `HomeOutlined` - 首页
- `AppstoreOutlined` - 应用
- `TrophyOutlined` - 奖杯/活动
- `TeamOutlined` - 团队
- `UserOutlined` - 用户
- `SettingOutlined` - 设置
- `FileOutlined` - 文件
- `FolderOutlined` - 文件夹
更多图标请参考:[Ant Design Icons](https://ant.design/components/icon-cn)
### Step 4: 关联租户菜单
`tenant_menus` 表中添加租户与菜单的关联关系。
**SQL 示例:**
```sql
-- 假设菜单ID为 30租户ID为 1
INSERT INTO tenant_menus (tenant_id, menu_id) VALUES (1, 30);
-- 如果刚插入菜单,可以使用 LAST_INSERT_ID()
INSERT INTO tenant_menus (tenant_id, menu_id) VALUES (1, LAST_INSERT_ID());
-- 批量关联(关联多个租户)
INSERT INTO tenant_menus (tenant_id, menu_id) VALUES
(1, 30),
(2, 30),
(3, 30);
```
## 完整示例
假设要新增一个「公告管理」页面:
### 1. 创建组件文件
**文件:** `frontend/src/views/announcements/Index.vue`
```vue
<template>
<div>
<a-card title="公告管理">
<a-table :columns="columns" :data-source="data" />
</a-card>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const columns = [
{ title: '标题', dataIndex: 'title' },
{ title: '发布时间', dataIndex: 'createdAt' },
{ title: '操作', key: 'action' },
]
const data = ref([])
</script>
```
### 2. 注册组件
**文件:** `frontend/src/utils/menu.ts`
```typescript
const componentMap: Record<string, () => Promise<any>> = {
// ... 其他组件
"announcements/Index": () => import("@/views/announcements/Index.vue"),
};
```
### 3. 添加菜单记录
```sql
INSERT INTO menus (name, path, component, icon, parent_id, sort, permission, tenant_id)
VALUES ('公告管理', '/announcements', 'announcements/Index', 'NotificationOutlined', NULL, 5, 'announcement:read', 1);
```
### 4. 关联租户
```sql
INSERT INTO tenant_menus (tenant_id, menu_id) VALUES (1, LAST_INSERT_ID());
```
### 5. 验证
1. 重新登录系统(清除缓存)
2. 检查侧边栏是否显示新菜单
3. 点击菜单验证页面是否正常加载
## 常见问题
### Q1: 菜单不显示?
检查以下几点:
1. `tenant_menus` 表是否已关联当前租户
2. 用户角色是否有该菜单的权限
3. 清除浏览器缓存后重新登录
### Q2: 点击菜单报 404
检查以下几点:
1. `componentMap` 是否已注册该组件
2. 组件文件路径是否正确
3. 查看控制台是否有警告信息
### Q3: 控制台警告「组件路径未在 componentMap 中定义」?
`menu.ts``componentMap` 中添加对应的组件映射。
### Q4: 如何添加需要权限的页面?
`menus` 表的 `permission` 字段设置权限标识,如 `announcement:read`,然后确保用户角色拥有该权限。
## 相关文件
| 文件 | 说明 |
|------|------|
| `frontend/src/utils/menu.ts` | 组件映射、菜单转换工具 |
| `frontend/src/router/index.ts` | 路由配置、动态路由加载 |
| `frontend/src/stores/auth.ts` | 用户认证、菜单数据存储 |
| `frontend/src/layouts/BasicLayout.vue` | 主布局、侧边栏菜单渲染 |