Files
WebTools/README.zh-CN.md
T

33 KiB
Raw Blame History

Web Tools

English

一个匿名访问、自托管的浏览器本地工具箱。支持多人同时使用;除全局导航顺序外,文本、密钥、文件、图片和计算结果均只存在于各自浏览器中,不会发送到服务端。

当前应用版本:2026.8.22。

内置工具

  • UTF-8 与 Hex 互转,固定路径为 /tools/utf8-hex
  • Base64 与 Base64 URL 编码、解码,解码结果支持 UTF-8、连续 Hex 和代码字节数组
  • AES-CMAC,支持 AES-128、AES-192 和 AES-256 密钥
  • 16 种 CRC-8/16/32/64 标准预设与自定义参数,支持内联 Hex 字节、BIN 和多 block Intel HEX
  • 固件 SHA-256 / SHA-512,支持 Intel HEX 有效数据和带地址/长度的 Block 校验头
  • RSA 2048/3072/4096 位密钥对,导出 PEM,以及可分别复制的 N/E Hex 或代码字节数组
  • RSA 签名验证,支持 PKCS#1 v1.5、RSA-PSS(默认)、SHA-256/384/512、PEM/X.509/N-E 公钥,以及文本、Hex、原始文件、Intel HEX 有效数据和 Block 校验头
  • 密码学安全随机数,默认 16 字节,支持连续 Hex、空格 Hex 和代码字节数组
  • JSON 格式化、压缩、校验和语法着色
  • XML 格式化、压缩、校验和语法着色
  • PNG 转多尺寸 ICO

首次部署且尚未保存过自定义配置时,默认分类顺序为“编码转换 → 校验计算 → 加密计算 → 格式化 → 图像处理”。已有 data/navigation.json 会保留用户排序,不会因升级被默认顺序覆盖。

交付物与源码

容器交付 ZIP 同时包含源码、测试、生产构建结果和部署文件,不是只有压缩后的网页。主要目录如下:

src/                         Vue 3 前端源码
  components/                所有工具共用的 UI 组件
  composables/               可复用的 Vue 状态与异步生命周期管理
  lib/                       可测试的纯计算与浏览器辅助逻辑
  tools/                     每个工具一个独立 Vue 组件
  workers/                   大文件计算使用的浏览器后台线程
  views/SettingView.vue      /tools/setting 工具管理页
server/                      零依赖 Node.js 静态服务和导航配置 API
shared/tool-catalog.json     工具与分类的权威元数据目录
shared/default-navigation.json  新部署的默认分类和工具顺序
tests/                       Vitest 单元测试
dist/                        npm run build 生成的生产前端
public/                      浏览器图标和 Web App Manifest
Dockerfile                   多阶段容器构建
docker-compose.yml           默认部署配置
THIRD_PARTY_NOTICES.md       第三方依赖许可说明
CHANGELOG.md                 版本变更、修复和验证记录

交付包不包含 node_modules。Docker 首次构建需要访问 Node 镜像仓库和 npm 软件源;若环境完全离线,应另外交付 Docker 镜像 tar。

架构约束

  • Vue 3、TypeScript、Vite 前端;Node.js 标准库服务端;不引入数据库。
  • 工具组件彼此独立并懒加载,公共交互使用 ToolPage、ModeTabs、TextEditor、FileDropField 和 src/styles.css 中的现有样式。CRC、固件 Hash 与 RSA 签名验证的文件模式共用 FileDropField 的文件选择、摘要、拖入更换和清空交互;PNG/ICO 的图片工作区有独立的预览与转换流程,不属于该共用控件范围。
  • 工具的计算、解析和文件生成逻辑放在 src/lib/,Vue 组件只负责状态与交互。
  • 大文件或长时间计算必须放入 src/workers/ 的 Web Worker,避免阻塞页面交互;Worker 仍只在浏览器本地处理数据。协议符合“解析后复用同一 Worker 计算”的文件工具应使用 useTransactionalFileWorker 管理候选 Worker、活动 Worker 和请求 ID,同时保留各工具独立的 Worker 协议、计算逻辑及 Vue 状态。
  • 路由和左侧导航由工具目录自动生成,增加普通工具时不得手工新增路由。
  • 工具输入只在浏览器内存中处理,不得发送给服务端、遥测服务或第三方接口。
  • 服务端只持久化导航顺序,文件为 /data/navigation.json,写入采用临时文件和原子替换。
  • /tools/setting 是固定但不公开显示的管理入口;项目没有登录、收藏、赞助或用户系统。
  • 页面必须保持统一 UI,并兼容桌面端和移动端竖屏。
  • 浏览器图标与左侧品牌标记保持一致。favicon.svg 是现代浏览器主图标,favicon.ico 内含 16/32/48 像素回退图,另提供 180 像素 Apple 图标、192/512 像素 Web App 图标和 512 像素 maskable 图标。

