# WXAPP 云函数接口迁移矩阵 ## 口径 - 基线来自旧 uni-app 源码静态扫描生成的 `SOURCE_API_ACTIONS`,共 91 个唯一 action。 - 统一新入口为 `POST /api/functions/xiaoshu/app/gateway`。 - 请求体统一使用 `{ "token": "", "params": { "action": "...", ... } }`;执行器会占用顶层 `id`,业务参数不得放在顶层。公开接口可省略 `token`,但仍必须保留 `params`。 - 已有云函数映射 29 个,源码清单内另有 62 个以 HTTP 501 和 `migration_blocked: <原因>` 显式拒绝。网关额外保留 `content_add_zt`、`product_add`、`product_upd` 3 个后端兼容阻塞项,因此线上 `blocked` 对象共 65 项;矩阵不存在未覆盖的源码 action。 - “已映射”表示已有云函数代码与权限边界;完成 H5 切换前仍需逐页响应字段回归。 ## 已映射的 29 个 action | 领域 | action | |---|---| | 版本 | `app_update` | | 内容 | `content_get`, `content_list`, `content_list_llk`, `content_uphis`, `node_get`, `node_list` | | 商品只读 | `product_get`, `product_list`, `product_stock_list` | | 账号 | `user_get`, `user_info_name`, `user_list`, `user_login_passwd`, `user_register`, `user_update`, `user_update_pwd`, `user_update_pwdall`, `e_user_list` | | 学习/预约 | `e_add_words`, `e_ck_list`, `e_get_21list`, `e_order_detail`, `e_order_tongji`, `e_record_detail`, `e_words_list`, `stu_record_update_v2`, `user_point_list` | | 反馈 | `guestbook_add` | 已实测 `content_list` 在公司帐套下返回 92,435 条,`modelId=56` 返回 108 条。读取用 Psql 并强制 `company=7pIbDBJmKx`,所有客户端输入均使用参数化查询。 `content_list` 已按 `CommonModel.itemId = addon.id` 重建下列规范化联表: | ModelID | 旧表 | 规范化类 | 已核验数量 | |---:|---|---|---:| | 52 | `ZL_C_ck` | `VocabularyWord` | 89,620 | | 53 | `ZL_C_lxjl` | `PracticeRecord` | 816 | | 54 | `ZL_C_order` | `CourseAppointment` | 345 | | 56 | `ZL_C_ss` | `DailyStudyRecord` | 108 | | 58 | `ZL_C_kcbd` | `CourseBinding` | 55 | | 59 | `ZL_C_skjl` | `LessonRecord` | 82 | | 60 | `ZL_C_gywjl` | `MemoryPracticeRecord` | 1,380 | | 61 | `ZL_C_cpda` | `AssessmentProfile` | 14 | `myfield`/`myfield2` 只允许白名单字段和参数化等值过滤,`orders` 只允许已映射字段的 `ASC`/`DESC` 或旧 `NEWID()` 随机排序。Model 53/54/56/58/59/60/61 的列表与详情禁止匿名读取,非管理员仅能访问本人或指派给自己的学员记录。 学习专用只读接口已按旧页面的真实响应形状重建: - `e_record_detail`:由 Model 56 学习记录解析 `xxqs`,再按其中的 `GeneralID` 联查 Model 52 与 `VocabularyWord`,保持原顺序并为每项返回旧页面要求的 `detail[0]`。 - `e_words_list`:只返回指定用户 `PracticeRecord.jrscb=1` 的生词,按 `scid -> CommonModel.generalId -> VocabularyWord.id` 联查词库详情,不再误返回 89,620 条全量词库。 - `e_ck_list`:按一个或多个词库单元返回 Model 52 词条,并按 `用户 + 单词 GeneralID` 联查 `PracticeRecord.xxcs/jrscb`,恢复旧页面的 `w_learned` 与生词状态。 - `e_add_words`:验证词库 ID 与用户归属后批量更新 `PracticeRecord`;`save=1` 递增学习次数,`ifnew=1/0` 加入/移出生词,首次学习会创建带云端来源标识的进度记录。 - `stu_record_update_v2`:按 `预约 GeneralID + 学员 ID` 幂等新增或更新 Model 56;校验预约归属和词库 ID,根据 `xxqs.check` 重算 `learned/ygg/djq`。线上运行时实际未暴露文档中的 `Psql.transaction`,因此新记录采用安全整数范围内的高熵数字 ID,并顺序写入 `DailyStudyRecord` 与 `CommonModel`;任一步失败都会补偿删除已创建记录,避免孤立数据。 - `e_order_detail`:以预约内容 `GeneralID` 联查 `CourseAppointment`,返回数组契约、旧字段别名和可恢复的课程名称。 - `e_order_tongji`:按交付包 `Pages/API/WXAPP.cshtml` 原公式恢复六个字符串字段。陪练按 `LessonRecord.jsmz` 统计课型 1/2/3,佣金分别为 20/40/40、时长分别为 0.5/1/1 小时;学员按 `CourseAppointment.szyh` 且 `dszt>10` 统计课型和时长,`t_total` 继续按旧逻辑统计 `PracticeRecord.yhid`。 - `e_get_21list`:以 `MemoryPracticeRecord` 为主记录,联查 Model 60、原学习记录和课程节点;学员按 `yhid`、教练收入列表按 `plid` 隔离。 迁移数据没有保存复习收入金额,也没有提供可验证的计价公式,因此 `e_get_21list_tj` 改为显式 501;收入列表仍返回复习事实,但用 `incomeRuleUnavailable=true` 标记金额不可恢复,不伪造收入。 ## 因目标 Schema/历史数据缺失而阻塞 | 能力 | action | 缺失项 | |---|---|---| | 购物车 | `cart_list` | 无购物车类 | | 优惠券 | `coupon_list`, `coupon_usrgot_add`, `coupon_usrgot_list` | 无优惠券实例和用户领取关系类 | | 订单/物流 | `order_delivery`, `order_get`, `order_list`, `order_signfor`, `user_shop_order`, `user_shop_sales` | 无订单、商品明细、销售和物流类 | | 订单评价 | `order_comment_add`, `order_comment_list` | 无评价类 | | 支付 | `payment_cart`, `payment_cart_again`, `payment_success` | 无订单/支付明细类 | | 发票 | `invoice_add`, `invoice_del`, `invoice_get`, `invoice_list`, `invoice_upd` | 无发票类 | | 收货地址 | `receaddr_add`, `receaddr_del`, `receaddr_get`, `receaddr_list`, `receaddr_upd` | 无地址类 | | 提现账户 | `user_bank_add`, `user_bank_del`, `user_bank_get`, `user_bank_list` | 无提现账户类 | | 收藏 | `user_star_add`, `user_star_del`, `user_star_is` | 无用户收藏关系类 | | 会员订单 | `user_group_usr_supply`, `user_group_usr_upgrade` | 无会员购买/续费订单类 | | 投票 | `vote_add`, `vote_ask`, `vote_question` | 无可证明的投票记录类 | | 部门 | `user_dept` | 无可证明的用户部门关系 | 上述接口要恢复 1:1 能力,必须先补建 Schema,并取得可迁移的旧数据;仅有空表或空成功响应不能算迁移完成。 ## 因外部服务、安全或合规而阻塞 | 能力 | action | 需要的前置条件 | |---|---|---| | 短信验证码 | `mcode_send`, `user_login_mobile`, `user_register_mobile` | 新短信服务商凭据、验证码存储和限流 | | 微信授权 | `user_sync2` | 新微信容器流程和凭据 | | 资金/积分 | `user_cash_add`, `user_cash_list`, `user_coin_recharge`, `user_exp_transfer`, `user_money_recharge`, `user_money_transfer` | 支付凭据、不可变事务账本和业务规则 | | 复习收入 | `e_get_21list_tj` | 旧迁移数据中的收入金额字段或经业务方确认的计价公式 | | 支付密码 | `user_update_paypwd` | 独立哈希服务和重置流程 | | 实名认证 | `user_rnauth_add`, `user_rnauth_get`, `user_rnauth_upd` | 合规审核、加密存储和访问审计 | ## 有数据但尚未能证明 1:1 语义 | 能力 | action | 待确认/待实现 | |---|---|---| | 内容写入 | `content_add`, `content_update` | `CommonModel` 与 addon 表双写事务 | | 商品写入 | `product_del`, `product_sale_change`, `product_stock_change` | 门店管理员权限与库存账本 | | 单元进度 | `unit_record_update` | 旧源码在接口调用前无条件 `return`;需业务方确认废弃或提供新的聚合规则 | | 预约状态 | `e_order_update_v2` | 旧状态 11 同时扣减 `_User.legacyUserData` 课时、写余额账本并按学习记录创建最多 15 条抗遗忘双表记录;云运行时实际没有事务,需完成可补偿的一致性方案 | | 发布 | `pub_add`, `pub_list` | `Pub` 业务类型、审核与可见范围 | ## 前端切换决策 Angular H5 已启用混合迁移路由: - `user_login_passwd` 已优先调用云函数:已完成 Parse 密码迁移的账号保存真实 `sessionToken` 并用该会话读取 `user_get`;尚未完成密码重置的旧账号在云函数返回 401/403 时自动回退旧登录,不中断存量用户。 - `app_update`、`node_list`、`node_get` 已切换至云函数。 - 持有真实 Parse 会话时,`e_add_words`、`e_ck_list`、`e_order_detail`、`e_order_tongji`、`e_record_detail`、`e_words_list`、`e_get_21list`、`stu_record_update_v2` 已切换至云函数;旧会话继续留在旧端点,避免存量账号在密码重置前中断。 - 不含 addon 条件的 `content_list` 和 Model 52 公开词库已切换;已持有 Parse 会话的用户会把字段白名单内的 Model 53/54/56/58/59/60/61 addon 查询切到云函数,仍使用旧会话的存量账号自动保留旧端点。 - 云函数返回同时提供规范化 camelCase 与旧系统 `GeneralID`/`NodeID`/`Title` 等字段别名。 - `product_list` 尚未切换:当前 `Product` 类只有库存变体字段,缺少旧页依赖的商品名称、价格、图片和正文联表。 在 62 个阻塞 action 中仍包含订单、支付和预约结束等主流程时,直接全量切换会导致页面大面积中断。剩余切换条件是: 1. 先对齐缺失 Schema/数据和第三方凭据。 2. 完成剩余 action 的云函数事务、权限和字段回归。 3. 将 H5 会话改为 Parse `sessionToken`,再一次性切换到 `/api/functions/xiaoshu/app/gateway`。