Files
Common_Platform/history/通用中后台框架建设规划.md
2026-04-28 16:27:16 +08:00

24 KiB
Raw Permalink Blame History

通用中后台底座平台建设规划

1. 系统定位

本系统定位为一个通用中后台基础框架。

本框架只提供中后台常用基础能力,不绑定任何具体业务。它的职责是提供稳定、轻量、现代的管理端基础设施,便于后续在同一工程内按需扩展页面、接口和基础模块。

本次设计只包含:

  • 前端通用框架
  • 后端通用框架
  • 用户、组织、角色、菜单、权限、字典、日志等基础模块

本次不包含:

  • 任何具体业务模块
  • 旧 Vue 页面兼容
  • 接口文档平台
  • 多语言
  • 微前端

2. 建设目标

核心目标:

  • UI 现代、极简、高级。
  • 前端轻便快速,交互顺滑,首屏和页面切换速度快。
  • 后端结构清晰,接口稳定,权限和日志能力完善。
  • 项目可以快速获得稳定的中后台基础能力。
  • 新页面开发路径固定、清晰、可复制。
  • 代码可读性优先,避免过度封装和框架魔法。

设计原则:

  • 只做底座,不预设业务。
  • 组件库负责基础 UI,不自研复杂 UI 框架。
  • 权限、菜单、字典、日志做成通用能力。
  • 数据查询、缓存、分页、错误处理形成统一模式。
  • 前后端边界清晰,前端不承载安全规则,后端必须做权限校验。

3. 技术栈

3.1 前端技术栈

推荐技术栈:

  • Vue 3
  • TypeScript
  • Vite
  • Vue Router
  • Pinia
  • TanStack Query
  • Naive UI
  • Tailwind CSS
  • lucide-vue-next
  • Axios
  • VueUse
  • Vitest
  • Playwright
  • ESLint
  • Prettier

说明:

  • Vue 3 使用 <script setup lang="ts"> 和 Composition API。
  • Pinia 只负责全局状态,不承载页面列表数据。
  • TanStack Query 负责服务端状态、缓存、刷新、分页、错误重试。
  • Naive UI 负责基础组件,不额外建设复杂主题系统。
  • Tailwind CSS 负责布局、间距、响应式和少量自定义样式。
  • lucide-vue-next 统一图标风格。
  • 系统只使用中文,不做多语言。

3.2 后端技术栈

推荐技术栈:

  • Kotlin
  • Ktor
  • kotlinx.serialization
  • Exposed
  • HikariCP
  • JWT
  • Logback
  • PostgreSQL
  • Redis
  • Docker Compose

说明:

  • Ktor 负责 HTTP 服务、认证、路由、异常处理。
  • kotlinx.serialization 作为 JSON 序列化方案。
  • Exposed 作为数据库访问层。
  • HikariCP 作为数据库连接池。
  • JWT 作为前后端认证令牌。
  • Logback 输出系统运行日志。
  • PostgreSQL 作为默认关系型数据库。
  • Redis 作为缓存、验证码、临时会话、限流等基础设施。
  • PostgreSQL、Redis 等配套组件统一用根目录 docker-compose.yml 管理。

4. 总体架构

flowchart LR
  Web["Vue3 管理端"]
  Api["Ktor API Server"]
  DB["PostgreSQL"]
  Cache["Redis"]

  Web -->|"HTTP API / JWT"| Api
  Api -->|"Exposed / HikariCP"| DB
  Api -->|"Redisson"| Cache

本框架分为两部分:

  • web:前端管理端。
  • server:后端 API 服务。

前端负责:

  • 登录页
  • 主布局
  • 动态菜单
  • 路由守卫
  • 页面渲染
  • 表格、表单、弹窗等交互
  • 查询缓存和请求状态管理
  • 按钮级权限展示控制

后端负责:

  • 登录认证
  • JWT 签发与校验
  • 用户管理
  • 组织管理
  • 角色管理
  • 菜单管理
  • 权限校验
  • 字典管理
  • 操作日志
  • 开放接口调用日志
  • 系统异常日志
  • PostgreSQL 连接池
  • Redis 客户端

5. 工程结构

建议采用前后端同仓库:

platform-a/
  docker-compose.yml
  web/
  server/

不建议一期引入复杂 monorepo。底座平台先保持清晰、直接、容易部署。

