diff --git a/h5/js/admin.js b/h5/js/admin.js
index b86e579..7c49b36 100644
--- a/h5/js/admin.js
+++ b/h5/js/admin.js
@@ -115,7 +115,7 @@ function loadRecords() {
var tr = el('tr');
var photos = it.photos || {};
var thumb = photos.front
- ? ''
+ ? '
'
: '无';
tr.innerHTML =
'
' + + var rawDl = data.raw_file + ? ' 下载完整原始 JSON' + : ''; + h += dSec('接口原始 JSON', ''); } else { h += dSec('接口原始 JSON', '展开/收起(' + (data.raw_file || '') + ')' + rawDl + '
' + esc(JSON.stringify(data.raw_json, null, 1)) + '无(失败记录或未落盘)'); diff --git a/h5/server.js b/h5/server.js index f8d62e6..87ad22a 100644 --- a/h5/server.js +++ b/h5/server.js @@ -524,13 +524,23 @@ function handleRecordsQuery(req, res, url) { function handleRecordDetail(req, res, id) { const rec = findRecord(id); if (!rec) return sendJson(res, 404, { ok: false, message: '记录不存在' }); - // 原始 JSON 全文:读文件失败给 null + // 原始 JSON 全文:读文件失败给 null。 + // face_maps 是整幅 base64 叠加图(单文件可达数 MB),详情页直接渲染会卡死浏览器: + // 展示层把各图层值替换为占位说明,完整原文件走 /api/admin/records/:id/raw 下载 let rawJson = null; if (rec.raw_file) { const fname = String(rec.raw_file).replace(/[^\w.,-]/g, ''); try { rawJson = JSON.parse(fs.readFileSync(path.join(DATA_DIR, fname), 'utf8')); } catch (e) { rawJson = null; } } + if (rawJson && rawJson.result && rawJson.result.face_maps) { + for (const k of Object.keys(rawJson.result.face_maps)) { + const v = rawJson.result.face_maps[k]; + if (typeof v === 'string' && v.length) { + rawJson.result.face_maps[k] = ``; + } + } + } // 版本链:它 retry_of 指向的(父)+ retry_of 指向它的(子) const all = readAllRecords(); const parent = rec.retry_of ? (all.find(r => r.record_id === rec.retry_of) || null) : null; @@ -548,6 +558,22 @@ function handleRecordDetail(req, res, id) { }); } +/* 完整原始 JSON 下载(face_maps base64 未裁剪,动辄数 MB,仅供复核下载,不做页面内展示) */ +function handleRawDownload(req, res, id) { + const rec = findRecord(id); + if (!rec || !rec.raw_file) return sendJson(res, 404, { ok: false, message: '记录或原始 JSON 不存在' }); + const fname = String(rec.raw_file).replace(/[^\w.,-]/g, ''); + const file = path.join(DATA_DIR, fname); + fs.readFile(file, (err, data) => { + if (err) return sendJson(res, 404, { ok: false, message: '原始 JSON 文件不存在' }); + res.writeHead(200, { + 'Content-Type': 'application/json; charset=utf-8', + 'Content-Disposition': `attachment; filename="${rec.record_id}-raw.json"` + }); + res.end(data); + }); +} + function handlePhoto(req, res, id, which) { const safe = String(id || '').replace(/[^\w-]/g, ''); const file = path.join(PHOTOS_DIR, safe, which + '.jpg'); @@ -710,6 +736,8 @@ async function handleAdmin(req, res, pathname, url) { try { const retryM = pathname.match(/^\/api\/admin\/records\/([\w-]+)\/retry$/); if (req.method === 'POST' && retryM) return await handleRetry(req, res, retryM[1]); + const rawM = pathname.match(/^\/api\/admin\/records\/([\w-]+)\/raw$/); + if (req.method === 'GET' && rawM) return handleRawDownload(req, res, rawM[1]); const detailM = pathname.match(/^\/api\/admin\/records\/([\w-]+)$/); if (req.method === 'GET' && detailM) return handleRecordDetail(req, res, detailM[1]); const photoM = pathname.match(/^\/api\/admin\/photos\/([\w-]+)\/(front|left|right)$/); diff --git a/reference/facepp-skinanalyze/credentials.env b/reference/facepp-skinanalyze/credentials.env deleted file mode 100644 index 95b2382..0000000 --- a/reference/facepp-skinanalyze/credentials.env +++ /dev/null @@ -1,16 +0,0 @@ -# ~/.openclaw/credentials.env — 统一凭据存放(勿提交 git、勿发到聊天) -# 用法: set -a; source ~/.openclaw/credentials.env; set +a - -# ---- 旷视 Face++(巨子测肤 skinanalyze_pro 测试接口)---- -# 试用key(cAa5...)已弃用: 旷视规则试用key不能调专业版。当前为正式key(EcZ...) -FACEPP_API_KEY=EcZiqYhA8eQSiRgXVem8mijgzPfSC2qp -FACEPP_API_SECRET=p62QRWv9tQitZ1tvXmEBV8AgmaS00lO8 - -# ---- FaceStyle 专业版调用参数 ---- -FACEPP_SKINANALYZE_URL=https://api-cn.faceplusplus.com/facepp/v1/skinanalyze_pro - -# ---- 飞书 / OCR(合同盖章核验项目)---- -# 实际值在 ~/Desktop/合同盖章核验项目/service/.env(未入库) - -# ---- 智谱 / 火山引擎 ---- -# 已存于 ~/.zshrc 及 openclaw.json providers 配置