fix(roi): 关闭 mock 营收 + 修 zod envBool 把 "false" 当 true 的 bug
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m6s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m6s
变更: - scheduler 加判断: MOCK_REVENUE_API=false 且 URL 仍指 /mock 时跳过 revenue cron, 避免对未挂载的端点 404 写错误日志 - config.ts 新增 envBool() preprocess: 替代 z.coerce.boolean(), 正确把 "false"/"0"/"no" 识别为 false (zod 默认所有非空串都是 true) - 影响:AI_ENABLED 和 MOCK_REVENUE_API 两个 boolean env 现在按字面值生效 副作用: - 数据库 1997 条 mock revenue + 5 条 unmapped 已清空 (mysql DELETE 手动执行) - 项目级 ROI 现在显示真实状态: 成本来自 commit 估算, 产出 ¥0 (待业务方接入) - 真实营收 API 就绪后只需改 REVENUE_API_BASE_URL 即可恢复 cron Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4a2ed8d414
commit
7b5a2a823c
@ -1,5 +1,12 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
// z.coerce.boolean() 把任何非空字符串当 true(包括"false"),用 preprocess 修正
|
||||
const envBool = (defaultValue: boolean) =>
|
||||
z.preprocess((v) => {
|
||||
if (typeof v !== 'string') return v;
|
||||
return ['true', '1', 'yes', 'on'].includes(v.toLowerCase());
|
||||
}, z.boolean()).default(defaultValue);
|
||||
|
||||
const envSchema = z.object({
|
||||
JWT_SECRET: z.string().min(16, 'JWT_SECRET must be at least 16 characters'),
|
||||
PORT: z.coerce.number().default(3200),
|
||||
@ -25,13 +32,13 @@ const envSchema = z.object({
|
||||
ADMIN_PASSWORD: z.string().min(6).default('Admin123!'),
|
||||
|
||||
// AI (豆包 Doubao / 火山引擎 Ark)
|
||||
AI_ENABLED: z.coerce.boolean().default(false),
|
||||
AI_ENABLED: envBool(false),
|
||||
AI_API_KEY: z.string().default(''),
|
||||
AI_MODEL: z.string().default('doubao-seed-2-0-pro-260215'),
|
||||
AI_BASE_URL: z.string().default('https://ark.cn-beijing.volces.com/api/v3'),
|
||||
|
||||
// ROI 外部营收 API
|
||||
MOCK_REVENUE_API: z.coerce.boolean().default(false),
|
||||
MOCK_REVENUE_API: envBool(false),
|
||||
REVENUE_API_BASE_URL: z.string().default('http://localhost:3200/mock'),
|
||||
REVENUE_API_KEY: z.string().default('mock-dev-key-12345'),
|
||||
});
|
||||
|
||||
@ -49,10 +49,16 @@ export function startScheduler(): void {
|
||||
});
|
||||
|
||||
// ROI 营收 ingest:每天 03:00 拉昨日营收
|
||||
revenueJob = new Cron('0 3 * * *', async () => {
|
||||
console.info('[SCHEDULER] ROI 营收 ingest 开始...');
|
||||
await runRevenueIngest().catch(e => console.error('[SCHEDULER] ROI 营收 ingest 失败:', e));
|
||||
});
|
||||
// 仅当 mock 启用 或 REVENUE_API_BASE_URL 不指向本地 mock 时才跑(避免对未挂载的端点请求拿 404)
|
||||
const revenueApiReady = config.MOCK_REVENUE_API || !config.REVENUE_API_BASE_URL.includes('/mock');
|
||||
if (revenueApiReady) {
|
||||
revenueJob = new Cron('0 3 * * *', async () => {
|
||||
console.info('[SCHEDULER] ROI 营收 ingest 开始...');
|
||||
await runRevenueIngest().catch(e => console.error('[SCHEDULER] ROI 营收 ingest 失败:', e));
|
||||
});
|
||||
} else {
|
||||
console.info('[SCHEDULER] 跳过营收 ingest cron: MOCK_REVENUE_API=false 且 REVENUE_API_BASE_URL 仍指向 mock');
|
||||
}
|
||||
|
||||
// ROI 资产摊销:每月 1 号 01:00
|
||||
amortizerJob = new Cron('0 1 1 * *', async () => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user