配套组件统一放在项目根目录 docker-compose.yml

docker-compose.yml
  postgres: PostgreSQL 18.3
  redis: Redis 8

本地开发默认连接:

PostgreSQL:
  host: localhost
  port: 5432
  database: platform_a
  user: platform_a
  password: platform_a_password

Redis:
  host: localhost
  port: 6379
  password: platform_a_redis_password

启动配套组件:

docker compose up -d

停止配套组件:

docker compose down

如果需要清空本地数据,再执行:

docker compose down -v

6. 前端架构设计

6.1 前端组织原则

前端按功能组织页面,不在文档中写死完整目录结构。目录和文件根据实际复杂度创建,避免为了满足规范而产生空目录、空文件。

基础原则:

  • 页面按功能组织。
  • 共享组件放在全局 components 目录。
  • 页面私有组件、组合逻辑、类型定义放在页面目录内。
  • 路由、状态、请求、布局、样式等基础能力保持清晰边界。
  • 简单页面可以只保留一个页面文件,复杂页面再拆分私有组件和逻辑。

6.2 页面组织规则

页面组织以可读性为准,不强制固定文件数量。

建议规则:

  • 页面入口负责结构和主要交互。
  • 页面私有逻辑只服务当前页面时,放在页面目录内。
  • 多页面复用的组件、工具、类型再上提到共享目录。
  • 表格列、搜索条件、弹窗状态等页面强相关内容优先靠近页面。

6.3 路由设计

路由分为静态路由和动态路由。

静态路由:

  • /login
  • /403
  • /404
  • /

动态路由:

  • 登录后从后端获取菜单。
  • 前端根据菜单里的 component 字段加载页面。
  • 菜单变化后,用户重新登录或刷新权限即可生效。

后端菜单返回示例:

{
  "id": "1001",
  "parentId": null,
  "type": "MENU",
  "path": "/system/users",
  "name": "SystemUsers",
  "component": "system/users/index",
  "title": "用户管理",
  "icon": "Users",
  "permission": "system:user:view",
  "sort": 10,
  "visible": true,
  "keepAlive": true
}

前端页面加载:

const viewModules = import.meta.glob('../features/**/index.vue')

组件路径规则:

system/users/index -> src/features/system/users/index.vue

SPA 页面需要支持页签栏和页面缓存:

  • 后台主体使用单页应用模式,页面切换不整页刷新。
  • 已打开页面进入页签栏,支持切换、关闭、刷新当前页签。
  • 菜单配置中的 keepAlive 控制页面是否缓存。
  • 页面缓存需要和动态路由、权限刷新配合,用户权限变化后应清理不可访问页面。
  • 列表查询数据仍由 TanStack Query 管理,页签缓存主要保留页面组件状态和表单状态。

6.4 Pinia 状态边界

Pinia 只保存全局状态:

  • 当前 token
  • 当前用户
  • 用户权限码
  • 用户菜单树
  • 当前布局状态
  • 字典缓存

不建议放入 Pinia

  • 表格列表数据
  • 分页数据
  • 搜索条件
  • 表单弹窗状态
  • 详情数据

这些服务端状态统一交给 TanStack Query 管理。

6.5 TanStack Query 使用规则

TanStack Query 用于:

  • 列表查询
  • 详情查询
  • 字典查询
  • 新增、修改、删除后的缓存刷新
  • 后台刷新
  • 请求错误状态
  • 加载状态

建议封装统一 query key

export const userKeys = {
  all: ['system', 'users'] as const,
  list: (params: UserQuery) => [...userKeys.all, 'list', params] as const,
  detail: (id: string) => [...userKeys.all, 'detail', id] as const,
}

Mutation 成功后按模块刷新:

queryClient.invalidateQueries({ queryKey: userKeys.all })

6.6 HTTP 请求封装

统一响应格式:

export interface ApiResult<T> {
  code: string
  message: string
  data: T
  traceId?: string
}

分页格式:

export interface PageResult<T> {
  items: T[]
  page: number
  pageSize: number
  total: number
}

HTTP 层职责:

  • 自动附加 JWT。
  • 处理 401 并跳转登录页。
  • 处理 403 并提示无权限。
  • 统一处理业务错误。
  • 记录 traceId

6.7 权限控制

