From 4c9f54e0a697a1beeabcdaf551e076e35a403ce9 Mon Sep 17 00:00:00 2001 From: "douboer@gmail.com" Date: Sat, 14 Feb 2026 10:55:14 +0800 Subject: [PATCH] update at 2026-02-14 10:55:14 --- miniapp/utils/sankey.js | 7 +++++-- src/core/parser.ts | 2 +- tests/core.spec.ts | 33 +++++++++++++++++++++++++++++++++ tests/miniapp.spec.ts | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 3 deletions(-) diff --git a/miniapp/utils/sankey.js b/miniapp/utils/sankey.js index d5001cc..3b557fe 100644 --- a/miniapp/utils/sankey.js +++ b/miniapp/utils/sankey.js @@ -2,7 +2,10 @@ * 统一清洗文本,避免空格导致节点重复。 */ function normalizeText(value) { - return String(value || '').trim(); + if (value === null || value === undefined) { + return ''; + } + return String(value).trim(); } /** @@ -236,7 +239,7 @@ function parseXlsxBuffer(buffer) { const rows = xlsx.utils.sheet_to_json(sheet, { header: 1, raw: false, - defval: '' + blankrows: false }); return toRawTable(rows); } diff --git a/src/core/parser.ts b/src/core/parser.ts index 85725cf..e7ce0d2 100644 --- a/src/core/parser.ts +++ b/src/core/parser.ts @@ -71,7 +71,7 @@ export function parseXlsxBuffer(buffer: ArrayBuffer): RawTable { const rows = XLSX.utils.sheet_to_json(sheet, { header: 1, raw: false, - defval: '' + blankrows: false }); return toRawTable(rows); diff --git a/tests/core.spec.ts b/tests/core.spec.ts index f418b7b..914ca41 100644 --- a/tests/core.spec.ts +++ b/tests/core.spec.ts @@ -1,6 +1,7 @@ import { readFileSync } from 'node:fs'; import { resolve } from 'node:path'; import { describe, expect, it } from 'vitest'; +import * as XLSX from 'xlsx'; import { buildSankeyData, parseCsvText, parseXlsxBuffer } from '../src/core'; describe('core parser & sankey', () => { @@ -45,6 +46,38 @@ describe('core parser & sankey', () => { expect(table.rows.length).toBeGreaterThan(0); }); + it('xlsx !ref 范围虚高时,不应错误膨胀行列数量', () => { + const sheet = XLSX.utils.aoa_to_sheet([ + ['source', 'target', 'value'], + ['A', 'B', 1] + ]); + sheet['!ref'] = 'A1:H20'; + const workbook = XLSX.utils.book_new(); + XLSX.utils.book_append_sheet(workbook, sheet, 'S1'); + const buffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'buffer' }); + const table = parseXlsxBuffer( + buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength) + ); + + expect(table.headers).toEqual(['source', 'target', 'value']); + expect(table.rows).toEqual([['A', 'B', '1']]); + }); + + it('xlsx 中 0 值应被正确保留', () => { + const sheet = XLSX.utils.aoa_to_sheet([ + ['source', 'target', 'value'], + ['A', 'B', 0] + ]); + const workbook = XLSX.utils.book_new(); + XLSX.utils.book_append_sheet(workbook, sheet, 'S1'); + const buffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'buffer' }); + const table = parseXlsxBuffer( + buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength) + ); + + expect(table.rows).toEqual([['A', 'B', '0']]); + }); + it('源数据非法时,告警包含单元格内容和位置', () => { const table = { headers: ['source', 'value', 'target'], diff --git a/tests/miniapp.spec.ts b/tests/miniapp.spec.ts index 631353d..4b7cda8 100644 --- a/tests/miniapp.spec.ts +++ b/tests/miniapp.spec.ts @@ -2,6 +2,7 @@ import { readFileSync } from 'node:fs'; import { createRequire } from 'node:module'; import { resolve } from 'node:path'; import { describe, expect, it } from 'vitest'; +import * as XLSX from 'xlsx'; const require = createRequire(import.meta.url); const { parseTableByFileName, parseXlsxBuffer } = require('../miniapp/utils/sankey.js') as { @@ -41,4 +42,36 @@ describe('miniapp utils sankey', () => { expect(table.headers.length).toBeGreaterThan(1); expect(table.rows.length).toBeGreaterThan(0); }); + + it('xlsx !ref 范围虚高时,不应错误膨胀行列数量', () => { + const sheet = XLSX.utils.aoa_to_sheet([ + ['source', 'target', 'value'], + ['A', 'B', 1] + ]); + sheet['!ref'] = 'A1:H20'; + const workbook = XLSX.utils.book_new(); + XLSX.utils.book_append_sheet(workbook, sheet, 'S1'); + const buffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'buffer' }); + const arrayBuffer = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength); + + const table = parseXlsxBuffer(arrayBuffer); + + expect(table.headers).toEqual(['source', 'target', 'value']); + expect(table.rows).toEqual([['A', 'B', '1']]); + }); + + it('xlsx 中 0 值应被正确保留', () => { + const sheet = XLSX.utils.aoa_to_sheet([ + ['source', 'target', 'value'], + ['A', 'B', 0] + ]); + const workbook = XLSX.utils.book_new(); + XLSX.utils.book_append_sheet(workbook, sheet, 'S1'); + const buffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'buffer' }); + const arrayBuffer = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength); + + const table = parseXlsxBuffer(arrayBuffer); + + expect(table.rows).toEqual([['A', 'B', '0']]); + }); });