feat: 报告页 V2.2 检测可视化 + 评分引擎审计 + 真值回归/e2e 闭环
- server.js: face_maps 改为白名单 5 图层完整 dataURL 透传(REPORT_MAPS,按魔数判 mime),marks 坐标随 result 原样透传;实测 return_marks 不支持毛孔/黑头等扩展标记 - skin-score.js: 按需求文档 V2.2 逐字审计修正 9 处(黑眼圈 dark_circle_severity、oil_desc/spot_flag §7.2 拼接、skintone 中文映射、轮廓预警档前缀、痘痘 heavy_note、50+精华全文、综合文案数值格式),契约引用 V2.0→V2.2 - app.js/index.html/css: 报告页 6 分类检测可视化(轮廓=正脸实拍、皱纹=正脸压暗+皱纹增强线、光滑=正脸+色斑/痣/痤疮标记、肤色=色沉图、敏感=红区图、痘痘=正脸+闭口/痤疮标记),数据驱动 VIZ_CAT 配置,优雅降级 - h5/test/: Excel 两组三视图真值回归 84/84(含案例2 AY 列扁平化数据重建 fixture) - h5/assets/mock/: 真实案例1 报告页 fixture(坐标与照片同比例缩放),?mock=1&screen=report 直渲 - e2e: Chrome 无头闭环 55/55(mock 全流程/直渲/真实 API 降级链路),截图存档 preview/e2e-20260926 - 自测: skin-score 83/83,fixture 冒烟 35/35
This commit is contained in:
+18
-3
@@ -99,6 +99,16 @@ function readBody(req, limitBytes) {
|
||||
|
||||
const sleep = ms => new Promise(r => setTimeout(r, ms));
|
||||
|
||||
/* ─── 报告页图层白名单:face_maps 只透传这几层,一行增删 ─── */
|
||||
const REPORT_MAPS = ['red_area', 'brown_area', 'texture_enhanced_lines', 'texture_enhanced_pores', 'texture_enhanced_blackheads'];
|
||||
|
||||
/* 按 magic bytes 判断图片格式并补 data: URL 前缀(实测 red_area/brown_area 为 jpeg 头、其余 png,不硬编码) */
|
||||
function toDataUrl(b64) {
|
||||
const head = Buffer.from(b64.slice(0, 16), 'base64');
|
||||
const mime = (head[0] === 0xFF && head[1] === 0xD8) ? 'image/jpeg' : 'image/png';
|
||||
return 'data:' + mime + ';base64,' + b64;
|
||||
}
|
||||
|
||||
/* 剥离 data:image/xxx;base64, 前缀,空值返回 '' */
|
||||
function stripDataPrefix(s) {
|
||||
return (s || '').replace(/^data:image\/[a-zA-Z0-9+.-]+;base64,/, '');
|
||||
@@ -175,10 +185,15 @@ async function handleAnalyze(req, res) {
|
||||
return res.end(JSON.stringify({ ok: false, code: 'INTERNAL_ERROR', message: ERR_MSG.INTERNAL_ERROR }));
|
||||
}
|
||||
const result = fpJson.result;
|
||||
// face_maps 是整幅 base64 叠加图,体积过大且报告页暂不使用;
|
||||
// 这里只保留其键名列表,便于前端/调用方知晓可用图层
|
||||
// face_maps 是整幅 base64 叠加图,体积很大:只透传报告页所需图层(REPORT_MAPS),
|
||||
// 值补 data: URL 前缀供前端 <img> 直接用;未选中的图层直接删除键;
|
||||
// marks 坐标字段(acne/brown_spot/mole/closed_comedones/wrinkle_mark 等)本就在 result 里,原样透传
|
||||
if (result.face_maps && typeof result.face_maps === 'object') {
|
||||
result.face_maps = Object.keys(result.face_maps);
|
||||
const maps = {};
|
||||
for (const k of REPORT_MAPS) {
|
||||
if (typeof result.face_maps[k] === 'string' && result.face_maps[k]) maps[k] = toDataUrl(result.face_maps[k]);
|
||||
}
|
||||
result.face_maps = maps;
|
||||
}
|
||||
// 下颌线结果在响应顶层 left_side_result/right_side_result(不在 result 内),
|
||||
// 个别批次可能嵌套在 side_result 下,两种层级都兼容
|
||||
|
||||
Reference in New Issue
Block a user