diff --git a/docs/产品功能文档.md b/docs/产品功能文档.md new file mode 100644 index 0000000..03f18b7 --- /dev/null +++ b/docs/产品功能文档.md @@ -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. 后续开发原则 + +- 先完成“可用且正确”的多租户闭环,再逐步增加高级能力。 +- 先保证租户、用户、名片、展示四条主链路打通,再扩展统计、审核、营销。 +- 小程序与后台字段模型保持统一,避免前后端重复定义和语义不一致。 diff --git a/docs/技术文档.md b/docs/技术文档.md new file mode 100644 index 0000000..c9631ee --- /dev/null +++ b/docs/技术文档.md @@ -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. 开发环境 + +适用场景: + +- 本地开发 +- 单人或小团队联调 + +建议配置: + +- CPU:4 核 +- 内存:8 GB +- 系统盘:100 GB SSD + +部署建议: + +- MySQL、Redis、MinIO 可通过 Docker Desktop 或本机服务运行 +- 后端、后台前端、小程序开发工具本地启动 + +### 2. 测试环境 + +适用场景: + +- 功能测试 +- 接口联调 +- UAT 验收 + +建议配置: + +- CPU:4 核 +- 内存:8 GB 到 16 GB +- 系统盘:100 GB SSD +- 数据盘:100 GB SSD + +部署建议: + +- 单台 Linux 服务器部署 `Nginx + Spring Boot + MySQL + Redis + MinIO` +- 使用 Docker Compose 管理服务,便于迁移和重建环境 + +### 3. 生产环境当前推荐 + +适用场景: + +- 仅服务 1 家事务所 +- 约 20 名后台用户 +- 小程序访问量较低到中等 +- 以名片展示、资料维护、图片上传为主 + +建议配置: + +- CPU:4 核 +- 内存: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` + +该方案在复杂度、交付速度、稳定性、私有化友好程度和后续扩展能力之间较为均衡,适合作为本项目第一阶段正式落地方案。后台统一多租户,小程序按租户独立发布,二者职责边界清晰,便于实施和运营。 diff --git a/docs/数据库设计文档.md b/docs/数据库设计文档.md new file mode 100644 index 0000000..4003865 --- /dev/null +++ b/docs/数据库设计文档.md @@ -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 导入任务表 +- 消息通知表 +- 线索与咨询记录表 + +第一阶段不建议提前引入过多非核心表,优先保证主链路稳定。 diff --git a/docs/本地中间件环境说明.md b/docs/本地中间件环境说明.md new file mode 100644 index 0000000..a2a59a2 --- /dev/null +++ b/docs/本地中间件环境说明.md @@ -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)` 对宿主机暴露端口