Ready for Review
As a 超级管理员, I want 将统一广告管理集成到租户后台,并从各租户admin后台移除广告管理功能,Server包切换到统一广告模块, so that 可以在租户后台统一管理所有租户的广告,所有租户用户端展示相同的广告数据,且小程序端无需任何修改。
@d8d/advertisements-module-mt 替换为 @d8d/unified-advertisements-module/api/v1/advertisements 和 /api/v1/advertisement-types 路由保持不变UnifiedAdvertisement 和 UnifiedAdvertisementType 实体[x] 任务1: 租户后台集成统一广告管理UI (AC: 1, 2, 8)
web/src/client/tenant/routes.tsx 添加广告管理路由web/src/client/tenant/layouts/MainLayout.tsx 添加菜单项(广告管理、广告类型管理)web/src/client/tenant/api_init.ts 中API客户端正确配置[x] 任务2: Admin后台移除广告管理功能 (AC: 3)
web/src/client/admin/routes.tsx 移除广告管理路由web/src/client/admin/layouts/MainLayout.tsx 移除菜单项@d8d/advertisement-management-ui-mt 和 @d8d/advertisement-type-management-ui-mt 的导入[x] 任务3: Server包替换模块引用 (AC: 4, 5, 6)
packages/server/src/index.ts 中:@d8d/advertisements-module-mt → @d8d/unified-advertisements-moduleAdvertisement, AdvertisementType → UnifiedAdvertisement, UnifiedAdvertisementTypeadvertisementRoutes, advertisementTypeRoutes → unifiedAdvertisementRoutes, unifiedAdvertisementTypeRoutesunifiedAdvertisementAdminRoutes, unifiedAdvertisementTypeAdminRoutesinitializeDataSource 中注册新实体packages/server/src/data-source.ts 中:packages/server/package.json 中:@d8d/advertisements-module-mt → @d8d/unified-advertisements-modulecd packages/server && pnpm typecheck[x] 任务4: Server包注册统一广告管理员路由 (AC: 1, 5, 8)
packages/server/src/index.ts 添加管理员路由注册:/api/v1/admin/unified-advertisements → unifiedAdvertisementAdminRoutes/api/v1/admin/unified-advertisement-types → unifiedAdvertisementTypeAdminRoutestenantAuthMiddleware(仅超级管理员可访问)[x] 任务5: E2E测试验证API兼容性 (AC: 5, 7)
web/tests/e2e/unified-advertisement-api.spec.ts 测试文件/api/v1/advertisements 端点返回统一广告数据/api/v1/advertisement-types 端点返回统一广告类型数据[x] 任务6: 集成测试验证管理员权限 (AC: 8)
packages/server/tests/integration/unified-advertisement-auth.integration.test.ts[x] 任务7: 更新史诗010文档 (AC: 完成)
docs/prd/epic-010-unified-ad-management.md 中标记故事010.006为完成测试成果:
data-testid 进行可靠的元素选择技术要点:
@hono/zod-openapi 的类型推断,通过 hc.rpc() 获取类型安全的客户端/api/v1/admin/unified-advertisementstenantAuthMiddleware,只有超级管理员(ID=1)可访问Server包集成:
packages/server/src/
├── index.ts # 主入口 - 需要修改
│ ├── 导入模块: @d8d/advertisements-module-mt → @d8d/unified-advertisements-module
│ ├── 实体注册: Advertisement → UnifiedAdvertisement
│ └── 路由注册: advertisementRoutes → unifiedAdvertisementRoutes
└── data-source.ts # 数据源配置 - 需要修改
└── 实体列表: Advertisement → UnifiedAdvertisement
租户后台集成:
web/src/client/tenant/
├── routes.tsx # 路由配置 - 需要添加广告管理路由
└── layouts/MainLayout.tsx # 布局组件 - 需要添加菜单项
Admin后台移除:
web/src/client/admin/
├── routes.tsx # 路由配置 - 需要移除广告管理路由
└── layouts/MainLayout.tsx # 布局组件 - 需要移除菜单项
用户端API(小程序使用,保持不变):
// 当前: advertisements-module-mt
// 切换后: unified-advertisements-module
// 路由路径和响应结构100%兼容
GET /api/v1/advertisements // 获取广告列表
GET /api/v1/advertisements/:id // 获取广告详情
GET /api/v1/advertisement-types // 获取广告类型列表
管理员API(新增,租户后台使用):
// 使用 tenantAuthMiddleware,仅超级管理员ID=1可访问
GET /api/v1/admin/unified-advertisements // 广告列表
POST /api/v1/admin/unified-advertisements // 创建广告
PUT /api/v1/admin/unified-advertisements/:id // 更新广告
DELETE /api/v1/admin/unified-advertisements/:id // 删除广告
GET /api/v1/admin/unified-advertisement-types // 广告类型列表
POST /api/v1/admin/unified-advertisement-types // 创建广告类型
PUT /api/v1/admin/unified-advertisement-types/:id // 更新广告类型
DELETE /api/v1/admin/unified-advertisement-types/:id // 删除广告类型
统一广告模块导出 [Source: packages/unified-advertisements-module/src/index.ts]:
// 实体
export { UnifiedAdvertisement } from './entities/unified-advertisement.entity';
export { UnifiedAdvertisementType } from './entities/unified-advertisement-type.entity';
// 管理员路由(新增,租户后台使用)
export { default as unifiedAdvertisementAdminRoutes } from './routes/admin/unified-advertisements.admin.routes';
export { default as unifiedAdvertisementTypeAdminRoutes } from './routes/admin/unified-advertisement-types.admin.routes';
// 用户路由(与原模块API兼容)
export { default as unifiedAdvertisementRoutes } from './routes/unified-advertisements.routes';
export { default as unifiedAdvertisementTypeRoutes } from './routes/unified-advertisement-types.routes';
Server包修改示例:
// packages/server/src/index.ts
// ===== 旧代码(删除)=====
import { Advertisement, AdvertisementType } from '@d8d/advertisements-module-mt';
import { advertisementRoutes, advertisementTypeRoutes } from '@d8d/advertisements-module-mt';
// ===== 新代码(使用)=====
import {
UnifiedAdvertisement,
UnifiedAdvertisementType
} from '@d8d/unified-advertisements-module';
import {
unifiedAdvertisementRoutes,
unifiedAdvertisementTypeRoutes,
unifiedAdvertisementAdminRoutes, // 新增:管理员路由
unifiedAdvertisementTypeAdminRoutes // 新增:管理员类型路由
} from '@d8d/unified-advertisements-module';
// ===== 数据源注册 =====
initializeDataSource([
// ...其他实体
// 旧: Advertisement, AdvertisementType,
新: UnifiedAdvertisement, UnifiedAdvertisementType,
]);
// ===== 路由注册 - 用户端(保持路径不变)=====
export const advertisementApiRoutes = api.route('/api/v1/advertisements', unifiedAdvertisementRoutes);
export const advertisementTypeApiRoutes = api.route('/api/v1/advertisement-types', unifiedAdvertisementTypeRoutes);
// ===== 路由注册 - 管理员端(新增)=====
export const adminUnifiedAdApiRoutes = api.route('/api/v1/admin/unified-advertisements', unifiedAdvertisementAdminRoutes);
export const adminUnifiedAdTypeApiRoutes = api.route('/api/v1/admin/unified-advertisement-types', unifiedAdvertisementTypeAdminRoutes);
路由配置 [Source: web/src/client/tenant/routes.tsx]:
// 添加广告管理路由
import { UnifiedAdvertisementManagement } from '@d8d/unified-advertisement-management-ui';
export const router = createBrowserRouter([
// ...
{
path: '/tenant',
element: <ProtectedRoute><MainLayout /></ProtectedRoute>,
children: [
// ...
{
path: 'unified-advertisements',
element: <UnifiedAdvertisementManagement />,
errorElement: <ErrorPage />
},
// ...
],
},
]);
路由配置 [Source: web/src/client/admin/routes.tsx]:
// 移除以下导入
// import { AdvertisementManagement } from '@d8d/advertisement-management-ui-mt';
// import { AdvertisementTypeManagement } from '@d8d/advertisement-type-management-ui-mt';
// 移除以下路由配置
// {
// path: 'advertisements',
// element: <AdvertisementManagement />,
// },
// {
// path: 'advertisement-types',
// element: <AdvertisementTypeManagement />,
// },
tenantAuthMiddleware [Source: docs/prd/epic-010-unified-ad-management.md]:
authMiddleware 进行多租户认证,但返回统一的广告数据(无tenant_id过滤)E2E测试重点 [Source: docs/architecture/testing-strategy.md]:
集成测试重点 [Source: docs/architecture/web-server-testing-standards.md]:
tenantAuthMiddleware,确保只有超级管理员可访问@d8d/advertisements-module-mt 包不动,便于回滚web/tests/e2e/unified-advertisement-api.spec.tspackages/server/tests/integration/unified-advertisement-auth.integration.test.ts| 测试类型 | 覆盖率要求 | 重点验证 |
|---|---|---|
| E2E测试 | 关键流程100% | API兼容性 |
| 集成测试 | ≥60% | 权限控制、数据源 |
# E2E测试(验证API兼容性)
cd web && pnpm test:e2e:chromium
# 集成测试(验证权限控制)
cd packages/server && pnpm test
# 类型检查
cd packages/server && pnpm typecheck
| Date | Version | Description | Author |
|---|---|---|---|
| 2026-01-03 | 1.0 | 初始故事创建 | James (Claude Code) |
| 2026-01-03 | 1.1 | 故事完成 - Ready for Review | James (Claude Code) |
| 2026-01-03 | 1.2 | 修复集成测试 - testClient调用方式修正 | James (Claude Code) |
| 2026-01-03 | 1.3 | 修复集成测试 - 全部17个测试通过 | James (Claude Code) |
| 2026-01-03 | 1.4 | E2E测试全部通过(50 passed, 5 skipped),更新测试策略文档 | James (Claude Code) |
claude-opus-4-5-20251101 (d8d-model)
集成测试修复 (第一轮): 修复 testClient 调用方式
../../src/api 导入路由集成测试修复 (第二轮): 修复API响应格式和数据清理
{ code, message, data: { list, total } } 而不是直接的数组data.data.list 而不是直接检查数组typeId 和 codedelete({}) 和 clear() 方法有外键约束问题find() + remove() 方法逐个删除集成测试修复 (第三轮): 修复测试生命周期和用户ID设置
afterEach 销毁数据源导致后续测试表不存在beforeAll 和 afterAll 而不是 beforeEach 和 afterEachsave() 后没有正确应用到数据库@d8d/advertisements-module-mt 替换为 @d8d/unified-advertisements-module/api/v1/advertisements 和 /api/v1/advertisement-types 保持不变/api/v1/admin/unified-advertisements 和 /api/v1/admin/unified-advertisement-types 路由docs/architecture/e2e-testing-standards.mddocs/architecture/testing-strategy.md (v3.1→v3.2)修改的文件:
web/src/client/tenant/routes.tsx - 添加广告管理路由web/src/client/tenant/menu.tsx - 添加广告管理菜单项web/src/client/tenant/api_init.ts - 初始化API客户端web/src/client/admin/routes.tsx - 移除广告管理路由web/src/client/admin/menu.tsx - 移除广告管理菜单项packages/server/src/index.ts - 替换模块导入和路由注册packages/server/src/data-source.ts - 替换实体注册packages/server/package.json - 替换依赖包docs/prd/epic-010-unified-ad-management.md - 更新史诗文档web/tests/e2e/playwright.config.ts - 修复testDir配置web/tests/e2e/unified-advertisement-api.spec.ts - 添加认证和修复响应解析docs/architecture/testing-strategy.md - 添加E2E测试规范引用新增的文件:
packages/server/tests/integration/unified-advertisement-auth.integration.test.ts - 管理员权限集成测试docs/architecture/e2e-testing-standards.md - E2E测试规范文档QA代理待填写