docs: 补充项目设计与环境文档

- 增加产品功能、技术方案与数据库设计说明

- 增加本地中间件环境与联调说明
This commit is contained in:
2026-03-20 12:45:23 +08:00
parent 425d8dd455
commit 74543cb9bf
4 changed files with 1921 additions and 0 deletions

479
docs/产品功能文档.md Normal file
View File

@@ -0,0 +1,479 @@
# 电子名片系统产品功能文档
## 1. 文档目的
本文档用于明确“电子名片 + 多租户后台管理系统”项目的业务目标、角色权限、功能范围、核心流程与交付边界,作为后续产品设计、技术开发、联调测试和验收的统一依据。
## 2. 项目概述
### 2.1 项目定位
本项目面向律师事务所、咨询机构、专业服务组织等“事务所型租户”,提供一套可运营、可配置、可扩展的电子名片系统:
- 前台:微信小程序,用于展示事务所信息、人员名片信息,并提供分享、拨号、导航、加联系人等能力。
- 后台:多租户管理系统,用于平台管理、租户管理、组织管理、用户管理、名片维护、素材管理和数据统计。
- 后端:统一提供租户、用户、名片、文件、统计等 API 服务,支撑小程序与后台管理系统。
### 2.2 业务目标
- 帮助事务所快速搭建统一品牌形象的电子名片体系。
- 帮助租户管理员统一维护事务所、部门、律师/员工信息。
- 帮助普通用户便捷维护个人电子名片,提高对外传播效率。
- 帮助平台方通过多租户能力统一服务多个事务所,降低交付和运维成本。
### 2.3 当前仓库现状
当前仓库已包含微信小程序静态原型,已具备以下页面雏形:
- 律所主页
- 律师列表页
- 律师详情页
- 浏览历史页
现阶段页面主要依赖本地 Mock 数据,后续需改造为对接后端接口的动态数据版本。
## 3. 目标用户与角色定义
### 3.1 角色划分
系统包含 3 类后台角色与 1 类前台访问身份:
| 角色 | 身份说明 | 核心职责 |
| --- | --- | --- |
| 超级管理员 | 平台运营方 | 管理租户、平台账号、平台配置、全局字典、全局监控 |
| 租户管理员 | 某个事务所的管理员 | 管理本租户的组织、人员、事务所资料、名片内容、素材与数据 |
| 普通用户 | 某个事务所下的成员 | 登录后台维护个人名片资料、查看个人数据、预览和分享名片 |
| 小程序访客 | 公众用户 | 浏览事务所主页、查看名片、拨号、保存联系人、导航、分享 |
### 3.2 权限边界
| 功能模块 | 超级管理员 | 租户管理员 | 普通用户 |
| --- | --- | --- | --- |
| 平台登录 | 支持 | 不支持 | 不支持 |
| 租户后台登录 | 可模拟排查 | 支持 | 支持 |
| 租户管理 | 全部 | 无 | 无 |
| 事务所信息维护 | 可查看 | 全部 | 只读 |
| 部门/组织维护 | 可查看 | 全部 | 只读 |
| 用户账号管理 | 全部 | 管理本租户用户 | 仅维护本人登录资料 |
| 角色授权 | 全部 | 分配本租户角色 | 无 |
| 名片信息维护 | 可查看 | 管理本租户全部名片 | 管理本人名片 |
| 素材管理 | 可查看 | 管理本租户素材 | 仅上传/替换本人素材 |
| 统计分析 | 全局 | 本租户 | 本人 |
| 数据隔离 | 平台可见全部 | 仅本租户 | 仅本人/本租户授权范围 |
## 4. 核心业务对象
### 4.1 核心对象
- 租户:一个事务所或公司/组织,是系统中的一级业务单元。
- 组织:租户下的部门、分所、业务组。
- 用户:租户下的可登录成员。
- 名片:用户对外展示的信息载体。
- 事务所主页:租户对外展示的机构简介、地址、专业领域、联系方式等信息。
- 素材:头像、徽标、封面图、二维码、附件等文件。
- 浏览记录:小程序端名片的访问行为数据。
### 4.2 核心关系
- 一个平台可管理多个租户。
- 一个租户可拥有多个组织节点。
- 一个租户可拥有多个用户。
- 一个用户默认对应一张电子名片。
- 一个租户对应一个对外展示主页,可关联多个办公地点、多个专业领域。
## 5. 产品功能范围
## 5.1 微信小程序端
### 5.1.1 律所主页
用于展示事务所品牌与入口信息。
功能点:
- 展示事务所 Logo、名称、封面图、简介
- 展示总部地址、办公地点列表、专业领域标签
- 展示一键跳转“人员列表”
- 展示咨询电话、导航入口
- 支持根据当前小程序绑定的 AppID 加载对应事务所信息
典型页面映射:
- 当前已有静态页面:`pages/firm/index`
### 5.1.2 人员名片列表
用于浏览某个租户下全部可公开展示的成员名片。
功能点:
- 按姓名、办公地点、专业领域搜索
- 按办公机构筛选
- 按专业领域筛选
- 卡片式展示头像、姓名、职务、专业方向
- 点击进入名片详情
- 一键拨打热线或跳转事务所位置
典型页面映射:
- 当前已有静态页面:`pages/lawyer-list/index`
### 5.1.3 个人名片详情
用于展示成员完整的对外名片信息。
功能点:
- 展示姓名、头像、职务、所属事务所/组织、联系方式、地址
- 展示个人简介、专业领域、二维码
- 支持拨打电话
- 支持保存到系统通讯录
- 支持打开地图导航
- 支持查看个人简介弹窗
- 支持分享小程序名片
- 支持记录浏览历史
典型页面映射:
- 当前已有静态页面:`pages/lawyer-detail/index`
### 5.1.4 浏览历史
用于提升回访效率。
功能点:
- 展示最近浏览的名片列表
- 展示浏览时间
- 支持点击再次进入名片
- 支持清空历史
说明:
- 当前原型为本地缓存方案,正式版本升级为“本地缓存 + 服务端埋点统计”双轨制。
典型页面映射:
- 当前已有静态页面:`pages/history/index`
### 5.1.5 分享与传播
功能点:
- 支持微信好友分享
- 支持微信会话卡片传播
- 支持通过二维码进入指定租户主页或指定个人名片页
- 支持在分享链路中保留租户信息与被分享对象信息
### 5.1.6 异常与空状态
功能点:
- 名片不存在提示
- 租户不存在或已停用提示
- 网络异常重试
- 暂无公开成员提示
- 暂无定位/电话/二维码配置提示
## 5.2 后台管理系统
后台管理系统为统一的 Web 管理端,登录后根据角色显示不同菜单与权限。
### 5.2.1 登录与账号体系
功能点:
- 账号密码登录
- 图形验证码
- 登录态续期与退出登录
- 角色鉴权、菜单鉴权、按钮鉴权
- 超级管理员与租户用户使用不同登录入口或同入口分流
- 支持用户首次登录后修改初始密码
- 支持重置密码
扩展项:
- 手机验证码登录
- 微信绑定登录
### 5.2.2 超级管理员端
#### 1. 租户管理
功能点:
- 新增/编辑/禁用租户
- 设置租户名称、编码、联系人、联系电话、状态、到期时间
- 设置租户套餐能力与上限
- 初始化租户管理员账号
- 配置租户对应的小程序 AppID、AppSecret、原始 ID、发布状态
- 查看租户使用情况
#### 2. 平台账号与权限管理
功能点:
- 平台管理员账号管理
- 平台角色管理
- 平台菜单与权限点管理
#### 3. 平台基础配置
功能点:
- 全局字典维护
- 系统参数维护
- 文件存储配置
- 微信小程序基础配置
- 小程序服务器域名、上传域名等平台级配置
#### 4. 租户小程序配置管理
功能点:
- 维护租户与微信小程序的绑定关系
- 配置并校验小程序 AppID 是否唯一
- 维护 AppSecret、原始 ID、名称、版本标记、启用状态
- 查看当前租户小程序配置是否完整
- 为后端公开接口提供 AppID 到租户的映射基础
#### 5. 全局监控与审计
功能点:
- 登录日志
- 操作日志
- 租户状态监控
- 错误告警概览
### 5.2.3 租户管理员端
#### 1. 事务所/公司/组织信息管理
功能点:
- 维护事务所名称、Logo、封面图、简介
- 维护总部地址、经纬度、联系电话
- 维护办公机构列表
- 维护专业领域列表
- 维护对外展示状态
#### 2. 组织架构管理
功能点:
- 部门/分所树维护
- 设置组织负责人
- 组织排序与展示控制
#### 3. 用户管理
功能点:
- 新增/导入/编辑/禁用用户
- 分配组织与角色
- 重置密码
- 设置是否公开展示
- 设置名片排序与推荐位
#### 4. 名片管理
功能点:
- 维护个人基础信息:姓名、职务、手机、邮箱、地址
- 维护个人扩展信息:简介、擅长领域、荣誉、执业证号、社交二维码
- 上传头像、二维码、宣传图
- 预览小程序展示效果
- 控制名片发布状态、上下架状态
#### 5. 素材与文件管理
功能点:
- 上传图片
- 查看图片使用情况
- 删除未引用素材
- 限制文件大小、格式
#### 6. 数据统计
功能点:
- 按用户查看名片浏览量
- 按时间查看访问趋势
- 查看热门名片排行
- 查看分享传播数据
### 5.2.4 普通用户端
普通用户登录后台后,仅维护本人相关信息。
功能点:
- 查看与编辑本人名片
- 上传本人头像、二维码
- 预览本人名片
- 查看本人浏览数据
- 修改密码
## 5.3 通用支撑能力
### 5.3.1 文件上传能力
- 支持头像、Logo、封面、二维码上传
- 支持图片压缩与格式校验
- 支持生成访问 URL
### 5.3.2 日志与审计
- 登录日志
- 操作日志
- 异常日志
- 关键业务日志
### 5.3.3 数据隔离
- 以租户为边界进行数据隔离
- 所有租户业务数据必须带租户归属
- 非平台角色不可跨租户读取和操作数据
### 5.3.4 可配置展示
- 支持控制成员是否公开
- 支持控制字段是否展示
- 支持控制租户主页是否启用
## 6. 核心业务流程
### 6.1 租户开通流程
1. 超级管理员创建租户。
2. 系统生成租户编码与初始租户管理员账号。
3. 超级管理员配置该租户对应的小程序 AppID 与相关参数。
4. 租户管理员首次登录,完善事务所资料。
5. 租户管理员创建组织并导入用户。
6. 用户补充个人名片信息并发布。
7. 小程序开始展示对应租户主页及成员名片。
### 6.2 普通用户名片维护流程
1. 普通用户登录后台。
2. 编辑个人信息、专业领域、联系方式、头像和二维码。
3. 点击保存并预览。
4. 若租户策略要求审核,则进入待审核状态。
5. 审核通过后在小程序端公开展示。
### 6.3 小程序访客浏览流程
1. 用户通过分享链接或二维码进入小程序。
2. 系统根据当前小程序 AppID 识别租户,并根据页面参数识别目标名片。
3. 加载事务所主页或名片详情。
4. 用户执行拨号、加联系人、导航、分享等动作。
5. 系统记录浏览、分享等统计数据。
## 7. 关键数据字段建议
### 7.1 事务所主页字段
- 租户名称
- 英文名称
- Logo
- 封面图
- 简介
- 联系电话
- 总部地址
- 经纬度
- 办公机构列表
- 专业领域列表
- 官网/公众号链接
- 展示状态
### 7.2 个人名片字段
- 用户姓名
- 性别
- 头像
- 职务/头衔
- 所属部门/分所
- 手机号
- 座机
- 邮箱
- 地址
- 擅长领域
- 个人简介
- 执业证号
- 教育/荣誉信息
- 微信二维码
- 名片封面图
- 对外展示状态
- 排序值
## 8. 非功能需求
### 8.1 安全性
- 后台接口必须鉴权
- 密码加密存储
- 操作日志可追溯
- 文件上传类型和大小受控
- 租户数据严格隔离
### 8.2 可用性
- 常规操作响应流畅
- 关键操作具备失败提示
- 网络失败可重试
- 页面需适配主流手机尺寸
### 8.3 可维护性
- 功能模块边界清晰
- 支持租户规模扩展
- 支持后续扩展审核、预约咨询、线索收集等能力
## 9. 版本建议
### 9.1 第一阶段MVP
建议优先落地以下能力:
- 多租户基础能力
- 超级管理员租户管理
- 租户管理员维护事务所与用户
- 普通用户维护本人名片
- 小程序动态化展示事务所主页、列表、详情、历史
- 文件上传
- 基础统计
### 9.2 第二阶段:增强版
- 名片审核流
- Excel 批量导入/导出
- 分享海报/专属二维码
- 数据大屏与更细粒度统计
- 微信绑定登录
- 消息通知
## 10. 验收标准
### 10.1 业务验收
- 可创建多个租户,且数据互不串扰
- 超级管理员可管理租户
- 租户管理员可管理本租户事务所信息和用户
- 普通用户可编辑本人名片
- 小程序可按租户维度展示对应事务所与用户名片
- 小程序动作能力可正常使用:拨号、分享、导航、加联系人
### 10.2 体验验收
- 页面信息完整、结构清晰
- 搜索/筛选结果正确
- 空状态、错误状态、无权限状态提示明确
- 后台操作路径简洁,表单校验清晰
## 11. 后续开发原则
- 先完成“可用且正确”的多租户闭环,再逐步增加高级能力。
- 先保证租户、用户、名片、展示四条主链路打通,再扩展统计、审核、营销。
- 小程序与后台字段模型保持统一,避免前后端重复定义和语义不一致。

