Repository Wiki
jason5ng32/MyIP

新增工具、可用性门控与界面集成

Advanced Tools 通过统一注册表声明工具身份、界面文案、懒加载组件和部署条件,再用 isToolAvailable() 决定工具是否出现在卡片与导航中。展示门控不等于访问控制:深链接不受这套门控限制。

目的与范围

本页面向新增或维护高级工具的开发者,覆盖注册字段、可用性判断、独立页面与抽屉的集成约定,以及国际化、界面交互、命令和结果事件的扩展要求。

工具自身的网络测试算法、后端鉴权、部署配置生成、成就计算和报告存储不在本页展开。涉及这些能力时,应分别阅读对应实现与前后端贡献规范,而不是把所有业务逻辑加入注册表。

**证据边界:**本页直接核对了 tools.js 与 tool-availability.js。路由、卡片、抽屉和事件总线的接入说明来自注册表注释及 frontend/AGENTS.md,本次未读取这些消费端的实现,不据此推断其错误界面、加载时序或清理细节。

概述

注册表解决的核心问题是多个入口之间的信息漂移。源码注释明确说明,路由数组与卡片数组曾分别手工维护;现在以一份按 slug 排列的工具清单描述它们共同需要的信息。

当前清单包含 15 个工具,其中:

  • 11 个条目没有部署展示条件,包括 Whois、DNS Resolver、IP Calculator 等。
  • asn 需要 configs.cloudFlare 为真值。
  • invisibilitytest、enhanceddnsleaktest、personacheck 需要 configs.originalSite 为真值。
  • personacheck 还带有 noStandalone: true,因为它依赖首页测试结果,运行这些测试会导航回首页。

这里的“可用”仅表示应当被列出,并不证明上游服务健康、用户已登录或当前操作具有额度。

来源:tools.js、tool-availability.js。

架构与集成边界

下图展示源码声明的注册表消费关系。路由及界面侧连线来自文件注释与前端规范;TOOL_BY_SLUG 和门控函数则有直接实现可核对。

Loading diagram...

Sources: tools.js、tools.js、tool-availability.js。

这个边界有三层含义:

  1. 工具元数据集中声明。 URL 身份、标题、说明与组件加载入口不应在多个列表中各维护一份。
  2. 部署能力统一解释。 列表消费者通过同一函数读取门控,不各自复制条件判断。
  3. 展示与执行分离。 隐藏入口不能代替后端权限检查,也不能阻止用户直接使用深链接。

注册字段与配置契约

工具条目

这些字段来自 JavaScript 对象约定,而不是已验证的运行时 schema;已读实现中没有条目校验器。

字段类型或实际形态缺省行为作用
slugstring未提供默认值稳定标识,供抽屉查询参数和 /tools/:slug 使用
emojistring未提供默认值卡片与抽屉标题图标
titleKeystring未提供默认值工具标题的 i18n 键
noteKeystring未提供默认值一行工具介绍的 i18n 键
component返回动态 import() 的函数未提供默认值抽屉及独立页面使用的懒加载组件入口
requiresOriginalSite可选 boolean省略时不检查原站标志要求 configs.originalSite 为真值才列出
requiresConfig可选 string省略时不检查具名配置将字段值作为 configs 的属性名读取
noStandalone可选 boolean已读源码未展示消费端缺省实现personacheck 用它表达不应提供独立工具页面

来源:tools.js。

运行时可用性配置

配置预期含义配置未到达时当前使用者
configs.originalSite是否为原站部署对应门控不通过invisibilitytest、enhanceddnsleaktest、personacheck
configs.cloudFlareRadar 相关能力标志对应门控不通过asn
configs[tool.requiresConfig]任意具名能力标志属性缺失时不通过供后续工具扩展

源码注释说明,配置异步到达,在此之前为 {}。函数使用 JavaScript 真值判断,不是 === true;因此字符串 "false" 也是真值。新增配置时应保持布尔语义,不能把该函数当作配置类型校验器。后端如何生成这些标志、是否由环境变量控制,本次读取范围内未确认。

来源:tool-availability.js。

可用性判断的真实控制流

API:isToolAvailable(tool, configs)

该函数没有 TypeScript 类型声明。根据实际实现,tool 是工具对象,configs 是运行时配置对象,返回值始终为 boolean(对于正常对象输入)。

步骤条件结果
1tool 为假值立即返回 false
2声明 requiresOriginalSite,但 configs?.originalSite 为假值返回 false
3声明 requiresConfig,但对应配置值为假值返回 false
4以上条件均未拒绝返回 true

两个门控同时存在时采用 AND 语义,必须全部满足。原站条件先检查,失败后不会继续读取具名配置。

