Files
2026-09-17 21:54:33 +08:00

9.2 KiB
Raw Permalink Blame History

小工具能力清单

小工具运行在受限容器中:纯本地、不联网,把它当作一个能力受限的浏览器页面。 以本文为基线:命中「不可用」项必须移除或改用替代写法。

目录

  • §1 可用能力
  • §2 Native 能力(JSBridge)
  • §3 不可用能力(Web API)
  • §4 不可用行为
  • §5 WebGL / 图形计算边界
  • §6 常见交互怎么实现
  • §7 能力扫描清单

1. 可用能力

页面与渲染

标准 HTML / CSS / JS 可用,但最终产物须满足目标内核基线:JS 见 js-compatibility.md,CSS 见 css-compatibility.md。可使用基线内的 Flexbox / Grid / 动画 / 媒体查询、Canvas 2D(getContext('2d'))、WebGL(getContext('webgl'/'webgl2'),能力边界见 §5、性能与低端机降级见 performance-budget.md §4–5),文本选择不限制。

媒体与文件

能力 用法 约束
摄像头 navigator.mediaDevices.getUserMedia({ video: true }) 用户手势触发 + 系统弹窗授权
麦克风 navigator.mediaDevices.getUserMedia({ audio: true }) 用户手势触发 + 系统弹窗授权
选择图片 / 拍照 <input type="file"> 系统选择器接管,仅能选图片和视频(无论 accept 如何设置)
音视频播放 <video> / <audio> 内联播放,媒体文件须打包在内

数据存储

localStorage / sessionStorage / IndexedDB / Cookie / Cache API 均可用,按小工具独立隔离,其他小工具与外部无法访问。

Cookie 仅作本地存储:可读写、按 origin 隔离,但因不联网不会随请求发往服务端,不能用于登录态 / 鉴权。需要本地存储优先用 localStorage / IndexedDB。数据不保证永久持久化。

交互

alert() / confirm() 可用,以原生 UI 展示。


2. Native 能力(JSBridge)

容器会注入 window.xhs.miniTool.*,通过它调用 Native 能力(发笔记、存相册、跳 App 页等)。

规则 说明
唯一入口 只用 window.xhs.miniTool.<apiName>(options),禁止自行 postMessage 到 bridge
契约来源 以 jsbridge-api.md 为准
参数校验 必填项、长度、数组上限等以 jsbridge-api.md 为准
本地路径 saveImageToPhotosAlbum.filePath 不支持网络 URL;base64 可先 writeTempFile 换 filePath
data:uri writeTempFile.data 必须是完整 data:<mime>;base64,...(canvas.toDataURL() 原样传),裸 base64 会失败
发笔记 postNote.mediaInfo 必填;图片走 image_resources[].url,视频走 video_resources
跳原生页 openRedPage.type 须命中 Native 规则表白名单,params 为语义参数

完整 API 列表、字段表与示例 → jsbridge-api.md。


3. 不可用能力(Web API)

以下 API 已禁用,调用会抛异常、返回空值或被拦截,必须移除或改用替代写法。

分类 涉及 API 替代方案
定位 navigator.geolocation.getCurrentPosition / watchPosition 移除
剪贴板 navigator.clipboard.readText / writeText、document.execCommand('copy'/'cut'/'paste') 展示可选中文本,引导用户长按 / 选中手动复制
硬件连接 navigator.bluetooth / navigator.usb / navigator.hid / navigator.serial 移除
传感器 new Accelerometer() / new Gyroscope() / new Magnetometer()、环境光、DeviceMotionEvent / DeviceOrientationEvent 改用触摸 / 指针手势(见 §5),摇一摇类移除
实时通信 new WebSocket()、new EventSource()、new RTCPeerConnection() 移除(不联网,无轮询替代)
后台运行 Web Worker、SharedWorker、Service Worker(navigator.serviceWorker.register) 移除,逻辑放主线程
屏幕 getDisplayMedia(屏幕共享)、Element.requestFullscreen(全屏由容器统一管理) 全屏用 CSS 沉浸式布局实现视觉全屏
设备信息 navigator.getBattery、navigator.connection、navigator.mediaDevices.enumerateDevices 移除
存储进阶 navigator.storage.persist(持久化)、跨域存储访问 移除,本地缓存用 localStorage / IndexedDB
凭据 navigator.credentials.get / create(WebAuthn)、navigator.locks 移除
窗口 window.open(弹新窗口)、window.prompt 单页内 JS 切换视图 DOM;输入用页内 Modal

