Easy Admin SaaS 是一个共享数据库的多租户业务底座。它不是单独的管理后台,而是由平台端、租户端、用户端和统一服务端组成,并在同一套基础能力上装载测算、心理测评、短剧和吃瓜热点等业务应用。

物理项目与交付物

目录 技术与形态 主要职责 交付方式
platform Vue 3、Vite、Element Plus、Pinia 平台运营、租户开通、平台管理员、全局配置、定时任务、升级和代码生成 独立静态管理站
tenant Vue 3、Vite、Element Plus、Pinia 租户员工、组织权限、用户、内容、渠道、装修、财务和业务应用管理 独立静态管理站
pc Nuxt 3、Element Plus、Pinia 登录用户的桌面 Web 入口,承载账户和各业务应用页面 SSR 服务或静态产物
uniapp Vue 3、uni-app、Pinia H5、小程序和 App 用户入口 按渠道构建的多端产物
server PHP 8、ThinkPHP 8、多应用模式 三类 API、公共模型、支付、短信、存储、微信和业务应用服务 PHP-FPM API 与任务进程

五个目录可以独立开发和发布,但服务端数据模型与接口契约是共同依赖。前端页面隐藏只能改善体验,真正的权限、租户隔离和业务校验必须由 server 完成。

总体拓扑

flowchart TB
  Platform[platform
平台运营后台] --> PA[platformapi] Tenant[tenant
租户管理后台] --> TA[tenantapi] PC[pc
Nuxt 用户端] --> UA[api] Uni[uniapp
H5 / 小程序 / App] --> UA PA --> Common[common
身份 / 支付 / 存储 / 渠道] TA --> Common UA --> Common TA --> SM[测算
suanming] UA --> SM TA --> TR[心理测评
testreport] UA --> TR TA --> VE[短剧
ve] UA --> VE TA --> CG[吃瓜热点
chigua] UA --> CG SM --> Common TR --> Common VE --> Common CG --> Common Common --> DB[(MySQL
业务事实)] Common --> Cache[(Redis
会话 / 缓存 / 锁)] Common --> Storage[本地 / OSS / COS / 七牛] Common --> Channels[微信 / 短信 / 支付]

服务端应用边界

ThinkPHP 的多应用入口对应三类不同信任级别,不能只把它们理解为 URL 前缀。

应用 调用方 已有模块 数据权限
platformapi 平台运营人员 租户、平台管理员、角色菜单、部门岗位、全局配置、计划任务、升级、生成器 可以治理多个租户,但每项跨租户操作都应审计
tenantapi 某一租户的管理员和员工 组织权限、用户、文章、微信渠道、页面装修、财务、充值和业务应用 只能访问当前租户及授权部门范围
api 最终用户 登录、账户、文章、搜索、支付、充值及各业务应用 只能访问自己的数据和当前租户公开内容
index 安装程序、健康检查或公开入口 环境初始化和无需业务身份的接口 不应暴露管理操作
common 仅供服务端内部复用 模型、枚举、列表、服务和基础能力 不直接作为公网应用入口

平台账号、租户员工和最终用户分别使用 Admin、TenantAdmin、User 及各自的 Session/Auth 模型。三套身份不能只靠一个角色字段混用,否则平台权限容易意外下放到租户或用户接口。

一次请求怎样流动

  1. 客户端向对应 API 发送 Token、渠道信息和业务参数;
  2. 入口中间件解析会话,并从可信会话确定 admin_id、user_id 与 tenant_id;
  3. 控制器接收参数,Validate 完成格式与边界校验;
  4. Logic 处理用例,Lists 负责有界分页查询,Service 处理支付、存储或跨模块协作;
  5. Model 在租户数据范围内读写 MySQL,需要时同步 Redis 缓存;
  6. API 返回统一响应,关键管理操作和资金变化写入日志。

客户端提交的 tenant_id 只能帮助定位请求,最终租户身份必须由域名、应用配置或登录会话推导,不能直接信任表单值。

平台治理与租户运营

平台层

平台端负责 SaaS 的控制面,包括租户生命周期、租户管理员、平台组织与 RBAC、全局存储和交易配置、定时任务、版本升级和开发工具。创建租户时,应在一个事务或可恢复流程中完成租户记录、初始管理员、默认角色菜单、基础配置和必要业务数据。

平台层可以查看租户状态和汇总指标,但不应默认进入租户业务数据。需要代运营或排障时,应记录操作人、目标租户、原因和前后值。

租户层

租户端负责组织、角色、菜单、员工、最终用户、内容、渠道、装修、财务以及已安装业务应用。租户角色的功能权限与部门数据范围需要同时生效:拥有菜单不代表可以读取全租户数据,拥有部门范围也不代表可以执行敏感按钮操作。

