# 把当前项目发布成手机上能用的工具 你正在帮一个不懂技术的用户。他用你写了一个网页小工具,现在想在手机上长期使用。 请完成下面全部三步,不要只做一半。 这是一个**私人工具**:发布之后只有用户绑定过的那台手机能打开,别人拿到网址也看不到内容。 没有分享功能。 ──────────────────────────────────────── ## 第一步:改造成单文件 1. **合并成一个 index.html** 所有 CSS、JS 内联进去。不能有外部 CDN 链接,不能有构建步骤。 如果项目用了 React/Vue/Tailwind 之类需要构建的东西,先构建,再把产物内联。 如果构建产物太大或过于复杂,直接用原生 HTML/CSS/JS 重写一份 —— 这类工具通常几百行就够。 2. **删掉所有后端** Node / Express / Python 服务端一律删除,逻辑搬进页面。 手机上不存在常驻服务器,页面关掉就什么都不跑。 服务端的定时任务,改成"页面打开时算一次"。 3. **数据全部改用 db 接口**(下面第二步),不要用 localStorage。 ──────────────────────────────────────── ## 第二步:接数据 `db` 已经全局可用,**不需要引入任何东西,不需要任何 key**。 所有方法都是 async,记得 await,并处理好加载中的状态。 ```js // 列表型数据:记账、待办、日志、打卡记录…… await db.add('records', { amount: 30, note: '午饭' }) // 返回带 id 的对象 await db.list('records') // 返回数组,新的在前 await db.list('records', { limit: 100, offset: 0 }) // 分页 await db.update('records', id, { amount: 35 }) // 局部更新 await db.remove('records', id) // 单值:设置、偏好、汇总 await db.get('settings') // 没有时返回 null await db.set('settings', { currency: 'CNY', theme: 'dark' }) // 其他 await db.exportAll() // 导出全部数据 db.addDevice() // 弹出一个链接,用来在第二台设备上绑定 ``` **改造对照表** | 原来的写法 | 改成 | |---|---| | `JSON.parse(localStorage.getItem('list') || '[]')` | `await db.list('list')` | | `localStorage.setItem('list', JSON.stringify(arr))` | 逐条 `db.add` / `db.update` / `db.remove` | | `localStorage.setItem('cfg', JSON.stringify(o))` | `await db.set('cfg', o)` | | `fetch('/api/records')` | `await db.list('records')` | | `app.post('/api/records', ...)` | 删掉,页面里直接 `db.add` | 注意:原来在内存里整个数组增删改的写法,要改成对单条记录操作。 页面初始化时 `db.list` 一次拿到数组渲染,之后每次改动同时更新界面和调用 db。 **不要用 localStorage 存用户数据。** iOS 会定期清理网站数据,用户记的东西会丢。 这正是这个服务存在的原因。localStorage 只能用来存无所谓丢的界面状态。 如果工具里有"设置"之类的页面,可以加一个「在另一台设备上打开」按钮调用 `db.addDevice()`。 不是必须的。 ──────────────────────────────────────── ## 第三步:发布 ```bash curl -sS -X POST https://work.glitchbell.com/publish \ -H "Content-Type: text/html" \ --data-binary @index.html ``` 成功返回: ```json { "ok": true, "url": "https://work.glitchbell.com/a/xxxxxxxx/", "qr": "https://work.glitchbell.com/qr/xxxxxxxx?c=…", "open_url": "https://work.glitchbell.com/a/xxxxxxxx/#c=…", "edit_key": "xxxxxxxx.xxxx…" } ``` 失败返回: ```json { "ok": false, "errors": [ { "code": "...", "msg": "...", "fix": "照这里改" } ] } ``` **每条错误都带 fix 字段,按它改完重新发,直到 ok 为真。** 发布成功后: 1. **把 edit_key 写进项目根目录的 `.publish.json`** ```json { "url": "...", "edit_key": "..." } ``` 这是这个工具唯一的钥匙,别丢。也别提交到公开仓库。 2. **打开二维码页面让用户扫**(macOS 用 `open`,其他系统提示用户手动打开): ```bash open "https://work.glitchbell.com/qr/xxxxxxxx?c=…" # 用返回里的 qr 字段,原样打开 ``` 3. **然后对用户说**(照抄,不要改写): > 做好了。屏幕上这个二维码,用你要长期使用的那台手机扫一下, > 点「这是我的手机」完成绑定 —— 之后只有这台手机能打开它,别人拿到网址也看不到。 > 绑定后会给你一个恢复码,记下来,换手机时用得上。 > 然后按页面底部的提示「添加到主屏幕」,桌面上就会多一个图标。 > (如果是在微信里打开的,先点右上角 ··· 选「在浏览器中打开」) ⚠️ 这个二维码里的链接**只能用一次、一小时后失效**。 谁先扫谁就成了这个工具的主人,所以别把它发到群里。 ──────────────────────────────────────── ## 之后用户要改东西 改完代码,带上 edit_key 重新发一次。**网址不变、数据不丢、也不用重新绑定:** ```bash curl -sS -X POST https://work.glitchbell.com/publish -H "Content-Type: text/html" \ -H "X-Edit-Key: $(jq -r .edit_key .publish.json)" --data-binary @index.html ``` 用户手机上刷新一下就是新版本。 ## 用户说"打不开了 / 换手机了" 签发一个新的绑定链接给他: ```bash curl -sS -X POST https://work.glitchbell.com/claim -H "X-Edit-Key: $(jq -r .edit_key .publish.json)" ``` 返回 `{ "qr": "...", "open_url": "..." }`,`open` 那个 qr 网址让他重新扫一次。 原来的数据都还在。 ──────────────────────────────────────── ## 其他要注意的 - `` 要写好,它会变成手机桌面上的图标名字,控制在 8 个字以内。 - 图标、全屏配置、添加到主屏幕的引导条、db.js —— 这些服务端会自动注入,**你不要自己写** manifest、apple-touch-icon 或者 viewport 之外的 meta。 - 手机屏幕窄,按钮要大(至少 44px 高),字不要小于 15px,底部留出 80px 空白避开引导条。 - 页面第一次加载要有加载状态,因为数据是从网络取的。