fix(report): recommend by measured skin age and align admin results
This commit is contained in:
+22
-8
@@ -257,6 +257,9 @@ function fillSuccess(rec, fpJson) {
|
||||
rec.detect_status = '成功';
|
||||
rec.fail_stage = null; rec.fail_code = null; rec.fail_msg = null;
|
||||
rec.skin_age = vm.skinAgeRaw;
|
||||
rec.skin_age_display = vm.skinAgeDisplay;
|
||||
rec.recommendation = vm.recommendation;
|
||||
rec.presentation = ReportUI.build(vm, fpJson.result);
|
||||
rec.total_score = vm.total;
|
||||
rec.jawline_angle_l = jawlineAngle(fpJson.left_side_result, 'left');
|
||||
rec.jawline_angle_r = jawlineAngle(fpJson.right_side_result, 'right');
|
||||
@@ -433,7 +436,7 @@ async function handleAnalyze(req, res) {
|
||||
let reportSaved = false, presentation = null, snapshotVm = null;
|
||||
try {
|
||||
snapshotVm = SkinScore.buildViewModel(result, payload.side, scoreProfile(rec));
|
||||
presentation = ReportUI.build(snapshotVm, result);
|
||||
presentation = rec.presentation || ReportUI.build(snapshotVm, result);
|
||||
accounts.storeReport(owner.id, { id: recordId, created_at: rec.created_at,
|
||||
version: '2026-10-09', profile, vm: snapshotVm, presentation, payload,
|
||||
photos: [front, left, right].map(b64 => b64 ? toDataUrl(b64) : null) });
|
||||
@@ -482,6 +485,12 @@ function photoUrls(rec) {
|
||||
}
|
||||
|
||||
/* 列表用的字段子集(不含 raw_json 与文案全文) */
|
||||
function displaySkinAge(rec) {
|
||||
if (Object.prototype.hasOwnProperty.call(rec, 'skin_age_display')) return rec.skin_age_display;
|
||||
// 旧记录没有展示值,沿用生成时的规则,不重算推荐或改写文件。
|
||||
if (rec.skin_age == null || rec.real_age == null) return rec.skin_age;
|
||||
return Math.min(Math.max(rec.skin_age, rec.real_age - 3), rec.real_age + 3);
|
||||
}
|
||||
function listItem(rec) {
|
||||
return {
|
||||
record_id: rec.record_id,
|
||||
@@ -490,6 +499,7 @@ function listItem(rec) {
|
||||
shoot_status: rec.shoot_status, upload_status: rec.upload_status, detect_status: rec.detect_status,
|
||||
fail_code: rec.fail_code, fail_msg: rec.fail_msg,
|
||||
total_score: rec.total_score, skin_age: rec.skin_age,
|
||||
skin_age_display: displaySkinAge(rec), recommendation: rec.recommendation || null,
|
||||
dims: rec.dims, group: rec.group,
|
||||
essence: rec.essence ? rec.essence.name : null,
|
||||
cost_ms: rec.cost_ms,
|
||||
@@ -576,7 +586,8 @@ function handleRecordDetail(req, res, id) {
|
||||
.map(r => ({ record_id: r.record_id, detect_status: r.detect_status, created_at: r.created_at }));
|
||||
sendJson(res, 200, {
|
||||
ok: true,
|
||||
record: rec,
|
||||
record: Object.assign({}, rec, { skin_age_display: displaySkinAge(rec),
|
||||
presentation: rec.presentation || accounts.reportPresentation(rec.owner_id, rec.record_id) }),
|
||||
raw_json: rawJson,
|
||||
photos: photoUrls(rec),
|
||||
versions: {
|
||||
@@ -733,21 +744,24 @@ function handleExport(req, res, url) {
|
||||
.sort((a, b) => (a.created_at < b.created_at ? 1 : -1));
|
||||
const dimP = (r, d) => (r.dims && r.dims[d]) ? r.dims[d].P : null;
|
||||
const dimS = (r, d) => (r.dims && r.dims[d]) ? r.dims[d].S : null;
|
||||
const dimLv = (r, d) => (r.dims && r.dims[d]) ? r.dims[d].level : null;
|
||||
const dimLv = (r, d) => (r.dims && r.dims[d]) ? ReportUI.levelMap[r.dims[d].level] : null;
|
||||
const header = ['记录ID', '创建时间', '年龄', '性别', '地区', '日常肤质', '拍摄状态', '上传状态', '检测状态',
|
||||
'失败环节', '失败码', '失败信息', '总分', '肌肤年龄',
|
||||
'紧塑力P', '紧塑力S', '紧塑力档', '活力感P', '活力感S', '活力感档', '稳定力P', '稳定力S', '稳定力档',
|
||||
'均分S', '产品组别', '推荐精华', '触发判据', '耗时ms'];
|
||||
'失败环节', '失败码', '失败信息', '总分', '原始肌龄(推荐依据)', '前端展示肌龄',
|
||||
'紧塑力P', '紧塑力S', '紧塑力档', '透亮感P', '透亮感S', '透亮感档', '稳韧力P', '稳韧力S', '稳韧力档',
|
||||
'均分S', '产品组别', '推荐精华', '触发判据', '耗时ms', '推荐规则版本', '推荐原因'];
|
||||
const lines = [header.join(',')];
|
||||
for (const r of filtered) {
|
||||
lines.push([
|
||||
r.record_id, r.created_at, r.real_age, r.gender, r.region, r.daily_skin_type,
|
||||
r.shoot_status, r.upload_status, r.detect_status,
|
||||
r.fail_stage, r.fail_code, r.fail_msg, r.total_score, r.skin_age,
|
||||
r.fail_stage, r.fail_code, r.fail_msg, r.total_score, r.skin_age, displaySkinAge(r),
|
||||
dimP(r, 'firm'), dimS(r, 'firm'), dimLv(r, 'firm'),
|
||||
dimP(r, 'vita'), dimS(r, 'vita'), dimLv(r, 'vita'),
|
||||
dimP(r, 'stab'), dimS(r, 'stab'), dimLv(r, 'stab'),
|
||||
r.avg_s, r.group, r.essence ? r.essence.name : null, r.trigger, r.cost_ms
|
||||
r.avg_s, r.group, r.essence ? ((ReportUI.products.find(p => p.match === r.essence.name) || {}).title || r.essence.name) : null,
|
||||
r.trigger, r.cost_ms,
|
||||
r.recommendation ? r.recommendation.version : '旧版规则(历史记录)',
|
||||
r.recommendation ? r.recommendation.reason : null
|
||||
].map(csvCell).join(','));
|
||||
}
|
||||
const fromTag = (q.from || 'all').replace(/[^\d-]/g, '');
|
||||
|
||||
Reference in New Issue
Block a user