更新记录

1.0.0(2026-10-29)

首个版本:识别 9 类敏感信息(手机号、身份证 18/15 位、银行卡 Luhn、统一社会信用代码 GB 32100、邮箱、中文姓名上下文、地址、IPv4、车牌),校验位先算后判并把不通过的标 valid=false;三档分级打码(L1 客服展示 / L2 日志埋点 / L3 对外导出),每档 9 类规则可查、可按类型只处理指定项,L3 身份证换 FNV-1a 关联标记、部分类型用定长星号避免反推长度;整段 / 逐行 CSV 保留表头 / 整文件三种入口,原文不动结果另存;重叠命中保留风险更高者;命中清单带位置、校验状态与判定依据。CSV 表头语义识别:列名对应类型时按该类型打码,字段数与表头不符则退回整行识别。UTS→Kotlin 编译通过(index.kt 1992 行、103 个函数,生成 classes.dex 68,520 字节),76 项回归测试全部通过;真机未执行(本轮无可用设备)。


平台兼容性

uni-app

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

szhzy-mask-guard

把工单、日志、导出文件里的敏感信息按类型认出来,再按档位打码。 识别 9 类,三档分级,整段 / 逐行 / 整文件都能处理。纯本地计算,不联网、不上传、不写日志。

适用场景:客服工单截图前脱敏、前端埋点日志落地前脱敏、对账明细导给第三方前脱敏、隐私合规自查。

验证状态

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

真机未验证的部分:Android 平台层的文本文件读取、content:// 授权 URI 转缓存、写出目录。 接入前请在自己的设备上先跑一遍「选文件 → 打码 → 写出」。 纯逻辑部分(识别、校验位、分档规则、打码、关联标记)已全部在 Node 下真实执行。

它不做什么

  • 不保证 100% 召回。识别靠规则 + 校验位,不靠模型。姓名、地址这类弱特征字段误漏都可能发生,涉及强合规场景请人工复核。
  • 不做格式保留。docx / pdf / xlsx 的内部结构不解析,只处理纯文本与 CSV 文本。Excel 请先导出成 CSV。
  • 不还原原文。打码是不可逆的(L3 的关联标记也只是摘要,不可反推)。
  • 不做加密。要加密存储请用专门的加密方案,本插件只负责「遮住」。
  • 不管图片与人脸。截图里的手机号识别不出来。

快速开始

import { maskTextApi, detectText, maskLinesApi, maskFile } from '@/uni_modules/szhzy-mask-guard'

// 1) 先看这段文字里有什么敏感信息(不改写)
const found = detectText({ text: ticket })
if (found.ok) {
  console.log(found.count, found.risk) // 命中数、最高风险等级 1/2/3
  found.hits.forEach((h) => console.log(h.type, h.value, h.valid, h.reason))
}

// 2) 按 L2(日志埋点)打码
const out = maskTextApi({ text: ticket, level: 2 })
console.log(out.text) // 已打码文本

// 3) CSV 逐行打码,保留表头
const csv = maskLinesApi({ text: csvText, level: 2, keepHeader: true })
console.log(csv.text)

// 4) 整个文件处理,原文不动,结果另存
const file = maskFile({
  path: filePath,          // 系统选择器给的路径或 content:// 授权 URI
  level: 3,
  fileName: '对账明细-脱敏',
  keepHeader: true
})
console.log(file.ok, file.path, file.masked)

同一段文字在三档下的实际输出(maskTextApi 的返回值去掉未变部分):

原文:联系人:张伟,手机 ***,统一社会信用代码 91440300MA5DB1XY3B
L1:联系人:张*,手机 138****8000,统一社会信用代码 9144**********XY3B
L2:联系人:张*,手机 138******00,统一社会信用代码 91**************3B
L3:联系人:*,手机 138****,统一社会信用代码 91****

L3 的身份证不是打星号,而是换成关联标记,同一号码每次输出一样、不同号码不一样,便于跨日志比对又不泄露原文:

11010519491231002X  →  #c50ffac5

API

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

