开发说明.md 11 KB

开发说明

文档版本:v1.14 最后更新:2026-04-03 20:10:25

1. 环境变量

参考 .env.example

当前最关键的变量:

  • APP_ENV
  • HTTP_ADDR
  • DATABASE_URL
  • JWT_ACCESS_SECRET
  • AUTH_SMS_PROVIDER
  • AUTH_DEV_SMS_CODE
  • WECHAT_MINI_APP_ID
  • WECHAT_MINI_APP_SECRET
  • WECHAT_MINI_DEV_PREFIX
  • LOCAL_EVENT_DIR
  • ASSET_BASE_URL
  • ASSET_PUBLIC_BASE_URL
  • ASSET_BUCKET_ROOT
  • OSSUTIL_PATH
  • OSSUTIL_CONFIG_FILE

2. 本地启动

cd D:\dev\cmr-mini\backend
.\start-backend.ps1

如果你想固定跑开发工作台常用端口 18090,直接执行:

cd D:\dev\cmr-mini\backend
.\scripts\start-dev.ps1

默认会设置:

  • APP_ENV=development
  • HTTP_ADDR=:18090
  • DATABASE_URL=postgres://postgres:asdf*123@192.168.100.77:5432/cmr20260401?sslmode=disable
  • AUTH_SMS_PROVIDER=console
  • WECHAT_MINI_DEV_PREFIX=dev-

启动后可直接打开:

当前 workbench 已覆盖两类调试链:

  • 用户主链:bootstrap -> auth -> entry/home -> event play/launch -> session -> result
  • 后台运营链:maps/playfields/resource-packs -> admin event source -> build -> publish -> rollback
  • 第一阶段生产骨架联调台:places -> map-assets -> tile-releases -> course-sources -> course-sets -> course-variants -> runtime-bindings
  • 第三刀最小接线验证:runtimeBinding -> release -> launch.runtime
  • 第四刀发布闭环验证:runtimeBinding -> publish(runtimeBindingId) -> release -> launch.runtime
  • 活动运营域第二阶段验证:presentation -> content bundle -> publish(presentationId, contentBundleId, runtimeBindingId) -> release
  • 活动运营域第二阶段第二刀验证:event detail / play / launch -> presentation + content bundle 摘要
  • 活动运营域第二阶段第三刀验证:release 摘要闭环 + content bundle import
  • 活动运营域第二阶段第四刀验证:presentation import -> event 默认 active 绑定 -> publish 空参继承
  • workbench 一键验证增强:一键默认绑定发布一键补齐 Runtime 并发布
  • /dev/bootstrap-demo 现在也会回填最小生产骨架:place / map asset / tile release / course source / course set / course variant / runtime binding

2.1 当前推荐验证方式

如果目标是验证“从测试数据准备到 release 继承是否完整”,优先使用 workbench 的一键流,而不是手工逐个点按钮。

当前推荐顺序:

  1. Bootstrap Demo
  2. 一键补齐 Runtime 并发布
  3. 一键标准回归

当前这条一键链会自动完成:

  • demo event / source / build / release 准备
  • presentation 导入
  • content bundle 导入
  • event 默认 active 绑定保存
  • 最小生产骨架准备:
    • place
    • map asset
    • tile release
    • course source
    • course set
    • course variant
    • runtime binding
  • publish
  • release 回读校验
  • play / launch / result / history 回归汇总
  • demo 活动残留 ongoing session 清理:
    • 会把 demo event 下历史遗留的 launched / running session 自动改成 cancelled

当前日志能力:

  • 每一步都会写到“响应日志”
  • 失败时会直接输出:
    • 错误消息
    • stack
    • 最后一次 curl
  • 成功时“预期结果”面板会直接给出:
    • Release ID
    • Presentation
    • Content Bundle
    • Runtime Binding
    • 判定
  • 成功跑完标准回归后,“回归结果汇总”会直接给出:
    • 发布链
    • Play
    • Launch
    • Result
    • History
    • Session ID
    • 总判定

3. 当前开发约定

3.1 开发阶段先不用 Redis

当前第一版全部依赖:

  • PostgreSQL
  • JWT
  • refresh token 持久化

