feat: 初始化项目结构并添加核心功能模块

- 新增文档模板和导航结构
- 实现服务器基础API路由和控制器
- 添加扩展插件配置和前端框架
- 引入多租户和权限管理模块
- 集成日志和数据库配置
- 添加核心业务模型和类型定义
This commit is contained in:
2026-03-17 22:07:19 +08:00
parent c0870dce50
commit 136c2fa579
728 changed files with 107690 additions and 5614 deletions

124
node-agent/src/index.ts Normal file
View File

@@ -0,0 +1,124 @@
import axios from 'axios';
import os from 'os';
export interface NodeTask {
id: string;
type: string;
payload: any;
shopId: string;
traceId: string;
}
/**
* [CORE_NODE_01] Win Node Agent
* @description 运行在 Windows 环境下的自管代理,负责无 API 平台的执行动作
*/
export class NodeAgent {
private hubUrl: string;
private nodeId: string;
private heartbeatInterval: number = 30000; // 30秒
private pollInterval: number = 10000; // 10秒
constructor(hubUrl: string) {
this.hubUrl = hubUrl;
this.nodeId = `WIN-${os.hostname()}-${process.pid}`;
}
/**
* 启动代理
*/
async start() {
console.log(`[Agent] Node ${this.nodeId} starting...`);
// 1. 注册节点
await this.register();
// 2. 开启心跳
const heartbeatTimer = setInterval(() => this.heartbeat(), this.heartbeatInterval);
// @ts-ignore
if (heartbeatTimer.unref) heartbeatTimer.unref();
// 3. 开启任务轮询
const pollTimer = setInterval(() => this.pollTasks(), this.pollInterval);
// @ts-ignore
if (pollTimer.unref) pollTimer.unref();
}
private async register() {
try {
console.log(`[Agent] Registering to Hub: ${this.hubUrl}`);
await axios.post(`${this.hubUrl}/api/v1/nodes/register`, {
nodeId: this.nodeId,
version: '1.0.0',
os: os.type(),
hostname: os.hostname(),
shops: [] // 实际应从本地配置加载
}).catch(err => {
// 如果 Hub 还没启动,忽略错误,仅打印
console.warn(`[Agent] Registration failed (Hub might be offline): ${err.message}`);
});
} catch (err: any) {
console.error(`[Agent] Registration error: ${err.message}`);
}
}
private async heartbeat() {
try {
console.log(`[Agent] Heartbeat...`);
await axios.post(`${this.hubUrl}/api/v1/nodes/heartbeat`, { nodeId: this.nodeId })
.catch(() => {}); // 忽略心跳失败
} catch (err: any) {
console.error(`[Agent] Heartbeat error: ${err.message}`);
}
}
private async pollTasks() {
try {
console.log(`[Agent] Polling for tasks...`);
const response = await axios.get(`${this.hubUrl}/api/v1/nodes/pull-task?nodeId=${this.nodeId}`)
.catch(() => ({ data: { task: null } }));
if (response.data && response.data.task) {
await this.executeTask(response.data.task);
}
} catch (err: any) {
console.error(`[Agent] Poll error: ${err.message}`);
}
}
private async executeTask(task: NodeTask) {
console.log(`[Agent] Executing task: ${task.id} (${task.type})`);
try {
// 模拟执行耗时
await new Promise(resolve => setTimeout(resolve, 2000));
// 实际应启动 Playwright 浏览器执行动作
console.log(`[Agent] Task ${task.id} executed successfully.`);
await this.reportReceipt({
taskId: task.id,
traceId: task.traceId,
status: 'success',
resultData: { platform: 'TikTok', action: 'PUBLISH' }
});
} catch (err: any) {
console.error(`[Agent] Task ${task.id} execution failed: ${err.message}`);
await this.reportReceipt({
taskId: task.id,
traceId: task.traceId,
status: 'failed',
errorMessage: err.message
});
}
}
private async reportReceipt(receipt: any) {
try {
console.log(`[Agent] Reporting receipt for Task: ${receipt.taskId}`);
await axios.post(`${this.hubUrl}/api/v1/publish/receipt`, receipt);
} catch (err: any) {
console.error(`[Agent] Failed to report receipt: ${err.message}`);
}
}
}

11
node-agent/src/main.ts Normal file
View File

@@ -0,0 +1,11 @@
import 'dotenv/config';
import { NodeAgent } from './index';
const HUB_URL = process.env.HUB_URL || 'http://localhost:3000';
const agent = new NodeAgent(HUB_URL);
agent.start().catch(err => {
console.error('[Agent] Fatal error:', err);
process.exit(1);
});