diff --git a/src/persistence/drafts.ts b/src/persistence/drafts.ts index 77db34d..a08eeb5 100644 --- a/src/persistence/drafts.ts +++ b/src/persistence/drafts.ts @@ -28,6 +28,30 @@ function isoOf(v: unknown): string { return v instanceof Date ? v.toISOString() : String(v); } +/** JSONB 不能存 \u0000(空字符),而指标复合键用其作分隔符。存储时编码为私有区字符,读取时还原。 */ +const NUL = '\u0000'; +const NUL_SENTINEL = '\uE000'; +function deepReplace(value: unknown, from: string, to: string): unknown { + if (typeof value === 'string') return value.split(from).join(to); + if (Array.isArray(value)) return value.map((v) => deepReplace(v, from, to)); + if (value !== null && typeof value === 'object') { + const out: Record = {}; + for (const [k, v] of Object.entries(value as Record)) { + out[k.split(from).join(to)] = deepReplace(v, from, to); + } + return out; + } + return value; +} +/** 存库前编码(去除 \u0000)。 */ +function encodeForm(form: unknown): unknown { + return deepReplace(form ?? null, NUL, NUL_SENTINEL); +} +/** 读出后还原。 */ +function decodeForm(form: unknown): unknown { + return deepReplace(form ?? null, NUL_SENTINEL, NUL); +} + /** 列出草稿(可按 assessorId 过滤),不返回 form 大字段。 */ export async function listDrafts(pool: pg.Pool, assessorId?: string): Promise { const where = assessorId ? 'WHERE assessor_id = $1' : ''; @@ -60,7 +84,7 @@ export async function getDraft(pool: pg.Pool, id: string): Promise>)[0]!; @@ -99,7 +123,7 @@ export async function upsertDraft(pool: pg.Pool, input: UpsertDraftInput): Promi assessorId: r.assessor_id != null ? String(r.assessor_id) : null, sourceAssessmentId: r.source_assessment_id != null ? String(r.source_assessment_id) : null, projectName: r.project_name != null ? String(r.project_name) : null, - form: r.form, + form: decodeForm(r.form), updatedAt: isoOf(r.updated_at), }; } diff --git a/src/server/index.ts b/src/server/index.ts index 83960e9..72e1428 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -799,6 +799,7 @@ app.post('/api/assessments/run', async (c) => { }); } catch (err) { const message = err instanceof Error ? err.message : '未知错误'; + console.error('[run] 评估运行失败:', err instanceof Error ? err.stack ?? err.message : err); return c.json({ error: message }, 400); } });