移动端 WebView 本身也不支持:支付 PaymentRequest、系统通知 / 推送、NFC、MIDI、XR / AR / VR、后台同步 / 下载、PWA 安装、窗口管理、指针 / 键盘锁定。一律移除。


4. 不可用行为

行为 说明 替代方案
网络请求 fetch / XMLHttpRequest、加载外部图片 / 字体 / 媒体等一切联网请求 所有资源打包在内,改本地相对引用;仅小型配置 / 数据可随包提供,大型只读数据集不适合小工具,见 performance-budget.md §2
动态执行代码 eval()、new Function() 改写为静态逻辑
WebAssembly WASM 编译执行(依赖 WASM 的库无法运行) 移除或改用纯 JS 实现
iframe / object 内嵌 iframe / object,或被外部页面嵌入 内容直接写进页面
表单跳转提交 <form> 提交跳转 addEventListener('submit', e => e.preventDefault()) 后用 JS 处理
文件下载 a[download]、blob 下载 移除
打开外链 / 新窗口 target="_blank"、window.open、跳转站外 URL 单页内 JS 切换视图 DOM
跳转其他小工具 小工具间互相跳转 移除
长按菜单 系统长按菜单已禁用 用自定义交互替代
插件 Flash 等浏览器插件 移除

5. WebGL / 图形计算边界

纯 WebGL 渲染可用,组合能力受限:

场景 是否可用
包内资源 / Canvas / 内存对象作为纹理 ✅
外部域名图片作为纹理 🔴 不联网,纹理须打包在内
依赖 WASM 的加速库(Draco / Basis / ONNX / 抠图算法等) 🔴
依赖 Worker 的离屏渲染(OffscreenCanvas + Worker) 🔴
SharedArrayBuffer 多线程 🔴

WebGL 适合用包内资源做本地渲染;AI 图像处理等重计算(需联网或 WASM 模型)无法支持。WebGL 可用不等于低端真机性能足够:DPR、像素、纹理、draw call、几何预算、动态降档与兜底必须遵守 performance-budget.md §4–5。


6. 常见交互怎么实现

需求 实现
手势 / 拖拽 / 滑动 addEventListener('touchstart'/'touchmove'/'touchend') 或 Pointer Events(pointerdown/move/up)
拍照 / 录音 getUserMedia(...),由按钮点击等用户手势触发 + 授权
选择图片 / 视频 <input type="file">
复制文本 展示可选中文本,引导用户长按 / 选中复制
视觉全屏 CSS 布局(100vh / flex + 隐藏滚动)
页面跳转 单页内用 JS 切换视图 DOM
输入弹窗 页内 Modal 组件
保存图片到相册 writeTempFile({ data: canvas.toDataURL(...) })(须完整 data:uri)→ saveImageToPhotosAlbum({ filePath }),见 jsbridge-api.md
发布笔记 postNote({ mediaInfo, title?, content? })
跳转 App 搜索 / 用户页等 openRedPage({ type, params? }),type 须在白名单内

7. 能力扫描清单

扫描代码,命中下列模式则必须删除或改用替代写法:

fetch( / XMLHttpRequest / new WebSocket( / new EventSource( / new RTCPeerConnection(
navigator.geolocation.getCurrentPosition / watchPosition
navigator.clipboard.readText / writeText  ·  document.execCommand('copy')
navigator.bluetooth / navigator.usb / navigator.hid / navigator.serial
navigator.getBattery / navigator.connection / navigator.credentials / navigator.locks
navigator.mediaDevices.enumerateDevices / navigator.mediaDevices.getDisplayMedia
navigator.storage.persist / navigator.serviceWorker.register
new Worker( / new SharedWorker(
new Accelerometer() / new Gyroscope() / new Magnetometer()
DeviceMotionEvent / DeviceOrientationEvent / addEventListener('devicemotion' / 'deviceorientation')
Element.requestFullscreen / webkitRequestFullscreen
eval( / new Function( / WebAssembly.
window.open( / window.prompt(
location.href = / location.assign(   (跳转站外 URL)
<form ...> 提交跳转  ·  <a ... download>  ·  target="_blank"
<iframe> / <object>
<script src="https://..."> / <link href="https://..."> / <img src="https://..."> / CSS url(https://...)
    —— 外部资源一律加载不到,须下载后打进 zip 改本地相对引用

允许保留:

navigator.mediaDevices.getUserMedia({ video / audio })   // 用户手势 + 授权
<input type="file">                                       // 选图片 / 视频
localStorage / sessionStorage / IndexedDB / Cookie / Cache API   // 独立隔离
alert() / confirm()
touch / pointer events                                    // 手势交互
标准 DOM / CSS / Canvas 2D / WebGL 渲染