site.webmanifest 只提供应用名称、颜色和图标元数据,便于浏览器添加到主屏幕。项目不注册 Service Worker,不启用离线缓存、安装提示或启动画面,避免部署更新后继续加载过期构建。

页面只提供统一介绍“一个匿名访问、自托管的浏览器本地工具箱”,同时写入标准 HTML description 和同文的 og:description,以兼容不同分享客户端;不设置自定义分享图片、其他 Open Graph 或平台专用字段,也不增加平台抓取器。分享平台可以回退使用页面标题和现有 favicon,但最终展示及缓存刷新时机由平台决定。

核心功能契约

以下行为属于已经发布的兼容性约束。修改时必须同步实现、页面提示、自动化测试和本文档,不能只调整界面文案。

  • UTF-8 / Hex 工具的固定 ID 为 utf8-hex,路径为 /tools/utf8-hex。它按 UTF-8 字节转换文本;Hex 输入接受连续形式,或以空白、英文逗号、中文逗号分隔的片段,并允许每个片段使用可选的 0x 前缀。无效 UTF-8 字节必须报错,不能静默替换字符。
  • Base64 支持标准和 URL-safe 形式;解码结果可显示为严格 UTF-8、连续 Hex 或 0x48, 0x9F, ... 字节数组。无效字符、错误填充和非规范编码必须报错。
  • AES-CMAC 密钥长度可选 128、192 或 256 位,默认 128 位,并分别严格要求 16、24 或 32 字节;不自动补零或截断。密钥和 Hex 消息接受连续 Hex,或空格、换行、英文/中文逗号分隔,并允许片段使用可选的 0x 前缀。CMAC 标签始终为 128 位;AES-128 向量遵循 RFC 4493,AES-192/256 向量遵循 NIST SP 800-38B。
  • CRC 支持内联 Hex 字节、BIN 和多 block Intel HEX,提供 16 种按位宽分组的标准预设,并允许自定义 Width、Poly、Init、XorOut、RefIn 和 RefOut。预设包括 CRC-8/SMBUS、MAXIM-DOW、SAE-J1850;CRC-16/ARC、DNP、IBM-3740、IBM-SDLC、KERMIT、MODBUS、USB、XMODEM;CRC-32/ISO-HDLC、ISCSI、MPEG-2;CRC-64/ECMA-182、XZ。界面保留常用别名:CRC-8、CCITT-FALSE、CCITT、X-25 和 CRC-32C;有歧义的 CCITT 只作为 KERMIT 后的辅助别名展示,并始终通过完整名称与 IBM-3740(CCITT-FALSE)区分。内联 Hex 接受连续形式,或以空白、英文逗号、中文逗号分隔的片段,并允许每个片段使用可选的 0x 前缀;空输入和无效字节格式会被拒绝,解析与计算均在独立 Web Worker 中完成。RefIn/RefOut 在页面中标为输入/输出位反转,不表示字节顺序或整个数据倒序。文件模式的总 CRC 对按地址升序拼接的有效数据计算,不填充地址空洞,同时输出每个 block 的结果。
  • 固件 Hash 只接受 Intel HEX,输出 SHA-256 和 SHA-512。“有效数据”与“Block 校验头”模式的确切字节流见“Intel HEX 与 Block 校验头固定语义”;默认校验头字节序为 Big Endian。
  • RSA 密钥对工具只生成 2048、3072、4096 位密钥,公钥指数固定为 65537。优先使用 Web Crypto,只有本地提供者不可用或失败时才动态加载 node-forge 回退,其随机种子仍只来自 crypto.getRandomValues;公钥为 SPKI PEM,私钥为 PKCS#8 PEM,N/E 可分别显示为连续 Hex 或代码字节数组。
  • RSA 签名验证工具只执行验证,不接收私钥或生成签名。它默认选择 RSA-PSS,并支持切换到 RSA PKCS#1 v1.5;Hash 支持 SHA-256/384/512,不支持 SHA-1。PSS 的 Salt Length 必须显式给出,默认取 Hash 长度与当前模数编码上限中的较小值,并受当前模数与 Hash 的编码上限约束。公钥可使用单个 SPKI PUBLIC KEY、PKCS#1 RSA PUBLIC KEY、X.509 CERTIFICATE PEM 块或 N/E Hex 参数;E 按无符号 Hex 整数解析,奇数位输入会在最左侧补一个 0,因此 10001、010001 均表示十进制 65537,其他 Hex 字节输入仍要求偶数位。X.509 只用于提取 RSA 公钥和展示 Subject、序列号、有效期,不验证证书链、颁发者、用途或可信状态。验证接受 1024 至 8192 位 RSA 公钥,低于 2048 位时显示兼容性警告。
  • 签名可输入 Hex、Base64 或 Base64 URL。待验证数据可为 UTF-8 原文、Hex 字节、原始文件字节、Intel HEX 按 32 位绝对地址升序拼接的有效数据,或带 Block 校验头的 Intel HEX 数据。“Intel HEX 有效数据”不填充地址空洞,也不加入校验头;“Block 校验头”对每个 block 加入与固件 Hash 相同的 8 字节二进制地址/长度头,默认 Big Endian,可显式切换 Little Endian。文件语义必须由用户明确选择,工具不得按扩展名自动推断或切换。
  • 安全随机数必须来自浏览器 crypto.getRandomValues,默认 16 字节,允许长度为 1 至 65,536 字节,支持连续 Hex、空格 Hex 和代码字节数组;切换显示格式不得重新生成随机数据。安全随机源不可用或抛错时直接失败,不使用普通伪随机回退。
  • JSON/XML 的格式化、压缩和校验均在浏览器本地完成。合法 XML 可以使用 parsererror 作为元素名;只把浏览器专用解析错误命名空间中的节点视为解析失败。语法着色超过资源限制时只能降级为完整纯文本,不能截断结果。
  • 文件选择、文件更换、清空、模式切换和组件卸载都可能使异步任务失效。旧 Worker、旧图像解码和旧密钥生成结果不得覆盖当前输入或已清空状态。CRC、固件 Hash 与 RSA 签名验证的文件模式在已有文件时支持把新文件直接拖入摘要区域;候选文件解析成功后才替换当前文件并清除旧结果,解析失败时保留当前文件和结果。

