6600bfaa99
新增纯 TS 预览裁剪 parse-preview:把解析 Vo 裁剪为摘要字段 (taskId/行数统计/开关/prompt),items/groups 整包剔除,可按 previewRowLimit/previewGroupLimit 有界保留样本行供表格展示。输入 对象永不修改,taskId 非法 fail-fast,属性读取抛错时零部分结果。 BrandSimilarAsinTab 的 parseFiles 改为只接收裁剪后的预览(保留 200 行样本),数千行 items 不再进入 Vue 响应式 ref。8 个测试覆盖 默认、批量、幂等、空、单元素、截断溢出、非法输入与 getter 故障。
63 lines
2.4 KiB
TypeScript
63 lines
2.4 KiB
TypeScript
/**
|
|
* 解析结果预览裁剪(Task 88)。
|
|
*
|
|
* 解析接口(similar-asin/parse)返回完整解析 Vo,其中 items 可能达数千行,
|
|
* 直接放入 Vue 响应式 ref 会造成大量响应式代理与内存放大。本模块把 Vo
|
|
* 裁剪为预览对象:只保留页面实际使用的摘要字段(taskId、行数统计、开关、
|
|
* prompt 等),items/groups 整包剔除;可按 previewRowLimit / previewGroupLimit
|
|
* 有界保留前 N 条样本行用于表格展示(limit 省略或为 0 时不保留)。
|
|
*
|
|
* 纯 TS 无副作用模块:输入对象永不修改;taskId 非法时 fail-fast 抛错;
|
|
* 属性读取抛错(如 Proxy getter 故障)时调用失败,不产生部分结果。
|
|
*/
|
|
export interface ParsePreviewOptions {
|
|
/** 保留的样本行条数(0 或不传表示不保留),不能为负数 */
|
|
previewRowLimit?: number
|
|
/** 保留的样本分组条数(0 或不传表示不保留),不能为负数 */
|
|
previewGroupLimit?: number
|
|
}
|
|
|
|
export function toParsePreview<T>(
|
|
result: T,
|
|
options: ParsePreviewOptions = {},
|
|
) {
|
|
if (typeof result !== 'object' || result == null) {
|
|
throw new Error('解析结果必须是对象')
|
|
}
|
|
const { previewRowLimit, previewGroupLimit } = options
|
|
if (previewRowLimit != null && !(previewRowLimit >= 0)) {
|
|
throw new Error('previewRowLimit 不能为负数: ' + previewRowLimit)
|
|
}
|
|
if (previewGroupLimit != null && !(previewGroupLimit >= 0)) {
|
|
throw new Error('previewGroupLimit 不能为负数: ' + previewGroupLimit)
|
|
}
|
|
const record = result as Record<string, unknown>
|
|
const taskId = record.taskId
|
|
if (typeof taskId !== 'number' || !Number.isFinite(taskId) || taskId <= 0) {
|
|
throw new Error('taskId 必须是正整数: ' + taskId)
|
|
}
|
|
|
|
const summary: Record<string, unknown> = {}
|
|
for (const key of Object.keys(record)) {
|
|
if (key === 'items' || key === 'groups') continue
|
|
summary[key] = record[key]
|
|
}
|
|
|
|
if (previewRowLimit != null && previewRowLimit > 0) {
|
|
const rows = record.items
|
|
if (Array.isArray(rows)) {
|
|
summary.previewItems = rows.slice(0, previewRowLimit)
|
|
}
|
|
}
|
|
if (previewGroupLimit != null && previewGroupLimit > 0) {
|
|
const groups = record.groups
|
|
if (Array.isArray(groups)) {
|
|
summary.previewGroups = groups.slice(0, previewGroupLimit)
|
|
}
|
|
}
|
|
return summary as Omit<T, 'items' | 'groups'> & {
|
|
previewItems?: unknown[]
|
|
previewGroups?: unknown[]
|
|
}
|
|
}
|