Redis 后面只在需要性能优化、限流或短期票据缓存时再接。

3.2 开发环境短信

当前默认可走 console provider。

用途:

  • 本地联调无需接真实短信供应商

3.3 微信小程序开发态

当前支持 dev- 前缀 code。

适合:

  • 后端联调
  • workbench 快速验证

3.4 本地配置目录

当前支持从根目录 event 导入本地配置文件。

相关环境变量:

  • LOCAL_EVENT_DIR
  • ASSET_BASE_URL

作用:

  • LOCAL_EVENT_DIR 决定本地 source config 从哪里读
  • ASSET_BASE_URL 决定 preview build 时如何把相对资源路径归一化成可运行 URL
  • ASSET_PUBLIC_BASE_URL 决定 publish 时如何把公开 URL 映射到 OSS 对象 key
  • ASSET_BUCKET_ROOT 决定发布对象上传到哪个 bucket 根路径
  • OSSUTIL_PATHOSSUTIL_CONFIG_FILE 决定 backend 发布 manifest 时使用哪个 OSS 客户端

4. Migration

当前 migration 文件在 migrations

执行原则:

  1. 按编号顺序执行
  2. schema 变更只通过新增 migration 完成
  3. 不直接改线上已执行 migration

5. 开发工作台

POST /dev/bootstrap-demo

它会保证 demo 数据存在:

  • tenant_demo
  • mini-demo
  • evt_demo_001
  • rel_demo_001
  • card_demo_001

GET /dev/workbench

这是当前最重要的联调工具。

可以直接测试:

  • 登录
  • 入口解析
  • 首页聚合
  • event play
  • 第一阶段生产骨架对象
  • 配置导入、preview build、publish build
  • launch
  • session start / finish
  • result
  • profile

补充说明:

  • publish build 现在会真实上传 manifest.jsonasset-index.json 到 OSS
  • 如果上传失败,接口会直接报错,不再出现“数据库里已有 release,但 OSS 上没有对象”的假成功
  • Save Event Defaults 会把当前 event 的默认 active 绑定写入:
    • currentPresentationId
    • currentContentBundleId
    • currentRuntimeBindingId
  • 之后 Publish Build 如果不显式填写这三项,会优先继承 event 默认 active 绑定

并且支持:

  • quick flow
  • scenario 保存/导入/导出
  • curl 导出
  • request history

当前第一阶段生产骨架联调台只做:

  • list
  • create
  • detail
  • binding

明确不做:

  • 正式后台 UI
  • edit
  • delete
  • batch
  • 审核流

活动运营域第二阶段当前也只做最小动作:

  • list
  • create
  • detail
  • publish 绑定
  • import

6. 当前推荐联调顺序

场景一:小程序快速进入

  1. bootstrap-demo
  2. login/wechat-mini
  3. me/entry-home
  4. events/{id}/play
  5. events/{id}/launch
  6. sessions/{id}/start
  7. sessions/{id}/finish
  8. sessions/{id}/result

场景二:APP 主身份

  1. auth/sms/send
  2. auth/login/sms
  3. me/entry-home
  4. launch
  5. session
  6. result

场景三:微信轻账号绑定手机号

  1. login/wechat-mini
  2. auth/sms/send with scene=bind_mobile
  3. auth/bind/mobile
  4. me/profile

场景四:配置发布到可启动 release

  1. bootstrap-demo
  2. dev/events/{eventPublicID}/config-sources/import-local
  3. dev/config-builds/preview
  4. dev/config-builds/publish
  5. events/{id}
  6. events/{id}/launch

场景五:第一阶段生产骨架最小闭环

/dev/workbench后台运营 模式中,按下面顺序操作:

  1. List PlacesCreate Place
  2. 在该 PlaceCreate Map Asset
  3. 在该 MapAssetCreate Tile Release
  4. Create Course Source
  5. 在该 MapAssetCreate Course Set
  6. 在该 CourseSetCreate Variant
  7. Create Runtime Binding

成功后应能拿到这些 ID:

  • placeId
  • mapAssetId
  • tileReleaseId
  • courseSourceId
  • courseSetId
  • courseVariantId
  • runtimeBindingId