多人使用与状态边界

  • 每个浏览器标签页拥有独立的 Vue 组件状态、文件对象、图像对象和 Web Worker。不同用户、浏览器或标签页不会共享工具输入与结果。
  • CRC、固件 Hash、RSA 密钥生成与签名验证、AES-CMAC、随机数、PNG/ICO、编码转换和格式化都在浏览器中执行;服务端没有工具计算接口。
  • /tools/setting 保存的是所有访问者共享的导航配置。同一服务进程会按进入导航操作队列的顺序串行处理读写,最后排队的保存生效;不提供版本冲突合并。
  • 旧导航配置中的历史工具 ID ascii-hex 会在读取时原位迁移为 utf8-hex,保留原分类和排序;新配置和应用路由只使用 utf8-hex。
  • 原子替换保证读取者看到完整的旧配置或新配置,不会看到写到一半的 JSON;它不保证保留多个用户各自的排序修改。
  • 已打开的页面不会实时接收其他用户保存的新顺序,刷新或重新打开后才会读取。
  • 深浅主题保存在当前浏览器同源 localStorage 中;系统剪贴板由操作系统管理。这两项不会改变工具计算结果。

资源限制

限制用于避免异常文件、解压后超大图像或高密度语法 token 长时间占用浏览器。修改这些数值时必须同步源码常量、测试和本文档。

