From dbc10239309e706eb2f966ab9b6d60e7e497881b Mon Sep 17 00:00:00 2001
From: fengyuan_yang <1976974459@qq.com>
Date: Mon, 26 Jan 2026 11:48:11 +0800
Subject: [PATCH] =?UTF-8?q?2026-01-26=20=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/utils/filePreview.js | 103 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 101 insertions(+), 2 deletions(-)
diff --git a/src/utils/filePreview.js b/src/utils/filePreview.js
index 2fd67b2..928709c 100644
--- a/src/utils/filePreview.js
+++ b/src/utils/filePreview.js
@@ -413,6 +413,105 @@ export async function previewText(blobData, fileName) {
}
}
+/**
+ * 清洗工作表数据,处理可能导致 sheet_to_html 失败的特殊值
+ * @param {Object} worksheet - 工作表对象
+ * @returns {Object} 清洗后的工作表
+ */
+function sanitizeWorksheet(worksheet) {
+ if (!worksheet) return worksheet
+
+ // 遍历工作表中的所有单元格
+ Object.keys(worksheet).forEach(cellRef => {
+ // 跳过特殊属性(如 !ref, !cols, !rows, !merges 等)
+ if (cellRef.startsWith('!')) return
+
+ const cell = worksheet[cellRef]
+ if (!cell) {
+ // 如果单元格为 undefined 或 null,设置为空字符串
+ worksheet[cellRef] = { t: 's', v: '' }
+ return
+ }
+
+ // 处理单元格值
+ if (cell.v === undefined || cell.v === null) {
+ cell.v = ''
+ cell.t = 's' // 设置类型为字符串
+ }
+
+ // 处理超链接 - 如果超链接目标是 undefined,移除超链接
+ if (cell.l && (cell.l.Target === undefined || cell.l.Target === null)) {
+ delete cell.l
+ }
+
+ // 处理富文本 - 如果富文本数组包含 undefined 元素
+ if (cell.r && Array.isArray(cell.r)) {
+ cell.r = cell.r.filter(item => item !== undefined && item !== null)
+ if (cell.r.length === 0) {
+ delete cell.r
+ }
+ }
+
+ // 处理公式错误
+ if (cell.t === 'e' && cell.v === undefined) {
+ cell.v = '#ERROR!'
+ }
+ })
+
+ return worksheet
+}
+
+/**
+ * 安全地将工作表转换为HTML
+ * @param {Object} worksheet - 工作表对象
+ * @param {Object} options - 转换选项
+ * @returns {String} HTML字符串
+ */
+function safeSheetToHtml(worksheet, options = {}) {
+ try {
+ // 先清洗数据
+ const sanitizedSheet = sanitizeWorksheet(worksheet)
+ return XLSX.utils.sheet_to_html(sanitizedSheet, options)
+ } catch (error) {
+ console.warn('sheet_to_html 转换失败,尝试使用 sheet_to_json 方式:', error)
+
+ // 备用方案:使用 sheet_to_json 转换后再生成HTML
+ try {
+ const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1, defval: '' })
+
+ if (!jsonData || jsonData.length === 0) {
+ return '
'
+ }
+
+ // 手动生成HTML表格
+ let html = ''
+ jsonData.forEach((row, rowIndex) => {
+ html += ''
+ if (Array.isArray(row)) {
+ row.forEach(cell => {
+ const tag = rowIndex === 0 ? 'th' : 'td'
+ // 确保cell值是字符串,处理各种类型
+ let cellValue = ''
+ if (cell !== undefined && cell !== null) {
+ cellValue = String(cell)
+ .replace(/&/g, '&')
+ .replace(//g, '>')
+ }
+ html += `<${tag}>${cellValue}${tag}>`
+ })
+ }
+ html += '
'
+ })
+ html += '
'
+ return html
+ } catch (jsonError) {
+ console.error('备用转换方案也失败:', jsonError)
+ return ''
+ }
+ }
+}
+
/**
* 预览Excel文件
* @param {ArrayBuffer} arrayBuffer - 文件数据(ArrayBuffer格式)
@@ -423,11 +522,11 @@ export function previewExcel(arrayBuffer, fileName) {
const workbook = XLSX.read(arrayBuffer, { type: 'array' })
const sheetName = workbook.SheetNames[0]
const worksheet = workbook.Sheets[sheetName]
- const htmlString = XLSX.utils.sheet_to_html(worksheet, { editable: false })
+ const htmlString = safeSheetToHtml(worksheet, { editable: false })
// 预先生成所有sheet的HTML
const sheetsHtml = workbook.SheetNames.map(name => {
- return XLSX.utils.sheet_to_html(workbook.Sheets[name], { editable: false })
+ return safeSheetToHtml(workbook.Sheets[name], { editable: false })
})
// 创建预览窗口