feat(admin): track capture-to-report conversion funnel
This commit is contained in:
@@ -29,6 +29,7 @@ const ReportUI = require('./js/report-ui.js');
|
||||
const BeijingTime = require('./js/beijing-time.js');
|
||||
const CaptureDiagnostics = require('./lib/capture-diagnostics.js');
|
||||
const WrinkleViews = require('./lib/wrinkle-views.js');
|
||||
const captureFunnel = require('./lib/capture-funnel.js')(path.join(DATA_ROOT, 'capture-funnel.jsonl'));
|
||||
const accounts = require('./lib/accounts.js')(path.join(DATA_ROOT, 'accounts'));
|
||||
|
||||
/* 服务端评分引擎:与 C 端同一份公式(禁止复制公式,直接复用) */
|
||||
@@ -751,6 +752,7 @@ function handleStats(req, res) {
|
||||
fail_total: failed.length,
|
||||
success_rate: finished.length ? Math.round(succeeded.length * 1000 / finished.length) / 10 : 0,
|
||||
avg_cost_ms: avgCost,
|
||||
capture_funnel: captureFunnel.stats(now),
|
||||
fail_dist,
|
||||
dim_dist,
|
||||
group_dist,
|
||||
@@ -874,6 +876,13 @@ async function handleAdmin(req, res, pathname, url) {
|
||||
http.createServer(async (req, res) => {
|
||||
const pathname = req.url.split('?')[0];
|
||||
if (await accounts.route(req, res, pathname)) return;
|
||||
if (req.method === 'POST' && pathname === '/api/capture-funnel') {
|
||||
if (!accounts.sameOrigin(req) || !accounts.session(req)) return sendJson(res, 403, { ok: false });
|
||||
try {
|
||||
const accepted = captureFunnel.ingest(JSON.parse((await readBody(req, 4096)).toString('utf8')));
|
||||
return sendJson(res, accepted ? 200 : 400, { ok: accepted });
|
||||
} catch (e) { return sendJson(res, e.message === 'TOO_LARGE' ? 413 : e instanceof SyntaxError ? 400 : 500, { ok: false }); }
|
||||
}
|
||||
if (req.method === 'POST' && pathname === '/api/skin-analyze') return handleAnalyze(req, res);
|
||||
if (req.method === 'GET' && pathname === '/api/health') {
|
||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||
|
||||
Reference in New Issue
Block a user