javascript
1export const isToolAvailable = (tool, configs) => { 2 if (!tool) return false; 3 if (tool.requiresOriginalSite && !configs?.originalSite) return false; 4 if (tool.requiresConfig && !configs?.[tool.requiresConfig]) return false; 5 return true; 6};

Source: tool-availability.js。

函数没有网络请求、缓存、状态写入、重试或显式 throw。configs 为 null 或 undefined 时,可选链避免属性访问错误;但没有门控的有效条目仍返回 true。

从配置到展示、从 URL 到工具

Loading diagram...

Sources: tools.js、tools.js、frontend/AGENTS.md。

阅读或排查时应把两条路径分开:列表路径判断展示条件;深链接路径不使用这些条件拦截。noStandalone 则是另一类页面适用性声明,并非 isToolAvailable() 的检查项。

新增工具的实施步骤与真实示例

以下示例均为当前仓库已有代码摘录,不是虚构的新工具脚手架。

1. 明确工具身份和承载方式

先确定稳定的 slug、工具组件、标题与说明键,以及工具是否适合独立页面。slug 同时进入 URL 和索引,是对外标识,不宜作为随文案变化的显示名称。

已有的公共工具条目如下:

javascript
{ slug: 'whois', emoji: '📓', titleKey: 'whois.Title', noteKey: 'advancedtools.Whois', component: () => import('@/components/advanced-tools/Whois.vue') },

Source: tools.js。

该条目不声明部署条件,因此门控不会等待任何配置标志。component 保存的是函数,不是在注册表求值时立即执行的导入;具体何时调用、如何显示加载与失败状态,由消费者决定,本次未核对其实现。

2. 只声明工具真正依赖的展示条件

ASN 工具的真实条目展示了具名能力门控:

javascript
{ slug: 'asn', emoji: '🛂', titleKey: 'asnprofile.Title', noteKey: 'advancedtools.AsnProfile', component: () => import('@/components/advanced-tools/AsnProfile.vue'), requiresConfig: 'cloudFlare' },

Source: tools.js。

这里不是要求原站,而是要求 cloudFlare 标志。不要因为一个工具调用后端,就自动为它增加 requiresOriginalSite;应按照实际部署依赖选择条件。也不要在卡片组件里新增一套特殊判断,前端规范要求统一通过 isToolAvailable() 读取门控。

来源:frontend/AGENTS.md。

3. 对依赖首页上下文的工具单独处理

javascript
{ slug: 'personacheck', emoji: '🎭', titleKey: 'personacheck.Title', noteKey: 'advancedtools.PersonaCheck', component: () => import('@/components/advanced-tools/PersonaCheck.vue'), requiresOriginalSite: true, noStandalone: true },

Source: tools.js。

requiresOriginalSite 表达列表展示条件;noStandalone 表达页面承载限制。源码注释给出的原因是 Persona Check 依赖首页测试结果,执行这些测试又会回到首页,独立页面会产生立即离开的体验。两者不能合并为同一种“禁用”状态。

来源:tools.js。

4. 保持索引与清单一致

注册表末尾直接生成 slug 索引:

javascript
export const TOOL_BY_SLUG = new Map(ADVANCED_TOOLS.map((tool) => [tool.slug, tool]));

Source: tools.js。

不需要另外维护一份 slug 到组件的手写映射。这个表达式也带来两个约束:

  • slug 必须唯一。 JavaScript Map 遇到重复键会保留后一个值,但原数组仍保留重复条目;已读实现没有重复检测。
  • 索引是构建时快照式派生。 它在模块求值时构建一次,不是响应式计算。后续直接向数组加入新条目,不会自动新增 Map 键;已有条目的对象引用则仍共享。

因此,当前机制更适合静态注册,不应未经额外设计就当作运行时插件注册 API。

界面与跨组件集成约定

本节是仓库明确规定的接入要求,而非对未读取组件实现的逐行分析。

Vue、界面原语与状态

  • 新代码使用 JavaScript 与 Vue Composition API,组件采用 <script setup>;不要引入 TypeScript 或 Options API。
  • 优先复用 shadcn-vue 界面原语。工具执行按钮采用 variant="action"、运行中的 Spinner 和禁用状态,避免重复提交的视觉入口。
  • 高级工具使用底部 Drawer;侧向面板使用 Sheet。Dialog、Sheet、Drawer 根组件接入覆盖层快捷键暂停机制,基于它们构建的界面继承这套约定。
  • 业务状态到颜色的映射通过 use-status-tone.js,避免各工具自定义互不一致的成功、等待、失败颜色。
  • 自由输入框遵守仓库列出的六项 AutoFill 防护属性,避免密码管理器及浏览器自动填充干扰工具输入。

来源:frontend/AGENTS.md、frontend/AGENTS.md、frontend/AGENTS.md。

