更新记录

1.0.0(2026-10-29)

首个版本:两张 CSV/TSV 按主键对齐,输出新增/删除/变更三类差异;差异按字段逐条列,带字段名与旧值→新值;数值容差(12.5 与 12.50 视为同一金额,0.01 以内不算差异);忽略列支持双向包含匹配;主键定位三级(精确/忽略大小写/包含),重复与空主键单独计数;只有一边有的列单独列出;引号与转义切分、逗号与制表符自动识别;差异 CSV 导出固定 5 列带 BOM;条目上限可配。UTS→Kotlin 编译通过(index.kt 983 行、57 个函数,生成 classes.dex 39,756 字节),71 项回归测试全部通过;真机未执行(本轮无可用设备)。


平台兼容性

uni-app

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
× √ × × √ × √ × ×
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
× × × × × × - × × - × ×

szhzy-sheet-diff

拿两张 CSV / TSV,按主键对齐,找出「只在旧表有、只在新表有、两边都有但字段变了」。 差异按字段逐条列出,数值列可设容差,结果可导出成差异 CSV。纯本地计算,不联网、不上传。

适用场景:供应商报价单两版核对、月度对账明细比上一期、ERP 导出与现场表格核对、改价前后的物料清单对照。

验证状态

项 结果
UTS → Kotlin 编译 通过(编译成功,无 error;index.kt 983 行 / 57 个函数,生成 classes.dex 39,756 字节)
纯逻辑回归测试 71 项,失败 0(dev-tools-uts/verify/sheet-diff/run-tests.mjs)
真机运行 未执行(本轮无可用设备,adb devices 为空)
iOS / 鸿蒙 不支持,仅 Android

