import { createServer, IncomingMessage, ServerResponse } from 'node:http'; type JsonValue = Record | Array; interface Candidate { platform: string; name: string; fans: string; price: number; score: number; styleMatch: number; status: string; reason: string; risk: string; } const port = Number(process.env.TIHAO_AI_API_PORT ?? 4300); const demoRequirements = [ { label: '客户/品牌', value: '客户A / 新锐护肤品牌', confidence: 96 }, { label: '投放目标', value: '新品种草、真实测评、站内转化蓄水', confidence: 92 }, { label: '平台需求', value: '小红书 20人、抖音 8人、B站 4人', confidence: 90 }, { label: '内容风格', value: '真实体验、通勤生活、轻专业成分党', confidence: 88 } ]; const demoRules = [ '按 Brief 平台优先提号', '默认推荐数量不少于需求 3 倍', '风格匹配低于 80% 自动降级', '黑名单与低配合度剔除', '优先近期采集有效价格' ]; const demoCandidates: Candidate[] = [ { platform: '小红书', name: '梨涡测评室', fans: '18.6万', price: 6800, score: 94, styleMatch: 91, status: '强推荐', reason: '近10篇中 9 篇为真实体验或成分拆解,互动中位数高于同价位账号 28%。', risk: '视频内容偏少,可作为图文主推。' }, { platform: '抖音', name: '林小林认真护肤', fans: '42.1万', price: 12800, score: 87, styleMatch: 82, status: '备选', reason: '爆文率和完播率表现稳定,预算接近上限,建议作为抖音头部备选。', risk: '单条报价较高,需确认档期。' } ]; function sendJson(response: ServerResponse, statusCode: number, payload: JsonValue): void { const body = JSON.stringify(payload); response.writeHead(statusCode, { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': 'Content-Type', 'Access-Control-Allow-Methods': 'GET,POST,OPTIONS', 'Content-Type': 'application/json; charset=utf-8', 'Content-Length': Buffer.byteLength(body) }); response.end(body); } function sendExcel(response: ServerResponse, filename: string, candidates: Candidate[]): void { const rows = candidates .map( (candidate) => ` ${escapeHtml(candidate.platform)} ${escapeHtml(candidate.name)} ${escapeHtml(candidate.fans)} ${candidate.price} ${candidate.score} ${candidate.styleMatch}% ${escapeHtml(candidate.status)} ${escapeHtml(candidate.reason)} ${escapeHtml(candidate.risk)} ` ) .join(''); const body = ` ${rows}
平台账号粉丝量报价综合分风格匹配推荐状态推荐理由风险提示
`; response.writeHead(200, { 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/vnd.ms-excel; charset=utf-8', 'Content-Disposition': `attachment; filename="${encodeURIComponent(filename)}"`, 'Content-Length': Buffer.byteLength(body) }); response.end(body); } function readBody(request: IncomingMessage): Promise> { return new Promise((resolve) => { let body = ''; request.on('data', (chunk) => { body += chunk; }); request.on('end', () => { if (!body) { resolve({}); return; } try { resolve(JSON.parse(body)); } catch { resolve({}); } }); }); } function escapeHtml(value: string): string { return value .replaceAll('&', '&') .replaceAll('<', '<') .replaceAll('>', '>') .replaceAll('"', '"'); } const server = createServer(async (request, response) => { const requestUrl = new URL(request.url ?? '/', `http://${request.headers.host ?? 'localhost'}`); if (request.method === 'OPTIONS') { sendJson(response, 200, { ok: true }); return; } if (request.method === 'GET' && requestUrl.pathname === '/api/health') { sendJson(response, 200, { ok: true, name: '提号AI Mock API', resourcesPath: 'D:\\公司优秀媒体资源库\\4月份资源库' }); return; } if (request.method === 'POST' && requestUrl.pathname === '/api/analyze-brief') { sendJson(response, 200, { requirements: demoRequirements, rules: demoRules, message: 'Demo 已模拟解析 Brief,真实环境会接入 Excel/Docx 解析与 LLM 抽取。' }); return; } if (request.method === 'POST' && requestUrl.pathname === '/api/recommend') { sendJson(response, 200, { candidates: demoCandidates, totalPool: 104, message: 'Demo 已模拟按规则生成推荐池。' }); return; } if (request.method === 'POST' && requestUrl.pathname === '/api/rules/learn') { sendJson(response, 200, { suggestions: [ { title: '小红书减少泛美妆号,优先生活方式和通勤场景', confidence: 93 }, { title: '抖音预算压低时保留爆文率高账号', confidence: 87 } ] }); return; } if (request.method === 'POST' && requestUrl.pathname === '/api/recommendations/export') { const body = await readBody(request); const candidates = Array.isArray(body['candidates']) ? (body['candidates'] as Candidate[]) : demoCandidates; sendExcel(response, '客户A-新锐护肤品牌-需求推荐名单.xls', candidates); return; } sendJson(response, 404, { ok: false, message: 'Not found' }); }); server.listen(port, () => { console.log(`Tihao AI mock API listening on http://localhost:${port}`); });