844
docs/技术文档.md Normal file
View File

@@ -0,0 +1,844 @@
# 电子名片系统技术文档
## 1. 文档目标
本文档用于定义本项目的技术架构、技术栈、中间件、数据隔离策略、部署方案与工程结构,目标是在满足 `JDK 21 + Spring Boot + Vue 3 + TypeScript` 约束下,实现一套轻量、稳定、易扩展的多租户电子名片系统。
## 2. 技术设计原则
- 正确性优先:先保证多租户隔离、权限控制、数据一致性和关键链路稳定。
- 轻量优先:优先采用单体模块化架构,避免过早拆分微服务。
- 稳定优先:使用成熟、社区活跃、可持续维护的主流组件。
- 扩展优先:模块边界清晰,为后续审核流、线索、预约、营销等功能预留能力。
## 3. 总体架构
系统由 3 个前后端子系统组成:
1. 后端服务:统一提供租户、账号、名片、文件、统计等业务接口。
2. 后台管理端:供超级管理员、租户管理员、普通用户登录管理数据。
3. 微信小程序:面向公众展示事务所与个人电子名片。
说明:
- 后台系统为多租户统一平台。
- 微信小程序按“1 个租户 = 1 个小程序 AppID”设计每个事务所拥有独立小程序。
- 多个租户的小程序可复用同一套后端服务与同一套代码模板,通过配置完成租户绑定。
```mermaid
flowchart LR
A["超级管理员 / 租户管理员 / 普通用户"] --> B["后台管理端 Vue3 + TS"]
C["微信访客"] --> D["微信小程序"]
B --> E["Spring Boot API"]
D --> E
E --> F["MySQL 8"]
E --> G["Redis"]
E --> H["MinIO"]
E --> I["日志/监控"]
```
## 4. 推荐工程结构
建议在当前仓库基础上扩展为如下结构:
```text
easycard/
├─ docs/ # 产品/技术/接口/部署文档
├─ backend/ # Spring Boot 后端
│ ├─ easycard-boot/ # 启动模块
│ ├─ easycard-common/ # 通用基础能力
│ ├─ easycard-module-system/ # 系统管理、权限、日志
│ ├─ easycard-module-tenant/ # 多租户管理
│ ├─ easycard-module-org/ # 组织/事务所信息
│ ├─ easycard-module-user/ # 用户与账号
│ ├─ easycard-module-card/ # 名片管理
│ ├─ easycard-module-file/ # 文件上传与素材管理
│ └─ easycard-module-stat/ # 浏览与分享统计
├─ admin-web/ # Vue3 后台管理端
└─ frontend_miniprogram/ # 微信小程序
```
说明:
- 当前仓库已存在 `frontend_miniprogram/`,后续应保持为独立子项目。
- 后端采用“单体应用 + 模块化分层”方案,控制复杂度,同时便于后续拆分。
## 5. 技术栈选型
## 5.1 后端技术栈
| 分类 | 选型 | 说明 |
| --- | --- | --- |
| JDK | JDK 21 | 满足长期支持版本要求 |
| 框架 | Spring Boot 3.3.x | 稳定、生态成熟 |
| Web | Spring MVC | 提供 REST API |
| 参数校验 | Spring Validation | 请求参数校验 |
| ORM | MyBatis-Plus | 开发效率高,适合后台管理型系统 |
| 数据库 | MySQL 8.0 | 成熟稳定,部署简单 |
| 缓存 | Redis 7 | 缓存、会话、验证码、热点数据 |
| 鉴权 | Spring Security 6 + JWT | 标准化、安全性强、扩展性好 |
| 对象存储 | MinIO | 轻量、私有化友好,可替换云 OSS |
| 数据迁移 | Flyway | 管理数据库版本与初始化脚本 |
| API 文档 | springdoc-openapi + Knife4j | 自动生成接口文档,方便联调 |
| 日志 | Logback | 默认稳定方案 |
| 对象映射 | MapStruct | 降低 DTO/VO 转换样板代码 |
| 构建 | Maven | Java 生态成熟、稳定 |
| 测试 | JUnit 5 + Spring Boot Test + Testcontainers | 保证接口与数据库集成质量 |
### 5.1.1 为什么不优先使用微服务
当前场景的核心复杂度在于:
- 多租户隔离
- 角色权限控制
- 小程序与后台双端联动
- 名片内容与文件管理
这些问题本质上更适合“模块化单体”优先解决。若过早拆分为微服务,会明显增加:
- 部署复杂度
- 联调成本
- 配置和监控成本
- 分布式事务与调用链复杂度
因此第一阶段推荐单体架构,待租户数量、访问量和团队规模增长后,再按模块拆分。
## 5.2 后台管理端技术栈
| 分类 | 选型 | 说明 |
| --- | --- | --- |
| 框架 | Vue 3 | 主流稳定 |
| 语言 | TypeScript | 类型安全 |
| 构建工具 | Vite | 启动与构建速度快 |
| 路由 | Vue Router | 标准路由方案 |
| 状态管理 | Pinia | 轻量清晰 |
| UI 组件库 | Element Plus | 适合中后台、生态成熟 |
| 请求库 | Axios | 简洁稳定 |
| 样式 | SCSS + CSS Variables | 可维护、便于主题化 |
| 表格/表单增强 | Element Plus 原生能力优先 | 减少额外依赖 |
| 图表 | ECharts | 用于统计分析页 |
## 5.3 微信小程序技术栈
| 分类 | 选型 | 说明 |
| --- | --- | --- |
| 框架 | 原生微信小程序 | 当前仓库已采用 |
| 语言 | TypeScript | 已有基础 |
| 样式 | Less | 当前仓库已采用 |
| 数据请求 | 封装 `wx.request` | 简洁稳定,避免引入额外运行时 |
| 本地缓存 | `wx.setStorageSync` / `wx.getStorageSync` | 用于轻量本地状态,如浏览历史 |
说明:
- 当前小程序已有静态页面和 Mock 数据,后续改造重点是抽离 API 层、租户配置、环境变量管理和错误处理。
- 本项目按“一个小程序对应一个租户”设计,小程序内不再依赖页面参数动态切换租户。
- 小程序租户识别以 `AppID` 为主键,后台需维护 `AppID -> tenant_id` 的映射配置。
## 6. 核心架构设计
## 6.1 多租户模型
第一阶段推荐使用:
- 共享数据库
- 共享数据表结构
- 业务表统一增加 `tenant_id`
该方案优点:
- 成本低
- 开发快
- 部署简单
- 适合中小规模 SaaS
需要重点保证:
- 所有租户业务表都必须带 `tenant_id`
- 查询默认按 `tenant_id` 过滤
- 非平台角色不可跨租户访问
- 日志中要记录操作人、租户、操作对象
补充说明:
- 多租户主要体现在后台管理端和后端数据层。
- 小程序虽然是“一租户一 AppID”但后端仍是统一多租户服务公开接口和管理接口都需要具备租户隔离能力。
### 6.1.1 表分类建议
平台级表:
- `sys_tenant`
- `sys_platform_user`
- `sys_platform_role`
- `sys_menu`
- `sys_dict`
- `tenant_miniapp_config`
租户级表:
- `tenant_user`
- `tenant_role`
- `tenant_user_role`
- `org_department`
- `org_firm_profile`
- `card_profile`
- `file_asset`
- `card_view_stat`
- `operation_log`
### 6.1.2 未来扩展策略
当单租户数据量或安全要求显著上升时,可平滑扩展为:
- 大租户独立数据库
- 普通租户共享数据库
为此后端需抽象租户上下文与数据访问入口,不把 `tenant_id` 获取逻辑写死在业务代码中。
### 6.1.3 小程序与租户绑定模型
本项目推荐采用:
- 后台:多租户统一平台
- 小程序:一个租户对应一个微信小程序 AppID
- 后端:统一一套服务,按小程序配置映射到具体租户
该模式的优点:
- 每个事务所有独立品牌入口,体验更清晰
- 不需要在小程序页面参数中显式传递 `tenantCode`
- 可直接以小程序 `AppID` 作为租户识别主键
- 每个租户可独立发布、独立审核、独立配置微信能力
- 后端仍可复用统一业务代码和统一数据库结构
需要接受的代价:
- 每增加一个租户,就需要新增一个小程序 AppID
- 小程序发布、审核、备案、类目维护成本会随租户数量线性增加
- 构建与配置管理需要支持按租户生成不同发行包
## 6.2 权限模型
推荐采用 RBAC 模型:
- 用户
- 角色
- 菜单
- 按钮权限点
- 数据范围
角色建议:
- `PLATFORM_SUPER_ADMIN`
- `TENANT_ADMIN`
- `TENANT_USER`
权限控制分 3 层:
1. 接口层:校验是否登录、是否具备角色/权限。
2. 服务层:校验数据归属与业务状态。
3. 数据层:统一追加租户过滤条件。
## 6.3 登录认证设计
### 6.3.1 后台管理端
采用 `JWT Access Token + Redis` 组合:
- 登录成功后签发短期 Access Token
- Redis 记录登录会话、验证码和黑名单
- 退出登录时清理 Redis 中的会话信息
这样做的原因:
- 便于水平扩容
- 比传统服务端 Session 更适合前后端分离
- Redis 介入后可控制踢下线、单点登录、风控扩展
### 6.3.2 微信小程序
小程序端建议区分两类访问:
- 公开访问:无需登录,可浏览公开名片
- 成员访问:后续如需在小程序维护本人名片,可通过微信登录绑定用户
第一阶段的最简实现:
- 小程序仅做公开展示
- 每个小程序在构建时写入固定 `AppID` 配置
- 小程序启动后直接读取当前租户配置并调用公开接口
若后续要支持小程序内登录:
- 前端调用 `wx.login()`
- 后端调用微信 `code2Session`
-`openid/unionId` 与系统用户绑定
### 6.3.3 小程序如何确定对应租户
由于本项目采用“一个小程序对应一个租户”的模式,因此租户识别以微信小程序 `AppID` 为主,不再依赖页面参数中的 `tenantCode`
推荐落地方式如下:
#### 1. 租户配置表维护小程序信息
建议新增配置表或配置字段:
- `tenant_id`
- `tenant_code`
- `miniapp_app_id`
- `miniapp_app_secret`
- `miniapp_name`
- `miniapp_original_id`
- `request_domain`
- `publish_status`
其中:
- `miniapp_app_id` 是当前方案中的租户识别主键
- `miniapp_app_secret` 仅后端保存,必须加密存储
- `request_domain` 用于约束该小程序实际访问的接口域名,可作为辅助校验项
后台管理端需要新增“小程序配置”功能,至少支持:
- 为租户录入和修改 `AppID`
- 配置 `AppSecret`
- 校验 `AppID` 全平台唯一
- 启停用小程序配置
- 查询当前租户是否已完成小程序配置
#### 2. 小程序构建时注入固定租户配置
每个租户的小程序发行包包含固定配置,例如:
```ts
export const tenantRuntimeConfig = {
appId: 'wx1234567890xxxxxx',
apiBaseUrl: 'https://api.example.com',
}
```
说明:
- `appId` 是前端运行时的固定配置
- 同一个租户的小程序所有页面默认只访问本租户数据
- 不允许在小程序内切换到其他租户
#### 3. 后端接口通过租户上下文处理公开请求
公开接口建议改为以下风格:
- `/api/open/profile`
- `/api/open/cards`
- `/api/open/card/{cardId}`
- `/api/open/card/{cardId}/view`
- `/api/open/card/{cardId}/share`
即:
- 小程序端不需要在路径中传 `tenantCode`
- 后端通过 `AppID` 识别当前租户
#### 4. 请求上下文的识别策略
推荐策略如下:
1. 小程序请求时显式传递 `X-Miniapp-Appid`
2. Spring Boot 在过滤器中解析 `X-Miniapp-Appid`
3. 后端查询 `tenant_miniapp_config` 获取对应 `tenant_id`
4.`tenant_id` 写入 `TenantContext`
5. 后续查询统一按 `tenant_id` 过滤
请求示例:
```http
GET /api/v1/open/profile
X-Miniapp-Appid: wx1234567890xxxxxx
```
对应的服务端逻辑:
```text
X-Miniapp-Appid -> tenant_miniapp_config -> tenant_id -> TenantContext
```
说明:
- 虽然 `X-Miniapp-Appid` 由前端传入,但其值来自构建时固定配置,不是页面动态参数
- `request_domain` 可作为辅助白名单校验,避免错误小程序配置访问非目标域名
- 对登录态接口和管理接口,仍必须叠加 token 与权限校验,不能只依赖 `AppID`
这种方式的优点是:
- 实现简单,适合当前单租户小程序模式
- 后端租户识别统一
- 与微信登录场景天然兼容,便于后续通过 `AppID + AppSecret` 调用 `code2Session`
#### 5. 管理端与小程序的数据边界
需要明确:
- 小程序公开接口只返回“已发布、允许公开”的租户信息和名片信息
- 即使攻击者伪造请求,也只能尝试访问公开数据,不应接触后台管理数据
- 后台管理接口仍然必须基于登录态、角色和 `tenant_id` 做严格隔离
#### 6. 构建与发布策略
一个租户一个小程序,建议采用“同一套源码,多套租户配置”的方式发布:
- 公共源码只维护一套
- 每个租户维护一份环境配置
- 打包时选择目标租户配置生成对应小程序包
建议配置文件结构:
```text
frontend_miniprogram/
├─ config/
│ ├─ tenants/
│ │ ├─ dev.default.ts
│ │ ├─ prod.nj_xx_law.ts
│ │ └─ prod.sample.ts
```
这样可以保证:
- 代码复用
- 配置隔离
- 发版过程可控
#### 7. 结论
在“一个小程序对应一个租户”的前提下,小程序识别租户的核心是:
- 小程序 `AppID`
- 后台维护的 `AppID -> tenant_id` 映射关系
- 小程序请求头中的 `X-Miniapp-Appid`
后端则通过统一的租户上下文机制,把请求路由到正确的租户数据范围。
## 6.4 文件存储设计
使用 MinIO 统一管理:
- 租户 Logo
- 用户头像
- 名片二维码
- 封面图
建议做法:
- 按业务分桶或目录管理
- 保存原始文件名、MIME、大小、哈希值
- 生成缩略图或压缩图
- 通过业务表引用文件 ID而非直接在业务表中散落 URL
## 6.5 统计设计
统计范围:
- 名片浏览次数
- 名片分享次数
- 热门名片排行
- 按日趋势统计
第一阶段建议方案:
- 实时写入行为日志
- 定时汇总到统计表
这样可以兼顾:
- 原始数据可追溯
- 查询统计页更高效
## 7. 分层设计
后端建议遵循以下分层:
- Controller参数接收、鉴权注解、响应封装
- Service业务编排、事务控制、权限校验
- Domain/Manager核心领域规则
- Mapper数据库访问
- DTO/VO输入输出模型
统一规范:
- 禁止 Controller 直接编写复杂业务逻辑
- 禁止 Service 直接暴露数据库实体给前端
- 输入输出对象分离,避免前端字段误改
## 8. API 设计建议
## 8.1 接口风格
- 统一 RESTful 风格
- 统一响应结构:`code``message``data`
- 列表接口统一支持分页
- 查询接口统一支持关键字、状态、时间区间筛选
## 8.2 接口分组建议
平台端:
- `/api/platform/auth/*`
- `/api/platform/tenants/*`
- `/api/platform/users/*`
- `/api/platform/config/*`
租户后台:
- `/api/tenant/auth/*`
- `/api/tenant/firm/*`
- `/api/tenant/org/*`
- `/api/tenant/users/*`
- `/api/tenant/cards/*`
- `/api/tenant/files/*`
- `/api/tenant/stats/*`
小程序公开端:
- `/api/open/profile`
- `/api/open/cards`
- `/api/open/card/{cardId}`
- `/api/open/card/{cardId}/view`
- `/api/open/card/{cardId}/share`
## 8.3 版本管理
建议从一开始就保留版本前缀:
- `/api/v1/...`
这样便于未来做不兼容升级。
## 9. 数据库设计建议
## 9.1 核心表
建议第一阶段至少包含以下核心表:
- `sys_tenant`:租户信息
- `tenant_miniapp_config`:租户与小程序配置映射
- `sys_user`:登录用户
- `sys_role`:角色
- `sys_user_role`:用户角色关系
- `org_department`:部门/分所
- `org_firm_profile`:事务所主页信息
- `card_profile`:个人名片主表
- `card_specialty`:名片专业领域
- `file_asset`:文件素材
- `card_view_log`:名片浏览日志
- `card_share_log`:名片分享日志
- `card_stat_daily`:名片按日统计表
- `sys_login_log`:登录日志
- `sys_operation_log`:操作日志
## 9.2 通用字段规范
每个业务表建议统一包含:
- `id`
- `tenant_id`
- `created_by`
- `created_time`
- `updated_by`
- `updated_time`
- `deleted`
说明:
- 平台级表可不包含 `tenant_id`
- 删除建议优先逻辑删除,关键日志表使用物理追加
### 9.3 小程序配置表建议
建议新增 `tenant_miniapp_config` 表,用于描述租户与微信小程序的绑定关系。
建议字段:
- `id`
- `tenant_id`
- `miniapp_app_id`
- `miniapp_app_secret`
- `miniapp_name`
- `miniapp_original_id`
- `request_domain`
- `version_tag`
- `publish_status`
- `created_time`
- `updated_time`
用途说明:
- 后台超级管理员或平台实施人员配置租户对应的小程序信息
- 后端在微信登录、发布管理、AppID 识别时使用该表
- 后续若增加多个环境,可在该表中扩展 `env` 字段区分测试和生产配置
约束建议:
- `miniapp_app_id` 全局唯一
- `tenant_id``miniapp_app_id` 建立唯一映射
- `miniapp_app_secret` 必须加密存储,不向前端返回
## 10. 部署方案
## 10.1 部署目标
目标是“轻量、稳定、可私有化部署”,推荐采用 Docker Compose 作为首期部署方式。
## 10.2 推荐中间件
| 组件 | 版本建议 | 用途 |
| --- | --- | --- |
| Nginx | 1.26+ | 反向代理、静态资源分发 |
| JDK | 21 | 运行 Spring Boot |
| MySQL | 8.0 | 主数据库 |
| Redis | 7 | 缓存与会话 |
| MinIO | 最新稳定版 | 文件存储 |
## 10.2.1 服务器配置建议
本项目第一阶段目标是“轻量、稳定、可扩展”,因此不建议一开始就采购过重的集群资源。推荐按环境和业务规模分层配置。
### 1. 开发环境
适用场景:
- 本地开发
- 单人或小团队联调
建议配置:
- CPU4 核
- 内存8 GB
- 系统盘100 GB SSD
部署建议:
- MySQL、Redis、MinIO 可通过 Docker Desktop 或本机服务运行
- 后端、后台前端、小程序开发工具本地启动
### 2. 测试环境
适用场景:
- 功能测试
- 接口联调
- UAT 验收
建议配置:
- CPU4 核
- 内存8 GB 到 16 GB
- 系统盘100 GB SSD
- 数据盘100 GB SSD
部署建议:
- 单台 Linux 服务器部署 `Nginx + Spring Boot + MySQL + Redis + MinIO`
- 使用 Docker Compose 管理服务,便于迁移和重建环境
### 3. 生产环境当前推荐
适用场景:
- 仅服务 1 家事务所
- 约 20 名后台用户
- 小程序访问量较低到中等
- 以名片展示、资料维护、图片上传为主
建议配置:
- CPU4 核
- 内存8 GB
- 系统盘50 GB SSD
- 数据盘100 GB SSD
- 带宽3 Mbps 到 5 Mbps
部署方式:
- 单机部署
- 使用 Docker Compose 部署 `Nginx + Spring Boot + MySQL + Redis + MinIO`
说明:
- 这是当前项目规模下更匹配的正式生产配置
- 对于 1 家事务所、20 名用户,该配置已能覆盖日常访问和后台维护需求
- 若图片、二维码、封面素材不多,`50 GB 系统盘 + 100 GB 数据盘` 基本足够
- MinIO、MySQL 数据目录建议挂载到数据盘,避免挤占系统盘
### 4. 容量规划建议
磁盘容量建议重点考虑以下部分:
- MySQL 数据量
- MinIO 文件素材
- 日志文件
- 数据库备份
经验建议:
- 当前项目规模下,初期生产环境总可用磁盘 150 GB 左右即可起步
- 若头像、二维码、宣传海报较多,可将数据盘扩展到 200 GB
- 数据库与对象存储应避免共用过小系统盘
### 5. 本项目首期推荐结论
按照当前明确范围:
- 1 家事务所
- 约 20 名用户
- 单租户使用
推荐采用以下生产配置:
- 1 台 4 核 8 GB Linux 云服务器
- 1 块 50 GB 系统盘
- 1 块 100 GB 数据盘
- 3 Mbps 到 5 Mbps 带宽
- Docker Compose 部署 `Nginx + Spring Boot + MySQL + Redis + MinIO`
如果希望多留一些冗余,可升级为:
- 1 台 4 核 16 GB 或 8 核 8 GB Linux 云服务器
- 数据盘提升到 200 GB
当前规模下,不需要一开始就做多机、主从或集群部署。
## 10.3 部署拓扑
```mermaid
flowchart TB
U["浏览器 / 微信小程序"] --> N["Nginx"]
N --> A["admin-web 静态站点"]
N --> B["backend API"]
B --> C["MySQL"]
B --> D["Redis"]
B --> E["MinIO"]
```
## 10.4 环境划分
建议至少划分 3 套环境:
- `dev`:本地开发环境
- `test`:测试联调环境
- `prod`:生产环境
每套环境均需独立配置:
- 数据库连接
- Redis 地址
- 对象存储地址
- JWT 密钥
- 微信小程序配置
补充说明:
- 由于采用“一租户一小程序”,生产环境需要为每个租户维护独立的小程序生产配置
- 测试环境可使用测试小程序 AppID 或体验版配置
## 10.5 配置管理
建议采用:
- Spring Profiles 区分环境
- 前端使用 `.env.development``.env.test``.env.production`
- 敏感配置通过环境变量注入,不写死在仓库
## 10.6 发布方式
推荐发布步骤:
1. 后端 Maven 打包为可执行 Jar。
2. 后台管理端 Vite 构建后部署到 Nginx 静态目录。
3. 选择目标租户的小程序配置,构建对应发行包。
4. 小程序通过微信开发者工具上传发布到该租户对应的小程序账号。
5. 数据库通过 Flyway 自动迁移到目标版本。
小程序发布补充要求:
- 每个租户需独立维护小程序 AppID、类目、服务器域名和上传主体信息
- 发布前需校验当前构建包是否使用了正确的租户配置
- 建议在后台配置中记录当前租户对应的小程序版本号和发布时间
- 后端在生产环境中以 `AppID` 作为公开接口租户识别的主键
### 10.6.1 Flyway 迁移约定
后端建议使用以下目录承载迁移脚本:
- [db/migration/mysql](/Users/slience/postgraduate/easycard/backend/easycard-boot/src/main/resources/db/migration/mysql)
首批迁移建议:
- `V1__create_core_schema.sql`:创建核心表结构
- `V2__seed_platform_base_data.sql`:初始化平台角色、菜单和字典
约束:
- 不回改已上线版本脚本
- 所有字段变更、新表、新索引均追加新版本
- 租户级默认数据在业务代码的“创建租户”流程中初始化,不直接写入平台基线迁移
## 11. 可观测性与运维
第一阶段建议最少落地以下能力:
- 应用日志滚动归档
- 登录日志与操作日志
- API 错误日志
- 文件上传失败日志
- 慢 SQL 排查
若进入正式商用阶段,建议增加:
- Prometheus + Grafana
- Spring Boot Actuator
- 异常告警通知
## 12. 安全设计
必须满足以下安全要求:
- 密码使用强哈希算法存储
- JWT 密钥与数据库密码不得入库明文
- 所有后台接口进行登录与权限校验
- 文件上传限制扩展名、大小与 MIME
- 公开接口做基础限流
- 防止越权读取其他租户数据
- 敏感操作写入审计日志
## 13. 开发实施建议
建议按以下顺序推进开发:
1. 先搭建后端基础框架、权限框架、租户框架、数据库脚手架。
2. 再完成后台管理端登录、租户管理、事务所管理、用户管理、名片管理。
3. 最后将微信小程序从 Mock 数据切换为真实接口,并补齐统计与异常处理。
## 14. 第一阶段交付清单
第一阶段建议交付内容如下:
- 后端基础框架与数据库脚本
- 超级管理员租户管理
- 租户管理员事务所管理、用户管理、名片管理
- 普通用户个人名片维护
- 小程序主页、列表、详情、历史动态化
- 文件上传
- 浏览统计
- 接口文档
- Docker Compose 部署文件
## 15. 技术结论
结合当前需求与仓库现状,推荐采用:
- 后端:`JDK 21 + Spring Boot 3.3 + Spring Security + MyBatis-Plus + MySQL + Redis + MinIO + Flyway`
- 后台:`Vue 3 + TypeScript + Vite + Pinia + Element Plus`
- 小程序:`原生微信小程序 + TypeScript + Less + 一租户一 AppID 的租户配置方案`
- 部署:`Nginx + Docker Compose`
该方案在复杂度、交付速度、稳定性、私有化友好程度和后续扩展能力之间较为均衡,适合作为本项目第一阶段正式落地方案。后台统一多租户,小程序按租户独立发布,二者职责边界清晰,便于实施和运营。