功能 当前限制 超限行为
CRC 固件文件 最大 64 MiB 首次选择时拒绝;替换时保留当前文件和结果
CRC 内联 Hex 解析后最大 1 MiB;原始输入最多 6 MiB 字符 在 Worker 中解析与计算,超限或空输入直接拒绝
Intel HEX 非空记录 最多 500,000 条 Worker 停止解析并显示错误
Intel HEX 数据块 最多 1,024 个 block Worker 停止解析并显示错误
Intel HEX 合并后的有效数据 最大 64 MiB 合并分配前拒绝,Worker 停止解析并显示错误
固件 Hash 文件及有效数据 文件最大 64 MiB,有效数据最大 64 MiB 首次选择或计算时拒绝;替换解析失败时保留当前文件和结果
RSA 签名验证内联数据 UTF-8 或 Hex 解析后最大 1 MiB;原始输入最多 6 MiB 字符 在分配超限结果前拒绝,并提示改用文件模式
RSA 签名验证文件 原始文件或 Intel HEX 文件最大 64 MiB;Intel HEX 有效数据或加入 Block 校验头后的验签数据最大 64 MiB 首次选择时拒绝;替换失败时保留当前文件和结果
RSA 签名验证输入 PEM 最大 64 KiB;N/E 与签名输入各最大 16 KiB;RSA 模数 1024 至 8192 位 解析或验证前拒绝
PNG 压缩文件 最大 32 MiB 创建预览前拒绝
PNG 尺寸 单边最大 16,384 像素,总计最大 32,000,000 像素 浏览器解码前拒绝
安全随机数 默认 16 字节,每次 1 至 65,536 字节 拒绝无效长度或不安全回退
JSON/XML 语法着色 最大 100,000 字符且不超过 10,000 个 token 结果仍完整显示,但降级为纯文本以减少 DOM 节点
导航配置请求体 最大 64 KiB 服务端返回 400

Docker Compose 部署

要求 Linux AMD64/ARM64、Docker Engine 24+、Docker Compose v2。

docker compose up -d --build

默认访问地址:http://服务器地址:9000

自定义宿主机端口时,在项目根目录创建 .env(可从 .env.example 复制),例如改为 9100:

WEB_TOOLS_PORT=9100

然后正常启动:

docker compose up -d --build

检查状态:

docker compose ps
docker compose logs --tail=100 web-tools

停止服务:

docker compose down

导航配置保存在 Docker 卷 web-tools-data 中的 /data/navigation.json。全新部署且从未保存过排序时,应用直接使用内置默认配置,该文件可能尚不存在;首次保存后会创建。删除或重建容器不会丢失已有配置,执行 docker compose down -v 才会删除该卷。

健康检查地址:http://服务器地址:9000/healthz

Cloudflare 反向代理与 CSP

服务端在每个响应的 Content-Security-Policy 中放入独立的 128 位密码学随机 nonce。Cloudflare JavaScript Detections 会从源站 CSP 响应头读取该 nonce,并把它加到代理注入的脚本上,因此 Bot Fight Mode 可在不启用 'unsafe-inline' 的情况下与严格 CSP 共存。不得把 nonce 改为固定值,也不得为消除控制台提示而放开 'unsafe-inline'。

项目自身不添加 Web Analytics、遥测或第三方脚本。Cloudflare Web Analytics 是部署层可选的浏览器 RUM,不是 CDN、WAF、DDoS 或 Bot 防护的必要条件;默认保持关闭时,Cloudflare 边缘流量统计仍然可用。若未来明确启用 Web Analytics,必须单独评审 CSP 外部脚本来源和“无统计/无遥测”文档契约。

Windows Server 部署(不使用 Docker)

要求安装 Git、Node.js 22.12.0 或更高版本,并使用 PowerShell 5.1 或更高版本。以下示例假设项目位于 C:\Services\WebTools。

首次克隆后安装依赖并构建:

Set-Location C:\Services\WebTools
npm.cmd ci --include=dev
npm.cmd run build

生产构建成功后,使用项目根目录的统一脚本启动:

powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\web-tools.ps1 start

默认监听 0.0.0.0:9000,导航配置保存在 C:\ProgramData\WebTools\data\navigation.json。可以通过参数覆盖:

powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\web-tools.ps1 start `
  -ListenAddress 127.0.0.1 `
  -Port 9100 `
  -DataDir C:\ProgramData\WebTools\data

不带操作参数运行 web-tools.ps1 时会显示交互菜单:

[1] Start current build (no update)
[2] Update from Git, rebuild, and start
[3] Update from Git and rebuild only
[0] Exit

日常双击或使用“使用 PowerShell 运行”打开脚本后,需要更新代码时选择 2;1 只启动磁盘上已有的 dist,不会拉取代码或重新构建。计划任务、快捷方式和自动化仍应显式传入 start、update 或 update -NoStart,不会进入菜单等待输入。

脚本不会自动修改 Windows 防火墙。需要从局域网访问默认端口时,可由管理员仅对专用网络配置入站规则:

New-NetFirewallRule -DisplayName 'Web Tools 9000' -Direction Inbound -Action Allow `
  -Protocol TCP -LocalPort 9000 -Profile Private

