# Epic-008: Server和Web多租户集成 - Brownfield Enhancement ## Epic Goal 将当前的单租户系统直接改为多租户系统,基于史诗007已完成的多租户包,在server和web中集成完整的租户数据隔离和租户管理功能,为后续按需拼装单租户或多租户系统提供基础。 **核心目标:直接改造现有单租户系统为多租户系统,按照现有包集成模式实现。** ## Epic Description ### Existing System Context **Current relevant functionality:** - 史诗007已完成11个多租户业务包的复制和26个前端管理界面包的创建 - 现有server使用单租户包路由(如`@d8d/user-module`),支持基础的用户、认证、文件等模块 - 多租户认证模块包(`@d8d/auth-module-mt`)中已实现租户上下文管理,在认证中间件中设置`c.set('tenantId', user.tenantId)` - web应用已集成用户管理UI包(`@d8d/user-management-ui`),展示包集成模式 - web中routes.tsx使用`import { UserManagement } from '@d8d/user-management-ui'`模式 - web中api_init.ts使用`userClientManager.init('/api/v1/users')`初始化客户端 - 共享包(shared-crud、shared-types、shared-utils)在两套系统中复用 - 数据库已支持多租户表结构(带_mt后缀的表) **Current limitations:** - server只能运行单租户模式,不支持多租户 - web应用只有用户管理使用包模式,其他管理界面仍为本地实现 - 缺乏租户上下文管理和租户数据隔离 - 认证系统不支持多租户用户隔离 - 前端路由不支持租户感知 **Technology stack:** - Backend: Node.js, TypeScript, Hono, TypeORM, PostgreSQL - Frontend: React 19, TypeScript, TanStack Query, React Hook Form - Authentication: JWT, Redis session management - Database: PostgreSQL with tenant isolation - Package Management: pnpm workspace **Integration points:** - 现有server路由注册机制 - 认证中间件和用户上下文 - 数据库连接和实体管理 - 前端API客户端和路由配置 - 共享UI组件包 ### Enhancement Details **What's being added/changed:** - 将server从单租户包改为多租户包(如`@d8d/user-module` → `@d8d/user-module-mt`) - 租户上下文管理,支持租户ID在请求链中传递 - 多租户认证中间件,支持租户感知的用户认证 - web应用全部改为使用多租户UI包(如`@d8d/user-management-ui-mt`) - 前端API客户端支持租户上下文传递 - 租户数据隔离验证和权限控制 **Enhanced architecture:** ``` packages/ ├── server/ # 改为多租户系统 │ ├── src/ │ │ └── index.ts (改为多租户包路由) ├── web/ # 全部改为多租户UI包 │ ├── src/ │ │ ├── client/ │ │ │ ├── admin/ │ │ │ │ └── routes.tsx (改为导入多租户UI包) │ │ │ ├── api_init.ts (改为初始化多租户客户端) │ │ │ └── pages/ (移除本地实现,全部使用包) └── 多租户包 (史诗007已完成) ├── @d8d/user-module-mt ├── @d8d/auth-module-mt (已包含租户上下文管理) ├── @d8d/file-module-mt ├── @d8d/user-management-ui-mt ├── @d8d/order-management-ui-mt └── ... (其他多租户UI包) ``` **How it integrates:** - 按照现有server包导入模式,将单租户包替换为多租户包 - 多租户模块包直接依赖多租户认证模块的认证中间件,其中已包含租户上下文管理 - 按照web中用户管理UI包的集成模式,将其他管理界面改为使用多租户UI包 - 保持现有API接口不变,新增租户相关API - 前端复用现有UI组件,新增租户管理功能 - 共享包在两套系统中继续复用 **Success criteria:** - server直接使用多租户包,无需环境变量切换 - 多租户模式下租户数据完全隔离 - web应用全部使用多租户UI包,移除本地实现 - 租户管理界面功能完整,支持租户CRUD操作 - 现有单租户功能不受影响,保持向后兼容 - 性能影响小于5%,租户过滤使用数据库索引 - 完整的测试覆盖和文档 ## Stories ### 阶段 1: Server多租户集成 1. **[x] Story 1:** Server多租户包替换和集成 - 在server的index.ts文件中,将单租户包替换为多租户包(如`@d8d/user-module` → `@d8d/user-module-mt`),包括包导入、实体初始化和路由注册,多租户模块包直接依赖多租户认证模块的认证中间件 2. **[x] Story 2:** Web多租户UI包全面集成 - 按照现有用户管理UI包的集成模式,将web中所有管理界面改为使用多租户UI包(如`@d8d/user-management-ui-mt`),移除本地实现 ### 阶段 2: 租户模块和UI包集成 3. **[x] Story 3:** 租户模块集成到server - 将租户模块包(@d8d/tenant-module-mt)集成到server中,包括租户管理路由、超级管理员认证和租户数据隔离功能,确保server能够支持租户管理操作 4. **Story 4:** 租户UI包集成到Web - 复制`web/src/client/admin`目录为`web/src/client/tenant`,在tenant目录中集成`@d8d/tenant-management-ui-mt`租户管理UI包,使用超级管理员认证系统(superadmin/admin123),添加租户管理路由和超级管理员认证逻辑,确保Web应用能够支持租户管理操作 ### 阶段 3: 系统集成和验证 5. **Story 5:** 多租户系统集成测试和验证 - 进行完整的系统集成测试,验证租户数据隔离、权限控制和性能表现,确保系统稳定性和可靠性 ## Compatibility Requirements - [x] 现有单租户APIs保持不变,多租户为可选功能 - [x] 数据库schema变更向后兼容,多租户使用独立表 - [x] 现有UI组件和设计模式保持不变 - [x] 性能影响最小化,租户过滤使用数据库索引 - [x] 配置向后兼容,现有配置继续有效 ## Risk Mitigation **Primary Risk:** 租户上下文管理复杂,可能影响现有请求处理 **Mitigation:** 使用AsyncLocalStorage管理租户上下文,确保线程安全 **Rollback Plan:** 租户功能为可选配置,可随时禁用回退到单租户模式 **Primary Risk:** 多租户路由切换可能引入路由冲突 **Mitigation:** 清晰的命名空间分离,单租户和多租户路由独立管理 **Rollback Plan:** 保持单租户路由不变,多租户路由可独立移除 **Primary Risk:** 前端租户管理界面与现有功能冲突 **Mitigation:** 租户管理作为独立模块,与现有管理界面分离 **Rollback Plan:** 租户管理界面可独立禁用,不影响现有功能 **Primary Risk:** 性能影响,租户过滤增加查询复杂度 **Mitigation:** 数据库索引优化,查询条件合并,性能基准测试 **Rollback Plan:** 租户过滤可配置禁用,回退到无租户过滤模式 ## Definition of Done - [ ] 所有故事完成且验收标准满足 (3/5 故事已完成) - [ ] server支持单租户/多租户模式动态切换 - [ ] 租户数据隔离验证通过 - [ ] 租户管理界面功能完整 - [ ] 现有单租户功能通过回归测试验证 - [ ] 性能基准测试通过,无明显性能下降 - [ ] 完整的单元测试和集成测试覆盖 - [ ] 使用文档和配置说明完整 - [ ] 向后兼容性验证通过 ## 架构设计详情 ### Server多租户包集成 ```typescript // 重构后的server入口 - 直接使用多租户包 // 当前实际写法(packages/server/src/index.ts:4-6) import { userRoutes as userModuleRoutes } from '@d8d/user-module' // 当前:单租户包 import { authRoutes as authModuleRoutes } from '@d8d/auth-module' // 当前:单租户包 import { fileRoutes as fileModuleRoutes } from '@d8d/file-module' // 当前:单租户包 // 改为多租户包 import { userRoutes as userModuleRoutes } from '@d8d/user-module-mt' // 改为:多租户包 import { authRoutes as authModuleRoutes } from '@d8d/auth-module-mt' // 改为:多租户包 import { fileRoutes as fileModuleRoutes } from '@d8d/file-module-mt' // 改为:多租户包 // 多租户认证模块包中已实现租户上下文(packages/auth-module-mt/src/middleware/auth.middleware.mt.ts:44-46) // 在认证中间件中设置租户上下文:c.set('tenantId', user.tenantId) ``` ### Web多租户UI包集成 ```typescript // web/src/client/admin/routes.tsx - 改为使用多租户UI包 import { UserManagement } from '@d8d/user-management-ui-mt' // 改为多租户UI包 import { OrderManagement } from '@d8d/order-management-ui-mt' // 改为多租户UI包 import { GoodsManagement } from '@d8d/goods-management-ui-mt' // 改为多租户UI包 // ... 其他管理界面包 // 路由配置 { path: 'users', element: , // 使用多租户UI包 }, { path: 'orders', element: , // 使用多租户UI包 }, { path: 'goods', element: , // 使用多租户UI包 } ``` ### 租户UI包集成实施步骤 ```bash # 1. 复制admin目录为tenant目录 cp -r web/src/client/admin web/src/client/tenant # 2. 修改tenant目录中的关键文件 # - web/src/client/tenant/index.tsx: 替换AuthProvider为租户专用的AuthProvider # - web/src/client/tenant/hooks/AuthProvider.tsx: 实现租户感知的认证逻辑 # - web/src/client/tenant/pages/Login.tsx: 添加租户选择功能 # - web/src/client/tenant/routes.tsx: 添加租户管理路由 # 3. 集成租户管理UI包 # - 在routes.tsx中添加租户管理路由 # - 在api_init.ts中初始化租户管理客户端 ``` ```typescript // web/src/client/tenant/routes.tsx - 添加租户管理路由 import { TenantsPage } from '@d8d/tenant-management-ui-mt'; // 在路由配置中添加 { path: 'tenants', element: , // 租户管理界面 }, // web/src/client/tenant/api_init.ts - 初始化租户管理客户端 import { tenantClientManager } from '@d8d/tenant-management-ui-mt/api'; // 初始化租户管理客户端 tenantClientManager.init('/api/v1/tenants'); // web/src/client/tenant/hooks/AuthProvider.tsx - 使用超级管理员认证 const handleLogin = async (username: string, password: string): Promise => { // 使用租户模块的超级管理员登录API const response = await tenantClientManager.get().login.$post({ json: { username, password } }); // ... 其他登录逻辑 }; // web/src/client/tenant/pages/Login.tsx - 超级管理员登录页 // 使用固定的超级管理员账号进行登录,无需租户选择 ``` ### API客户端初始化 ```typescript // web/src/client/api_init.ts - 改为初始化多租户客户端 import { userClientManager } from '@d8d/user-management-ui-mt/api' // 改为多租户包 import { orderClientManager } from '@d8d/order-management-ui-mt/api' // 改为多租户包 import { goodsClientManager } from '@d8d/goods-management-ui-mt/api' // 改为多租户包 // 初始化多租户客户端 userClientManager.init('/api/v1/users') orderClientManager.init('/api/v1/orders') goodsClientManager.init('/api/v1/goods') ``` ### 前端租户上下文管理 ```typescript // 租户上下文Hook export function useTenant() { const [currentTenant, setCurrentTenant] = useState(null); const switchTenant = useCallback(async (tenantId: number) => { // 切换租户逻辑 const response = await tenantClient.switchTenant({ tenantId }); setCurrentTenant(response.data); // 更新API客户端租户上下文 updateApiClientTenant(tenantId); }, []); return { currentTenant, switchTenant, isMultiTenant: !!currentTenant }; } // API客户端租户上下文 export function createApiClient(baseURL: string, tenantId?: number) { const client = rpcClient(baseURL); // 添加租户上下文到请求头 if (tenantId) { client.$default.headers.set('X-Tenant-ID', tenantId.toString()); } return client; } ``` ### 租户管理界面 ```typescript // 租户管理页面组件 export function TenantsPage() { const { data: tenants, isLoading } = useQuery({ queryKey: ['tenants'], queryFn: () => tenantClient.index.$get() }); const createMutation = useMutation({ mutationFn: (data: CreateTenantDto) => tenantClient.index.$post({ json: data }), onSuccess: () => { // 刷新租户列表 queryClient.invalidateQueries({ queryKey: ['tenants'] }); } }); return (

