From 2cf67e31eaaaaa8ad994f36ac7dc66104ec56ced Mon Sep 17 00:00:00 2001 From: "douboer@gmail.com" Date: Sat, 14 Feb 2026 10:17:02 +0800 Subject: [PATCH] update at 2026-02-14 10:17:02 --- miniapp/pages/index/index.js | 2 +- miniapp/utils/sankey.js | 81 ++++++++++++++++++++++++++++++++---- 2 files changed, 74 insertions(+), 9 deletions(-) diff --git a/miniapp/pages/index/index.js b/miniapp/pages/index/index.js index 3a7ecc3..9823ca7 100644 --- a/miniapp/pages/index/index.js +++ b/miniapp/pages/index/index.js @@ -275,7 +275,7 @@ function buildColumnRenderRows(headers, sourceDataColumn, sourceDescMap, targetD function toFriendlyParseError(error, fallbackMessage) { const message = error && error.message ? String(error.message) : ''; if (message.indexOf('xlsx 解析') >= 0) { - return '当前环境未启用 xlsx 解析,请先在开发者工具执行“构建 npm”'; + return message || '当前环境未启用 xlsx 解析,请先在开发者工具执行“构建 npm”'; } return message || fallbackMessage; } diff --git a/miniapp/utils/sankey.js b/miniapp/utils/sankey.js index 0f86ba5..aa20c9c 100644 --- a/miniapp/utils/sankey.js +++ b/miniapp/utils/sankey.js @@ -12,20 +12,78 @@ function normalizeText(value) { * - 使用缓存避免每次解析都重复 require */ let cachedXlsxModule; +let cachedXlsxLoadErrorMessage = ''; + +/** + * 兼容 CommonJS / ESM 默认导出差异,统一拿到 xlsx API。 + */ +function normalizeXlsxModuleShape(moduleValue) { + if (moduleValue && typeof moduleValue.read === 'function' && moduleValue.utils) { + return moduleValue; + } + if ( + moduleValue && + moduleValue.default && + typeof moduleValue.default.read === 'function' && + moduleValue.default.utils + ) { + return moduleValue.default; + } + return null; +} + +/** + * 返回最近一次 xlsx 模块加载失败原因,便于页面层展示详细信息。 + */ +function getXlsxLoadErrorMessage() { + return cachedXlsxLoadErrorMessage; +} + function getXlsxModule() { if (cachedXlsxModule !== undefined) { return cachedXlsxModule; } - try { - cachedXlsxModule = require('xlsx'); - } catch (error) { - // 兜底:兼容开发者工具未正确挂载 npm 解析时,直接从 miniprogram_npm 目录加载。 + + const loadAttempts = [ + { + label: "require('xlsx')", + loader: () => require('xlsx') + }, + { + label: "require('../miniprogram_npm/xlsx/xlsx')", + loader: () => require('../miniprogram_npm/xlsx/xlsx') + }, + { + label: "require('../miniprogram_npm/xlsx/dist/xlsx.mini.min')", + loader: () => require('../miniprogram_npm/xlsx/dist/xlsx.mini.min') + }, + { + label: "require('../miniprogram_npm/xlsx/dist/xlsx.full.min')", + loader: () => require('../miniprogram_npm/xlsx/dist/xlsx.full.min') + } + ]; + + const failedReasons = []; + for (let i = 0; i < loadAttempts.length; i += 1) { + const attempt = loadAttempts[i]; try { - cachedXlsxModule = require('../miniprogram_npm/xlsx'); - } catch (fallbackError) { - cachedXlsxModule = null; + const loaded = attempt.loader(); + const normalized = normalizeXlsxModuleShape(loaded); + if (normalized) { + cachedXlsxModule = normalized; + cachedXlsxLoadErrorMessage = ''; + return cachedXlsxModule; + } + failedReasons.push(`${attempt.label}: 模块导出结构不符合预期`); + } catch (loadError) { + const detail = + loadError && loadError.message ? String(loadError.message) : '未知异常'; + failedReasons.push(`${attempt.label}: ${detail}`); } } + + cachedXlsxModule = null; + cachedXlsxLoadErrorMessage = failedReasons.join(' | '); return cachedXlsxModule; } @@ -155,6 +213,12 @@ function parseCsvText(csvText) { function parseXlsxBuffer(buffer) { const xlsx = getXlsxModule(); if (!xlsx) { + const loadErrorDetail = getXlsxLoadErrorMessage(); + if (loadErrorDetail) { + throw new Error( + `当前环境未启用 xlsx 解析,请先在开发者工具执行“构建 npm”。加载详情: ${loadErrorDetail}` + ); + } throw new Error('当前环境未启用 xlsx 解析,请先在开发者工具执行“构建 npm”'); } @@ -321,5 +385,6 @@ module.exports = { parseCsvText, parseXlsxBuffer, parseTableByFileName, - buildSankeyData + buildSankeyData, + getXlsxLoadErrorMessage };