只允许本机或由反向代理访问时,使用 -ListenAddress 127.0.0.1,无需开放该端口。

从 Git main 分支更新时,先在运行窗口按 Ctrl+C 停止服务,再执行:

powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\web-tools.ps1 update

更新脚本只接受干净的 Git 工作区和当前 main 分支,使用 git pull --ff-only origin main 避免隐式合并。随后执行 npm ci --include=dev、生产构建并自动重新启动服务。npm ci 会先删除现有 node_modules 再按 package-lock.json 完整重建,不需要手工删除旧依赖。只更新和构建、不立即启动时增加 -NoStart。

脚本不会读取、覆盖或删除 C:\ProgramData\WebTools\data。PowerShell 窗口关闭后前台服务会停止;如使用 Windows 计划任务,应让任务执行 web-tools.ps1 start,更新时停止任务、运行 web-tools.ps1 update -NoStart,然后重新启动任务。

Windows 单 EXE 交付状态

当前版本不交付 Windows 单 EXE。正式支持的部署方式仍是 Docker,或 Windows 上的 Node.js、Git 与 web-tools.ps1。对于自用 Windows Server,现有脚本更容易检查、更新和排障,因此单 EXE 不是必要条件。

若后续明确需要把程序交付给没有 Node.js 环境的 Windows 用户,建议采用 Node.js Single Executable Application(SEA),不要为本项目引入 Electron。实现时至少需要:

  1. 增加专用的 EXE 启动入口,并把生产 dist/、工具目录和默认导航配置作为只读资源嵌入。
  2. 抽象静态资源读取方式,使 Node 服务既能读取开发时的文件系统,也能读取 EXE 内嵌资源。
  3. 增加 SEA 配置、注入工具(通常为 postject)、build:exe 脚本以及 Windows x64/ARM64 分架构构建。
  4. 继续把 navigation.json 放在 EXE 外部的可写数据目录,默认使用 C:\ProgramData\WebTools\data,升级 EXE 时不得覆盖它。
  5. 增加 Windows Server 启动、端口、静态资源、/tools/setting、更新替换和杀毒软件兼容性冒烟测试。
  6. 正式对外分发时补充 EXE 图标/版本资源,并考虑 Authenticode 代码签名;未签名程序可能触发 SmartScreen 警告。

这项改造对源码体积影响不大,通常只是数十 KB 级的入口、资源适配和构建脚本,并增加少量开发依赖;真正明显的是发布产物。每个架构的 EXE 会包含 Node.js 运行时,常见为约 60-100 MB 未压缩、约 30-60 MB 压缩,具体随 Node 版本和资源大小变化。EXE 和中间产物必须保持在 .gitignore 或发布目录中,不提交到 Git,因此仓库不会明显膨胀;增加的主要成本是分架构构建、签名、测试和更新维护。

启动故障排查

  • ENOENT ... dist\\index.html:当前目录只有源码或尚未生成生产前端。先执行 npm.cmd ci --include=dev 和 npm.cmd run build,再启动服务;直接执行 node server\\index.mjs 不会替代构建步骤。
  • 页面能打开但左侧没有新工具:仅重新构建 dist 不会更新已经运行的 Node 进程。停止旧进程后重新启动,并在浏览器执行一次强制刷新(Ctrl+F5)。
  • 新工具仍未出现:确认服务输出的 Navigation config 路径与实际数据目录一致。旧的 navigation.json 会保留用户排序,只在服务重启后首次读取 API 时补入新工具。
  • 关闭 PowerShell 窗口后服务消失:前台启动是预期行为。需要长期运行时使用 Windows 计划任务或服务管理器,让任务执行 web-tools.ps1 start,不要依赖打开的交互窗口。

工具管理

管理入口不显示在页面中,直接访问:

http://服务器地址:9000/tools/setting

