feat(h5): allow guest access without login and retain history only for WeChat

This commit is contained in:
xsl
2026-10-13 15:23:23 +08:00
parent 98935dd168
commit 1fdbb575b0
29 changed files with 2561 additions and 1866 deletions
+21 -14
View File
@@ -267,7 +267,7 @@ function scoreProfile(rec) {
}
/* 检测成功:用 SkinScore.buildViewModel 计算并补全记录字段(复用同一份公式) */
function fillSuccess(rec, fpJson) {
function fillSuccess(rec, fpJson, persist = true) {
// Observation only: do not block, re-shoot, retry or alter scoring based on it.
rec.capture_quality = CaptureDiagnostics.assess(fpJson);
const vm = SkinScore.buildViewModel(fpJson.result, {
@@ -299,7 +299,7 @@ function fillSuccess(rec, fpJson) {
rec.essence_line = vm.essence ? vm.essence.text : null;
rec.trigger = (vm.essence && vm.essence.triggers) ? vm.essence.triggers.join(',') : null;
rec.notes = vm.notes || [];
rec.raw_file = dumpRaw(fpJson);
rec.raw_file = persist ? dumpRaw(fpJson) : null;
}
/* 检测失败:补失败字段 */
@@ -311,7 +311,7 @@ function fillFailure(rec, code) {
}
/* 执行一次检测:计时调用 Face++,按结果补全记录(成功/失败都落库)。返回 Face++ 原始返回 */
async function runDetect(rec, front, left, right) {
async function runDetect(rec, front, left, right, persist = true) {
rec.detect_status = '检测中';
rec.updated_at = nowIso();
const t0 = Date.now();
@@ -325,7 +325,7 @@ async function runDetect(rec, front, left, right) {
fillFailure(rec, 'INTERNAL_ERROR');
} else {
try {
fillSuccess(rec, fpJson);
fillSuccess(rec, fpJson, persist);
} catch (e) { // 评分异常按检测失败落库,但不改写 C 端成功响应(原始结果仍透传)
console.log(`[analyze] 评分异常: ${e.message}`);
fillFailure(rec, 'INTERNAL_ERROR');
@@ -372,10 +372,13 @@ async function callFacepp(front, left, right) {
}
async function handleAnalyze(req, res) {
res.setHeader('Cache-Control', 'no-store');
let rec = null; // 记录:正脸照片校验通过后创建(此前失败无从落库)
let persist = false;
try {
const owner = accounts.session(req);
if (!owner) return sendJson(res, 401, { ok: false, message: '请先登录后检测' });
persist = owner.kind === 'wechat';
if (!accounts.sameOrigin(req)) return sendJson(res, 403, { ok: false, message: '请求来源不匹配' });
const body = JSON.parse((await readBody(req, 20 * 1024 * 1024)).toString('utf8'));
// 三个 image 字段先做类型检查:非字符串视为缺失(左/右图缺失时仅发正脸,接口自动降级为单视图)
@@ -394,7 +397,7 @@ async function handleAnalyze(req, res) {
/* ── 记录落库:生成 record_id → 写照片 → 落一条 detect_status=检测中 ── */
const profile = normalizeProfile(body.profile);
const recordId = newRecordId();
const photos = writePhotos(recordId, { front, left, right });
const photos = persist ? writePhotos(recordId, { front, left, right }) : {};
rec = {
record_id: recordId,
owner_id: owner.id,
@@ -420,11 +423,13 @@ async function handleAnalyze(req, res) {
retry_of: null, retry_count: 0
};
rec.capture_diagnostics = CaptureDiagnostics.normalize(body.capture_diagnostics);
appendRecord(rec);
console.log(`[record] 新检测记录 ${recordId}(${rec.shoot_status},照片${Object.keys(photos).length}/3)`);
if (persist) {
appendRecord(rec);
console.log(`[record] 新检测记录 ${recordId}(${rec.shoot_status},照片${Object.keys(photos).length}/3)`);
}
const fpJson = await runDetect(rec, front, left, right);
updateRecord(rec);
const fpJson = await runDetect(rec, front, left, right, persist);
if (persist) updateRecord(rec);
if (fpJson.error_message) {
const code = fpJson.error_message.split(':')[0];
@@ -458,10 +463,12 @@ async function handleAnalyze(req, res) {
try {
snapshotVm = SkinScore.buildViewModel(result, payload.side, scoreProfile(rec));
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) });
reportSaved = true;
if (persist) {
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) });
reportSaved = true;
}
} catch (e) { console.error('[report] 完整报告保存失败:', e.message); }
res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
res.end(JSON.stringify({
@@ -475,7 +482,7 @@ async function handleAnalyze(req, res) {
}
}));
} catch (e) {
if (rec) { // 记录已创建但流程异常:按检测失败补全,便于后台看到这条调用
if (rec && persist) { // 仅微信检测失败记录落库;游客不保留异常记录。
fillFailure(rec, e.message === 'TOO_LARGE' ? 'IMAGE_FILE_TOO_LARGE' : 'NETWORK_ERROR');
rec.updated_at = nowIso();
updateRecord(rec);