鸿蒙单词打卡实战笔记:Appwrite 云函数抽词去重与 AI Shell 追问 JWT 鉴权 401
导读
今天在鸿蒙开发实践中心看了一个入门案例——“单词打卡学习:HarmonyOS + Appwrite 端云一体化”(预计练习 120 分钟),随后在 AI DevSpace 打开 AI Shell,围绕案例里“云函数 execute 权限从 [“any”] 收紧后怎么传 JWT、返回 401 怎么排查”追问了一轮。本文是当天的实操笔记:先讲案例怎么做,再讲云函数的坑位,最后贴 AI Shell 的追问实录。
一、案例在做什么:一个能跑通的端云一体单词 App
案例做的是一个鸿蒙单词打卡应用,端侧用 ArkTS,云端用自托管的 Appwrite(云函数 Functions 与 NoSQL 文档数据库)。四个页面分工清楚:
- 登录页:邮箱 + 密码注册 / 登录,邮箱唯一,密码使用 MD5 哈希存储;
- 首页:今日单词量、进度条、连续打卡天数、待学习单词入口;
- 闪卡学习页:看词想义、翻卡看释义和例句,学完标记 learned;
- 测试页:看词选义的 10 道小测,测完成绩回写学习记录。
核心能力就四项:闪卡学习、看词选义测试、学习进度条、连续打卡统计。难度定位入门,但端云一体该有的环节一个不少,适合第一次把 ArkTS 和云函数串起来练手。
二、端云一体怎么搭:3 个集合 + 6 个云函数
数据层是 3 个集合:
- users_col:用户。账号唯一,密码 MD5 哈希,另存连续打卡天数和总学习量;
- words_col:单词。字段有单词、释义、音标、例句和难度,db-init 云函数内置了 58 个词;
- learn_records_col:学习记录。user_id、date、word_ids、今日学习量、正确题数。
逻辑层是 6 个云函数:register、login、getDailyWords、learnWord、getProgress、db-init,统一跑在 node-16.0 运行时上。前端不直接读写数据库集合,而是调云函数:ArkTS 侧用 @ohos.net.http 发 POST 请求到 /v1/functions/{functionId}/executions,body 是执行入参;返回后要做“两段解析”——先看 execution 层的状态,再解析内层 responseBody 里的业务字段,两段都要判错。
三、getDailyWords 的抽词与去重逻辑
getDailyWords 是理解这个案例的关键函数:它每次从 words_col 随机抽 10 个单词,同时在 learn_records_col 里按 user_id + date 查当日记录——当日已有记录就直接复用,避免同一天重复抽词导致“今日单词”口径漂移;没有记录才生成新的一批并写记录。
learnWord 每学一个词记一笔,字段包括 wordId、是否正确、学习时间;getProgress 再按当日聚合,算出今日已学量、正确率与连续打卡天数,首页进度条就是根据它渲染的。记住一个分工:云函数负责“规则与数据一致性”(抽词、去重、打卡统计),端侧负责“状态与体验”(@State 渲染、进度条、页面导航)。
四、云函数发布时的五个坑位
按案例步骤实际做下来,最容易踩的五处:
- ESM 默认导出。node-16.0 运行时是 ESM 模式,handler 必须用 export default 导出,直接写 module.exports 起不来。
- SDK 版本。node-appwrite 用 v11(函数打包时就要指定),低版本在运行时会报 EBADENGINE。
- 打包方式。源码 + node_modules 一起打成 tar.gz 再上传到控制台部署。
- execute 权限。默认 [“any”],任何人可调;改成登录用户可见后要走 JWT / Session 鉴权(见第六节)。
- API Key 权限。调用方 API Key 必须先勾选对应权限,缺 scopes 会报 missing scopes——这类错先查 Key 权限,不要急着改代码。
部署成功后能在控制台看到部署状态 online,三张表都建好,db-init 执行一遍就有 58 个单词可用。
五、排障三件套:401、missing scopes、EBADENGINE
案例文档给了三类典型错误,处理顺序是固定的:先确认部署成功(online),再核对权限与凭证,最后才看业务逻辑:
- 401:execute 权限或凭证问题。
- missing scopes:API Key 权限没勾够。
- EBADENGINE:node-appwrite 版本或运行时版本不对。
把三类错分开处理,不要混在一起猜。前端两段解析也要匹配:execution 层报错说明云函数没跑起来,responseBody 里报错才是业务逻辑的问题。
六、AI Shell 追问实录:execute 收紧后,JWT 怎么传?
案例看到这里,我在 AI DevSpace 打开 AI Shell 问了一个具体问题:execute 从 [“any”] 改成只允许登录用户后,ArkTS 端调用 POST /v1/functions/{id}/executions 时应该怎么传 JWT?返回 401 应该先检查哪几项?AI Shell 检索了 Appwrite 官方文档后给了两条路和一张 401 检查清单:
方式 A(推荐):Session Header。登录后直接用 account.createEmailPasswordSession 返回的 $secret,请求头写 X-Appwrite-Session: <secret> 即可,不用再换 token。注意这里用的是 $secret,不是 $id;本案例当前架构(登录后立即调云函数)用这种方式最省事。
方式 B:JWT Bearer。先发 POST /v1/account/jwts 换取 JWT,响应里的 jwt 字段就是 token;请求头写 X-Appwrite-JWT: <纯 JWT 字符串>,不要加 Bearer 前缀。JWT 有效期只有 15 分钟,适合“现用现取”的场景。
401 检查清单三项:第一,凭证是否过期(JWT 15 分钟过期,Session 失效也要重登);第二,请求头格式(X-Appwrite-JWT 不要 Bearer 前缀;X-Appwrite-Project 填正确的项目 ID;X-Appwrite-Session 用 $secret 不是 $id);第三,登录本身是否成功(返回 201、status true、MFA 没过都会导致后续调用 401)。
七、上线前的安全与性能三点
- 安全:先把 execute 从 [“any”] 收紧到 [“users”],登录态稳定后再考虑加防刷(比如请求频率限制);不要裸 HTTP 上线,前面挂 HTTPS 反代,Appwrite 控制台与前端域名拉齐。
- 性能:learnedWords 建议缓存一天(MMKV),getDailyWords 一个请求可以带回单词与今天的学习记录,减少首屏请求数;刷新页面后单词列表重新加载是正常行为,不是 Bug。
- 异常处理:云函数内部对非法参数直接返回错误响应,接口层不要再吞掉错误,端侧按错误码给提示。
八、今天的小结
第一,端云一体的正确分工是“云端管规则、端侧管体验”。抽词、去重、打卡这些一旦口径变了就会乱的逻辑,一定要放在云函数里;端侧只做渲染和交互,这样改规则不用发版。
第二,排障要分层。部署、权限、凭证、业务这四层是按顺序排查的:401 先看 execute 和凭证,missing scopes 看 API Key,EBADENGINE 看版本——每一层都有明确的报错信号。
第三,AI Shell 的追问价值在于“带着上下文问”。问题里给出具体函数名、集合名和权限现状,得到的回答就能直接落地:这次追问的 Session / JWT 两条方案和 401 清单,可以直接照着改案例代码。
附:相关链接
- 点赞
- 收藏
- 关注作者
评论(0)