admin-migration-status.md 8.4 KB

Angular 管理后台与云函数迁移状态

已确认的迁移基线

  • 旧 Web 交付物是 ASP.NET Core 发布包,没有 .sln、.csproj 与原始 Razor 管理页面源码。
  • ZoomLaCMS.dll 可恢复 79 个后台控制器、至少 1,042 个公开动作;详细清单见 legacy-admin-inventory.generated.md。
  • 线上 Parse 应用为 7pIbDBJmKx_main,当前可见 109 个 Schema,其中 96 个为 SQL Server 规范化迁移目标类。
  • 核心数据已存在:CommonModel 92,435、VocabularyWord 89,620、NodeAuth 5,935、PracticeRecord 816、CourseAppointment 345、DailyStudyRecord 108、LessonRecord 82。
  • 迁移开始前 Function 表为空;本阶段已部署 9 个云函数。

本阶段已实现

  • Angular 18 独立管理端路由 /admin,包含独立登录、后台布局、概览、动态 Schema 表格、动态编辑表单、分页、搜索、软删除和迁移状态页。
  • 后台迁移状态页直接读取线上 xiaoshu.app.gateway/migration_status,动态显示已实现 action 数量及完整阻塞原因清单,不再使用前端硬编码阻塞计数。
  • 后台“全部数据类”目录由管理员云函数实时返回白名单,所有已开放规范化类均可从界面进入动态列表/编辑页;_Session、Function 等敏感系统类不进入目录。
  • 动态编辑器对 Object/Array 执行 JSON 类型校验,错误格式会阻止保存;Relation、File、GeoPoint 等无法安全通用写入的 Parse 类型由前后端共同设为只读,避免结构化字段被字符串覆盖。
  • 动态资源表按 objectId/name/title/username 等业务字段稳定优先展示,总页数采用向上取整;只读类使用查看抽屉且不显示保存/删除操作。
  • _User 详情抽屉已接入专用 resetPassword 管理员云函数,执行 8 位最小长度与二次确认;新密码不进入通用资源字段或前端持久化存储。
  • _User 新建入口已改为专用 createUser 管理员云函数:帐套内校验邀请账号,事务锁原子分配 legacyUserId,固定默认普通组 1,并初始化旧版余额/经验数据;请求不接受管理员或角色字段,开户密码也不进入通用资源草稿。
  • 旧 User_API 的锁定、解锁和移动用户组已迁为专用 userBatch 管理员云函数:支持每批 1–100 人、强制帐套边界,原子同步 isDisabled/legacyUserData.State 或 legacyGroupId/legacyUserData.GroupID;停用会撤销全部 Parse 会话,普通管理员不能停用自己或管理其他管理员。旧版账号登录也会拒绝已停用/已删除用户。
  • _User 的状态、旧用户 ID、旧用户组与旧资料 JSON 已从通用字段编辑中移除;密码重置和用户删除新增管理员目标保护并撤销目标会话,避免绕过专用一致性流程。
  • 当前线上 Group 表为空;用户组移动只接受当前帐套中真实存在的 Group.groupId,界面会明确提示先在“全部数据类”建立用户组,不会把不存在的默认编号伪装成可选组。
  • 旧 GroupAdd/GroupAdd_Submit 已迁为专用 saveGroup:新增组使用 PostgreSQL 事务锁在帐套内原子分配只读 groupId,校验同名组、父组归属与层级循环;通用保存不能绕过。删除组前会拒绝仍被用户或下级组引用的记录。
  • 旧 ContentManage_Status、ContentManage_Del、回收站恢复与 ContentMove_Submit 已迁为专用 contentBatch:支持每批 1–100 条内容、限定旧状态 -3/-2/-1/0/99、校验目标节点帐套并保留 addon 关联。CommonModel 的 generalId/modelId/nodeId/itemId/tableName/status/sourceKey/orderId 改为通用只读;新增按钮关闭,避免只写主表却遗漏模型附表。
  • _User 与 CommonModel 表格已补齐当前页全选和批量工具栏,可直接批量停用/解锁/移动用户组,以及审核、回收、恢复、移动内容节点;翻页或重新查询会清空选择,避免误操作隐藏页记录。
  • 迁移状态页已接入从反编译基线自动生成的 1,042 项旧后台动作台账,可按模块、action、原因与状态搜索筛选;当前保守登记为 9 项已实现、12 项部分实现、111 项数据阻塞、185 项基础设施阻塞、725 项待逐项核验。生成器和 admin-coverage:check 会阻止台账与源码基线漂移。
  • Parse 登录只在浏览器保存当前 sessionToken;masterKey 只在部署进程中使用。
  • 云函数网关强制校验管理员身份、company 帐套、类白名单、字段白名单和敏感字段过滤。
  • _Session 不开放,Function 源码不开放通用查询或编辑;用户密码只允许专用重置操作。
  • 8 个管理/CMS 函数均验证未认证请求返回 401;临时帐套管理员完成真实只读冒烟测试后已删除。
  • 第 9 个 xiaoshu.app.gateway 已覆盖旧 H5 源码的全部 91 个 action:28 个已映射,源码清单内 63 个显式返回 501 阻塞原因;动态调用的兼容 action content_add_zt 也已映射,product_add、product_upd 仍显式阻塞,因此线上为 29 个已实现、65 个阻塞项。经典注册/资料更新、课程词库进度、六类余额/积分账本读取、学习次数/生词状态、直属团队/VIP 统计、陪练预约学员分组、15 段复习计划、7 类规范化内容新增/更新、预约状态/课时账本/抗遗忘批量创建及旧版统计公式均已完成;缺主表的商品读取、缺短信校验的密码重置及其他缺副表模型继续按请求明确 501。详见 wxapp-cloud-action-matrix.md。
  • 旧数据的 isDeleted 在部分物理表与 Parse Schema 不一致,把它放入 Parse 查询条件会返回 500;网关改为公司条件查询后在结果侧兼容过滤。
  • Angular H5 已开始按页回归切换:账号密码登录、版本、栏目、公开内容、8 类 addon 联表,以及学习记录详情、预约详情、生词本、21 天抗遗忘列表可走云函数;私有读取只在真实 Parse 会话下切换,其余 action 仍由显式迁移路由保留旧端点。

