# SAAS 架构概览 > 面向技术决策会议的架构说明文档。本文档聚焦 SAAS 多租户-公司-部门-用户-角色架构设计、当前实现状态与未来发展方向。 --- ## 1. 项目定位 **GVS-DSDK** 是一套面向中小企业(SMB)的 SAAS 化企业管理平台,包含: - **多租户 SAAS 框架**:支持租户入驻、审核、隔离 - **企业资源管理(GERP)**:组织、角色、权限、菜单、工单、资产、文档 - **三大业务引擎**:分佣引擎、支付网关、统计引擎 - **分布式通信底座(MSYNC)**:服务注册、发现、分布式事务 ## 2. 技术栈 | 层 | 技术 | |---|---| | 后端框架 | Django 4.2+ / DRF / SimpleJWT | | 异步任务 | Celery + Redis(可降级同步) | | 实时通信 | Socket.IO(python-socketio) | | 数据库 | MySQL 5.7+(7 库分库路由) | | 缓存 | Redis(可降级 locmem) | | 安全 | bcrypt / AES-256-GCM / JWT | | 前端 | 原生 HTML/JS + 自研 NeoUI/GERPUI 组件 | | 部署 | Gunicorn + Nginx 反向代理 | ## 3. 双包架构 ``` ┌─────────────────────────────────────────────────────┐ │ d:\SMANAGE(项目根) │ │ │ │ ┌──────────────────────┐ ┌──────────────────────┐│ │ │ gvsds │ │ gvsdsdk ││ │ │ 主服务器(业务层) │◄─┤ 分布式 SDK(薄封装)││ │ │ - Django 项目 │ │ - 协议契约层 ││ │ │ - 14 个业务 App │ │ - 惰性加载 ││ │ │ - 完整业务实现 │ │ - PascalCase 协议 ││ │ └──────────────────────┘ └──────────────────────┘│ │ ▲ ▲ │ │ │ │ │ │ ┌──────────────────────┐ ┌──────────────────────┐│ │ │ ATestCServer │ │ TempLate/ ││ │ │ 子服务器示例 │ │ 前端模板资源 ││ │ │ 通过 SDK 接入 │ │ GERP/AKS/MSOC 等 ││ │ └──────────────────────┘ └──────────────────────┘│ └─────────────────────────────────────────────────────┘ ``` ### 3.1 `gvsds` — 主服务器 - 14 个 Django App:`core / gerp / ugm / crb / invite / ccgo / sve / t4 / mc / doc / api / msync / payment / commission / stats` - 7 库分库路由:`Users / GerpCore / Plans / Tasks / T4PC / Document / Minecraft` - 6 个自定义中间件:IP 过滤、域名注入、当前角色注入、服务认证、攻击检测、错误日志 ### 3.2 `gvsdsdk` — 分布式 SDK / 通用 SAAS 服务层 - **服务层**:从薄封装演进为**通用 SAAS 服务层**——`RoleManager / AuthManager / AdminUserManager / TenantManager / CompanyManager / DepartmentManager / MessageManager / MenuManager / WorkOrderManager / InventoryManager / AssetManager / AuditManager / OrderManager / StatsManager / UserService` 等,gvsds 视图层通过它们访问数据(裸 ORM 已基本消除) - **惰性加载(PEP 562)**:130+ 符号按需 import - **双类导出**:自有实现(无 Django 依赖,子服务器可用)+ 服务端实现(依赖 Django ORM) - **msync 原生实现(1.1.0)**:通信底座已从 `gvsds.apps.msync` 整体迁入 `gvsdsdk/msync`(models/registry/ogm/transaction/auth + Django 集成层),可脱离 gvsds 独立部署(屏蔽 gvsds 后全模块独立导入验证通过) - **引擎**:`CommissionEngine`(分佣)、`PaymentManager`(支付)、`OrderManager`(订单状态机)、`StatsManager`(统计)、`TransactionManager`(分布式事务) ### 3.3 主从通信机制 - **版本校验**:启动时 `gvsdsdk.check_min_version('1.1.0')`,主从必须一致(版本兼容矩阵见 `gvsdsdk/VERSION_MATRIX.md`) - **Socket.IO 协议**:20+ 事件,全程 PascalCase 字段 - **支付网关自动注册**:`gvsdsdk/apps.py` 的 `ready()` 钩子 --- ## 4. SAAS 多租户架构(核心) ### 4.1 组织四层架构 ``` ┌──────────────────────────────────────────────────────────┐ │ 第 4 层:鉴权规则层(运行时) │ │ 操作权限 (RBAC) 数据权限 (ABAC + RoleScope) │ ├──────────────────────────────────────────────────────────┤ │ 第 3 层:角色权限载体层 │ │ Role + UserRole + RolePermission │ ├──────────────────────────────────────────────────────────┤ │ 第 2 层:岗位模板层(初始化快照) │ │ PositionTemplate + PositionTemplatePermission │ │ CopyToRole 一次性复制,后续独立演进 │ ├──────────────────────────────────────────────────────────┤ │ 第 1 层:组织人事层 │ │ Tenant → Company → Department │ │ UserDept(员工-部门多对多) │ │ Position(人事职务标签,与权限解耦) │ │ Workgroup(跨部门工作组) Shop(商铺,归公司) │ └──────────────────────────────────────────────────────────┘ ``` ### 4.2 数据模型核心表(共 17 张 SAAS 表) | 分类 | 表名 | 职责 | |---|---|---| | **租户** | `Tenant` | 多租户根,含审核状态/到期时间 | | **组织** | `Company` / `CompanyInfo` / `Department` / `Workgroup` | 公司树/工商信息/部门树/跨部门组 | | **用户** | `User` / `UserAvatar` / `User2FA` / `UserPending2FA` / `UserLoginLog` / `AccountActivation` / `Password` / `UserIDCard` | 用户身份与认证 | | **角色权限** | `Role` / `Permission` / `UserRole` / `RolePermission` | RBAC 核心 | | **岗位模板** | `PositionTemplate` / `PositionTemplatePermission` | 权限初始化快照 | | **人事标签** | `Position` | 职务标签(与权限解耦) | | **商铺** | `Shop` / `RoleShop` | 多商铺体系 | | **ABAC** | `UserABAC` | 属性访问控制(补充) | | **审计** | `AuditLog` / `AbnormalUserLog` | 操作审计 + 攻击溯源 | ### 4.3 关键设计决策 #### (1) Position 与权限**完全解耦** - 人事职务标签(`Position`)仅用于人事管理,**不直接绑定权限** - 调岗/升职只修改 `Position`,权限只通过 `UserRole → RolePermission → Permission` 走 - 规避了业界常见错误:把职务直接绑权限导致调岗时权限树重算 #### (2) PositionTemplate 的"快照复制"机制 - 模板 → 角色 = **一次性复制**(`CopyToRole`),复制后两者无运行时绑定 - 模板调整只影响**之后新建**的角色,已有角色不被动变更 - 避免了"模板改一个字段,全员权限突然变了"的运维灾难 #### (3) UserRole 实体化 + 关联表(部门/工作组多对多) `UserRole` 是"用户↔角色"的**实体化中间表**(联合唯一:同一用户+同一角色仅一行): - **权限分配**:User ↔ Role 多对多(`UserRoleUUID` 作为全局唯一关联实体) - **组织归属**:不再放 UserRole 上,改走关联表(多对多): - `UserRoleDepartment`:(用户-角色对) ↔ 部门(`UserRoleUUID + DeptUUID`) - `UserRoleWorkgroup`:(用户-角色对) ↔ 工作组(`UserRoleUUID + WorkgroupUUID`) - **成员类型**:`RoleType`(0=成员 / 1=负责人/组长)冗余在关联表,**按部门/工作组区分** **优势**:一个用户-角色对可同时挂多个部门/工作组,且在不同部门可分别标注成员/负责人 **注意**:UserRole 上的遗留字段(`DeptUUID / WorkgroupUUID / RoleType`)已废弃删除(见 gvsdsdk 0002 迁移), 全部语义以关联表为准。 #### (4) 角色作用域四档数据权限(`RoleScope`) | 类型 | 判定条件 | 可见范围 | |---|---|---| | `admin` | IsSuperuser/IsStaff 或 `admin:super` 权限 | 全公司 | | `dept_manager` | `UserRoleDepartment.RoleType=1`(按当前公司过滤,可多部门) | 本部门成员 | | `workgroup_lead` | `UserRoleWorkgroup.RoleType=1`(按当前公司过滤,可多工作组) | 本工作组成员 | | `member` | 其他 | 仅自己 | ### 4.4 运行时鉴权流程 ``` HTTP Request │ ├─► JWTAuthentication → User 实例 ├─► CurrentRoleMiddleware → request.current_role (Role) ├─► DomainMiddleware → request.current_company_uuid │ ├──► 操作权限校验:PermissionVerifier(permission, attrs, user, request) │ ├─ ABAC:UserABAC.HierarchicalPermissionIdentifiers ∋ attr? │ └─ RBAC:RolePermission(角色)→Permission.PermCode ∋ attr? │ (含请求级缓存,消除 N+1) │ └──► 数据权限校验:RoleScope.GetUserScope(request) └─ ApplyScopeToQueryset(qs, scope, table_name) 按 admin/dept_manager/workgroup_lead/member 差异化过滤 ``` ### 4.5 主键设计 - 全程使用 `BINARY(16)` UUID 主键 - 优势:分布式生成、无 ID 冲突、不暴露顺序信息 - 代价:InnoDB 聚簇索引无序,写入有页分裂开销(可考虑改 UUIDv7) --- ## 5. 三大业务引擎 ### 5.1 分佣引擎(`CommissionEngine`) | 策略 | Type | 说明 | |---|---|---| | `PercentageStrategy` | `percentage` | 比例分账,支持保底/封顶 | | `FixedStrategy` | `fixed` | 固定金额 | | `TieredStrategy` | `tiered` | 阶梯分账 | | `RemainderStrategy` | `remainder` | 剩余归平台 | | `WithdrawalFeeStrategy` | `withdrawal_fee` | 提现手续费 | 支持:规则配置 → 触发分佣 → 预结算 → 邀请链分佣 → 查询统计 ### 5.2 支付网关(`PaymentManager`) | 渠道 | 支付方式 | 转账 | |---|---|---| | 微信支付 | JSAPI/Native/H5/小程序 | 支持 | | 支付宝 | APP/H5/Native | 支持 | | 银行卡 | APP/H5/Native | 仅 bank 类型 | 支持:网关配置 → 支付/查询/退款/转账 → 回调处理 ### 5.3 统计引擎(`stats`) - Celery 定时任务:每日重置 / 每月重置 / 排行榜构建 / 过期清理 - 按角色差异化仪表盘 --- ## 6. 当前实现状态 ### 6.1 已完成 - ✅ 14 个业务 App 完整实现 - ✅ 多租户入驻审核工作流 - ✅ RBAC + ABAC 混合鉴权 - ✅ 分佣引擎 + 支付网关 + 统计引擎 - ✅ MSYNC 分布式通信(注册/发现/OGM/Saga 事务) - ✅ 文件分片上传 + 资产管理 - ✅ 操作审计日志 + 攻击检测 - ✅ **服务层化迁移(P0/P1/P2 全部完成,2026-08-07)**:role_scope 数据权限底座、form_service 角色/用户链路、菜单/工单/消息/物品/背包/文档/文件资产、25 个 ViewSet queryset、form_service 通用增删改落库、doc 视图/统计任务/审计清理等全部收敛到 gvsdsdk(详见项目记忆「服务层化迁移进度」);invite/sve/t4/ccgo 已定性为业务定制留在 gvsds(与 CRB/MC 同边界) ### 6.2 已知技术债 | 优先级 | 问题 | 影响 | |---|---|---| | ~~高~~ | ~~Role/Permission 模型双份定义~~:✅ 已收敛(2026-08-10)——gvsds 各 app 模型统一 `from gvsdsdk.models import`,SDK 为唯一模型源 | — | | 高 | 部分表(User/Dept/Workgroup/Shop)无 TenantUUID | 跨租户查询需 JOIN,删除租户困难(待迁移脚本补列回填) | | 中 | ABAC 实现本质是 RBAC(字符串集合) | 已文档更正为"属性标识符补充层",真 ABAC 重构列入中期规划 | | 中 | 数据权限硬编码 `if table_name == 'X'` | 违反开闭原则 | | 中 | 缺乏软删除机制 | 误删不可恢复 | | ~~中~~ | ~~stats 双轨~~:✅ 已统一(2026-08-07)——`StatEngine`(gvsds/apps/stats/manager.py)已删除,编排方法全部并入 gvsdsdk `StatsManager`,视图/Celery 任务统一走 SDK | — | | 低 | UUID 主键无序导致索引膨胀 | 大数据量写入性能下降 | --- ## 7. 未来发展方向(会议讨论建议项) ### 7.1 短期(1-3 个月) 1. ~~统一 Role/Permission 模型~~:✅ 已收敛(2026-08-10)——视图层统一经 gvsdsdk Manager 访问,模型层 gvsds 统一从 gvsdsdk import,双份定义消除 2. **补全 TenantUUID 字段**:所有租户语义表直接打 `TenantUUID`,简化跨租户查询与租户删除 3. **数据权限策略化**:用策略模式替代 `if table_name == 'X'`,每个模型注册自己的 `ScopeFilter` 4. ~~更新根 README.md~~:✅ 已反映当前 Django 架构 5. ~~统一 stats 双轨实现~~:✅ 已收敛——`StatEngine` 删除,`StatsManager` 补齐编排方法(DefineMetric/GenerateDailyRanking/QueryRanking/RunScheduledResets/BuildRankings 等),视图与 Celery 任务统一经 gvsdsdk 访问 ### 7.2 中期(3-6 个月) 1. **重构 ABAC 为真正的属性访问控制**:支持时间/IP/资源所有者/字段级权限 2. **引入软删除机制**:`DeletedAt` + `DeletedByUUID`,配合审计日志实现数据恢复 3. **支付网关扩展**:增加 PayPal/Stripe 适配(出海场景) 4. **租户配额管理**:用户数/数据量/API 调用次数配额 ### 7.3 长期(6+ 个月) 1. **拆分协议层**:把 gvsdsdk 拆为 `gvsds-protocol`(纯协议)+ `gvsds-business`(业务能力),主从各自依赖 2. **改用 UUIDv7 或 Snowflake**:解决主键无序问题 3. **多区域部署**:基于 MSYNC 实现跨地域多活 4. **微服务化拆分**:gerp/payment/commission/stats 可独立部署 --- ## 8. 关键架构原则 1. **PascalCase 全链路一致**:从数据库字段 → Python 类 → Socket.IO 事件 → 前端,无转换层 2. **优雅降级**:Redis/Celery/网关依赖缺失时自动降级,开发环境零依赖启动 3. **配置外置**:`app.ini` + `secrets.ini` + 环境变量三层配置,支持 12-factor 部署 4. **薄封装 SDK**:协议契约层与业务实现层分离,主从可独立演进 5. **Position 与权限解耦**:人事标签不绑权限,避免调岗重算 --- ## 9. 联系与维护 - **主仓库**:`d:\SMANAGE` - **SDK 包**:`gvsdsdk/`(pyproject.toml v1.0.0) - **子服务器示例**:`ATestCServer/` - **设计文档**:`docs/commission_engine.md` / `docs/payment_gateway.md` / `docs/stats_engine.md` --- **本架构文档用于技术决策会议参考,详细 API 与字段定义见 [gvsdsdk/API.md](file:///d:/SMANAGE/gvsdsdk/API.md) 与 [gvsdsdk/README.md](file:///d:/SMANAGE/gvsdsdk/README.md)。**