View File

@@ -0,0 +1,432 @@
# 电子名片系统数据库设计文档
## 1. 文档目标
本文档用于固定电子名片系统第一阶段的数据库模型,覆盖多租户后台、小程序 `AppID` 绑定、组织/用户/名片、素材、统计、审计等核心模块,并与当前产品文档、技术文档保持一致。
对应初始化脚本:
- [easycard_init.sql](/Users/slience/postgraduate/easycard/database/mysql/easycard_init.sql)
- [V1__create_core_schema.sql](/Users/slience/postgraduate/easycard/backend/easycard-boot/src/main/resources/db/migration/mysql/V1__create_core_schema.sql)
- [V2__seed_platform_base_data.sql](/Users/slience/postgraduate/easycard/backend/easycard-boot/src/main/resources/db/migration/mysql/V2__seed_platform_base_data.sql)
## 2. 设计原则
### 2.1 总体原则
- 数据库MySQL 8.x
- 字符集:`utf8mb4`
- 排序规则:`utf8mb4_0900_ai_ci`
- 架构模式:单库单 Schema多租户共享表结构
- 多租户隔离:业务表统一使用 `tenant_id`
- 小程序租户识别:使用 `miniapp_app_id` 映射到 `tenant_id`
### 2.2 关键约束
- 平台级数据使用 `tenant_id = 0`
- 租户业务数据必须带 `tenant_id > 0`
- 小程序 `AppID` 全平台唯一
- 一个租户在同一环境仅允许一条小程序配置
- 用户、角色、组织编码、专业领域编码等按租户唯一
### 2.3 删除策略
- 核心业务表默认使用逻辑删除字段 `deleted`
- 日志和统计明细表默认不做逻辑删除
- 需要唯一约束的业务表,唯一索引统一带上 `deleted`
### 2.4 主键策略
第一阶段采用:
- `BIGINT UNSIGNED AUTO_INCREMENT`
原因:
- 对当前规模足够简单稳定
- 便于直接落地和排查问题
- 后续如需分布式 ID可在应用层平滑切换
### 2.5 外键策略
第一阶段不强依赖数据库物理外键,采用“应用层维护逻辑关联 + 数据库索引约束”的方式。
原因:
- 更适合多租户共享表结构
- 更利于后续表结构演进
- 避免逻辑删除和历史日志场景下的迁移成本
## 3. 核心实体关系
```mermaid
erDiagram
SYS_TENANT ||--o{ TENANT_MINIAPP_CONFIG : has
SYS_TENANT ||--o{ SYS_USER : owns
SYS_TENANT ||--o{ SYS_ROLE : owns
SYS_TENANT ||--o{ ORG_DEPARTMENT : owns
SYS_TENANT ||--|| ORG_FIRM_PROFILE : owns
SYS_TENANT ||--o{ ORG_FIRM_PRACTICE_AREA : owns
SYS_TENANT ||--o{ CARD_PROFILE : owns
SYS_TENANT ||--o{ FILE_ASSET : owns
SYS_USER ||--o{ SYS_USER_ROLE : has
SYS_ROLE ||--o{ SYS_USER_ROLE : assigned
SYS_ROLE ||--o{ SYS_ROLE_MENU : grants
SYS_MENU ||--o{ SYS_ROLE_MENU : bound
ORG_DEPARTMENT ||--o{ SYS_USER : contains
SYS_USER ||--|| CARD_PROFILE : owns
CARD_PROFILE ||--o{ CARD_PROFILE_SPECIALTY : has
ORG_FIRM_PRACTICE_AREA ||--o{ CARD_PROFILE_SPECIALTY : references
FILE_ASSET ||--o{ FILE_ASSET_USAGE : used_by
CARD_PROFILE ||--o{ CARD_VIEW_LOG : viewed
CARD_PROFILE ||--o{ CARD_SHARE_LOG : shared
CARD_PROFILE ||--o{ CARD_STAT_DAILY : aggregated
```
## 4. 模块划分
### 4.1 平台与租户
- `sys_tenant`
- `tenant_miniapp_config`
- `sys_config`
### 4.2 账号与权限
- `sys_user`
- `sys_role`
- `sys_user_role`
- `sys_menu`
- `sys_role_menu`
### 4.3 基础字典
- `sys_dict_type`
- `sys_dict_item`
### 4.4 组织与事务所信息
- `org_department`
- `org_firm_profile`
- `org_firm_practice_area`
### 4.5 名片与素材
- `card_profile`
- `card_profile_specialty`
- `file_asset`
- `file_asset_usage`
### 4.6 统计与审计
- `card_view_log`
- `card_share_log`
- `card_stat_daily`
- `sys_login_log`
- `sys_operation_log`
## 5. 关键表设计说明
## 5.1 `sys_tenant`
用途:
- 平台租户主表
- 管理事务所基础信息、到期时间、资源上限、启停用状态
关键字段:
- `tenant_code`:租户编码,平台唯一
- `tenant_name`:租户名称
- `tenant_status``ENABLED / DISABLED / EXPIRED`
- `user_limit`:用户上限
- `storage_limit_mb`:素材存储空间上限
## 5.2 `tenant_miniapp_config`
用途:
- 维护租户与微信小程序的映射关系
- 后端通过 `miniapp_app_id` 识别租户
关键字段:
- `tenant_id`
- `env_code``DEV / TEST / PROD`
- `miniapp_app_id`
- `miniapp_app_secret`
- `miniapp_original_id`
- `request_domain`
- `publish_status``UNCONFIGURED / DRAFT / PUBLISHED / DISABLED`
关键约束:
- `miniapp_app_id` 全局唯一
- `tenant_id + env_code + deleted` 唯一
## 5.3 `sys_user`
用途:
- 平台用户与租户用户统一账号表
关键字段:
- `tenant_id`:平台用户固定为 `0`
- `user_type``PLATFORM / TENANT`
- `username`
- `password_hash`
- `dept_id`
- `user_status``ENABLED / DISABLED / LOCKED`
- `must_update_password`
关键约束:
- `tenant_id + username + deleted` 唯一
## 5.4 `sys_role`
用途:
- 平台角色和租户角色统一管理
关键字段:
- `role_scope``PLATFORM / TENANT`
- `role_code`
- `role_name`
- `data_scope``ALL / TENANT / DEPT / SELF`
- `is_builtin`
关键约束:
- `tenant_id + role_code + deleted` 唯一
补充说明:
- 平台初始化脚本仅预置平台超级管理员角色
- `TENANT_ADMIN``TENANT_USER` 这类租户内置角色,应在“创建租户”流程中按租户自动生成
## 5.5 `org_department`
用途:
- 表示总部、分所、部门、业务组等组织树
关键字段:
- `parent_id`
- `dept_type``HEADQUARTERS / BRANCH / DEPARTMENT / GROUP`
- `dept_code`
- `dept_name`
- `leader_user_id`
- `display_order`
说明:
- 小程序前端展示办公机构列表时,可直接读取 `HEADQUARTERS / BRANCH` 类型节点
## 5.6 `org_firm_profile`
用途:
- 事务所对外展示主信息
关键字段:
- `firm_name`
- `firm_short_name`
- `logo_asset_id`
- `hero_asset_id`
- `intro`
- `hotline_phone`
- `hq_address`
- `hq_latitude`
- `hq_longitude`
关键约束:
- 一个租户仅允许一条有效事务所主页记录
## 5.7 `org_firm_practice_area`
用途:
- 租户级专业领域字典
关键字段:
- `area_code`
- `area_name`
- `display_order`
- `area_status`
## 5.8 `card_profile`
用途:
- 用户电子名片主表
关键字段:
- `user_id`
- `card_name`
- `card_title`
- `mobile`
- `email`
- `avatar_asset_id`
- `wechat_qr_asset_id`
- `bio`
- `certificate_no`
- `education_info`
- `honor_info`
- `is_public`
- `publish_status`
- `display_order`
- `view_count`
- `share_count`
关键约束:
- 一个用户默认一张名片,`tenant_id + user_id + deleted` 唯一
## 5.9 `card_profile_specialty`
用途:
- 名片与专业领域的关联表
说明:
- 保留 `specialty_name` 快照,避免租户修改专业领域名称后历史展示失真
## 5.10 `file_asset`
用途:
- 管理头像、Logo、封面图、二维码等素材
关键字段:
- `storage_provider`
- `bucket_name`
- `object_key`
- `original_name`
- `file_ext`
- `mime_type`
- `file_size`
- `file_hash`
- `access_url`
- `asset_status`
## 5.11 `file_asset_usage`
用途:
- 记录素材被哪个业务对象引用
- 支持后台查看图片使用情况
关键字段:
- `asset_id`
- `biz_type`
- `biz_id`
- `field_name`
## 5.12 `card_view_log` / `card_share_log` / `card_stat_daily`
用途:
- `card_view_log`:原始浏览明细
- `card_share_log`:原始分享明细
- `card_stat_daily`:按日聚合统计
说明:
- 原始明细用于追溯
- 聚合表用于后台统计查询
## 5.13 `sys_login_log` / `sys_operation_log`
用途:
- 平台与租户后台的登录审计
- 关键业务操作审计
说明:
- 这两张表是安全审计与问题排查的基础,不建议省略
## 6. 状态字段建议值
### 6.1 租户状态
- `ENABLED`
- `DISABLED`
- `EXPIRED`
### 6.2 用户状态
- `ENABLED`
- `DISABLED`
- `LOCKED`
### 6.3 小程序发布状态
- `UNCONFIGURED`
- `DRAFT`
- `PUBLISHED`
- `DISABLED`
### 6.4 名片发布状态
- `DRAFT`
- `PUBLISHED`
- `OFFLINE`
### 6.5 文件状态
- `UPLOADED`
- `ACTIVE`
- `ARCHIVED`
- `DELETED`
## 7. 索引设计原则
- 所有高频业务表统一创建 `tenant_id` 索引
- 所有按编码查找的字段创建唯一索引或普通索引
- 行为日志按 `tenant_id + card_id + 时间` 建索引
- 聚合统计表按 `tenant_id + stat_date``tenant_id + card_id + stat_date` 建索引
## 8. 初始化脚本说明
初始化脚本文件:
- [easycard_init.sql](/Users/slience/postgraduate/easycard/database/mysql/easycard_init.sql)
- [Flyway 迁移目录](/Users/slience/postgraduate/easycard/backend/easycard-boot/src/main/resources/db/migration/mysql/README.md)
脚本内容包含:
- 数据库创建
- 全部核心表 DDL
- 索引与唯一约束
- 默认平台角色初始化
- 默认基础菜单初始化
- 默认字典类型与字典项初始化
Flyway 版本化脚本拆分为:
- `V1__create_core_schema.sql`:只负责建表和索引
- `V2__seed_platform_base_data.sql`:只负责平台级基础数据
## 9. 后续扩展建议
当项目进入第二阶段,可在当前模型上继续扩展:
- 名片审核表
- 微信用户绑定表
- Excel 导入任务表
- 消息通知表
- 线索与咨询记录表
第一阶段不建议提前引入过多非核心表,优先保证主链路稳定。

