- 将服务文件按功能分类到core、ai、analytics、security等目录 - 修复logger导入路径问题,统一使用相对路径 - 更新相关文件的导入路径引用 - 添加新的批量操作组件导出文件 - 修复dashboard页面中的类型错误 - 添加dotenv依赖到package.json
161 lines
4.7 KiB
TypeScript
161 lines
4.7 KiB
TypeScript
import { Request, Response } from 'express';
|
|
import db from '../../config/database';
|
|
import { isValidSyncStatusTransition } from '../../core/guards/state-transition.guard';
|
|
import { AuditService } from '../../services/utils/AuditService';
|
|
|
|
export class SyncController {
|
|
/**
|
|
* [UX_DEV_03] 接收插件端上报的 E2E 异常
|
|
*/
|
|
static async reportAudit(req: Request, res: Response) {
|
|
try {
|
|
const { action, targetType, targetId, metadata } = req.body;
|
|
const { tenantId, shopId, taskId, traceId, userId, roleCode } = (req as any).traceContext;
|
|
|
|
await AuditService.log({
|
|
tenantId,
|
|
shopId,
|
|
taskId,
|
|
traceId,
|
|
userId,
|
|
roleCode,
|
|
module: 'SYNC',
|
|
action: action || 'AUDIT_REPORT',
|
|
resourceType: targetType || 'sync',
|
|
resourceId: targetId ? String(targetId) : undefined,
|
|
result: 'success',
|
|
source: 'extension',
|
|
metadata,
|
|
});
|
|
res.json({ success: true });
|
|
} catch (error: any) {
|
|
res.status(500).json({ success: false, error: error.message });
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 分发产品数据至全平台 (Mock 实现,实际应触发各平台发布 Worker)
|
|
*/
|
|
static async distribute(req: Request, res: Response) {
|
|
try {
|
|
const { originalUrl, productData } = req.body;
|
|
const { tenantId, shopId, taskId, traceId, userId, roleCode } = (req as any).traceContext;
|
|
|
|
const platforms = ['Temu', 'TikTok', 'Shopee'];
|
|
|
|
for (const platform of platforms) {
|
|
const existing = await db('cf_sync_status')
|
|
.where({ originalUrl, platform })
|
|
.first();
|
|
|
|
if (existing) {
|
|
await db('cf_sync_status')
|
|
.where({ id: existing.id })
|
|
.update({
|
|
status: 'pending',
|
|
productData: JSON.stringify(productData || {}),
|
|
updated_at: new Date()
|
|
});
|
|
} else {
|
|
await db('cf_sync_status').insert({
|
|
originalUrl,
|
|
platform,
|
|
status: 'pending',
|
|
productData: JSON.stringify(productData || {}),
|
|
created_at: new Date(),
|
|
updated_at: new Date()
|
|
});
|
|
}
|
|
}
|
|
|
|
await AuditService.log({
|
|
tenantId,
|
|
shopId,
|
|
taskId,
|
|
traceId,
|
|
userId,
|
|
roleCode,
|
|
module: 'SYNC',
|
|
action: 'DISTRIBUTE',
|
|
resourceType: 'sync',
|
|
resourceId: String(originalUrl || ''),
|
|
result: 'success',
|
|
source: 'console',
|
|
});
|
|
res.json({ success: true, data: { triggered: true } });
|
|
} catch (error: any) {
|
|
res.status(500).json({ success: false, error: error.message });
|
|
}
|
|
}
|
|
|
|
static async recordAction(req: Request, res: Response) {
|
|
try {
|
|
const { platform, action, status } = req.body;
|
|
const { tenantId, shopId, taskId, traceId, userId, roleCode } = (req as any).traceContext;
|
|
|
|
await AuditService.log({
|
|
tenantId,
|
|
shopId,
|
|
taskId,
|
|
traceId,
|
|
userId,
|
|
roleCode,
|
|
module: 'SYNC',
|
|
action: 'RECORD_ACTION',
|
|
resourceType: 'sync_log',
|
|
resourceId: platform,
|
|
afterSnapshot: { action, status },
|
|
result: 'success',
|
|
source: 'console',
|
|
});
|
|
|
|
res.json({ success: true });
|
|
} catch (error: any) {
|
|
res.status(500).json({ success: false, error: error.message });
|
|
}
|
|
}
|
|
|
|
/**
|
|
* [FSM] 状态流转控制
|
|
*/
|
|
static async updateStatus(req: Request, res: Response) {
|
|
const { id } = req.params;
|
|
const { status } = req.body;
|
|
const { tenantId, shopId, taskId, traceId, userId } = (req as any).traceContext;
|
|
|
|
try {
|
|
const record = await db('cf_sync_status').where({ id }).first();
|
|
if (!record) return res.status(404).json({ success: false, error: 'Sync record not found' });
|
|
|
|
const previousStatus = record.status;
|
|
const nextStatus = status;
|
|
|
|
if (!isValidSyncStatusTransition(previousStatus, nextStatus)) {
|
|
return res.status(400).json({ success: false, error: `Invalid sync status transition: ${previousStatus} -> ${nextStatus}` });
|
|
}
|
|
|
|
await db('cf_sync_status').where({ id }).update({ status: nextStatus, updated_at: new Date() });
|
|
|
|
await AuditService.log({
|
|
tenantId,
|
|
shopId,
|
|
taskId,
|
|
traceId,
|
|
userId,
|
|
module: 'SYNC',
|
|
action: 'UPDATE_SYNC_STATUS',
|
|
resourceType: 'sync',
|
|
resourceId: String(record.id),
|
|
beforeSnapshot: { status: previousStatus },
|
|
afterSnapshot: { status: nextStatus },
|
|
result: 'success',
|
|
source: 'node',
|
|
});
|
|
|
|
res.json({ success: true });
|
|
} catch (err: any) {
|
|
res.status(500).json({ success: false, error: err.message });
|
|
}
|
|
}
|
|
}
|