可以调整分类顺序、分类内工具顺序及工具所属分类。保存时采用同目录临时文件和原子替换。

导出配置(至少保存过一次排序后执行):

docker compose cp web-tools:/data/navigation.json ./navigation.json

导入配置:

docker compose cp ./navigation.json web-tools:/data/navigation.json
docker compose restart web-tools

升级应用前建议导出该文件。新版本增加工具时,服务端会保留已有顺序,并把缺少的新工具追加到其默认分类。

离线镜像

若交付目录包含 personal-web-tools-2026.8.22-amd64.tar,可直接导入:

docker load -i personal-web-tools-2026.8.22-amd64.tar
docker compose up -d --no-build

当前源码 ZIP 本身不是 Docker 镜像 tar。

本地开发

要求 Node.js 22.12.0 或更高版本。首次安装使用锁定依赖:

npm ci

终端一运行开发配置服务。这里的 8081 仅用于 Vite 开发代理,不是生产默认端口。PowerShell:

$env:PORT = '8081'
$env:DATA_DIR = (Join-Path (Get-Location) 'data')
node .\server\index.mjs

Bash:

PORT=8081 DATA_DIR=./data node server/index.mjs

终端二运行 Vite;/api 和 /healthz 会代理到 127.0.0.1:8081:

npm run dev

生产模式本地运行:

npm run build
npm start

生产服务默认监听 0.0.0.0:9000。

新增工具或修改 shared/tool-catalog.json、shared/default-navigation.json 后,不能只执行 npm run build。Node 服务会在启动时加载工具目录;必须先停止旧进程,再重新执行 npm start(Windows Server 使用 web-tools.ps1 start,Docker 使用 docker compose up -d --build)。服务重启后,已打开的浏览器页面还需要刷新,才会重新读取导航 API;已有 data/navigation.json 不会被覆盖,只会自动补入缺少的新工具。

完整工程检查:

npm run check
npm audit --audit-level=low

npm run check 会依次运行全部 Vitest 测试、TypeScript/Vue 类型检查和生产构建。服务端测试使用随机本地端口验证 SPA 直达路由、静态资源 404 与缓存策略、导航 API、请求大小限制及跨源浏览器写入拦截。

自动化测试还覆盖标准算法向量、Base64 规范性、16 种 CRC 预设的名称/参数/Check 值、空输入与 64 位结果边界、CRC 内联 Hex 已知向量/多种分隔格式/资源上限、Intel HEX 记录与 block 边界、固件 Hash 与大小端 Block 头向量、RSA PKCS#1 v1.5/PSS 三种 Hash、PEM/X.509/N-E 公钥解析、签名编码与 PSS 盐长边界、原始文件、Intel HEX 有效数据与大小端 Block 校验头的验签字节语义、文件替换成功提交、失败保留旧状态、过期 Worker 响应隔离和 Worker 生命周期异常、PNG 头部与像素限制、导航排序纯函数、目录/图标/懒加载组件一致性,以及原子写入失败后的临时文件清理。

增加工具

Intel HEX 与 Block 校验头固定语义

固件 Hash、RSA 签名验证与 CRC 共用经过校验的 Intel HEX 解析器,但使用独立纯逻辑、Worker 和 Vue 页面。解析器处理扩展段/线性地址,将数据按 32 位绝对地址排序,合并连续记录,去重内容一致的重叠记录,并拒绝冲突或越过 0xFFFFFFFF 的数据。记录文本、记录校验和、EOF 和启动地址不参与 Hash 或签名验证。

摘要计算优先使用浏览器原生 Web Crypto;通过普通 HTTP 局域网地址访问而无法使用 SubtleCrypto 时,自动回退到项目内已有的 node-forge SHA-256/SHA-512 实现。两条路径都在 Web Worker 中本地处理,不会把固件数据发送到服务端。

“有效数据”模式的总输入为所有 block 数据按地址升序直接拼接,不填充地址空洞。“Block 校验头”模式在每个 block 前加入 8 个二进制字节:

uint32 startAddress
uint32 dataLength

默认使用 Big Endian,可以显式切换 Little Endian。两个字段始终为 4 字节;dataLength 只表示该 block 的有效数据字节数,不包含 8 字节校验头。总输入严格为 Header1 || Data1 || Header2 || Data2 ...。固件 Hash 对该输入输出总 SHA-256/SHA-512 和每个 block 的独立摘要;RSA 签名验证则把同一输入交给所选 RSA/Hash 算法验证。不得把固定宽度 Hex 文本误作为 ASCII 字符加入计算,也不得隐式使用运行设备的原生端序。