SQL 视图 / 函数替代状态

旧对象 云函数替代 状态 说明
ZL_StripeHtmlTag、ZL_StripeTrimstr cms.content-normalizer 已实现 保守转换为纯文本,覆盖脚本、样式、实体和空白
ZL_EX_UserView cms.users.extended 已实现 过滤密码、哈希、会话、Token 与 Secret
ZL_Exam_ClassView cms.exams.classes 已实现基础投影 当前目标类缺少可证明的学校/年级 Pointer 时不伪造关联
ZL_Guest_BarView cms.guest.bar 已实现基础投影 支持帐套与分页
ZL_SearchView cms.search 已实现 搜索 CommonModel 并清理输出 HTML
ZL_User_PlatView cms.users.platform 已实现 使用合并进 _User 的 legacy 平台资料
ZL_User_WXView cms.users.wechat 已实现 使用合并进 _User 的微信资料并过滤密钥
ZL_CartProView — 数据阻塞 目标 Schema 无购物车类,且迁移登记没有可用行
ZL_Order_PayedView — 数据阻塞 目标 Schema 无订单/支付明细类
ZL_Order_ProSaleView — 数据阻塞 目标 Schema 无订单商品明细类
ZL_Order_ShareView — 数据阻塞 目标 Schema 无订单分享关系类
ZL_Plat_BlogView — 数据阻塞 目标 Schema 无博客正文/回复类

仍需逐页专用迁移

动态 Schema CRUD 覆盖的是规范化业务数据管理能力,不代表旧后台 1,042 个动作已逐页复刻。考试组卷、微信配置、订单支付、模板编辑、数据库备份、站点集群、PowerShell、文件管理等必须逐项判断:

  1. 有目标业务类且仍属当前产品范围:新增专用 Angular 页面和专用云函数。
  2. 需要第三方密钥或基础设施权限:取得新系统凭据后再实现,前端不得存储密钥。
  3. 依赖未迁移表、IIS、Windows 文件系统或旧 Zoomla 运行时:列入最终无法迁移清单,不以空成功响应代替。

管理员启用前置条件

线上 435 个 _User 在核验时没有任何 isAdmin=true、role=admin 或 adminRoleKey 管理员。系统因此默认不可登录管理端。上线前必须由持有 Parse masterKey 的部署人员为明确指定的现有用户设置:

  • isAdmin: true
  • roles: ["admin"]
  • company: Pointer<Company>

跨帐套管理员才可设置 adminRoleKey: "super-admin";不允许从浏览器执行管理员提权。