真机未验证的部分:Android 平台层的文件读取(content:// 授权 URI 转缓存)与差异 CSV 写出。 比对逻辑(切分、主键定位、容差、三类差异、统计、CSV 输出)已全部在 Node 下真实执行。

它不做什么

  • 不读 xlsx / xls。Excel 请先用 szhzy-xlsx-export 导出成 CSV,或用 WPS / Excel「另存为 CSV」。
  • 不做模糊匹配。主键必须能对上,P-1001 与 P1001 是两个键。名字打错了会报成「一删一增」。
  • 不是数据库 diff。不做字段类型变更、索引变更这类结构比对。
  • 不支持多表 / 多 sheet。一次两张表,多张就分多次比。
  • 不合并三方。只做两方差异,不做 base/ours/theirs 三路合并。

快速开始

import { compareText, compareFiles, previewTable } from '@/uni_modules/szhzy-sheet-diff'

// 1) 先看看两张表长什么样(列名对不对、列数是否一致)
const a = previewTable({ path: pathA })
console.log(a.headers, a.rows, a.cols)

// 2) 直接比对两段文本
const r = compareText({
  textA: csvOld,
  textB: csvNew,
  key: '编号',        // 不传则取第一列
  tolerance: 0.01,   // 数值容差,0.01 表示差一分钱不算差异
  ignoreFields: ['备注']  // 不参与比较的列
})
console.log(r.summary) // { added, removed, changed, changedRows, same, duplicateKeys, emptyKeys, diffTotal }
console.log(r.items[0]) // { kind, title, key, field, oldValue, newValue }

// 3) 比对两个文件,并把差异清单写成 CSV
const f = compareFiles({
  pathA: fileOld,      // 系统选择器给的路径或 content:// 授权 URI
  pathB: fileNew,
  key: '编号',
  writeCsv: true,
  fileName: '报价差异-2026-10.csv'
})
console.log(f.path, f.bytes, f.summary)

同一份示例数据(两张报价单)的真实输出:

变更 P-1001 数量 500 → 600
变更 P-1001 交期 2026-10-15 → 2026-10-18
变更 P-1003 单价 23.00 → 23.50
变更 P-1006 交期 2026-10-22 → 2026-10-24
新增 P-1007      → 接线端子 | 2P | 2000 | 0.32 | 2026-10-25
删除 P-1004 铝基板 1.2M | 1.0mm | 600 | 6.20 | 2026-10-20 →

汇总:新增 1、删除 1、变更 4(涉及 3 行)、完全一致 2。

API

所有方法返回统一信封 { ok, code, message, ... },不抛异常。

方法 入参 返回要点
compareText { textA, textB, key?, tolerance?, ignoreFields?, maxItems? } summary、items[]、columns、onlyInA、onlyInB、truncated
compareFiles 同上 + { pathA, pathB, dir?, fileName?, bom?, writeCsv? } 同上 + path(差异 CSV 路径)、bytes
previewTable { path } 或 { text } headers、rows、cols、delimiter、sample(前 5 行)
findColumn { headers, name } index、matched,用于让用户点选主键列
toCsv { textA, textB, key?, delimiter? } csv 文本 + summary(不落盘)
kinds — 三种变更类型
getOutputDir — 默认输出目录(应用外部私有目录)
getVersion — 插件版本

参数

参数 默认 说明
key 第一列表头 主键列名;精确匹配 → 忽略大小写 → 包含匹配
tolerance 0 数值容差。两边都是数字时按差额比较,0.01 表示一分钱以内不算差异
ignoreFields [] 不参与比较的列,支持包含匹配(配「备注说明」也能命中列名「备注」)
maxItems 2000 差异条目上限,超出置 truncated: true,但 summary 仍按全量统计
writeCsv false 是否把差异清单写成文件
bom true 写 UTF-8 BOM,Excel 双击不乱码

差异条目字段

字段 说明
kind added / removed / changed
title 中文名:新增 / 删除 / 变更
key 主键值
field 变更的字段名;新增与删除为空
oldValue / newValue 旧值 / 新值;新增只有 newValue,删除只有 oldValue

汇总字段

字段 说明
added / removed 只在 B / 只在 A 的行数
changed 字段级变更条数(一行改两列算 2)
changedRows 有变更的行数
same 完全一致的行数
duplicateKeys 主键重复的行数(按首次出现为准)
emptyKeys 主键为空被跳过的行数
diffTotal added + removed + changed

差异 CSV 结构

固定 5 列,任何下游工具都能直接吃:

变更类型,主键,字段,旧值,新值
变更,P-1001,数量,500,600
变更,P-1003,单价,23.00,23.50
新增,P-1007,,,接线端子 | 2P | 2000 | 0.32 | 2026-10-25
删除,P-1004,,铝基板 1.2M | 1.0mm | 600 | 6.20 | 2026-10-20,

新增 / 删除行的「旧值/新值」里放的是整行内容(不含主键),用 | 分隔,方便一眼看出这行是什么。

错误码

code 含义 处理建议
EMPTY 没传 textA/textB/pathA/pathB 检查参数
NO_HEADER 至少一张表解析不出表头 确认是 CSV/TSV 且首行是列名
KEY_NOT_FOUND 主键列找不到 报错信息里会列出两边实际列名
TOO_LARGE 单表超过 20000 行 先分片
FILE_NOT_FOUND 文件不存在 确认选择器返回的路径
READ_FAILED 读文件失败 content:// 授权可能已过期,重新选
WRITE_FAILED 写差异表失败 检查 dir 是否可写

演示工程

demo-sheet-diff/ 两个页面:

  • 对账差异核对:两版报价单(6 行 vs 6 行)比对,顶部四个数字(新增 1 / 删除 1 / 变更 4 / 一致 2),下面按字段逐条列差异,旧值划线、新值绿色;
  • 差异表导出:选两张表 → 比对 → 写出 diff-report.csv,附 CSV 预览与写出结果。

预览环境(H5)用固定示例数据走通页面流程,页面标注「示例数据」;装到 Android 后同一次操作读的是真实文件。

隐私说明

  • 不联网、不上传、不写日志、不采集统计。
  • 两张表只在内存中比对,插件不自行缓存。
  • 输出文件默认写应用外部私有目录(getExternalFilesDir),不需要存储权限。

授权

购买授权后可在自己的产品(含为客户定制的项目)中不限项目数、不限安装量使用。 源码授权另允许阅读与二次开发,但不得把插件本身(含修改版)再次分发或销售。详见 license.md。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

无系统权限。读取调用方用系统文件选择器交过来的文件(路径或 content:// 授权),写出走应用外部私有目录。

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集、不上传任何数据,不访问网络,不写日志。两张表只在本机内存中比对;差异清单由调用方决定是否落盘,默认写应用外部私有目录。

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无

暂无用户评论。