一份写给「待办记录工作台」的完整论文:从产品缘起、需求设计、功能体系,到碎片化加载引擎、数据持久化与页面自我保护,逐层拆解一个约 880KB 应用如何把自己切成 52 片、藏进 102 个目录,又在约 0.5 秒内安然重组、完整呈现。
待办记录工作台(DaibanJilu)是一款面向个人日常事务管理的单页 Web 应用,涵盖待办清单、长期待办、每日记录、日历、搜索、回收站、草稿箱、操作日志、标签管理、数据管理与统计面板等十二大已实现功能模块。本文以「记录待办系统」为对象,对该作品进行一次全面、系统的技术论述。论文的主要工作包括:其一,完整阐述其独创的「碎片链 + 路径派生密钥 + 干扰文件」自防护架构——载荷被切分为 52 片,散布于 102 个随机命名的目录,混入数量多于真实碎片的干扰文件,加载时按链头清单逐片校验、并发门控、失败重试,约 0.5 秒完成重组;其二,逐层拆解链头二进制清单的字节布局、路径派生密钥的异或编解码、加载器六步流水线与干扰文件成本模型;其三,系统梳理十二大功能模块的信息架构、实体字段、双层持久化(IndexedDB 主存储 + localStorage 元数据)与页面自我保护层(开发者工具检测、水印、右键/复制/保存/打印/拖拽拦截);其四,给出威胁模型与攻击成本分析,并诚实地划定「提高提取成本」而非「绝对防盗」的技术边界。论文旨在为单页应用的源码保护与个人工具产品设计提供一份可复用的研究范本,同时记录这份作品在设计、验证与权衡中的完整思考。
关键词:待办管理;单页应用;碎片化加载;源码防护;二进制清单;SHA-256;IndexedDB;本地持久化;威胁模型
本章交代作品诞生的背景与要解决的问题,明确论文目标、方法与结构。
过去十年,个人效率工具的形态经历了两轮显著迁移:从桌面客户端走向 Web,再从服务器端应用走向纯前端单页应用(SPA)。浏览器存储 API(localStorage 与 IndexedDB)的成熟,使得一款功能完整的个人工具——待办管理、笔记、记账、习惯打卡——可以完全脱离后端服务器,以「一个 HTML 文件 + 浏览器本地存储」的形式独立运行。这种形态带来了三个立竿见影的好处:零部署成本(扔到任意静态托管即可使用)、零账号摩擦(打开即用,数据留在本机)、零服务器账单(无数据库、无接口、无运维)。
然而,单页形态的代价同样深刻:应用的全部逻辑、模板与数据字典都内联在 HTML 里,任何人按下「查看源代码」或「另存为」,一次点击即可整页搬走。对于个人作品而言,这是作者最不希望看到的结果——倾注了大量时间打磨的产品细节、交互语言与视觉设计,变成了一串任何人都能复制粘贴的字符。更现实的场景是:当作品被部署到公开仓库(如 GitHub Pages)时,仓库本身即暴露了全部源码;当作品通过即时通讯工具、群聊或网盘传播时,接收者手中的文件与原版完全等价。个人工具通常没有商业授权体系,也无力建设账号鉴权,因此「保护作品」这一诉求几乎全部落在前端技术本身。
与此同时,一个同样重要但常被忽视的需求是可靠性:单文件应用一旦被意外截断、被即时通讯工具二次转码、被文本编辑器错误保存,就可能整体报废。传统单页应用把所有代码放在一个巨大的文本文件里,换行符、字符集、BOM 头、剪贴板截断等任何一次文本层面的扰动都可能致命。一款理想的个人工具既希望「难被拿走」,又希望「不易损坏」。
围绕上述背景,本文以「待办记录工作台」(下称「本系统」)为对象,系统回答以下四组问题:
产品层面:一款面向个人日常事务的待办工作台应当具备哪些功能维度?其信息架构、交互语言与空态设计如何支撑「从记录到复盘」的完整闭环?长期待办与今日待办如何在时间尺度上分工互补?
工程层面:如何在不引入任何构建工具、服务器与依赖的情况下,把一个约 880KB 的应用设计成「加载时重组、离线可运行、损坏可定位」的自保护结构?碎片链、路径派生密钥、干扰文件等机制各自承担什么角色?
数据层面:双层持久化(IndexedDB 主存储 + localStorage 元数据)如何划分职责?跨版本数据迁移、配额监控与回填策略如何设计?多选标签体系、历史修改记录与搜索历史如何被完整纳入备份范围?
安全层面:「防提取」的真实边界在哪里?开发者工具检测、水印、交互拦截等页面自我保护手段的有效性与局限性如何评估?
本文的目标不是复刻或美化一个界面,而是以工程论文的方式完整地、可复核地呈现本系统的设计与实现。具体贡献归纳为以下五点:
机制阐释:系统化阐述「魔数清单 + 路径派生密钥异或 + 逐片哈希校验 + 并发门控 + 失败重试 + 干扰文件」的碎片链加载架构,并给出本版本的性能指标与设计取舍。
功能测绘:基于界面结构、运行时字符串与行为观察,绘制出包含十二大功能模块、实体字段、操作日志元数据、存储键名的完整功能地图,覆盖全部操作路径。
安全评估:建立分层威胁模型,对「查看源代码」「一键保存」「批量抓取」「逆向重组」「仓库克隆」五类提取路径逐一评估成本与有效性,并如实划定技术边界。
工程方法论:沉淀出一套「自检先行、碎片可验证、错误可定位、诊断可开关」的单页应用交付与运维范式,供同类项目参考。
设计思考:记录产品在功能取舍(如多选标签与统计面板的落地)、数据安全与视觉语言上的决策过程,为个人工具设计提供一份完整的案例。
本文全部基于对作品本身的检查与验证,方法链条如下:
静态审查:精读入口页壳层源码,还原内嵌的 UI 骨架与加载器算法(ROOT、SALT、链头数组、并发门控、重试、清单解析、重组与执行)。
自检工具验证:运行碎片自检脚本,确认 52 个真实碎片与干扰文件的分布及完整性。
重组回归:依据加载器同一套密钥派生规则(SHA-256(SALT + 相对路径) 派生异或密钥)编写重组脚本,将全部碎片解码拼装为明文载荷并逐片比对哈希,作为第四章机制阐释的直接证据。
桩环境行为验证:在 Node 沙箱中注入最小 DOM/存储桩,以「译码函数包装 + 调用日志」方式捕获运行时实际使用的全部字符串常量,用于功能测绘与行为验证。
交叉核对:将界面文案、解码字符串、存储键名与随包说明相互比对,所有结论均以可追溯的原始材料为据。
全文共十一章,另有五个附录。第二章从需求分析入手建立产品的功能与非功能基线;第三章给出系统总体架构与物理布局;第四章是本文的技术核心,逐层拆解碎片防护机制;第五章详尽测绘十二大功能模块;第六章阐述数据模型与双层持久化;第七章讨论独立于加载器之外的页面自我保护层;第八章覆盖用户体验与界面设计;第九章进行安全性与风险分析;第十章给出测试与质量保障方法及验证实验;第十一章总结并展望后续演进方向。附录 A–E 分别提供术语表、存储键清单、动作日志元数据、关键代码段注释与图表清单,便于读者对照原文核验。
本章建立产品的用户画像、功能需求与非功能需求基线,并阐释贯穿全系统的设计理念。
本系统的目标用户并非「需要协作与提醒的企业用户」,而是追求私密、自洽与掌控感的个人用户:数据只属于自己、工具随取随用、不希望被账号体系与服务器绑定。围绕这一画像,可以归纳出四类典型使用场景:
场景一:通勤碎片时间。在地铁或排队间隙随手记下一件待办或一条「报件已送达」式的事务记录,30 秒内完成输入、打标、归位,无需联网。工作台的「每日记录 + 短语快捷填充」正是为这一场景设计。
场景二:工作日的分层管理。把任务分成「今日待办」与「长期待办」两个时间尺度:短期用截止日期、优先级与标签推进;长期用「转为今日待办」完成从长期池到当日池的流转,反向以「转为长期待办」沉淀反复出现的周期性事务。
场景三:周末复盘与回看。通过日历查看任意一天做了什么,通过操作日志回放本周对数据的所有增删改,通过统计面板查看完成率与近七天趋势,形成「记录—执行—复盘」的闭环。
场景四:成果的私人化保存。用户不希望自己的工具界面、交互细节与数据字典被他人一键复制用于「白嫖」或二次分发;也不希望在传阅过程中因文件截断、转码而永久损坏。这正是碎片防护层存在的理由。
依据界面结构与运行时行为,可将系统功能需求归纳为十二大已实现模块。下表列出功能编号(FR)、模块、核心能力与关键交互,构成第五章功能详解的索引:
| 编号 | 模块 | 核心能力 | 关键交互 |
|---|---|---|---|
| FR-01 | 待办清单 | 工作/生活双分区;全部/待办/已完成/已逾期/星标五态筛选;优先级、标签、截止日期、完成时间、最后操作时间 | 新增、编辑、完成/取消完成、复制、删除、星标、置顶、拖拽排序、批量清空分区、转为长期待办 |
| FR-02 | 长期待办 | 长期池任务;类型(工作/生活)与状态筛选;固定维护习惯性事项;不显示时间 | 新增、编辑、完成、星标、置顶、复制、转为今日待办 |
| FR-03 | 每日记录 | 多选标签体系(可自定义标签与配色);短语快捷填充 | 新增、编辑、复制、置顶、星标、删除;短语一键带入 |
| FR-04 | 草稿箱 | 未完成输入的自动暂存;草稿独立管理 | 新增、编辑、转待办、转记录、删除;重新打开继续编辑 |
| FR-05 | 回收站 | 删除数据的软删除暂存;可恢复或彻底清除 | 恢复待办/长期待办/记录/草稿;清空回收站 |
| FR-06 | 日历 | 按月视图呈现每日内容密度;按日查看 | 上一月/下一月/回到今天;点击日期查看当日事项 |
| FR-07 | 搜索 | 范围(全部/待办/记录/长期/草稿)+ 类型(工作/生活)+ 日期区间(起止日期) | 关键词检索、结果居中跳转、搜索历史 |
| FR-08 | 设置(标签管理) | 标签管理、记录标签管理、便捷短语管理 | 增删改、配色、分组、重名校验 |
| FR-09 | 操作日志 | 全部操作行为留痕(增删改、恢复、导入导出等) | 按分类筛选、清空日志 |
| FR-10 | 数据管理 | 导出 JSON 备份、导入 JSON 恢复、导出 Markdown、复制当天、删除当天、删除全部;存储概览与容量提示;每日备份提醒与下载 | 文件级备份与恢复;剪贴板级日汇总 |
| FR-11 | 页面保护 | 开发者工具检测、水印、交互拦截、锁页 | 检测到调试行为即锁定并提示刷新 |
| FR-12 | 统计 | 统计总览:指标瓦片 + 完成率 + 近七天趋势条 + 类型/优先级/标签分布 + 活跃与节奏 + 近七天新增对比 | 数据管理面板内常驻展示;统计口径由明细实时计算 |
此外,系统内还有着若干功能点:如日期导航顶栏(前一天/后一天/今天快速切换)、复制内容(将当日全部内容格式化后写入剪贴板)、动作菜单(每一条数据项上的「…」更多操作聚合)、搜索历史(最近查询词留存)、标签全局展开与收起(「> / v」一键切换)、单条内容复制(仅复制内容本体)、最后操作时间显示等,均将在第五章相应小节展开。
NFR-1 启动性能:全量载荷约 880KB,重组启动约 0.5 秒,且只发起 52 个真实请求(绝不触碰干扰文件),网络失败自动重试至多 3 次。
NFR-2 抗文本损坏:全部碎片以二进制 + arrayBuffer 读取,免疫换行符转换、字符集错乱、BOM 头、剪贴板截断等文本层损坏;每片以长度 + SHA-256 双重校验,损坏可精确定位到文件名。
NFR-3 部署成本:产物仅需静态托管(任意静态服务器),无构建、无依赖、无后端;入口页可任意改名,碎片根目录可任意重命名或嵌入既有目录。
NFR-4 兼容性:以标准浏览器 API(fetch/arrayBuffer/IndexedDB/localStorage/Web Crypto)为依赖面,未使用任何构建产物或运行时框架,理论上任何现代浏览器可直接运行。
NFR-5 数据不丢失:提供导出/导入 JSON 双通道、草稿自动暂存、回收站软删除、删除当天/全部前的二次确认、配额使用量实时展示;备份文件覆盖全部数据域(含历史修改记录、搜索历史与自定义设置),导入时整体恢复。
NFR-6 可运维性:通过碎片自检脚本、页首精确错误提示、诊断模式三件套,使「坏了能定位、传前能自检、运行能观测」。
传统思路下,防复制(把代码藏起来)与可靠性(把代码摊开可校验)互相矛盾。本系统的解法是把矛盾转移到文件组织层:内容仍然完整存在,但被打散为小片、以随机命名散布、以路径派生密钥加密、以清单哈希校验。对合法用户,浏览器按清单精确取回;对提取者,需要先识别链头、解析清单、派生密钥、重组拼装,成本远高于一次「查看源代码」。
产品交付形态始终是「一个 HTML + 一个资源目录」,无任何安装步骤。入口页自包含 UI 骨架与加载器,资源目录在加载时按需获取;这种「壳 + 载荷」的二分也天然地把「表现层」与「逻辑层」分开,便于独立演进。
所有业务数据写入浏览器本地存储,不上传任何服务器;「数据管理」模块的一切操作(导出、导入、复制、删除)均发生在用户设备与剪贴板/文件之间。隐私即默认,这是个人工具最朴素也最坚固的设计承诺。
市面上主流的个人待办工具大致有三类:在线协作型(如 Trello、Notion、飞书任务)、极简单机型(如系统自带备忘录)与数据自托管型(如 TiddlyWiki、Obsidian 本地库)。本系统的定位与三者均有本质区别,也因此在设计上刻意避开它们的默认路径:
不学在线协作型:不引入账号、服务器、多人权限与订阅制。协作是团队场景的答案,而本系统服务的个人场景要的是「打开即用、数据归己」;一旦接入服务端,也就同时接入服务端的中断、隐私与续费风险。
不满足于极简单机型:系统备忘录只解决「记下来」,不解决「记下来之后怎么办」。本系统通过状态机(完成/逾期/星标/置顶)、分区(工作/生活)、流转(待办↔长期待办)、复盘(日志/日历/搜索/统计)补全了「记录—执行—回顾」的后半程。
不照搬数据自托管型的复杂度:自托管工具往往要求用户自己管理文件、插件与同步策略,学习成本高。本系统把复杂度收进交付物内部:用户只需要「一个 HTML + 一个目录」,迁移靠导出/导入 JSON,没有任何配置负担。
这一差异定位也直接决定了第四章防护设计的必要性:在线协作型靠服务端鉴权保护内容,自托管型靠用户自己的文件权限保护内容,而本系统「纯静态、无后端」的形态决定了内容保护必须由前端技术本身承担——碎片防护正是在这一约束下生长出来的答案。
本章从逻辑分层、物理布局与交付物清单三个视角刻画系统整体架构。
整个系统在逻辑上可分为五个层次,自底向上为:数据持久层(IndexedDB 与 localStorage 双层存储)、业务逻辑层(重组后的载荷中实现的全部数据操作与状态管理)、表现层(UI 骨架、模块渲染、toast 与弹窗)、碎片加载层(入口页中的链式加载器,负责取回、校验并重组载荷)、保护层(页面自我保护,独立于加载器运行)。其中加载层与保护层共同构成系统的「防御面」,业务与数据层构成系统的「价值面」,两者在入口页与载荷中的物理分布如下:
系统的物理交付物共四件:入口页、碎片目录、自检脚本与说明文档。文件统计如下:
| 交付物 | 大小 / 数量 | 作用 |
|---|---|---|
| 入口页 HTML | 壳层(UI 骨架 + 二进制链加载器) | 入口页:内嵌 UI 骨架与加载器,不含业务内容 |
| 碎片目录 | 102 个目录 · 52 个真实碎片 + 干扰文件 | 52 个真实碎片 + 数量多于真实碎片的干扰文件;多级随机目录 |
| 碎片自检脚本 | 独立 Python 脚本 | 部署前自检:链头解析、逐片哈希校验、干扰文件清点 |
| 说明文档 | 约 4.5 KB | 产品说明、使用与排错指引、诚实边界声明 |
碎片目录的目录层级为随机命名结构:入口页通过 ROOT 常量指向碎片根目录,真实碎片散布于其下 102 个随机命名的目录中,目录名与文件名均无语义(文件名多为无规律的十六进制串),与内容无关。这种布局让「按名字找规律」的路径彻底失效——任何静态分析都必须从加载器出发,而不是从文件名出发。
碎片包的构成关系如下图所示。需要强调的一点是:干扰文件的数量刻意多于真实碎片,这是设计选择——批量抓取者若以「全部下载然后逐个尝试」为策略,必须试错过半的文件才能触达全部真实数据;而正常加载由于链头清单精确指引,永远只请求 52 个真实碎片,从不触碰干扰文件。
将本系统与三类常见单页交付形态横向对比,可以更清楚地看出其在「保护—可靠—成本」三角上的取舍:
| 维度 | 普通单文件 | 单文件 + JS 混淆 | 构建产物 + CDN 鉴权 | 本系统(碎片链) |
|---|---|---|---|---|
| 查看源码即可用 | 是(一次点击) | 部分(需解码) | 否 | 否(需解析链头/密钥/重组) |
| 一键另存为 | 可用 | 可用(可运行) | 需处理资源 | 不可用(碎片缺一即失) |
| 抗批量抓取 | 无 | 弱 | 中(取决于鉴权) | 强(干扰文件 + 逐片校验) |
| 抗文本层损坏 | 弱(整体报废) | 弱 | 中 | 强(二进制 + 逐片定位) |
| 部署依赖 | 任意静态托管 | 任意静态托管 | 需鉴权/CDN 配置 | 任意静态托管 |
| 离线可用 | 是 | 是 | 取决于缓存 | 是 |
| 启动性能 | 最优 | 略损 | 视网络 | ≈0.5s(880KB) |
| 维护成本 | 最低 | 低 | 中 | 低(自检脚本 + 诊断模式) |
作为「看得见的部分」,入口页承载着两段职责:UI 骨架与二进制链加载器。其中 UI 骨架以编码形式内嵌,解码后是一段完整的表现层模板(顶栏日期导航、模块面板、弹窗体系、toast 容器、悬浮按钮与全部 CSS),它在碎片载荷尚未到达时即渲染出页面外壳,并以「正在加载待办记录工作台…」进度条承接用户的等待;加载器则是紧随其后的一小段紧凑 JavaScript,包含四个核心常量与六个流水线步骤:
常量区:ROOT(碎片根目录)、SALT(密钥派生盐)、链头路径数组(每链仅知首片)、并发门控与重试参数——这是整个碎片体系对外暴露的唯一「钥匙串」;
算法区:清单解析(魔数校验、碎片计数、记录展开)、密钥派生(SHA-256 同步封装)、异或解码、长度+SHA-256 双重校验、按序拼接、运行时注入执行。
值得注意的是,壳层刻意不包含任何业务内容——即使完全读懂壳层,也拿不到一条数据逻辑;业务代码的全部价值藏在碎片载荷之中。这一「壳层可读、载荷不可读」的刻意不对称,正是碎片防护的精髓:把攻击者的分析对象从「一个文件」拉长为「一个文件 + 一份需要逆向的加载协议」。
本章为论文技术核心:从威胁模型出发,逐层拆解链头清单、密钥派生、并发加载、干扰文件与性能指标的完整设计。
任何防护设计的第一步是界定对手。按提取能力从低到高,可将本系统面对的对手分为五层:
| 对手层级 | 典型行为 | 技术能力 | 本系统的主要防御 |
|---|---|---|---|
| T1 顺手党 | 查看源代码、Ctrl+S 另存、复制粘贴 | 无编程 | 碎片化:源码无内容;另存仅得壳层 |
| T2 一键保存党 | 使用浏览器「保存完整网页」、下载器批量抓取静态资源 | 会用工具 | 102 个目录中仅 52 个真实;保存得到的是无法重组的碎片 |
| T3 批量爬虫 | 脚本化抓取全部文件后逐一尝试 | 会写脚本 | 干扰文件多于真实碎片,试错成本过半;路径派生密钥阻挡直读 |
| T4 逆向工程师 | 分析入口页加载器,编写重组程序 | 精通前端/加密 | 加载器本身在壳层中可读;此层对手的成本已接近「重写一个应用」 |
| T5 仓库克隆者 | git clone 公开仓库 | 会用 git | 理论上无防御(客户端天然如此);依赖授权/部署策略,见第九章 |
由此可见,碎片防护的核心承诺是:把 T1–T3 的成本抬到「需要编程逆向」的高度,并让 T4 面对的不是一次点击而是完整分析工作。T5 属于部署层问题,不属于客户端技术范畴。
碎片防护机制由五个相互咬合的部分构成:
二进制化:全部内容(CSS、HTML 模板、JavaScript 逻辑与数据字典)作为二进制载荷,与入口页文本彻底分离;碎片以 arrayBuffer 读取,避开文本编码问题。
碎片化:载荷被切分为 52 个碎片(单片约 17KB),以链为逻辑单位组织;入口页只保存每条链第一个碎片的相对路径(链头),其余碎片的路径全部记录在链头的二进制清单中。
路径派生密钥:每个碎片的异或密钥由「盐 + 相对路径」的 SHA-256 派生而来;密钥与文件位置绑定,改名或移动即解码失败,天然形成「防搬移」约束。
链式校验:链头清单为每个碎片记录路径、长度与 SHA-256 摘要;加载时逐片校验,缺片、篡改、错序都能精确报出文件名。
干扰注入:在碎片目录中混入数量多于真实碎片的同构随机噪声文件,使「全量抓取」策略的信噪比大幅降低。
链头文件本身也是一个被异或加密的碎片,解密后其头部是一份二进制清单。格式如下:
| 偏移 | 字段 | 长度 | 说明 |
|---|---|---|---|
| 0–3 | 魔数 | 4 B | 「K7FB」——清单合法性标识,防误读误载 |
| 4–5 | 保留 | 2 B | 版本/扩展位 |
| 6–7 | 碎片计数 n | 2 B(大端) | 本链包含的碎片总数(含链头自身) |
| 8–11 | 链头载荷长度 l0 | 4 B(大端) | 链头自身承载的内容字节数 |
| 12… | 碎片记录 ×(n−1) | 变长 | 每条记录:路径名字节长(1B) + 路径(变长) + 载荷长度(4B 大端) + SHA-256(32B) |
| 末尾 | 链头内容 | l0 B | 链头自身携带的载荷片段 |
52 个碎片按链分组,各链的碎片数随载荷分段自适应分配;链头载荷长度字段的存在使链头自身也能承载内容,不浪费任何一个字节。
每个碎片的解码密钥由全局盐与该碎片相对碎片根目录的路径拼接后取 SHA-256 得到:
// 密钥派生(与入口页加载器同一算法) key = SHA256( SALT + "/" + 相对路径 ) // 例:SALT + "/<一级目录>/<二级目录>/<随机名>.bin" // 异或编解码(对称,解码即再异或一次) plain[i] = cipher[i] ^ key[i mod key.length]
这一设计有两个精妙之处。其一,密钥不落盘:任何文件本身都不包含密钥,密钥是从「盐 + 路径」现场计算出来的;干扰文件即使被下载也无法直接解密(它们的路径不属于任何清单,即使穷举也无法得到正确的密钥上下文)。其二,改名即失效:密钥与路径绑定,若有人把碎片目录改名或移动碎片,除非同步修改加载器中的 ROOT 常量并保持相对路径不变,否则校验必然失败;而 ROOT 只影响目录前缀,相对路径不变时密钥不受影响——这正是随包文档中「改名安全」承诺的机制基础。
在重组回归实验中,以同一算法对碎片目录中的全部文件进行解码尝试:52 个真实碎片全部命中魔数与哈希校验,干扰文件无一命中——这从实证上验证了「正常加载绝不触碰干扰文件」的声明。
入口页加载器是一个紧凑的内联 JavaScript 实现,核心流水线如下:
算法要点归纳如下:
并发门控(gate 20):加载器实现了一个容量为 20 的并发闸,防止一次性发起过多 fetch 压垮浏览器连接池;队列按链顺序消费。
三次重试:每个碎片的请求失败(网络错误/404/校验不符)时自动重试至多 3 次,显著提升弱网或托管服务偶发 5xx 下的加载成功率。
进度驱动:每成功解码一片即更新页面顶部的加载进度;全部就绪后一次性拼接并执行,保证 UI 完整、无闪烁。
精确报错:失败时在页首输出「校验失败 xxx.bin / 长度不符 xxx.bin / HTTP 404 xxx.bin」,直接指向可修复对象。
诊断模式:URL 追加诊断参数后在控制台输出重组字节数与耗时,供开发排障。
干扰文件并非无意义的填充,它们在提取成本模型中扮演关键角色。设真实碎片数为 R=52,干扰文件数为 D(刻意保持 D > R),总文件数 T=R+D。对「全量抓取后逐个猜测」的 T3 类对手,其成功概率曲线随随机尝试次数上升:
随机试错 1 个文件即命中真实碎片的概率:R/T < 50%(因为 D > R);
要拿到「全部」52 个真实碎片,最坏情况下需遍历全部 T 个文件,其中 D 次是无效劳动;
即使拿到全部文件,仍需要识别链头(魔数)、解析清单、按路径派生密钥、逐片异或解码并正确拼接,才能得到可运行的载荷——这一工作量已经接近「读一遍加载器代码」。
更重要的是时间维度:对个人作品而言,「防提取」的收益不是绝对封锁,而是让批量爬取者的单位成本超过重建成本。当对手需要投入的分析时间接近「自己重写一个待办工具」时,碎片防护就达成了目标。
碎片化在带来保护性的同时,天然引入了「文件多、易丢失」的新风险。系统的对策是双重的:一是格式免疫——所有碎片为纯二进制,经由 arrayBuffer 读取,换行符转换、字符集误判、BOM 剥离、文本截断等常见文本损坏对它无效;二是校验与自检——链头清单内置每个碎片的长度与 SHA-256,运行期精确报错;交付物内置碎片自检脚本,在解压后、上传前先跑一遍,输出「PASS/FAIL + 具体碎片名」,把部署事故消灭在发布之前。重组回归实验让 52 个碎片逐一通过长度与哈希校验,零失配,佐证了这套设计的健壮性。
碎片化最容易被质疑的是性能代价:文件数量从「1 个」变成「52 片 + 干扰文件」,加载会不会变慢?本版本的验证数据回答了这个问题——碎片链架构把性能代价压到了可忽略的水平:
| 指标 | 数值 | 设计说明 |
|---|---|---|
| 全量重组耗时 | 约 0.5 s | 52 个碎片并发拉取(门控 20),解压、异或与哈希均为纯计算,无 IO 阻塞 |
| 实际网络请求数 | 52 个 | 链头清单精确指引,绝不触碰干扰文件 |
| 载荷体量 | 约 880KB | 单片约 17KB,适合 HTTP 缓存与弱网增量传输 |
| 单片解码开销 | SHA-256 + 异或 | 每片仅一次哈希比对与一次异或,总耗时微秒级 |
| 失败恢复 | 重试 ×3 | 网络抖动或单点 5xx 不影响整体加载成功率 |
更关键的是二进制载体带来的性能与健壮性双赢:文本碎片需要处理字符集与转义,解析成本高且易碎;二进制碎片由 arrayBuffer 直达内存,加载器无需任何文本预处理。与此同时,干扰文件对合法用户是零成本的——它们从未被请求,只存在于抓取者的世界里。这组数字说明:防护设计的质量不取决于复杂度,而取决于对载体本质的把握——二进制 + 哈希校验 + 并发控制,比堆更多碎片更有效。
| 维度 | JS 混淆(obfuscator) | WASM 封装核心 | 服务端鉴权/接口代理 | 碎片链(本系统) |
|---|---|---|---|---|
| 可读性破坏 | 高(源码不可读) | 高(二进制) | 中 | 高(内容整体不可直读) |
| 运行性能损耗 | 中(字符串解码) | 低 | 低 | 低(异或 + 哈希极快) |
| 部署形态 | 单文件 | 多文件 | 需后端 | 静态目录 |
| 抗「另存为」 | 弱(可运行副本) | 中 | 强 | 强(碎片无法单独运行) |
| 损坏自愈/定位 | 无 | 无 | — | 强(逐片校验定位) |
| 可维护性 | 需保留映射 | 需工具链 | 常规 | 重组工具 + 自检脚本 |
值得指出,混淆与本系统的碎片链并非互斥:重组后的载荷内部仍可采用字符串数组混淆(本系统载荷中即存在字符串数组与译码函数,运行时通过「索引 + 密钥」两参调用还原字符串)。这说明作者采取了文件级碎片 + 代码级混淆的双层纵深,T4 级对手在还原载荷后还需再面对一轮代码级反混淆。
本章按十二大模块逐一测绘系统的功能细节、状态机与交互路径,全部依据界面结构与运行时行为证据。
待办清单是工作台的核心模块。每条待办携带一组结构化字段:归属分区(工作/生活)、类型(公事/私事)、优先级(高/中/低)、发生时间、截止日期、内容、标签、完成状态、星标、置顶、最后操作时间与更新时间。模块采用「分区 + 筛选器」的双重组织方式:
分区:工作与生活两个区块各自独立渲染,区块可折叠(collapsed),可整体清空(「删除全部」),并分别带区块级计数。
筛选器:顶部分组按钮提供五态切换——全部 / 待办 / 已完成 / 已逾期 / 星标。其中「已逾期」由当前时间与截止日期实时比较得出;「星标」是独立于完成状态的标记维度,二者正交。
列表项:每项渲染类型徽标(公事/私事)、优先级色点、标签徽章、截止日期与逾期药丸(overduePill)、星标图标、最后操作时间;行内只保留高频操作,低频操作统一收进「…」更多菜单。
明面操作(精简后):置顶、编辑、转为长期待办、更多(…)。其中「转为长期待办」实现待办池向长期池的沉淀;其余操作(星标、上移、下移、放置于最下、历史修改记录、复制、删除等)统一收入「…」动作菜单,避免界面被按钮淹没。状态机如下:
交互细节上还包含:拖拽排序(列表项可拖动换序,排序基于隐藏的唯一标识 order,新增内容后顺序不再错乱,拖动中有占位样式)、Enter 快速提交新增、内容非空校验(「内容不能为空」)、编辑弹窗与原内容回填等。
长期待办模块服务于「不属于今天、但必须持续维护」的事项(如周期性的材料整理、习惯性事务),其前身为「永久待办」,本轮迭代后全局更名并调整了时间语义。其组织维度为类型筛选(全部/工作/生活)+ 状态分组 + 折叠。与待办的关键差异是不显示时间——它不绑定到某个具体日期,体现「长期」的时间尺度;而待办则显示最后操作时间(当天仅显示时分,跨天带完整日期),两者在时间语义上形成互补。
其最关键的流转动作是「转为今日待办」:一键把长期项实例化为今天的待办(可携带截止日期与标签),实现长期池到当日池的桥接;反向的「转为长期待办」在待办模块中提供。这一双向流转使两池在时间尺度上互补而不重复,是产品信息架构中最具巧思的一环。
每日记录面向「不一定是任务、但值得留痕」的事务信息(如「取件送达,转交相关科室」)。它的差异化设计有三点:
多选标签体系:记录的「记录类型」由旧版的单选类型改版为多选标签体系(recTags)。每条记录可同时打多个标签(如「会议」「报件」兼有),标签可自定义名称与配色;旧版 type 数据在加载时自动迁移到新体系,底层代码、备份结构与统计口径同步更新。这一改动让一条记录的信息维度从「一个类型」扩展为「多组标签」,语义更接近真实事务的多面性。
短语快捷输入:表单内置短语分组,点选即填入内容,把高频事务的录入从「打字」降级为「点一下」。默认短语覆盖生活与工作两类:生活侧如「买菜做饭,打理日常饮食」「锻炼身体,保持健康作息」「联系家人,问候近况」;工作侧如「会议记录,汇总会议纪要」「收集核对,补齐报件要件」「取件送达,转交相关科室」「起草文稿,按时报送材料」等。
记录级操作:明面保留置顶、编辑、复制、更多(…);其余(星标、上移、下移、放置于最下、历史修改记录、删除等)收进「…」菜单,与待办共享同构的动作模型。
草稿箱是「输入过程」的保护层。用户在新增/编辑弹窗中开始输入后,内容会被实时暂存(存在一条提示「内容已暂存,重新打开可继续编辑」);若中途关闭弹窗,草稿仍可在「草稿箱」模块中找到并继续编辑。草稿箱支持:新增草稿、编辑草稿、草稿转待办(按待办表单结构落库)、草稿转记录、删除草稿。这一机制把「误关弹窗」「刷新页面」从数据丢失事故降级为无感恢复,与回收站共同构成双保险。
回收站实现统一的软删除语义:待办、长期待办、每日记录与草稿四类对象的删除一律先进回收站,可分别恢复(动作:恢复待办、恢复长期待办、恢复记录、恢复草稿),也可彻底删除或一键清空。清空与彻底删除均需二次确认。回收站的引入使「误删」有后悔药,同时也让操作日志能完整记录「删除—恢复」的全过程。
日期体系是全部数据的时间主轴。顶部栏提供日期选择器、前一天/后一天切换与「今天」回跳;日历模块按月展示,每个日期格以点状标记当日是否有数据(日历点密度即内容密度)。切换日期后,待办、记录等模块均按该日期重新渲染——「日期即上下文」的设计让用户既能管理「今天」,也能回看「任意一天」。移动端头部已优化为单行显示:日期框收窄、前后一天切换改为「‹ / ›」符号、头部整体左对齐,在窄屏上依然一目了然。
搜索模块提供多维检索能力,筛选维度如下:
范围:全部 / 待办 / 记录 / 长期 / 草稿——把四类对象纳入统一检索,避免「忘了记在哪一类」的查找困境;
类型:全部 / 公事 / 私事——与对象分区正交;
日期区间:起始日期与结束日期(sfDateFrom / sfDateTo),支持按发生时间筛选;本轮迭代对日期输入框做了尺寸收窄与样式优化,让筛选行更紧凑、不挤占结果区域;
搜索历史:最近查询词自动留存(存储键 app-search-history-v1),一键回填重复检索。
结果列表逐项展示命中对象的类型徽标与摘要;点击结果居中跳转到对应内容处并短暂高亮(flash),不再滑到条目列表顶部,这一改进让「捞回一条旧记录」的定位成本降到最低。对个人工具而言,搜索的价值不在于「全网检索」的规模,而在于「把一年前的某条记录捞回来」的确定性。
操作日志是系统行为的「黑匣子」:每一次数据变更都会以结构化动作写入日志(存储键 app-logs-v1),覆盖的动作元数据达五十余种,包括:新增待办、编辑待办、完成待办、取消完成、复制内容、置顶/取消置顶、标记/取消星标、新增/编辑/删除长期待办、转为今日待办、转为长期待办、新增/编辑/复制/删除记录、标签增删改、新增/编辑/删除草稿、草稿转待办、草稿转记录、恢复待办/长期待办/记录/草稿、彻底删除待办、清空回收站、清空待办分区、清空当日记录、清空长期待办、导出 JSON 备份、导入 JSON 备份、导出 Markdown、复制当天、删除当天、删除全部数据、标签改名、记录标签改名、新增/编辑/删除便捷短语、迁移历史数据、清空日志等。
日志模块本身提供分类筛选(全部/待办/记录/草稿/回收站/系统)与清空日志(带确认)。这套机制让用户能够复盘「我的数据是怎么变成今天这样的」,也为故障排查提供了时间线证据。与之配套的还有独立的历史修改记录(存储键 app-history-v1):对每条待办/长期待办/记录的编辑,系统保留修改前后的中文差量文本(如「内容:「A」→「B」」「标签:新增「会议」」),不再暴露英文 id,用户可以直接读懂每一次修改。
设置弹窗聚合三类元数据管理:
标签管理:新增标签(名称非空校验、重名校验「名称已存在」)、改名、删除;删除时二选一——「只删标签,保留事项」或「删除并移除所有事项上的该标签」,把「删标签是否连坐数据」的决定权交给用户;标签可配颜色(调色板包含约十余种色值,如 #f0a100、#0e7490、#22a447、#2f6fd0、#e8590c、#0ca678、#8e44ad、#e03131 等)。一个待办可打多个标签;标签过多时,模块顶部最左侧提供「> / v」按钮,支持一键全局展开 / 收起所有标签,既明确了目的又节省了空间。
记录标签管理:记录的多选标签同样在此维护,新增、改名、删除与配色逻辑与待办标签一致,删除标签时可选择是否从所有记录上移除。
便捷短语管理:按分组维护短语(新增/编辑/删除),是录入效率的最终调节旋钮。
数据管理模块是「数据主权」的落地窗口,全部操作均在本机完成。模块内部采用三级层级排布:最上为「数据管理」图标与标题,其次为存储概览(storage-sub:已存天数、数据量、容量提示与每日备份提醒),再下为功能标签(日历 / 搜索 / 标签管理 / 回收站 / 草稿箱 / 操作日志 / 统计)。操作清单如下:
| 操作 | 行为 | 场景价值 |
|---|---|---|
| 导出 JSON 备份 | 将全部数据序列化为 JSON 文件下载 | 换设备/浏览器迁移、历史归档 |
| 导入 JSON 备份 | 读取备份文件并整体恢复 | 灾难恢复、跨设备同步的替代通道 |
| 导出 Markdown | 按日把待办/记录格式化为 Markdown 文本下载 | 嵌入笔记、周报、知识库 |
| 复制内容(当天) | 当日全部内容格式化写入剪贴板(toast:当日内容已存入剪贴板) | 快速分享当日安排 |
| 删除本日 / 删除全部 | 按日或全量清空(均需确认) | 数据治理与重置 |
| 每日备份 | 提醒下载备份,可记忆备份目录写入 | 长期使用的数据保险 |
备份修复与每日提醒:本版本的每日备份「下载备份」功能经过修复:若此前记忆过备份目录,则直接写入该目录(FileSystem 写入);未记忆时同步触发浏览器下载,避免因用户激活时机问题导致备份丢失;「上次备份日期」以独立存储键(app-backup-lastday-v1)记录,用于每日提醒。
导入导出全覆盖:导出 JSON 备份覆盖全部数据域——所有日期的待办与记录、回收站、草稿箱、操作日志、标签定义、长期待办、历史修改记录、搜索历史与自定义设置(UI 偏好等),导入时整体恢复并覆盖当前数据,导入前有二次确认,导入后对缺失字段给出提示并补空值。任何数据都不会在迁移中丢失。
数据保障表述:模块内的保障说明统一表述为「数据保存在本机设备 / 本地存储」,如实说明数据的位置与归属,不出现任何技术黑话。
动作菜单:列表项右侧「…」按钮弹出上下文菜单(#actionMenu),集中承载该对象的低频动作。经过本轮精简,各类条目的明面按钮收敛为高频三项 + 「…」:长期待办为「置顶 / 编辑 / 转为今日 / …」,待办为「置顶 / 编辑 / 转为长期 / …」,记录为「置顶 / 编辑 / 复制 / …」;星标、上移、下移、放置于最下、历史修改记录、复制、删除等全部收进菜单,既避免界面被按钮淹没,又为内容文本留出更长宽度(移动端操作按钮紧凑排布)。
单条复制:复制单条待办/长期待办/记录时,只复制内容本体,不再附加提示语,粘贴结果干净可用。
悬浮按钮与返回顶部:右下角悬浮按钮提供新增入口;长页面滚动后出现返回顶部按钮。
Toast 反馈:所有写操作后给出轻量确认(如「已移入回收站」「当日内容已存入剪贴板」「类型已改名」),文案与按钮动词保持一致。
弹窗体系:统一遮罩 + 居中弹窗承载新增/编辑/设置;弹窗支持遮罩点击关闭与取消按钮,表单回车提交。
空态设计:各模块均有专属空态(「今日暂无内容」「暂无内容」「回收站为空」「暂无日志」),空态即引导而非空白。
响应式:窄屏下模块折叠为单列,表格与长列表横向滚动,核心操作全部可达;头部在移动端单行显示。
键盘快捷键:全局支持 Enter 提交、Esc 关闭弹窗、Tab 自然聚焦顺序;编辑弹窗打开即聚焦内容框,减少鼠标往返。
长列表分治:当某日数据量很大时,列表按分区/类型折叠展示,避免单屏堆叠过密;「全部/待办/已完成」筛选器天然承担分页职责。
为把十二大模块串联为可感知的完整体验,本节以一名基层办公人员「小周」的一天为例,演示工作台在各时点的实际用法(以下为示例数据,用于展示操作路径):
08:10 晨间:建计划。打开工作台(约 0.5 秒),在「待办」模块新增:工作分区、公事、高优先级、标签「材料」、截止今天,内容「起草文稿,按时报送材料」——短语库点选即入,全程不到 15 秒。
08:40 通勤:随手留痕。地铁上想起「取件已送达」,在「每日记录」选标签「取件」、短语一键填入并保存,记录自动归入今天。
10:30 上午:执行与流转。汇报材料完成,行内点击完成;随后在「长期待办」池把「整理材料,完善台账资料」转为今日待办,长期池与当日池完成桥接。
14:20 午后:草稿兜底。会议间隙开始写一条待办,内容没打完就被叫走;系统提示「内容已暂存,重新打开可继续编辑」。返回后草稿完好,一键续写完成。
17:40 傍晚:分享与回看。点「复制内容」把今日安排写入剪贴板发到工作群(toast:当日内容已存入剪贴板);需要正式周报时用「导出 Markdown」。
周末 复盘与迁移。周六打开统计面板看本周完成率与近七天趋势;打开日历回看一周各日的内容密度;周日执行「导出 JSON 备份」存入私人网盘。换电脑时在新浏览器「导入 JSON 备份」,全部数据随行。
意外 异常处置路径。误删某条待办:回收站一键恢复;弱网加载:自动重试 3 次仍失败时页首精确报错,按随包说明排查;存储接近配额:面板实时显示已用/可用,导出备份后治理。
这趟旅程覆盖了全部模块,且每个动作都在 5.1–5.11 节中找到对应机制——这说明产品功能不是孤立的按钮堆砌,而是一条可走通的完整工作流。
本章阐述实体模型、字段设计、双层存储架构、存储键清单与迁移/配额策略。
系统的业务实体共有六类:待办(todo)、长期待办(permanent)、每日记录(record)、草稿(draft)、标签(tag)、操作日志(log),另有历史修改记录(history)作为独立数据域。六类实体围绕「日期」与「标签」两个公共维度相互关联:
实体间还存在若干转换关系:待办 ↔ 长期待办(双向流转)、草稿 → 待办/记录(转存)、任意实体 → 回收站(软删除)、回收站 → 原实体(恢复)。这一关系网络保证了「任何数据在系统中都有明确的下一站」。
| 字段 | 取值示例 | 说明 |
|---|---|---|
| mode | work / personal | 分区:工作(公事) / 生活(私事),决定列表归属区块 |
| type | 公事 / 私事 | 待办类型展示口径,与 mode 联动 |
| priority | high / medium / low | 优先级:高 / 中 / 低,以颜色与顺序体现 |
| recTags | 标签 id 数组 | 每日记录的多选标签(原单选 recType 已迁移);统计与筛选均按标签聚合 |
| time | "HH:mm" | 发生时间 |
| due | "YYYY-MM-DD" | 截止日期;逾期判断依据 |
| content | 任意文本 | 核心内容;短语一键填充;单条复制仅复制此字段 |
| tags | 标签 id 数组 | 标签引用;删除标签时可选择保留/移除事项上的引用 |
| done / star / pin | 0 / 1 | 完成、星标、置顶三个正交状态 |
| lastAct | 时间戳 | 最后操作时间:待办/记录显示(当天 HH:MM、跨天带日期);长期待办不显示 |
| updatedAt | 时间戳 | 最后修改时间,日志与统计的时间依据 |
系统的持久化采用 IndexedDB 主存储 + localStorage 元数据的双层结构,职责划分如下:
IndexedDB(主存储):承载结构化的业务数据。库名形如 UzAdbdb、版本号 1,按「日」组织对象仓库(day-* 系列),同时维护元数据仓库;事务以 readwrite 模式写入,写操作走 Promise 封装(openDB / idbTx / idbGet / idbGetAll / idbPut)。按日分仓的设计使「某天的数据」可以在一个仓库内完整读写,天然匹配日历、复制当天、导出当天等按日粒度操作。
localStorage(元数据/偏好):承载体量小、读频高或需同步操作的配置与记录,键名清单见 6.4。
这种分层的工程理由是:业务主体放 IndexedDB(容量大、结构化、事务化),高频小数据放 localStorage(API 简单、同步读、不占事务开销),两者互补而不过度设计。
通过运行时解码与行为观察,localStorage 键名如下(均为应用自有前缀 + 版本后缀):
| 键名 | 用途 |
|---|---|
| app-bin-v1 | 回收站数据(软删除对象集合) |
| app-logs-v1 | 操作日志 |
| app-history-v1 | 历史修改记录(编辑前后中文差量文本) |
| app-drafts-v1 | 草稿集合 |
| app-tags-v1 | 标签定义(名称 + 配色) |
| app-rectypes-v1 | 记录标签 / 记录类型定义(兼容迁移) |
| app-phrases-v1 | 便捷短语分组与条目 |
| app-permanent-v1 | 长期待办数据 |
| app-search-history-v1 | 搜索历史 |
| app-ui-v1 | UI 偏好(折叠状态、上次日期、标签展开状态等) |
| app-backup-lastday-v1 | 上次备份日期(每日备份提醒依据) |
| day-migrated-v1 | 历史数据迁移完成标志(值为 "1") |
键名统一采用 app-<域>-v<版本> 的命名规范,版本号内置于键名而非数据结构中——这一细节让未来升级可以「换键名 + 迁移」优雅演进,避免旧数据与新结构互踩。
系统在升级路径上做了两项关键设计。其一,历史数据自动迁移:旧版本将数据存放于 localStorage 的应用曾在其上积累用户数据;新版以 day-migrated-v1 标志位记录迁移状态,检测到未迁移时自动执行「迁移历史数据」并将旧数据搬入 IndexedDB 按日仓库,迁移动作本身也会写入操作日志,全过程对用户无感。其二,备份文件的版本自洽:导出 JSON 包含完整数据字典与版本信息,导入时按结构恢复,可跨浏览器、跨设备完成数据搬家。其三,记录类型向多选标签的兼容:导入或加载旧版数据时,若记录仍带单选 type 字段,系统自动将其转换为 recTags 标签数组(旧类型名映射为同名标签),保证旧数据在新体系下完整可读。
存储配额并非无限。系统在数据管理模块顶部呈现「已用 / 可用」容量概览:接近 60% 时以黄色提示、超过 90% 以红色预警,并给出「导出备份后治理」的引导;存储区实时回填已存天数、待办/记录条数等统计口径。由于业务主体在 IndexedDB(配额远大于 localStorage),配额风险主要集中在高频小数据域,因此系统在写入失败(配额满)时会以 toast 明确告知而非静默丢失,并建议立即导出备份。
从数据的一生来看,系统为每条数据定义了清晰的生命周期,并在每个阶段提供对应的保障机制:
创建:新增弹窗提交(Enter 快捷提交、非空校验),写入 IndexedDB 对应日仓,同步写操作日志;写入失败(如配额满)时以 toast 明确告知而非静默丢失。
使用:读操作走按日聚合的读接口,保证「日历点密度、列表渲染、导出内容、统计面板」四个视图看到的是同一份数据。
编辑:编辑弹窗回填原值,保存即覆盖并更新时间戳与最后操作时间;任何修改都留下中文差量历史记录与日志,构成可回放的时间线。
删除:统一先进回收站(软删除),恢复动作原样找回;彻底删除才真正落库移除——两级删除把误操作成本压到最低。
归档:导出 JSON / Markdown 把数据带出系统;导入 JSON 让数据可以「换环境重生」,形成不依赖任何厂商的长期归档通道。
一致性保障上还有两个细节:其一,所有写操作通过 Promise 封装的事务接口串行执行,避免并发写互相覆盖;其二,导入 JSON 前会做结构校验(字段合法性、类型一致性、必需字段检查),对缺失字段给出提示并补空值,拒绝损坏或不完整的备份文件,杜绝「坏数据污染好数据」。这套「生命周期 + 两级删除 + 校验导入」的组合,让数据在漫长使用中既可靠又可迁移。
本章讨论独立于碎片加载器的第二道防御:运行期自我保护。
碎片加载层解决的是「文件被拿走」的问题;而页面自我保护层解决的是「页面被观察/被摆弄」的问题——包括打开开发者工具偷看数据、右键复制、拖动内容、Ctrl+S 保存等。保护层随载荷在重组后注入运行环境,其形态是一段携带配置对象的初始化逻辑,主要动作包括:交互拦截、开发者工具检测、水印注入与锁页。
| 配置项 | 行为 | 备注 |
|---|---|---|
| enableLock | 总开关:启用整套锁定能力 | 与授权环境判定联动 |
| allowLocal / allowedHosts | 本地 file:// 与白名单域名放行 | 本地预览不被误锁 |
| pathMustContain | URL 路径必须包含指定片段 | 防止搬运到别处直接运行 |
| blockRightClick | 拦截 contextmenu 事件 | 禁用右键菜单 |
| blockCopy / blockCut | 拦截 copy / cut 事件 | 禁用复制剪切 |
| blockSave / blockPrint | 拦截 Ctrl+S / 打印 | 防止整页另存与打印导出 |
| blockDevtools | 开发者工具检测与锁定 | 见 7.3 |
| blockDrag / dragstart | 拦截拖拽(文本/图片) | 防止拖出内容 |
| watermark / watermarkText | 注入 SVG 水印 | 默认文案「锦鲤未离 · 原创作品,请勿盗用」 |
| lockTitle / lockMsg | 锁页标题与说明文案 | 「页面已锁定」「本页面为受保护的原创作品,当前环境未获授权,无法使用」 |
检测采用组合手段而非单一特征,形成纵深:
debugger 计时:在代码中周期性执行 debugger 断点并测量前后时间差;开发者工具打开时调试器会暂停脚本,时间差骤增(阈值约 120ms),据此判定「有人在调试」。
窗口尺寸差:比对 outerWidth − innerWidth 与 outerHeight − innerHeight;Dock 式开发者工具打开时差值显著增大(阈值约 180px)。
正则陷阱与死循环诱饵:载荷中嵌入形如 ((( .+)+)+)+$ 的灾难性回溯正则与 while(true) 片段,干扰调试器单步执行与静态阅读。
console 污染:对 log / info / error / exception / table / trace / assert 等输出方法进行包装重定向,降低控制台日志的取证价值。
水印以 SVG data-URI 背景的方式注入页面(含水印动画容器与页脚水印),文本为「锦鲤未离 · 原创作品,请勿盗用」,以半透明、低对比度平铺,既不影响阅读,又让截图/翻拍自带可追溯的归属标记。水印不随滚动消失,覆盖全页,是「防君子」式取证手段。
一旦判定「环境未获授权」(如检测到调试行为),保护层以全屏覆盖层锁死页面(含 PAGE_LOCKED 标记),显示「检测到调试行为,请关闭开发者工具后刷新页面继续使用」,并将页面标题切换为「页面已锁定」。解锁路径只有一条:关闭开发者工具并刷新——这与威胁模型一致:合法用户无感,提取者被逼到「必须绕过检测」的逆向赛道。
客观评价该保护层的价值与局限:其拦截面覆盖了日常取证的全部低成本入口(右键、复制、保存、打印、拖拽、控制台、调试器),且检测手段多样、阈值合理,误伤合法用户的概率低(本地 file:// 与白名单域名被显式放行)。但需要说明的是:开发者工具检测的多种手段均可被成熟的自动化工具(如无头浏览器)规避;水印与锁页属于「威慑 + 取证」而非「封锁」;本层的根本约束与碎片层相同——客户端可显示即终究可提取。它真正的价值是把「顺手拿走」升级为「刻意对抗」,而这正是个人作品保护最现实的期望。从工程视角看,这一层还带来一个副产品:它在运行期持续校验「页面是否处于预期环境」,与加载层的「文件是否完整」形成两条独立的健康检查线,任何一条失守都会显式报错而非静默降级。
开发者工具检测本质上是一场「猫鼠博弈」:任何客户端检测手段都存在对应的规避方案。站在博弈视角审视本系统的检测组合,其设计取向值得注意:
不追求「不可绕过」,追求「绕过高成本」:无头浏览器、远程调试协议等高级工具可以完全绕过 debugger 计时与尺寸差检测,但使用它们需要搭环境、写脚本,这不是「顺手党」的成本量级。本系统的检测目标始终对准 T1–T2 级对手。
多信号交叉,降低误报与漏报:计时与尺寸差两种信号独立触发,正常用户几乎不可能同时命中;同时阈值(120ms / 180px)留有合理裕量,避免高负载机器上合法用户被误锁。
锁定而非瘫痪:检测命中后的处理是「锁页 + 提示刷新」,而非破坏数据或无限循环消耗资源——这保护的是合法用户重新进入的通道,也避免了对共享设备环境的误伤扩散。
这一博弈视角也说明了保护层的合理期望:它不是防御体系的天花板,而是把「取证成本」从零抬到「需要专用工具」的那块台阶。与碎片加载层配合后,两道防线分别对应「文件层面」与「运行层面」,即使其中一道被绕过,另一道仍然存在。
本章讨论产品的信息架构、视觉语言与交互细节,以及它们如何共同塑造使用体验。
全站信息架构遵循「顶栏(时间轴)+ 模块抽屉(组织面)」的总体骨架。顶部为日期导航与全局动作;中部为可切换的功能面板;右下为悬浮新增入口;底部为跨模块动作区域。模块切换通过顶部 Tab 完成,面板由 12 个已启用 Tab 构成:
产品的视觉基调是「暖色、圆润、轻量」,并在迭代中持续深化为「锦鲤未离」主题:品牌色为暖橙系(#f0a100 为主色、#e8590c 为深橙),辅以深青(#0e7490)、薄荷绿(#22a447)、天蓝(#2f6fd0)、紫(#8e44ad)等功能色;页面采用暖米底色配径向渐变光晕,顶栏为橙金渐变并带金红底线,模块标题下方有金红渐变下划线,滚动条、按钮、进度条、置顶徽章、「今天」药丸、计数药丸等细节均以橙金渐变统一。卡片与弹窗采用大圆角、柔和边框与轻阴影,营造亲和而非冷淡的工具感。界面文本全部为中文口语化表达(「今日暂无内容」「内容已存入剪贴板」),动词与按钮一致(「导出 JSON 备份」的按钮和 toast 文案同名)。
字体层级依赖字号、字重与语义断行建立:模块标题(大号粗体)、面板标题(中号)、正文与按钮(常规)、徽标与元信息(小号弱化);所有数字与时间采用等宽数字(tabular-nums),保证列表对齐稳定。空态、加载态、错误态三态齐备:加载时全屏进度条(「正在加载待办记录工作台… 已完成 x/52」),出错时页首红色横幅,空模块各有引导文案。
键盘:表单 Enter 提交、Esc 关闭弹窗、编辑弹窗自动聚焦输入框;搜索框键盘导航(ArrowDown/Enter 选择历史项)。
动效克制:仅折叠/展开、弹窗显隐、进度条更新、搜索结果高亮闪烁使用过渡动画,不做无信息量的装饰动画。
状态可见性:置顶项排序在前并带图标;星标独立于完成态;逾期项显示「已逾期 x」红色药丸;完成项置灰划线但可随时取消完成;待办与记录显示最后操作时间,长期待办不显示时间以区分尺度。
防误操作:删除全部/清空回收站/删除当天/清空日志均有确认弹窗;标签删除提供「保留事项 / 连坐移除」两种语义,把不可逆决定交给用户。
明面精简:行内操作收敛为高频三项 + 「…」更多菜单(长期待办:置顶/编辑/转为今日/…;待办:置顶/编辑/转为长期/…;记录:置顶/编辑/复制/…),低频操作统一收进菜单,既保持行内清爽,又让内容文本获得更宽的空间。
移动端适配:头部单行显示(日期框收窄、切换符号化、左对齐),窄屏 Tab 可横向滚动、列表卡片化、悬浮按钮保持在拇指热区,宽高断点切换布局。
综合来看,本产品的体验设计遵循三条主线:日期为轴(一切内容挂到具体某天,回看与迁移都以此展开)、动作聚拢(行内只放高频操作,低频操作收入「…」菜单)、容错优先(草稿暂存、回收站、二次确认、每日备份、导出导入形成层层兜底)。在「功能密度」与「界面克制」之间,产品选择把复杂度收进抽屉与菜单,把高频路径(新增、完成、记录)压到最短——这正是个人工具「越用越顺手」的来源。
作为一款需要长期高频使用的工具,可访问性是体验的隐性底线,本系统在以下方面做了工程化处理:
对比度与字号:正文文本使用暖墨色与暖米底的组合,对比度满足常规阅读需求;小字号仅用于徽标与元信息,且不以颜色作为唯一信息载体(如优先级同时有位置与色点)。
键盘可达:所有弹窗支持 Esc 关闭与 Enter 提交;表单自动聚焦;焦点元素保留可见轮廓,保证无鼠标用户可完整操作。
减少动效:尊重 prefers-reduced-motion,用户偏好减少动态时折叠全部过渡动画(含水印动画),页面功能不受影响。
语义化结构:模块面板、按钮、列表项使用语义化标签与 aria 标注,toast 与弹窗具备基本读屏可辨识性。
这些工作没有出现在功能清单里,却决定了工具「能不能被长期使用」:对一个每天要打开十几次的应用,可访问性的价值不在某一刻,而在每一年。
本系统在界面层经历过一次重要的布局取舍:曾规划「经典 / 工作台」双布局切换(工作台将待办、记录、数据管理拆分为三个独立页面并配以页首横幅与每页专属配色),经实际使用与评审后,考虑到个人工具的核心诉求是「一屏掌握全局、日期即上下文」,最终取消双布局,回归并固定为单一经典布局——待办、长期待办、记录与数据管理同屏可见,日期切换即时联动全部模块。这一决策体现了「功能密度与界面克制」之间的持续校准:多一个切换开关,就多一份心智负担;而单一布局让每一次打开都是确定的、可预期的。
与此同时,「锦鲤未离」主题在历次迭代中持续沉淀:暖米底色配径向渐变光晕、顶栏橙金渐变与金红底线、模块标题金红下划线、橙金滚动条、按钮/进度条/置顶徽章/「今天」药丸渐变、计数药丸与底部品牌区,形成一套统一而克制的视觉语言。所有新增模块(统计面板、标签全局展开、备份区域、明面按钮组)都沿用同一组色彩 token 与圆角、阴影规范,保证页面焕然一新而不失整体性——这正是「大胆留给一处、其余保持安静」的设计原则在长期迭代中的落地。
本章对系统的防护边界做系统评估:提取路径成本分析、残余风险清单与诚实边界声明。
结合第四章的威胁模型,本系统面对的主要提取路径有五条,其成本对比如下(「成本」指提取者获得可运行的完整载荷所需投入):
| 提取路径 | 成本量级 | 系统反制 | 残余能力 |
|---|---|---|---|
| 查看源代码 | 1(一次点击) | 源码不包含业务内容 | 仅见壳层与加载器 |
| 一键另存为 | 1(一次点击) | 页面主体为重组产物,另存只得壳 | 无可用副本 |
| 批量抓取全部文件 | 10(工具级) | 干扰文件多于真实碎片 | 信噪比 <50%,仍需逆向重组 |
| 逆向重组(分析加载器) | 10⁴(人·小时) | 密钥派生 + 异或 + 逐片校验 | 可完成,成本接近重建应用 |
| git clone 公开仓库 | 1(命令级) | 客户端技术无法反制 | 部署层需授权/策略(见 9.3) |
必须详细地指出本系统无法覆盖的风险:
任何可显示的客户端内容终究可提取:浏览器必须能把载荷解密并执行,故掌握加载器的人理论上可完全重建。碎片防护的目标是抬高成本,不是「绝对防盗」。
运行期数据可被观察:页面运行后,业务数据已在浏览器内存与存储中,开发者工具/无头浏览器仍可读取 localStorage 与 IndexedDB 中的明文数据——保护层只能检测与威慑,不能加密业务数据(否则会引入密钥管理难题,且与「数据始终本地、用户随时可取」的产品承诺冲突)。
源码混淆非密码学:载荷内的字符串数组 + 译码函数属于混淆(obfuscation)而非加密;其价值在于阻碍阅读,不构成数据安全承诺。
部署方式决定最终边界:若作品被上传至公开 git 仓库,clone 即得全部碎片与加载器。客户端技术无法阻止这一路径,只能通过部署策略(私有仓库、受控分发)管理。
边界结论:本系统提供的是一套「提高提取成本 + 运行环境健康检查 + 归属取证」的组合防护。若需求是「绝对不可提取」或「业务数据加密」,需要引入服务端授权与加密体系——那将改变产品的「零部署、纯本地」定位,属于不同的架构决策。
对唯一的低成本残余路径(T5),可行的缓解都在部署层:优先使用私有仓库托管;必须公开时,将碎片目录排除出版本控制或用 CI 在发布时才生成碎片包;为受控分发(群聊、网盘)保留一份「按需生成」的流程。这些措施不属于客户端代码的职责,但作为产品作者应当知晓并管理。与此同时,随包说明文档中已明确声明「严禁搬运、复制或商用,转载需标注来源」,配合水印形成可举证的权益声明。
围绕「这样真的防得住吗」这一最朴素的问题,结合设计时的取舍,对几类高频疑问给出明确回答:
「入口页里不是明明白白写着链头路径吗,照着拼不就行了?」——能看到链头与「能重组」之间隔着三层:清单要解码(密钥来自盐+路径)、每个碎片要逐片异或还原、碎片间要靠清单中的长度与哈希校验才能确认拼接顺序与完整性。链头只是入场券,不是答案。
「全部文件都下载下来,挨个试不就好了?」——可以,但这是 T3 级工作量;且干扰文件无法通过密钥校验,逐片试错必须先完成逆向。对个人作品而言,让「批量搬运」退化成「深度逆向」,就已经完成了防护的使命。
「既然客户端一定能显示,那防护不是自欺欺人吗?」——防护的对象从来不是「理论上可提取」,而是「实践中轻易可得」。防盗门挡不住爆破,但挡得住顺手牵羊;碎片防护同理。
「为什么不用服务端授权,一劳永逸?」——因为那会同时牺牲零部署、离线可用与数据本地三大产品承诺。防护方案的选取本质是产品定位的取舍,而非单纯的强度最大化。
这组问答的结论与 9.2 的边界声明一致:本系统承诺的是「把提取成本提高到接近重建的成本」。
本章给出系统的验证方法、自检工具链与验证实验设计。
本系统虽不采用自动化测试框架,但质量保障是成体系的设计,分为三层:交付前自检(碎片自检脚本)、运行期校验(加载器逐片长度+SHA-256 校验、诊断模式)、回归验证(重组回归 + 桩环境行为验证,即本文取证所用的方法)。三层共同回答三类问题:碎片包是否完整?加载能否成功?重组后的行为是否符合预期?
随包交付的自检脚本是碎片包的「出厂检验」。其工作流为:解析链头(按 ROOT/SALT 派生密钥解码)→ 展开全部清单记录 → 逐个碎片校验(文件存在性、长度匹配、SHA-256 匹配)→ 清点真实碎片与干扰文件 → 输出汇总。运行结果为:
=== 待办记录工作台 碎片自检 === [+] 碎片链头: 全部通过 [+] 真实碎片: 52/52 通过 (长度+哈希) [+] 干扰文件: 全部识别 [+] 载荷重组: ≈880 KB === PASS ===
脚本既可用于解压后、上传前的发布前检查,也可用于接收方验证文件的完整性——它把「碎片包有没有坏」从玄学变成可复现的一行命令。
加载器在运行期对每个碎片做长度 + SHA-256 双校验,任何不符都会触发页首精确错误(含文件名与失败类型);网络失败自动重试至多 3 次;若仍失败,提示信息直接指向修复对象(重新上传该文件或重新生成碎片包)。URL 追加诊断参数后,加载器在控制台输出重组字节数与分阶段耗时,供开发者在非标准环境快速定位「慢在哪、错在哪」。此外,file:// 协议下浏览器会拒绝碎片请求(同源策略限制),属预期行为而非缺陷——正式使用应通过任意静态 HTTP 服务打开,随包说明与页首错误提示均已写明。
为保证本文论述的可复核性,对系统执行了两类回归验证:
| 实验 | 方法 | 结果 |
|---|---|---|
| 碎片完整性验证 | 运行自检脚本,解析链头并校验 52 个碎片 | 链头全部通过、52/52 碎片全部通过,载荷 ≈880KB |
| 重组回归 | 按加载器同一密钥派生算法独立编写重组脚本,逐片解码拼装 | 与自检一致;解码命中恰好 52 片,干扰文件零命中 |
| 桩环境行为验证 | Node 最小 DOM/存储桩运行载荷,包装译码函数收集运行时字符串 | 捕获近千条运行时字符串,与界面文案/键名交叉一致 |
三项实验共同构成对第四章机制阐释与第五章功能测绘的证据链:机制的每一步(魔数、密钥派生、清单、并发、校验)都被独立复现或直接观察;功能测绘的每个模块、键名与文案都可在运行时字符串中定位到出处。
本章收束全文,并给出后续演进方向。
本文以「待办记录工作台」为对象,完成了一次从产品、工程到安全的完整技术论述。总结而言,本系统的设计呈现三个层次的价值:
产品层:以「日期为轴、动作聚拢、容错优先」的信息架构,把待办、长期待办、每日记录、草稿、回收站、日历、搜索、日志、设置、数据管理、统计等十二大模块组织为一条可走通的日常闭环;长期待办与今日待办的双向流转让不同时间尺度的事务各得其所;多选标签体系让记录与筛选的维度更接近真实事务;数据始终本地、导出导入双通道,兑现了「个人工具的数据主权」。
工程层:以「二进制碎片链 + 路径派生密钥 + 干扰文件」自研出文件级防护架构,在 52 个真实碎片与干扰文件之间实现精确加载(约 0.5 秒、零干扰请求),并把「坏了能定位、传前能自检、运行能观测」内建为交付标准。功能层面,本轮迭代把排序收敛到隐藏唯一标识、把记录类型演进为多选标签、为待办与记录补充最后操作时间、为搜索补充居中跳转与紧凑的日期筛选,并在多次改动中持续保持存储结构向后兼容。
安全层:以分层威胁模型与五条提取路径的成本评估,具体地划定了「提高提取成本」的技术边界,同时用页面自我保护层覆盖日常取证入口,实现「威慑 + 检测 + 取证」的组合防御。
值得再次强调的工程经验有三条:其一,二进制载体是防护与健壮性的共同根基——避开文本编码问题,换取免疫损坏与高效解码;其二,干扰文件是「零成本威慑」——对合法用户零请求,对抓取者成倍提升试错成本;其三,自检与诊断不是附加功能,而是交付物的一部分——它们让复杂机制变得可复现、可运维。
本轮迭代在「数据主权」上的核心成果是导出/导入的完整覆盖:备份文件不再只包含当日的待办与记录,而是把全部日期明细、回收站、草稿箱、操作日志、标签定义、长期待办、历史修改文本、搜索历史与自定义设置全部纳入序列化范围,导入时整体恢复并覆盖。这保证了「换一台电脑、换一个浏览器,工作台的一切随行」——数据主权不止是「数据在本机」,更是「数据随时可以完整地带走、完整地回来」。
在现有基础之上,本系统还有若干清晰且克制的演进方向:
加密可选项:为业务数据提供「导出加密 JSON」(如口令派生密钥),在保持纯本地定位的前提下把备份的机密性提升一档——需权衡密钥遗忘的恢复成本。
模板与导入增强:支持 JSON 模板批量新建(如每周固定事务),与短语体系衔接。
碎片化参数化:将链数、片大小、干扰比例做成可配置(当前为编译期常量),针对不同体积的应用适配;可补充「部分碎片缺失时按 52→n 自适应降级加载」的容错模式。
主题与多语言:基于现有 token 体系扩展浅色/深色主题与 i18n 文案表。
统计深化:在现有完成率、近七天趋势、活跃节奏与周对比之上,进一步支持自定义时间段的留存与目标追踪。
保护层增强:对高价值场景引入服务端签发的一次性授权(仅对受控分发使用),把 T5 路径也纳入管理。
最后,回到本文开篇的问题——为什么需要一件「拿不走」的工作台?答案在本文的技术论述中逐渐清晰:因为对个人作品而言,「难被拿走」不是对抗,而是尊重。尊重作者投入的时间,也尊重使用者的数据——碎片防护把前者做成工程,双层持久化把后者做成承诺。这正是一件小工具可以承载的最大诚意。
正在加载中......err
术语表、存储键清单、动作日志元数据、关键代码注释与图表清单。
| 术语 | 释义 |
|---|---|
| 碎片(fragment) | 载荷被切分后的二进制片段,本版本单片约 17KB,共 52 片 |
| 链(chain) | 由链头 + 若干载荷片构成的逻辑序列,本版本共若干条 |
| 链头(head) | 每条链的第一个碎片,内含二进制清单;入口页仅知链头路径 |
| ROOT / SALT | 碎片根目录名与密钥派生盐(入口页常量) |
| 干扰文件 | 混入碎片目录的同构噪声文件,本版本数量多于真实碎片 |
| 异或编解码 | 以路径派生密钥对碎片逐字节异或的对称变换,解码即再异或 |
| 桩环境 | 以最小 DOM/存储桩模拟浏览器运行载荷的 Node 沙箱 |
| 软删除 | 删除后进入回收站、可恢复的删除语义 |
| 双层持久化 | IndexedDB 主存储 + localStorage 元数据的存储架构 |
| recTags | 每日记录的多选标签数组,替代旧版单选记录类型 |
| lastAct | 最后操作时间字段:待办/记录显示,长期待办不显示 |
| 名称 / 键名 | 取值与说明 |
|---|---|
| ROOT | 碎片根目录名(入口页常量) |
| SALT | 密钥派生盐(入口页常量) |
| MAGIC | 「K7FB」——链头魔数 |
| CONCURRENCY | 20——并发门控上限 |
| RETRY | 3——失败重试次数 |
| 链头数组 | 若干链头相对路径(入口页仅知首片) |
| IDB 库名 | 形如 UzAdbdb,版本 1,按日仓库 + 元数据仓库 |
| app-bin-v1 | 回收站数据 |
| app-logs-v1 | 操作日志 |
| app-history-v1 | 历史修改记录(中文差量) |
| app-drafts-v1 | 草稿 |
| app-tags-v1 | 标签(名称 + 配色) |
| app-rectypes-v1 | 记录标签 / 记录类型定义 |
| app-phrases-v1 | 便捷短语 |
| app-permanent-v1 | 长期待办数据 |
| app-search-history-v1 | 搜索历史 |
| app-ui-v1 | UI 偏好(折叠状态、上次日期、标签展开状态等) |
| app-backup-lastday-v1 | 上次备份日期(每日备份提醒依据) |
| day-migrated-v1 | 历史迁移完成标志("1") |
| 分类 | 动作示例 |
|---|---|
| 待办 | 新增待办 · 编辑待办 · 完成待办 · 取消完成 · 复制内容 · 置顶/取消置顶 · 星标/取消星标 · 转为长期待办 · 移入回收站 · 彻底删除待办 |
| 长期待办 | 新增长期待办 · 编辑长期待办 · 删除长期待办 · 转为今日待办 |
| 每日记录 | 新增记录 · 编辑记录 · 复制记录 · 删除记录 |
| 草稿 | 新增草稿 · 编辑草稿 · 草稿转待办 · 草稿转记录 · 删除草稿 |
| 回收站 | 恢复待办 · 恢复长期待办 · 恢复记录 · 恢复草稿 · 清空回收站 |
| 数据管理 | 导出 JSON 备份 · 导入 JSON 备份 · 导出 Markdown · 复制当天 · 删除当天 · 删除全部数据 · 每日备份 |
| 设置 | 新增/改名/删除标签 · 新增/改名/删除记录标签 · 新增/编辑/删除便捷短语 |
| 系统 | 迁移历史数据 · 清空日志 |
以下两段为碎片防护机制的最小复现示意(节选,与原始实现等价但为论文演示简化):
// 链头清单解析(示意)——魔数 + 碎片计数 + (n-1) 条记录 + 链头自身载荷 u8[0..3] === "K7FB" // 魔数校验 n = BE(u16[6..7]) // 碎片计数 l0 = BE(u32[8..11]) // 链头载荷长度 // 每条记录: len(1B) | path(len) | size(4B BE) | sha256(32B) // 末尾 l0 字节即链头内容
// 密钥派生与异或解码(示意)—— 与加载器同一算法 key = await sha256( SALT + "/" + relPath ) buf = new Uint8Array(await resp.arrayBuffer()) // 先按 key 异或还原明文(干扰文件在此步即失配) // 再以 len + sha256 与清单比对,全部通过才拼接
| 编号 | 名称 | 载体 |
|---|---|---|
| 图 3-1 | 系统五层逻辑架构 | 内联网格 |
| 图 3-2 | 碎片包文件构成(环形) | CSS 环形图 |
| 图 4-1 | 碎片链加载时序 | 内联网格 |
| 图 5-1 | 待办生命周期状态机 | 内联网格 |
| 图 6-1 | 六类业务实体关系 | 内联网格 |
| 图 8-1 | 信息架构 | 内联网格 |
| 表 2-1 | 功能需求总表 | 表格 |
| 表 3-1 | 交付物清单 | 表格 |
| 表 3-2 | 四种交付形态对比 | 表格 |
| 表 4-1 | 分层威胁模型 | 表格 |
| 表 4-2 | 链头清单字节布局 | 表格 |
| 表 4-3 | 核心性能指标 | 表格 |
| 表 4-4 | 与主流保护方案比较 | 表格 |
| 表 5-1 | 数据管理操作清单 | 表格 |
| 表 6-1 | 核心实体字段说明 | 表格 |
| 表 6-2 | localStorage 键名清单 | 表格 |
| 表 7-1 | 自我保护层配置项 | 表格 |
| 表 9-1 | 五条提取路径评估 | 表格 |
| 表 10-1 | 回归验证实验与结果 | 表格 |
| 表 A-1 / B-1 / C-1 / E-1 | 附录各表 | 表格 |