前端提供三种权限控制:

  1. 路由权限:无菜单权限不能进入页面。
  2. 按钮权限:无操作权限不显示按钮。
  3. 组件权限:复杂页面局部区域可按权限隐藏。

按钮示例:

<PermissionButton permission="system:user:create">
  新增用户
</PermissionButton>

前端权限只负责体验,后端接口必须再次校验权限。

6.8 UI 风格

整体风格:

  • 现代
  • 极简
  • 高级
  • 工作台
  • 信息密度适中
  • 视觉安静

布局建议:

  • 左侧导航栏
  • 顶部操作栏
  • 面包屑
  • 页签栏
  • 内容区使用浅灰背景
  • 页面主体使用白色内容面板

视觉规范:

  • 不做花哨渐变背景。
  • 不做厚重阴影。
  • 不做复杂主题编辑器。
  • 卡片只用于真正需要分组的信息。
  • 表格页筛选区要轻,不做大面积表单堆叠。
  • 图标统一使用 lucide-vue-next。
  • 中文字体默认使用系统字体。

推荐 Tailwind 基础风格:

body {
  @apply bg-slate-50 text-slate-950 antialiased;
}

推荐主题变量:

:root {
  --app-bg: #f8fafc;
  --app-surface: #ffffff;
  --app-border: #e2e8f0;
  --app-text: #0f172a;
  --app-muted: #64748b;
  --app-primary: #2563eb;
  --app-success: #16a34a;
  --app-warning: #d97706;
  --app-danger: #dc2626;
}

6.9 Naive UI 主题

Naive UI 通过 NConfigProvider 统一配置:

  • primary color
  • border radius
  • font family
  • component size
  • message provider
  • dialog provider
  • notification provider

建议默认尺寸:

  • 表格:small
  • 表单:medium
  • 按钮:medium
  • 弹窗:保持紧凑

6.10 前端基础页面

一期前端页面:

  • 登录
  • 工作台首页
  • 用户管理
  • 组织管理
  • 角色管理
  • 菜单管理
  • 字典管理
  • 操作日志
  • 开放接口调用日志

7. 后端架构设计

7.1 后端目录结构

当前 server 已经按基础框架骨架整理为:

server/
  src/main/kotlin/com/bbit/platform/
    Application.kt
    common/
      ApiResult.kt
      BizException.kt
    config/
      AppConfig.kt
    database/
      system/
        SysUserTable.kt
        SysOrgTable.kt
        SysRoleTable.kt
        SysMenuTable.kt
        SysUserRoleTable.kt
        SysRoleMenuTable.kt
        SysDictTypeTable.kt
        SysDictItemTable.kt
        SysOperationLogTable.kt
        SysApiAccessLogTable.kt
      business/
    plugins/
      CorsPlugin.kt
      DatabasePlugin.kt
      LoggingPlugin.kt
      RedisPlugin.kt
      SecurityPlugin.kt
      SerializationPlugin.kt
      StatusPagesPlugin.kt

当前结构说明:

  • Application.kt 负责应用启动和插件装配。
  • common 放统一响应、业务异常等公共模型。
  • config 放应用配置读取。
  • plugins 放 Ktor 插件和基础设施配置,数据库连接与 dbQuery 当前也放在 DatabasePlugin.kt
  • database/system 放系统基础表定义。
  • database/business 预留给后续具体功能表,不在底座阶段预设业务表。

后续只补必要目录,保持结构直接、清晰:

server/
  src/main/kotlin/com/bbit/platform/
    common/
      PageResult.kt
      PageQuery.kt
      ErrorCode.kt
      TraceContext.kt
    security/
      JwtService.kt
      PasswordService.kt
      PermissionService.kt
      SecurityPrincipal.kt
      RequirePermission.kt
    bootstrap/
      DatabaseInitializer.kt
      SeedData.kt
    modules/
      auth/
      system/
        user/
        org/
        role/
        menu/
        dict/
      logs/
        operation/
        apiaccess/

模块目录内部按需拆分 RoutesServiceDtos,不提前创建空文件。

7.2 当前默认配置

当前 server/src/main/resources/application.yaml 只保留底座需要的配置:

ktor:
  application:
    modules:
      - com.bbit.platform.ApplicationKt.module
  deployment:
    port: 8080

app:
  name: "Platform A"
  env: "local"

