openapi: 3.0.3 info: title: BLS Project Console API version: 1.0.0 description: | BLS Project Console 后端 API(与当前实现保持一致)。 servers: - url: http://localhost:3001 paths: /api/health: get: summary: Health check responses: '200': description: OK content: application/json: schema: type: object properties: status: type: string required: [status] /api/projects: get: summary: 获取项目列表(来自 Redis 项目心跳列表) responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/ProjectsResponse' '503': description: Redis 未就绪 content: application/json: schema: $ref: '#/components/schemas/ProjectsErrorResponse' /api/projects/migrate: post: summary: 从旧 *_项目心跳 键迁移到 项目心跳 列表 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/MigrateRequest' responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/MigrateResponse' '500': description: Migration failed content: application/json: schema: $ref: '#/components/schemas/MigrateErrorResponse' /api/logs: get: summary: 获取指定项目的日志 parameters: - in: query name: projectName required: true schema: type: string - in: query name: limit required: false schema: type: integer default: 200 responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/LogsResponse' /api/commands: post: summary: 发送控制指令到目标项目 API requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CommandRequest' responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/CommandResponse' components: schemas: Project: type: object properties: id: type: string description: 项目 id(当前实现为 projectName) name: type: string description: 项目名称 apiBaseUrl: type: string nullable: true description: 项目 API 地址(基础 URL) lastActiveAt: type: integer format: int64 nullable: true description: 最新心跳时间(Unix 时间戳毫秒) status: type: string enum: [online, offline, unknown] isOnline: type: boolean ageMs: type: integer format: int64 nullable: true required: [id, name, status, isOnline] ProjectsResponse: type: object properties: success: type: boolean projects: type: array items: $ref: '#/components/schemas/Project' count: type: integer required: [success, projects, count] ProjectsErrorResponse: type: object properties: success: type: boolean message: type: string projects: type: array items: $ref: '#/components/schemas/Project' required: [success, message, projects] MigrateRequest: type: object properties: deleteOldKeys: type: boolean default: false dryRun: type: boolean default: false MigrateResponse: type: object properties: success: type: boolean message: type: string migrated: type: integer projects: type: array items: type: object properties: projectName: type: string apiBaseUrl: type: string nullable: true lastActiveAt: type: integer format: int64 nullable: true required: [projectName] listKey: type: string example: 项目心跳 deleteOldKeys: type: boolean required: [success, message] MigrateErrorResponse: type: object properties: success: type: boolean message: type: string error: type: string required: [success, message] LogsResponse: type: object properties: logs: type: array items: type: object additionalProperties: true projectStatus: type: string nullable: true heartbeat: type: object nullable: true properties: apiBaseUrl: type: string nullable: true lastActiveAt: type: integer format: int64 nullable: true isOnline: type: boolean ageMs: type: integer format: int64 nullable: true CommandRequest: type: object properties: targetProjectName: type: string command: type: string required: [targetProjectName, command] CommandResponse: type: object properties: success: type: boolean message: type: string commandId: type: string targetUrl: type: string upstreamStatus: type: integer upstreamData: nullable: true required: [success, message]