View File

@@ -0,0 +1,166 @@
# 本地容器环境说明
## 1. 目标
本文档说明如何在本机通过 Docker Compose 快速启动电子名片项目所需的完整容器环境。
当前提供的服务包括:
- MySQL 8.0
- Redis 7
- MinIO
- Spring Boot 后端
- Vue 管理后台Nginx 托管)
对应文件:
- [docker-compose.yml](/Users/slience/postgraduate/easycard/docker-compose.yml)
- [MySQL Dockerfile](/Users/slience/postgraduate/easycard/docker/mysql/Dockerfile)
- [MySQL 配置](/Users/slience/postgraduate/easycard/docker/mysql/conf.d/my.cnf)
- [Redis 配置](/Users/slience/postgraduate/easycard/docker/redis/redis.conf)
- [Backend Dockerfile](/Users/slience/postgraduate/easycard/docker/backend/Dockerfile)
- [Frontend Dockerfile](/Users/slience/postgraduate/easycard/docker/frontend-admin/Dockerfile)
- [Nginx 配置](/Users/slience/postgraduate/easycard/docker/frontend-admin/nginx.conf)
## 2. 启动方式
在项目根目录执行:
```bash
docker compose up -d --build
```
查看状态:
```bash
docker compose ps
```
停止并保留数据卷:
```bash
docker compose down
```
停止并删除数据卷:
```bash
docker compose down -v
```
## 3. 服务说明
### 3.1 MySQL
- 容器名:`easycard-mysql`
- 数据库:`easycard`
- 用户:`root`
- 密码:`root`
说明:
- 首次启动时会自动执行 [easycard_init.sql](/Users/slience/postgraduate/easycard/database/mysql/easycard_init.sql)
- 该脚本当前只负责创建 `easycard` 数据库
- 表结构、平台基础数据、演示数据由后端启动后的 Flyway 脚本统一执行
- 数据持久化目录:`docker/data/mysql`
- 当前不对宿主机暴露端口,仅允许 Docker 内网访问
### 3.2 Redis
- 容器名:`easycard-redis`
- 默认未设置密码
说明:
- 当前为本地开发配置
- 后续若进入联调或准生产环境,建议补充访问密码
- 数据持久化目录:`docker/data/redis`
- 当前不对宿主机暴露端口,仅允许 Docker 内网访问
### 3.3 MinIO
- 容器名:`easycard-minio`
- 用户名:`minioadmin`
- 密码:`minioadmin`
说明:
- `minio-init` 会在启动后自动创建 `easycard` bucket
- 当前脚本默认给该 bucket 开启下载访问,便于本地联调图片访问
- 数据持久化目录:`docker/data/minio`
- 当前不对宿主机暴露端口,仅允许 Docker 内网访问
### 3.4 Backend
- 容器名:`easycard-backend`
- 端口:`8112`
说明:
- 使用 [docker/backend/Dockerfile](/Users/slience/postgraduate/easycard/docker/backend/Dockerfile) 进行多阶段构建
- 容器启动时使用 `docker` profile
- 日志目录挂载到 `docker/data/backend/logs`
- 首次启动会等待 MySQL 健康检查通过后再启动
接口地址:
- [http://localhost:8112/api/v1/system/ping](http://localhost:8112/api/v1/system/ping)
- [http://localhost:8112/swagger-ui/index.html](http://localhost:8112/swagger-ui/index.html)
### 3.5 Frontend Admin
- 容器名:`easycard-frontend-admin`
- 端口:`8081`
说明:
- 使用 [docker/frontend-admin/Dockerfile](/Users/slience/postgraduate/easycard/docker/frontend-admin/Dockerfile) 构建前端产物
- 通过 Nginx 托管前端静态资源
- Nginx 会将 `/api``/swagger-ui``/v3/api-docs` 反向代理到 backend 服务
- Nginx 日志目录挂载到 `docker/data/nginx/logs`
访问地址:
- [http://localhost:8081](http://localhost:8081)
## 4. 与后端配置的对应关系
当前后端默认配置位于:
- [application.yml](/Users/slience/postgraduate/easycard/backend/easycard-boot/src/main/resources/application.yml)
容器内部联通使用:
- `DB_HOST=mysql`
- `DB_PORT=3306`
- `DB_NAME=easycard`
- `DB_USERNAME=root`
- `DB_PASSWORD=root`
- `REDIS_HOST=redis`
- `REDIS_PORT=6379`
- `REDIS_DATABASE=0`
- MinIO 服务名:`minio`
## 5. 数据挂载目录
当前容器数据与日志均挂载到宿主机目录:
- `docker/data/mysql`
- `docker/data/redis`
- `docker/data/minio`
- `docker/data/backend/logs`
- `docker/data/nginx/logs`
这样做的好处:
- 便于本地排查数据
- 重建容器后数据仍保留
- 便于备份和手工清理
## 6. 注意事项
- `easycard_init.sql` 当前仅适用于手工建库和 Docker 首次建库
- 若重新执行初始化脚本,请先删除 MySQL 数据卷,否则 MySQL 不会再次执行 `/docker-entrypoint-initdb.d`
- 若需要重建表结构和演示数据,请删除 MySQL 数据后重新启动 backend由 Flyway 重新执行版本脚本
- 若本机已有 8112 或 8081 端口占用,需要同步调整后端和前端端口映射
- 当前仅 `frontend-admin(8081)``backend(8112)` 对宿主机暴露端口