database:
  url: "jdbc:postgresql://localhost:5432/platform_a"
  user: "platform_a"
  password: "platform_a_password"
  maximumPoolSize: 16
  minimumIdle: 4

redis:
  url: "redis://127.0.0.1:6379"
  password: "platform_a_redis_password"

security:
  jwt:
    issuer: "platform-a"
    audience: "platform-a-admin"
    realm: "Platform A"
    secret: "change-me-to-a-strong-secret"
    accessTokenTtlMinutes: 120

cors:
  allowedHosts: "localhost:5173,127.0.0.1:5173"

已经移除的非底座配置:

  • 邮件 SMTP
  • 阿里云 SDK
  • LLM API Key
  • 具体业务配置
  • 旧项目命名配置

7.3 后端分层规则

每个模块保持简单分层:

  • RoutesHTTP 路由,处理参数绑定和响应。
  • Service:可供路由复用的服务,承载业务逻辑、权限逻辑、事务边界和必要的数据访问。
  • Dtos:请求和响应对象。

规则:

  • Route 不写复杂业务逻辑。
  • Service 是事务、业务规则和可复用能力的主要承载层。
  • DTO 和数据库实体不要混用。

7.4 统一响应

@Serializable
data class ApiResult<T>(
    val code: String,
    val message: String,
    val data: T? = null,
    val traceId: String? = null
)

成功:

{
  "code": "0",
  "message": "成功",
  "data": {}
}

失败:

{
  "code": "SYSTEM.USER_NOT_FOUND",
  "message": "用户不存在",
  "traceId": "..."
}

7.5 认证设计

登录流程:

  1. 用户提交账号和密码。
  2. 后端校验用户状态。
  3. 后端校验密码。
  4. 后端签发 JWT。
  5. 前端保存 token。
  6. 前端调用 /api/auth/me 获取用户、菜单、权限。

JWT 内容建议:

{
  "sub": "userId",
  "username": "admin",
  "orgId": "1",
  "roles": ["admin"],
  "tokenVersion": 1
}

后端需要支持:

  • token 过期。
  • 用户禁用后拒绝访问。
  • 修改密码后通过 tokenVersion 使旧 token 失效。

7.6 权限模型

采用 RBAC

sys_user
sys_role
sys_menu
sys_user_role
sys_role_menu

菜单类型:

  • CATALOG:目录
  • MENU:页面
  • BUTTON:按钮或接口权限

权限码格式:

system:user:view
system:user:create
system:user:update
system:user:delete
system:role:assign
system:menu:update
system:dict:view
log:operation:view
log:api-access:view

接口权限校验示例:

post("/api/system/users") {
    requirePermission("system:user:create")
}

7.7 组织模型

组织使用树结构:

id
parent_id
name
code
sort
status

组织用于:

  • 用户归属
  • 数据范围预留
  • 后续数据范围控制的基础

一期建议先完成组织树和用户归属,数据范围可以预留字段,不做复杂实现。

7.8 字典模型

字典分为:

  • 字典类型
  • 字典项

字典类型示例:

user_status
org_status
menu_type
log_status

前端登录后可加载常用字典,也可以按需查询。字典适合放入 Pinia 缓存。

字典和代码枚举需要区分:

  • 代码枚举用于系统逻辑强依赖的固定值,例如菜单类型、用户状态、角色状态、日志状态。
  • 业务字典用于展示、筛选、颜色标识和可配置选项。
  • 后端逻辑不能依赖后台随意维护的字典项来决定安全规则。
  • 字典项可以影响前端展示,但不能绕过后端权限、状态和数据校验。

7.9 初始化数据

初始化数据放在后端工程内维护,由服务端负责创建和升级基础数据。初始化逻辑应支持重复执行,避免多次启动或多次部署后产生重复数据。

建议初始化内容:

  • 默认组织:总部或默认组织。
  • 默认管理员用户:admin。
  • 默认角色:超级管理员。
  • 默认菜单:工作台、系统管理、用户管理、组织管理、角色管理、菜单管理、字典管理、日志管理。
  • 默认权限码:页面权限和关键按钮权限。
  • 默认字典:用户状态、组织状态、角色状态、菜单类型、日志状态。