方法 入参 返回要点
detectText { text, types? } hits[]、count、risk(只识别不改写)
maskTextApi { text, level=2, types?, char='*' } text、masked、risk、hits[]、counts[]、lines
maskLinesApi { text, level=2, keepHeader=true, types?, char='*' } 同上,逐行处理,可保留首行表头
maskFile { path, level=2, keepHeader=false, byLine=true, dir?, fileName?, bom=true, types?, char? } 同上 + path(新文件路径)、fileName、bytes
verifyCode { kind: 'idcard'\|'bank'\|'uscc', value } valid、digits,用于录入时就地校验
fingerprint { value } digest(8 位十六进制关联标记)
policyOfLevel { level } rules[]:该档每类保留前几位、后几位
policyMatrix — 三档规则一次性取出,做对照表用
types — 支持的 9 类清单,含 risk 与 how(识别依据)
getOutputDir — 默认输出目录(应用外部私有目录)
getVersion — 插件版本

命中项字段

字段 说明
type phone / idcard / bank / uscc / email / name / address / ip / plate
title 中文名,直接可上屏
value 命中的原始片段
start / end 在原文中的位置,可用来做高亮
valid 校验位是否通过(仅 idcard / bank / uscc 有意义);false 表示原数据本身可能是脏的
risk 1 低 / 2 中 / 3 高
reason 判定依据,如「11 位号码,1 开头且第二位 3-9」

三档分级

档位 用途 手机号 身份证 银行卡 姓名
L1 客服展示(能核对身份) 留 3+4 留 6+2 留 4+4 留姓
L2 日志埋点(默认) 留 3+2 留 3+1 留 4+2 留姓
L3 对外导出(最严) 留 3 + 定长 4 星 关联标记 留 4 + 定长 4 星 全遮

fixed 项用定长星号替代变长数字,避免从星号个数反推出原文长度。

单类型覆盖:传 types: ['phone', 'idcard'] 就只处理这两类,其余原样保留。

识别依据

类型 怎么认
手机号 11 位、1 开头、第二位 3-9;兼容 +86 / 86 前缀与空格、连字符分隔
身份证 18 位加权模 11 校验;15 位老号按长度识别
银行卡 16-19 位,Luhn 校验;不通过的仍按卡号打码并标 valid=false
统一社会信用代码 18 位 GB 32100 加权模 31 校验,须含字母
邮箱 @ 前后按字符集回溯,域名须带点且顶级域 ≥2 位
中文姓名 紧跟「姓名/联系人/收货人/申请人/负责人/经办人/签收人/业务员/开票人」等关键词,且首字为常见姓氏
地址 省级行政区名开头,尾部出现路/街/号/村/镇/区/县等门牌特征
IPv4 四段 0-255
车牌 省份简称 + 发牌机关字母 + 5 位号牌

重叠处理:同一位置命中多类时保留风险更高的那个(身份证优先于银行卡,因为 18 位数字两者都像)。

错误码

code 含义 处理建议
EMPTY 入参为空 检查 text / path / value 是否传了
KIND_UNKNOWN verifyCode 的 kind 不在三选一里 只能是 idcard / bank / uscc
READ_FAILED 文件读不出来 content:// 授权可能已失效,重新选择
WRITE_FAILED 写文件失败 检查 dir 是否可写
FILE_NOT_FOUND 文件不存在 确认选择器返回的路径有效

演示工程

demo-mask-guard/ 两个页面:

  • 工单脱敏:一段客服工单文本,切换 L1/L2/L3 看打码结果差异,下方命中清单带风险徽章与校验状态,再下面是三档保留位对照表;
  • 批量脱敏:CSV 明细表处理前/后对照,展示逐行打码 + 保留表头,末尾是处理说明与写出结果卡。

预览环境(H5)用固定样本数据走通页面流程,结果卡会标注「预览环境」;装到 Android 后同一次操作走的是真实插件。

隐私说明

  • 不联网、不上传、不写日志、不采集统计。
  • 待处理文本只在内存中,处理完随调用返回,插件不自行缓存。
  • 输出文件默认写应用外部私有目录(getExternalFilesDir),不需要存储权限。
  • 关联标记是 FNV-1a 32 位摘要,不是加密,不要当密码学哈希用。

授权

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

隐私、权限声明

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

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

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

插件不采集、不上传任何数据,不访问网络,不写日志。待脱敏文本只在本机内存中处理;处理结果由调用方决定是否落盘,默认写应用外部私有目录。

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

无

暂无用户评论。