This commit is contained in:
xsl
2026-10-10 14:23:43 +08:00
parent 658b232a39
commit 2a7593b736
11 changed files with 528 additions and 149 deletions
+19 -8
View File
@@ -27,7 +27,7 @@ const RECORDS_FILE = path.join(DATA_ROOT, 'records.jsonl'); // 检测记录(一
/* 服务端评分引擎:与 C 端同一份公式(禁止复制公式,直接复用) */
const SkinScore = require('./js/skin-score.js');
/* ─── 密钥加载:环境变量优先,其次 apikey.bash,最后 reference 下的 credentials.env ─── */
/* ─── 密钥加载:环境变量优先,其次 apikey.bash,最后 reference 下的 credentials.env / key.env ─── */
function loadCredentials() {
if (process.env.SKIN_API_KEY && process.env.SKIN_API_SECRET) {
return { key: process.env.SKIN_API_KEY, secret: process.env.SKIN_API_SECRET };
@@ -38,15 +38,21 @@ function loadCredentials() {
const secret = (txt.match(/SKIN_API_SECRET\s*=\s*["']?([A-Za-z0-9_-]+)/) || [])[1];
if (key && secret) return { key, secret };
} catch (e) { /* 文件不存在则继续下一级兜底 */ }
try {
const txt = fs.readFileSync(path.join(ROOT, '..', 'reference', 'facepp-skinanalyze', 'credentials.env'), 'utf8');
const key = (txt.match(/FACEPP_API_KEY\s*=\s*["']?([A-Za-z0-9_-]+)/) || [])[1];
const secret = (txt.match(/FACEPP_API_SECRET\s*=\s*["']?([A-Za-z0-9_-]+)/) || [])[1];
if (key && secret) return { key, secret };
} catch (e) { /* 文件不存在则走下面的报错 */ }
for (const credentialFile of ['credentials.env', 'key.env']) {
try {
const txt = fs.readFileSync(path.join(ROOT, '..', 'reference', 'facepp-skinanalyze', credentialFile), 'utf8');
const key = (txt.match(/FACEPP_API_KEY\s*=\s*["']?([A-Za-z0-9_-]+)/) || [])[1];
const secret = (txt.match(/FACEPP_API_SECRET\s*=\s*["']?([A-Za-z0-9_-]+)/) || [])[1];
if (key && secret) return { key, secret };
} catch (e) { /* 文件不存在则尝试下一个配置文件 */ }
}
if (process.env.LOCAL_PREVIEW === '1') {
console.warn('[本机预览] 未配置 Face++ 密钥,真实检测不可用;演示入口: /?mock=1');
return null;
}
console.error('[启动失败] 找不到密钥:请设置 SKIN_API_KEY / SKIN_API_SECRET 环境变量,');
console.error(' 或在项目根目录放置 apikey.bash(内容为 export SKIN_API_KEY=... 等),');
console.error(' 或在 reference/facepp-skinanalyze/credentials.env 放置 FACEPP_API_KEY=... 等');
console.error(' 或在 reference/facepp-skinanalyze/credentials.env 或 key.env 放置 FACEPP_API_KEY=... 等');
process.exit(1);
}
const CRED = loadCredentials();
@@ -306,6 +312,7 @@ async function runDetect(rec, front, left, right) {
/* 调用 Face++ 专业版三视图测肤;
* 接口超时/网络错误(fetch 抛错)、HTTP 5xx、CONCURRENCY_LIMIT_EXCEEDED → 等 4s 重试 1 次(V2.0 第七章) */
async function callFacepp(front, left, right) {
if (!CRED) return { error_message: 'NO_API_CREDENTIALS' };
const form = new FormData();
form.append('api_key', CRED.key);
form.append('api_secret', CRED.secret);
@@ -754,6 +761,10 @@ async function handleAdmin(req, res, pathname, url) {
http.createServer((req, res) => {
const pathname = req.url.split('?')[0];
if (!CRED && req.method === 'POST' && (pathname === '/api/skin-analyze' || /^\/api\/admin\/records\/[\w-]+\/retry$/.test(pathname))) {
req.resume();
return sendJson(res, 503, { ok: false, code: 'NO_API_CREDENTIALS', message: '本机尚未配置 Face++ 密钥,请先配置密钥或使用演示模式(?mock=1)' });
}
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' });