实现规则:

  • 初始化数据按稳定编码执行 upsert,例如 usernamerole.codemenu.permissiondict_type.code
  • 管理员账号固定为 admin,初始化密码固定写入后端种子数据,首次登录后可在系统内修改。
  • 初始化逻辑不写在路由里,建议放在 bootstrap/SeedData.kt
  • 数据库表初始化和种子数据初始化分开,方便后续迁移到正式迁移工具。
  • 初始化失败应让服务启动失败,避免系统处于半初始化状态。

8. 日志设计

日志分三类:

  1. 系统运行日志
  2. 操作日志
  3. 开放接口调用日志

8.1 系统运行日志

系统运行日志通过 Logback 输出。

记录内容:

  • 应用启动
  • 数据库连接
  • 接口异常
  • 未捕获异常
  • 慢请求
  • 关键配置加载结果

建议输出:

  • 控制台日志
  • 文件日志
  • 按日期滚动
  • 错误日志单独文件

8.2 操作日志

操作日志记录后台用户在系统内的关键操作。

典型场景:

  • 登录成功
  • 登录失败
  • 新增用户
  • 修改用户
  • 禁用用户
  • 删除用户
  • 分配角色
  • 修改菜单
  • 修改字典
  • 重置密码

操作日志字段:

id
trace_id
user_id
username
org_id
operation_type
operation_name
http_method
request_path
request_params
ip
user_agent
status
error_message
cost_ms
created_at

敏感字段处理:

  • 密码不记录。
  • token 不记录。
  • 身份证、手机号等可按规则脱敏。

实现方式:

  • 提供 OperationLog 注解或路由扩展。
  • 对关键接口显式声明操作名称。
  • 在请求结束后统一落库。

示例:

post("/api/system/users") {
    withOperationLog("新增用户") {
        requirePermission("system:user:create")
        userService.create(call.receive())
    }
}

8.3 开放接口调用日志

开放接口调用日志用于记录平台对外提供的 API 被调用情况。

适用场景:

  • 第三方系统调用平台接口。
  • 内部其他系统调用平台接口。
  • 后续开放 API 网关接入。

字段:

id
trace_id
app_key
app_name
http_method
request_path
request_headers
request_body
response_code
response_body
ip
status
error_message
cost_ms
created_at

敏感字段处理:

  • Authorization 不记录原文。
  • 签名密钥不记录。
  • 请求体和响应体限制长度。
  • 大请求体不记录 body。

一期可以先设计数据表和查询页面,开放接口鉴权可后续完善。

9. 数据库设计

9.1 基础表

sys_user
sys_org
sys_role
sys_menu
sys_user_role
sys_role_menu
sys_dict_type
sys_dict_item
sys_operation_log
sys_api_access_log

9.2 通用字段

建议所有业务表保留:

id
created_at
created_by
updated_at
updated_by
deleted_at
deleted_by
version

说明:

  • id 建议使用雪花 ID 或 UUID。
  • created_atupdated_at 使用数据库时间或服务端统一时间。
  • 默认使用软删除,删除时设置 deleted_atdeleted_by
  • 查询默认过滤 deleted_at is null
  • 唯一约束需要考虑软删除数据,避免已删除数据长期占用唯一值。
  • version 用于乐观锁。
  • 操作日志、开放接口调用日志等纯追加日志表不做软删除,也不需要 updated_atdeleted_at

软删除规则:

  • 普通删除接口默认执行软删除,不直接物理删除数据。
  • 删除前需要校验引用关系,例如角色被用户使用、组织下存在用户、菜单被角色引用。
  • 系统内置数据可以禁止删除,只允许禁用。
  • 物理删除只作为维护操作,不暴露为普通管理端能力。
  • 恢复已删除数据不是一期能力,但表结构保留恢复可能性。

9.3 用户表

sys_user
  id
  username
  password_hash
  nickname
  real_name
  phone
  email
  avatar
  org_id
  status
  token_version
  last_login_at
  last_login_ip
  created_at
  created_by
  updated_at
  updated_by
  deleted_at
  deleted_by
  version

9.4 组织表

sys_org
  id
  parent_id
  name
  code
  sort
  status
  created_at
  created_by
  updated_at
  updated_by
  deleted_at
  deleted_by
  version

9.5 角色表

sys_role
  id
  name
  code
  description
  status
  data_scope
  created_at
  created_by
  updated_at
  updated_by
  deleted_at
  deleted_by
  version

9.6 菜单表

