feat: 添加MSW模拟服务和数据源集成

refactor: 重构页面组件移除冗余Layout组件

feat: 实现WebSocket和事件总线系统

feat: 添加队列和调度系统

docs: 更新架构文档和服务映射

style: 清理重复接口定义使用数据源

chore: 更新依赖项配置

feat: 添加运行时系统和领域引导

ci: 配置ESLint边界检查规则

build: 添加Redis和WebSocket依赖

test: 添加MSW浏览器环境入口

perf: 优化数据获取逻辑使用统一数据源

fix: 修复类型定义和状态管理问题
This commit is contained in:
2026-03-19 01:39:34 +08:00
parent cd55097dbf
commit 0dac26d781
176 changed files with 47075 additions and 8404 deletions

View File

@@ -1,47 +1,386 @@
import { Router } from 'express';
import { BizStrategyController } from '../controllers/BizStrategyController';
import { requireTraceContext } from '../../core/guards/trace-context.guard';
import { requirePermission } from '../../core/guards/rbac.guard';
import { Router, Request, Response } from 'express';
import StrategyService from '../../services/StrategyService';
import StrategyRecommendationService from '../../services/StrategyRecommendationService';
import { logger } from '../../utils/logger';
import { authenticate, authorize } from '../middleware/auth';
const router = Router();
/**
* [BIZ_AI_16] 交互式策略建议 (Actionable Insights)
*/
router.get('/advice', requireTraceContext, requirePermission('strategy:read'), BizStrategyController.getAdvice);
router.post('/advice/approve', requireTraceContext, requirePermission('strategy:execute'), BizStrategyController.approveAdvice);
router.get('/advice/:adviceId/explanation', requireTraceContext, requirePermission('strategy:read'), BizStrategyController.getAdviceExplanation);
router.get('/strategies', authenticate, async (req: Request, res: Response) => {
try {
const { category, isActive, isFeatured, limit, offset } = req.query;
/**
* [UX_IAT_01] 自治控制中心:停机与模式切换
*/
router.post('/kill-switch', requireTraceContext, requirePermission('strategy:kill'), BizStrategyController.toggleKillSwitch);
router.post('/mode', requireTraceContext, requirePermission('strategy:write'), BizStrategyController.updateAutonomousMode);
router.get('/status', requireTraceContext, BizStrategyController.getAutonomousStatus);
const result = await StrategyService.getAllStrategies({
category: category as string,
isActive: isActive === 'true' ? true : isActive === 'false' ? false : undefined,
isFeatured: isFeatured === 'true' ? true : isFeatured === 'false' ? false : undefined,
limit: limit ? parseInt(limit as string) : undefined,
offset: offset ? parseInt(offset as string) : undefined
});
/**
* [FE_SB_01] 策略仿真沙盒 (Sandbox Dashboard)
*/
router.post('/sandbox/run', requireTraceContext, requirePermission('strategy:write'), BizStrategyController.runSandboxSimulation);
router.get('/sandbox/results', requireTraceContext, requirePermission('strategy:read'), BizStrategyController.getSandboxResults);
res.json({
success: true,
data: result.strategies,
total: result.total
});
} catch (error) {
logger.error('[StrategyRoutes] Error fetching strategies:', error);
res.status(500).json({
success: false,
message: 'Failed to fetch strategies'
});
}
});
/**
* [BIZ_SC_11] 供应链询盘流 (Semi-Inquiry)
*/
router.post('/inquiry/start', requireTraceContext, BizStrategyController.startInquiry);
router.post('/inquiry/:inquiryId/review', requireTraceContext, BizStrategyController.reviewInquiry);
router.post('/inquiry/:inquiryId/send', requireTraceContext, BizStrategyController.sendInquiry);
router.post('/inquiry/:inquiryId/accept', requireTraceContext, BizStrategyController.acceptAndPurchase);
router.get('/strategies/featured', authenticate, async (req: Request, res: Response) => {
try {
const limit = req.query.limit ? parseInt(req.query.limit as string) : 5;
const strategies = await StrategyService.getFeaturedStrategies(limit);
/**
* [BIZ_TRADE_02] 多仓库存编排 (Inventory Orchestration)
*/
router.get('/inventory/orchestrate', requireTraceContext, BizStrategyController.orchestrateInventory);
router.post('/inventory/transfer', requireTraceContext, BizStrategyController.approveTransfer);
res.json({
success: true,
data: strategies
});
} catch (error) {
logger.error('[StrategyRoutes] Error fetching featured strategies:', error);
res.status(500).json({
success: false,
message: 'Failed to fetch featured strategies'
});
}
});
/**
* [BIZ_AIS_01] 独立站套利回流 (Pixel Feedback)
*/
router.post('/pixel/event', requireTraceContext, BizStrategyController.collectPixelEvent);
router.get('/strategies/trending', authenticate, async (req: Request, res: Response) => {
try {
const limit = req.query.limit ? parseInt(req.query.limit as string) : 5;
const strategies = await StrategyRecommendationService.getTrendingStrategies(limit);
res.json({
success: true,
data: strategies
});
} catch (error) {
logger.error('[StrategyRoutes] Error fetching trending strategies:', error);
res.status(500).json({
success: false,
message: 'Failed to fetch trending strategies'
});
}
});
router.get('/strategies/search', authenticate, async (req: Request, res: Response) => {
try {
const { q } = req.query;
if (!q || typeof q !== 'string') {
return res.status(400).json({
success: false,
message: 'Search query is required'
});
}
const strategies = await StrategyService.searchStrategies(q);
res.json({
success: true,
data: strategies
});
} catch (error) {
logger.error('[StrategyRoutes] Error searching strategies:', error);
res.status(500).json({
success: false,
message: 'Failed to search strategies'
});
}
});
router.get('/strategies/category/:category', authenticate, async (req: Request, res: Response) => {
try {
const { category } = req.params;
const strategies = await StrategyService.getStrategiesByCategory(category);
res.json({
success: true,
data: strategies
});
} catch (error) {
logger.error('[StrategyRoutes] Error fetching strategies by category:', error);
res.status(500).json({
success: false,
message: 'Failed to fetch strategies by category'
});
}
});
router.get('/strategies/:id', authenticate, async (req: Request, res: Response) => {
try {
const { id } = req.params;
const strategy = await StrategyService.getStrategyById(id);
if (!strategy) {
return res.status(404).json({
success: false,
message: 'Strategy not found'
});
}
res.json({
success: true,
data: strategy
});
} catch (error) {
logger.error('[StrategyRoutes] Error fetching strategy:', error);
res.status(500).json({
success: false,
message: 'Failed to fetch strategy'
});
}
});
router.get('/strategies/:id/similar', authenticate, async (req: Request, res: Response) => {
try {
const { id } = req.params;
const strategies = await StrategyRecommendationService.getSimilarStrategies(id);
res.json({
success: true,
data: strategies
});
} catch (error) {
logger.error('[StrategyRoutes] Error fetching similar strategies:', error);
res.status(500).json({
success: false,
message: 'Failed to fetch similar strategies'
});
}
});
router.post('/strategies', authenticate, authorize('strategy:create'), async (req: Request, res: Response) => {
try {
const strategy = await StrategyService.createStrategy({
...req.body,
created_by: (req as any).user?.id || 'system'
});
res.status(201).json({
success: true,
data: strategy,
message: 'Strategy created successfully'
});
} catch (error) {
logger.error('[StrategyRoutes] Error creating strategy:', error);
res.status(500).json({
success: false,
message: 'Failed to create strategy'
});
}
});
router.post('/strategies/:id/activate', authenticate, async (req: Request, res: Response) => {
try {
const { id } = req.params;
const tenantId = (req as any).user?.tenantId;
if (!tenantId) {
return res.status(400).json({
success: false,
message: 'Tenant ID not found'
});
}
const merchantStrategy = await StrategyService.activateStrategy({
tenantId,
strategyId: id,
config: req.body.config
});
res.status(201).json({
success: true,
data: merchantStrategy,
message: 'Strategy activated successfully'
});
} catch (error: any) {
logger.error('[StrategyRoutes] Error activating strategy:', error);
res.status(400).json({
success: false,
message: error.message || 'Failed to activate strategy'
});
}
});
router.get('/my-strategies', authenticate, async (req: Request, res: Response) => {
try {
const tenantId = (req as any).user?.tenantId;
const { status } = req.query;
if (!tenantId) {
return res.status(400).json({
success: false,
message: 'Tenant ID not found'
});
}
const strategies = await StrategyService.getMerchantStrategies(
tenantId,
status as 'ACTIVE' | 'PAUSED' | 'COMPLETED' | 'FAILED'
);
res.json({
success: true,
data: strategies
});
} catch (error) {
logger.error('[StrategyRoutes] Error fetching merchant strategies:', error);
res.status(500).json({
success: false,
message: 'Failed to fetch merchant strategies'
});
}
});
router.post('/my-strategies/:id/pause', authenticate, async (req: Request, res: Response) => {
try {
const { id } = req.params;
const tenantId = (req as any).user?.tenantId;
if (!tenantId) {
return res.status(400).json({
success: false,
message: 'Tenant ID not found'
});
}
await StrategyService.pauseStrategy(id, tenantId);
res.json({
success: true,
message: 'Strategy paused successfully'
});
} catch (error: any) {
logger.error('[StrategyRoutes] Error pausing strategy:', error);
res.status(400).json({
success: false,
message: error.message || 'Failed to pause strategy'
});
}
});
router.post('/my-strategies/:id/resume', authenticate, async (req: Request, res: Response) => {
try {
const { id } = req.params;
const tenantId = (req as any).user?.tenantId;
if (!tenantId) {
return res.status(400).json({
success: false,
message: 'Tenant ID not found'
});
}
await StrategyService.resumeStrategy(id, tenantId);
res.json({
success: true,
message: 'Strategy resumed successfully'
});
} catch (error: any) {
logger.error('[StrategyRoutes] Error resuming strategy:', error);
res.status(400).json({
success: false,
message: error.message || 'Failed to resume strategy'
});
}
});
router.post('/my-strategies/:id/complete', authenticate, async (req: Request, res: Response) => {
try {
const { id } = req.params;
const tenantId = (req as any).user?.tenantId;
const { roi, revenue } = req.body;
if (!tenantId) {
return res.status(400).json({
success: false,
message: 'Tenant ID not found'
});
}
if (roi === undefined || revenue === undefined) {
return res.status(400).json({
success: false,
message: 'ROI and revenue are required'
});
}
await StrategyService.completeStrategy(id, tenantId, { roi, revenue });
res.json({
success: true,
message: 'Strategy completed successfully'
});
} catch (error: any) {
logger.error('[StrategyRoutes] Error completing strategy:', error);
res.status(400).json({
success: false,
message: error.message || 'Failed to complete strategy'
});
}
});
router.get('/recommendations', authenticate, async (req: Request, res: Response) => {
try {
const tenantId = (req as any).user?.tenantId;
if (!tenantId) {
return res.status(400).json({
success: false,
message: 'Tenant ID not found'
});
}
const recommendations = await StrategyRecommendationService.getPersonalizedRecommendations(tenantId);
res.json({
success: true,
data: recommendations
});
} catch (error) {
logger.error('[StrategyRoutes] Error fetching recommendations:', error);
res.status(500).json({
success: false,
message: 'Failed to fetch recommendations'
});
}
});
router.get('/recommendations/category/:category', authenticate, async (req: Request, res: Response) => {
try {
const { category } = req.params;
const tenantId = (req as any).user?.tenantId;
if (!tenantId) {
return res.status(400).json({
success: false,
message: 'Tenant ID not found'
});
}
const recommendations = await StrategyRecommendationService.getCategoryRecommendations(
category,
tenantId
);
res.json({
success: true,
data: recommendations
});
} catch (error) {
logger.error('[StrategyRoutes] Error fetching category recommendations:', error);
res.status(500).json({
success: false,
message: 'Failed to fetch category recommendations'
});
}
});
export default router;