文件、短信记录、通知、支付方式等对象在源码中同时存在平台版和租户版模型。维护时要明确哪些是平台模板,哪些是租户覆盖值,避免修改平台默认值后覆盖租户的既有配置。

公共能力与业务应用

类型 主要对象或服务 架构边界
身份与组织 管理员、租户员工、用户、角色、菜单、部门、岗位、会话 三类身份分开鉴权,部门范围进入每个列表查询
内容与装修 文章、分类、页面、Tabbar、热搜 内容发布与页面装修可以复用,但数据必须带租户范围
渠道能力 公众号、小程序、网页配置、微信请求 渠道凭据仅在服务端保存,并按租户读取
交易能力 支付配置、支付方式、充值、退款、账户流水 金额变化使用事务、幂等业务号和不可变流水
基础设施 文件、短信、对象存储、代码生成、定时任务 通过 Driver 或 Service 收口供应商差异
业务应用 测算、心理测评、短剧、吃瓜热点 自己维护订单和领域数据,通过公共支付、用户和存储能力接入

业务应用不是简单页面集合。例如测算包含产品、订单、分销和提现,心理测评包含项目、订单、评分引擎和支付,短剧包含分类、剧集、观看记录、订单与 VOD。它们可以复用平台能力,但不能把领域状态全部塞进通用订单或用户表。

四个业务应用在代码中都有独立的控制器、Logic、模型和安装命令,并同时接入租户后台与用户 API。详细设计分别见测算应用、心理测评、短剧应用和吃瓜热点。

多租户数据隔离

共享数据库模式的关键不是“表里有 tenant_id”,而是所有访问路径都能保持租户上下文。

访问位置 必须检查的内容
新增与修改 服务端写入当前租户,不接受前端任意指定;更新条件同时包含主键和租户
列表与详情 列表、详情、导出和统计都加入租户及部门范围
唯一约束 租户内唯一的数据使用 tenant_id + 业务字段 组合索引
缓存 Key 至少包含租户和业务对象标识,平台模板与租户配置分开
文件 对象存储路径带租户命名空间,下载时再次鉴权
定时任务 任务负载显式携带租户,执行前验证租户仍有效
操作日志 记录操作者身份类型、租户、业务对象和请求编号

跨租户汇总属于平台治理用例,应进入单独查询路径,不能通过“临时去掉 tenant_id 条件”实现。

支付、存储与渠道

支付服务已经按微信、支付宝和基础支付接口分层。推荐以业务订单号作为幂等键:创建支付单、接收回调、确认业务订单和写账户流水分别记录状态,重复回调只返回已处理结果。退款同样需要退款业务号和原支付单关系。

存储 Driver 支持本地、阿里云、腾讯云、七牛和服务器存储。数据库只保存文件元数据与对象 Key,业务表引用文件 ID;切换供应商时由驱动生成访问地址,不在历史业务数据中批量替换完整 URL。

微信、短信和支付凭据按租户配置存放,运行时通过当前租户加载。日志必须过滤 Access Token、签名密钥、手机号验证码和支付原始报文中的敏感字段。

部署与故障域

运行单元 扩缩容与发布 主要故障影响
platform / tenant 静态站 CDN 或静态 Web 服务独立发布 对应后台不可用,不应中断用户端业务
pc 根据 Nuxt 模式部署 SSR 或静态产物 桌面用户端不可用,移动端可继续工作
uniapp 各渠道独立发版 单一渠道故障不影响其他端
PHP API 尽量无状态扩容,会话放共享缓存 登录和业务操作受影响
定时任务与升级任务 单实例或分布式锁 通知、清理或升级延迟,不应阻塞普通请求
MySQL / Redis 分别保存事实与临时状态 MySQL 故障禁止资金写入;Redis 故障需明确降级策略
对象存储与第三方渠道 超时、重试、熔断和回调校验 文件、短信或支付延迟,业务订单需保持可恢复状态

当前架构债务与改进顺序

  1. 统一租户上下文:在三个 API 入口形成唯一的上下文对象,避免每个 Logic 自行读取 tenant_id;
  2. 自动化隔离测试:为详情、列表、导出、统计、缓存和任务补充跨租户访问测试;
  3. 插件边界:给业务应用定义安装、配置、菜单、数据和卸载契约,减少对 common 的反向依赖;
  4. 交易一致性:统一支付、充值、退款和分销的幂等键、状态机与对账规则;
  5. 异步任务:把短信、媒体处理、批量安装和通知移出同步请求,并保存任务状态;
  6. 配置治理:所有域名、密钥和供应商配置进入环境变量或密钥服务,轮换源码中曾出现的固定凭据;
  7. 可观测性:用请求 ID、租户 ID、用户 ID 和业务单号串联 API、任务与第三方回调。

具体怎样判断一个能力应进入公共层还是独立业务应用,可继续阅读模块边界。

站内搜索

没有找到内容!