建议第一次联调时用这组最小规则:

  • Place 先建 1 个
  • 每个 Place 先只建 1 个 MapAsset
  • 每个 MapAsset 先只建 1 个 TileRelease
  • 每个 CourseSet 先只建 1 个默认 CourseVariant
  • RuntimeBinding 先只绑定当前正在验证的 Event

这条链当前只验证对象关系闭环,不验证:

  • 发布链切换
  • launch 返回运行对象字段
  • EventPresentation
  • ContentBundle

场景六:第三刀最小接线验证

/dev/workbench后台运营 模式中,先完成“场景五”,再按下面顺序操作:

  1. Get Pipeline
  2. 确认当前 Release ID
  3. 填或复用 Runtime Binding ID
  4. Bind Runtime
  5. Get Release
  6. 切回 前台联调
  7. 对同一个 event 执行 Launch

场景七:活动运营域第二阶段最小闭环

/dev/workbench后台运营 模式中,按下面顺序操作:

  1. Get Event
  2. Create Presentation
  3. Create Bundle
  4. Assemble Source
  5. Build Source
  6. 在发布区填:
    • Runtime Binding ID
    • Presentation ID
    • Content Bundle ID
  7. Publish Build
  8. Get Release

成功后应能在 release 返回中看到:

  • runtime
  • presentation
  • contentBundle

并且这 3 类绑定当前都已固化到 event_release

成功后应能看到:

  • GET /admin/releases/{releasePublicID} 返回 runtime
  • POST /events/{eventPublicID}/launch 返回 launch.runtime

当前阶段的约束是:

  • 只新增 runtime 字段块
  • 不改旧的:
    • resolvedRelease
    • business
    • variant
  • release 如果没挂 runtimeBindingId,则 launch.runtime 为空

场景八:活动运营域第二阶段第三刀验证

/dev/workbench后台运营 模式中,先完成“场景七”,再按下面顺序操作:

  1. Create Presentation 或直接复用现有 Presentation ID
  2. Import Bundle
  3. Get Bundle
  4. Get Pipeline
  5. Publish Build
  6. Get Release
  7. 切回 前台联调
  8. Event Detail
  9. Event Play
  10. Launch

成功后应能同时看到这三组摘要:

  • release.presentation.templateKey / version
  • release.contentBundle.bundleType / version
  • release.runtime.placeId / mapId / tileReleaseId / courseVariantId

同时客户端消费侧应保持一致:

  • GET /events/{eventPublicID}
  • GET /events/{eventPublicID}/play
  • POST /events/{eventPublicID}/launch

当前 Content Bundle Import 只做统一导入入口,不做复杂资源平台:

  • 输入:
    • title
    • bundleType
    • sourceType
    • manifestUrl
    • version
    • assetManifest
  • 输出:
    • bundleId
    • bundleType
    • version
    • assetManifest
    • status

场景七:第四刀发布闭环验证

/dev/workbench后台运营 模式中,先完成“场景五”,再按下面顺序操作:

  1. Create Runtime Binding
  2. Get Pipeline
  3. 确认 Build ID
  4. 在发布区填 Runtime Binding ID
  5. Publish Build
  6. Get Release
  7. 切回 前台联调
  8. 对同一个 event 执行 Launch

成功后应能看到:

  • POST /admin/builds/{buildID}/publish 返回带 runtime
  • GET /admin/releases/{releasePublicID} 返回同一条 runtime
  • POST /events/{eventPublicID}/launch 返回同一条 launch.runtime

当前第四刀的兼容要求是:

  • 旧的“先 publish,再 bind runtime”路径继续可用
  • 新的“publish 时直接传 runtimeBindingId”优先推荐
  • 不修改旧的:
    • resolvedRelease
    • business
    • variant

7. 当前后续开发建议

文档整理完之后,后面建议按这个顺序继续:

  1. 抽出更通用的 play context -> launch 模型
  2. 补赛事与报名层
  3. 补页面配置和白标首页
  4. 再考虑实时网关票据

不要跳回去把玩法规则塞进 backend。