可分享输入与 URL 同步

前端规范以 AsnProfile 为范例:监听 route.query.q,并使用 immediate 选项,使首次挂载和抽屉打开后的查询参数变化都能触发处理;每次执行时通过 router.replace 更新查询参数。同时考虑 /tools/ 和 ?tool= 两种承载形式。

这一约定的重点是不要只在初次挂载读取输入,否则一个已经打开的工具可能无法响应后来变化的分享链接参数。这里未提供复制式代码,因为本次没有读取 AsnProfile 的实际 watcher 实现。

来源:frontend/AGENTS.md。

国际化

注册表只保存 titleKey 与 noteKey,不应把显示文案硬编码到条目里。涉及用户可见文案的改动必须在同一次变更中覆盖所有 full locale;beta locale 可以沿既定 fallback chain 回退。仓库规范也要求变更日志同步遵守 full locale 覆盖要求。

来源:tools.js、AGENTS.md。

命令、完成事件与报告

当新工具需要跨组件协作时,区分两个方向:

需求仓库规定的机制集成注意点
通知一次测试已经完成emitAppEvent 领域事件工具不直接操作成就;成就规则和守卫由外部机制负责
请求某个工具执行操作dispatchAppCommand通过命令总线,不跨组件使用模板 ref 触发业务
注册命令处理者use-app-command.jssetup 阶段注册、与作用域绑定;调用者先等待命令可用
把结果加入可分享报告完成事件、builder、schema新可报告测试需同时更新事件、构建器和 schema;不能只更新渲染界面

报告链接公开可访问,规范明确要求在 builder 层排除访客输入的敏感内容,而不是只在 renderer 中隐藏。命令错误约定包含 auth、quota、input,总线补充 unavailable、timeout;这些是集成契约,不是 isToolAvailable() 的异常类型。

来源:frontend/AGENTS.md。

边界情况、并发与运维注意事项

展示门控不是权限屏障

requiresOriginalSite 只检查配置标志,不检查登录态。配置门控不会拦截 ?tool= 或 /tools/:slug。如果工具需要私有 API、额度限制或身份校验,必须在相应执行路径落实,不应依赖卡片不可见。

根目录规范把访问控制与超时放在共享后端机制中,并要求上游 HTTP 调用经过 fetchUpstream。本页未读取这些中间件或工具 handler,因此不列举具体接口的鉴权返回码。

来源:tool-availability.js、AGENTS.md。

配置晚到与缺失

配置到达前,受门控工具不可用,无门控工具可用。这是注释明确描述的行为。配置改变后重新调用函数会得到新结果,但函数本身不会发起刷新或订阅变化;消费端是否通过响应式计算重新评估,本次未核对。

配置名拼写错误与真实能力关闭都会表现为对应属性是假值,函数不会区分两种原因。排查“工具卡片消失”时,先核对条目的配置键,再核对实际配置值,而不是先排查组件导入。

性能与并发

门控只有固定数量的属性读取和分支,单次调用为常数级操作,不产生异步竞争。注册表构建 Map 需要遍历一次工具数组;数组与 Map 同时持有条目对象引用。

动态导入函数为延迟加载提供入口,但不代表列表门控会阻止代码被加载,也不意味着存在取消、重试或错误恢复。工具内部网络请求的并发、超时、取消和重复执行策略,需要在各工具实现中单独核对。

这一层没有数据库写入或用户设置持久化,也没有后台作业;不要把工具注册信息与工具运行结果混为一类数据。

验证清单与测试边界

仓库规范要求可脱离真实网络执行的非视觉逻辑随改动附带测试,并以 pnpm check 执行测试与构建;UI 渲染、浏览器 API 和真实网络行为不属于其规定的纯逻辑测试范围,视觉变化需要人工验证。本次没有读取测试文件,因此以下是建议新增或核对的验收项,不是已有测试覆盖声明。

验证项应核对的行为
缺失工具isToolAvailable() 返回 false
无门控工具、配置缺失有效条目返回 true
原站门控缺失或假值拒绝,真值放行
具名配置门控精确读取 requiresConfig 指定的键
双门控任一条件不满足即拒绝
配置晚到使用新配置重新评估后,返回值相应变化
重复 slug防止数组展示与 Map 解析不一致
深链接不把列表门控错误地扩展成路由权限控制
页面适用性noStandalone 工具不被当作普通独立页面处理
分享与抽屉已打开工具能响应 q 的变化
国际化与视觉full locale 文案齐全,按钮、加载、覆盖层与快捷键行为符合规范

来源:AGENTS.md、AGENTS.md、frontend/AGENTS.md。

相关链接

Sources

(4 files)
(root)
frontend
frontend/data
frontend/utils