1. 先定义稳定标识

为工具选择永久的 kebab-case id,例如 url-encode。已发布工具的 id 不应修改,因为路由、懒加载映射和用户保存的导航配置都依赖它。

确定工具所属分类。新增分类时,需要同时更新:

  • shared/tool-catalog.json 中的 categories
  • shared/default-navigation.json 中的 categories

仅新增工具时,分类配置版本仍保持 version: 1,不要因为工具数量变化而升级配置格式版本。

2. 编写独立计算逻辑

将编码、解析、加密、校验或文件生成逻辑放入 src/lib/。优先使用浏览器标准 API或经过验证的现有依赖,不在 Vue 组件中堆积算法实现。

在 tests/ 添加正常输入、边界输入、无效输入和已知测试向量。涉及字节的工具必须明确 UTF-8、Hex、Base64、换行及分隔符语义,避免隐式改变数据。

文件或高开销工具还必须定义文件大小、记录数量、图像尺寸或输出 DOM 数量等资源上限。异步工具在清空、更换输入或卸载后必须忽略旧任务结果;计算量较大的文件解析与 CRC 计算放入 Web Worker。若新工具采用“解析文件后继续在同一 Worker 中计算”的协议,应优先复用 FileDropField 和 useTransactionalFileWorker;候选文件解析成功前不得销毁当前 Worker、文件摘要或结果。

3. 编写统一的工具页面

在 src/tools/ 新增一个 Vue 组件,并参考现有 Base64Tool.vue 或与需求最接近的工具。

  • 页面外层使用 ToolPage。
  • 文本输入输出优先使用 TextEditor。
  • 模式切换使用 ModeTabs。
  • 操作按钮使用 Lucide 图标和现有 action-button 类。
  • 必须提供清空、错误提示和必要的复制/粘贴操作。文件工具的交互与现有协议匹配时复用 FileDropField,不要复制一套相近的上传框和替换状态。
  • 不增加登录、收藏、赞助、遥测、外部网络请求或独立视觉风格。
  • 在窄屏下确认控件不溢出、不重叠,文字不会遮挡。

4. 登记工具元数据

在 shared/tool-catalog.json 的 tools 中增加:

{
  "id": "url-encode",
  "title": "URL 编解码",
  "category": "encoding",
  "description": "编码和解码 URL 组件。",
  "icon": "Link"
}

id 必须唯一,category 必须存在。icon 使用 Lucide Vue 图标名称。

在 shared/default-navigation.json 的目标分类工具数组中加入相同 id,位置即新部署的默认显示顺序。

5. 注册图标与懒加载组件

在 src/tools/registry.ts 中完成三件事:

  1. 从 @lucide/vue 导入目录中填写的图标。
  2. 把图标加入 iconComponents。
  3. 把工具 id 和 defineAsyncComponent(() => import(...)) 加入 toolComponents。

工具目录、默认导航和注册表中的 id 必须完全一致。路由会从注册表自动生成,不需要修改 src/router.ts。

现有自动化测试会校验目录分类、工具 ID、图标注册和懒加载组件映射。新增工具后若漏改任一处,npm test 或应用启动会直接报错。

6. 验证兼容性

npm run check
npm audit --audit-level=low

还应在真实浏览器中检查:

  • 新工具的默认路径 /tools/<id> 可以直接打开和刷新。
  • 左侧导航、搜索和 /tools/setting 正常显示新工具。
  • 已保存的旧 navigation.json 在服务重启并首次读取后会自动补入新工具;仅重新构建 dist 不会刷新已经运行的 Node 进程。
  • 桌面端和约 390 x 844 的移动端竖屏布局正常。
  • 浏览器控制台无错误,工具内容没有发往服务端。

AI 接手清单