租户管理

); } ``` ## 实施策略 ### 阶段化实施 1. **第一阶段**: Server多租户集成(多租户包替换、租户上下文、认证增强) 2. **第二阶段**: Web多租户UI包集成(全面使用多租户UI包、移除本地实现) 3. **第三阶段**: 系统集成和验证(集成测试、性能测试、文档) ### 数据迁移策略 - 多租户系统使用全新数据,不迁移现有单租户数据 - 提供数据导出导入工具 - 保持两套系统数据独立 ## 技术实现要点 ### 向后兼容性保证 1. **包替换**: 直接替换单租户包为多租户包,保持相同API接口 2. **API 不变**: 现有单租户API接口和行为保持不变 3. **数据独立**: 多租户使用独立的数据表 4. **性能隔离**: 两套系统性能互不影响 ### 安全性考虑 1. **租户隔离**: 严格的租户数据隔离机制 2. **权限控制**: 租户间数据访问权限控制 3. **输入验证**: 所有用户输入进行严格的验证和转义 4. **审计日志**: 租户操作审计日志记录 ### 性能优化 1. **数据库索引**: 确保租户ID字段有合适的索引 2. **查询优化**: 租户过滤条件与现有查询条件合并 3. **连接池**: 优化数据库连接池配置 4. **缓存策略**: 租户级缓存策略 ## 测试策略 ### 单元测试 - 租户上下文管理测试 - 多租户包集成测试 - 认证中间件增强测试 - 前端租户Hook测试 ### 集成测试 - 租户数据隔离验证测试 - 租户管理界面功能测试 - 性能基准测试 ### 回归测试 - 现有单租户功能回归测试 - 向后兼容性验证测试 - API接口兼容性测试 --- ## Story Manager Handoff "请为这个brownfield epic开发详细的用户故事。关键考虑因素: - 这是基于史诗007已完成的多租户包,在现有Node.js + TypeScript + Hono + TypeORM + PostgreSQL + React技术栈上的集成 - 集成点:现有server包导入模式(packages/server/src/index.ts)、web中用户管理UI包的集成模式 - 需要遵循的现有模式:server直接包导入、web中UI包集成、Hono中间件、TypeORM实体、React组件、TanStack Query数据获取 - 关键发现:多租户模块包直接依赖多租户认证模块的认证中间件,其中已实现租户上下文管理(`c.set('tenantId', user.tenantId)`),无需额外添加租户中间件 - 故事结构简化:Server多租户集成(包替换、实体初始化、路由注册)在同一个文件中完成,前端无需租户上下文管理 - 关键兼容性要求:现有单租户系统完全不变、直接替换为多租户包、性能影响最小化 - 每个故事必须包含验证现有功能保持完整的回归测试 该epic应按照现有包集成模式,将server和web直接改为多租户系统,为后续按需拼装不同系统提供基础。" --- **🤖 Generated with [Claude Code](https://claude.ai/code)** via [Happy](https://happy.engineering) **Co-Authored-By: Claude ** **Co-Authored-By: Happy **