sys_menu
  id
  parent_id
  type
  title
  name
  path
  component
  icon
  permission
  sort
  visible
  keep_alive
  status
  created_at
  created_by
  updated_at
  updated_by
  deleted_at
  deleted_by
  version

9.7 字典表

sys_dict_type
  id
  code
  name
  status
  remark
  created_at
  created_by
  updated_at
  updated_by
  deleted_at
  deleted_by
  version

sys_dict_item
  id
  type_id
  label
  value
  color
  sort
  status
  remark
  created_at
  created_by
  updated_at
  updated_by
  deleted_at
  deleted_by
  version

10. 后端接口范围

一期接口范围:

POST /api/auth/login
POST /api/auth/logout
GET  /api/auth/me

GET    /api/system/users
POST   /api/system/users
GET    /api/system/users/{id}
PUT    /api/system/users/{id}
DELETE /api/system/users/{id}
PUT    /api/system/users/{id}/status
PUT    /api/system/users/{id}/password
PUT    /api/system/users/{id}/roles

GET    /api/system/orgs
POST   /api/system/orgs
PUT    /api/system/orgs/{id}
DELETE /api/system/orgs/{id}

GET    /api/system/roles
POST   /api/system/roles
GET    /api/system/roles/{id}
PUT    /api/system/roles/{id}
DELETE /api/system/roles/{id}
PUT    /api/system/roles/{id}/menus

GET    /api/system/menus
POST   /api/system/menus
PUT    /api/system/menus/{id}
DELETE /api/system/menus/{id}

GET    /api/system/dict-types
POST   /api/system/dict-types
PUT    /api/system/dict-types/{id}
DELETE /api/system/dict-types/{id}

GET    /api/system/dict-items
POST   /api/system/dict-items
PUT    /api/system/dict-items/{id}
DELETE /api/system/dict-items/{id}

GET    /api/logs/operation
GET    /api/logs/api-access

接口路径不带版本号,系统规模不大,默认使用稳定路径。为了避免后续频繁破坏前端和已有调用方,需要遵守接口兼容规则:

  • 已发布接口路径尽量不改名、不删除。
  • 响应字段只增不减,不修改已有字段含义。
  • 请求字段新增时必须有默认行为,不能让旧前端请求失败。
  • 枚举值可以新增,但前端必须对未知枚举有兜底展示。
  • 废弃字段先保留一段时间,代码中标记 deprecated,再择机清理。
  • 错误码保持稳定,前端不要依赖错误文案做逻辑判断。
  • 破坏性调整优先新增接口,再逐步迁移旧接口。

11. 前端页面范围

一期页面范围:

登录页
工作台首页
用户管理
组织管理
角色管理
菜单管理
字典类型管理
字典项管理
操作日志
开放接口调用日志
403
404

页面标准能力:

  • 查询
  • 分页
  • 新增
  • 编辑
  • 删除
  • 启用/禁用
  • 权限控制
  • 操作反馈

12. 开发规范

12.1 前端规范

  • 统一使用 TypeScript。
  • 统一使用 <script setup>
  • 请求统一走 api/http.ts
  • 服务端状态统一使用 TanStack Query。
  • 全局状态才进入 Pinia。
  • 页面文件夹按功能组织。
  • 组件命名使用 PascalCase。
  • API 文件按模块拆分。
  • 表格列配置尽量靠近页面,不抽成难读的全局配置。

12.2 后端规范

  • 统一使用 kotlinx.serialization DTO。
  • Route 不写复杂业务逻辑。
  • Service 负责事务、业务规则和必要的数据访问。
  • 所有接口返回 ApiResult
  • 所有异常进入统一异常处理。
  • 所有需要权限的接口必须显式声明权限码。
  • 关键操作必须记录操作日志。
  • 新增和修改统一维护审计字段。
  • 删除默认软删除,普通查询默认排除已删除数据。
  • 初始化数据由后端 bootstrap 模块负责,必须可重复执行。
  • 字典和代码枚举边界清晰,安全规则不能依赖可配置字典。
  • 数据库结构先用 Exposed Table 定义表达清楚,正式生产前再补迁移脚本管理机制。

13. 建设顺序

详细建设顺序单独维护在 建设顺序.md

整体分为四期:

  1. 一期:基础后端。
  2. 二期:完整后端。
  3. 三期:基础前端。
  4. 四期:完整前端。