后续由 AI 增加或修改工具时,应先阅读本文件,然后依次检查:

  1. shared/tool-catalog.json 和 shared/default-navigation.json
  2. src/tools/registry.ts
  3. 与目标功能最接近的 src/tools/*.vue
  4. src/components/ToolPage.vue、TextEditor.vue、ModeTabs.vue;文件工具还要检查 FileDropField.vue
  5. 相关 src/lib/、src/workers/ 和 tests/;采用解析/计算 Worker 协议时还要检查 src/composables/useTransactionalFileWorker.ts
  6. 涉及工具登记或导航行为时,检查 server/navigation.mjs 中的导航兼容逻辑

AI 不应仅修改 dist/;必须修改源码并重新构建。不得覆盖或删除用户的 data/navigation.json。发现工作区已有未说明的改动时应保留并兼容,不得擅自回退。

处理多人访问、文件工具或异步计算时,还必须检查本文档中的“多人使用与状态边界”和“资源限制”,避免重新引入共享状态、旧任务覆盖新输入或无上限解析。

完成任务后至少报告:修改内容、关键数据格式选择,以及实际执行的测试和构建结果。只有在任务要求制作发布包时,才需要报告容器包/ZIP 路径及 SHA-256。涉及 UI 的改动还要进行桌面、中间宽度和移动端浏览器验收。

版本与发布

应用版本的唯一权威来源是 package.json。版本采用 npm/SemVer 兼容的日历版本 YYYY.M.D,例如 2026.8.22;月份和日期不使用前导零。每个自然日只发布一个正式版本,需要预发布验证时可使用 YYYY.M.D-rc.N。package-lock.json 记录完整依赖树、下载地址和完整性摘要,供 npm ci 复现安装;其中项目自身的版本会在文件顶部和 packages[""] 中各出现一次,其余 version 都是第三方依赖版本,不应手工统一修改。

使用 npm version YYYY.M.D --no-git-tag-version 可以同步更新 package.json 与 package-lock.json。按当前工程结构,一次完整版本发布需要更新以下 5 个已跟踪文件:

  1. package.json
  2. package-lock.json
  3. docker-compose.yml 中的镜像标签
  4. README.zh-CN.md 中的当前版本和离线镜像文件名
  5. CHANGELOG.md

README.md 不硬编码版本号,而是指向 package.json,因此无需为每次版本升级修改。AppSidebar.vue 构建时直接读取 package.json,无需手工改其中的版本字符串。发布新版本时:

  1. 先更新版本号,再同步镜像标签、本文档和 CHANGELOG.md。
  2. 运行 npm run check 和 npm audit --audit-level=low。
  3. 重新生成未跟踪的 dist/ 生产构建。
  4. 重新制作源码/容器部署 ZIP,以及任务要求的可选 Docker 镜像 tar,并生成 SHA-256。
  5. 检查发布包不包含 node_modules、运行数据、令牌、.env 或其他本机文件。

版本号固定显示在左侧导航底部;版权信息 Copyright © mid All Rights Reserved. 固定显示在所有页面底部。第三方许可保留在 THIRD_PARTY_NOTICES.md。

安全边界

  • 应用代码无登录、无统计、无遥测、无 CDN 资产和第三方网络请求;部署时可在外层使用 Cloudflare 反向代理。
  • /tools/setting 是固定但不显示的入口,不构成身份认证;直接公开到互联网时任何访问者都可能修改排序。
  • 工具内容仅在浏览器内存中处理,默认不会持久化。
  • 容器以非 root 用户运行,根文件系统只读,全部 Linux capabilities 已移除。
  • 服务端只接受不超过 64 KiB 的导航 JSON 配置。
  • 服务端只提供静态文件、GET/PUT /api/navigation 和 GET /healthz。
  • 只有无扩展名且明确请求 HTML 的前端路由会回退到 index.html;缺失的 JS、CSS 和其他资源返回 404。
  • 浏览器发起的导航配置写入只接受 Sec-Fetch-Site: same-origin;缺少该请求头的非浏览器客户端仍可写入,因此这项检查不能替代身份认证或外层访问控制。
  • JSON API 响应使用 Cache-Control: no-store,避免浏览器缓存导航和健康状态。
  • 只有文件名带构建指纹的 dist/assets/ 资源使用一年 immutable 缓存;HTML、favicon、Manifest 和其他稳定文件名资源使用 no-cache,更新后会重新验证。
  • 安全响应头禁止第三方脚本、跨站嵌入、摄像头、麦克风和定位权限;每个响应的 CSP 使用独立 128 位 nonce 兼容 Cloudflare JavaScript Detections,不允许 'unsafe-inline'。