修复草稿保存500:JSONB 不支持 \u0000,指标复合键分隔符在草稿持久化时编码/还原;run 失败补充错误日志
This commit is contained in:
@@ -28,6 +28,30 @@ function isoOf(v: unknown): string {
|
|||||||
return v instanceof Date ? v.toISOString() : String(v);
|
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<string, unknown> = {};
|
||||||
|
for (const [k, v] of Object.entries(value as Record<string, unknown>)) {
|
||||||
|
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 大字段。 */
|
/** 列出草稿(可按 assessorId 过滤),不返回 form 大字段。 */
|
||||||
export async function listDrafts(pool: pg.Pool, assessorId?: string): Promise<DraftSummary[]> {
|
export async function listDrafts(pool: pg.Pool, assessorId?: string): Promise<DraftSummary[]> {
|
||||||
const where = assessorId ? 'WHERE assessor_id = $1' : '';
|
const where = assessorId ? 'WHERE assessor_id = $1' : '';
|
||||||
@@ -60,7 +84,7 @@ export async function getDraft(pool: pg.Pool, id: string): Promise<DraftRecord |
|
|||||||
assessorId: r.assessor_id != null ? String(r.assessor_id) : null,
|
assessorId: r.assessor_id != null ? String(r.assessor_id) : null,
|
||||||
sourceAssessmentId: r.source_assessment_id != null ? String(r.source_assessment_id) : null,
|
sourceAssessmentId: r.source_assessment_id != null ? String(r.source_assessment_id) : null,
|
||||||
projectName: r.project_name != null ? String(r.project_name) : null,
|
projectName: r.project_name != null ? String(r.project_name) : null,
|
||||||
form: r.form,
|
form: decodeForm(r.form),
|
||||||
updatedAt: isoOf(r.updated_at),
|
updatedAt: isoOf(r.updated_at),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -90,7 +114,7 @@ export async function upsertDraft(pool: pg.Pool, input: UpsertDraftInput): Promi
|
|||||||
input.assessorId ?? null,
|
input.assessorId ?? null,
|
||||||
input.sourceAssessmentId ?? null,
|
input.sourceAssessmentId ?? null,
|
||||||
input.projectName ?? null,
|
input.projectName ?? null,
|
||||||
JSON.stringify(input.form ?? null),
|
JSON.stringify(encodeForm(input.form)),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
const r = (res.rows as Array<Record<string, unknown>>)[0]!;
|
const r = (res.rows as Array<Record<string, unknown>>)[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,
|
assessorId: r.assessor_id != null ? String(r.assessor_id) : null,
|
||||||
sourceAssessmentId: r.source_assessment_id != null ? String(r.source_assessment_id) : null,
|
sourceAssessmentId: r.source_assessment_id != null ? String(r.source_assessment_id) : null,
|
||||||
projectName: r.project_name != null ? String(r.project_name) : null,
|
projectName: r.project_name != null ? String(r.project_name) : null,
|
||||||
form: r.form,
|
form: decodeForm(r.form),
|
||||||
updatedAt: isoOf(r.updated_at),
|
updatedAt: isoOf(r.updated_at),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -799,6 +799,7 @@ app.post('/api/assessments/run', async (c) => {
|
|||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const message = err instanceof Error ? err.message : '未知错误';
|
const message = err instanceof Error ? err.message : '未知错误';
|
||||||
|
console.error('[run] 评估运行失败:', err instanceof Error ? err.stack ?? err.message : err);
|
||||||
return c.json({ error: message }, 400);
|
return c.json({ error: message }, 400);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user