Files
suixinkan_ios_new/suixinkan/Core/Core.md
汉秋 00c3cd0a93 接入友盟统计与 U-APM,并优化宣传页打卡点标签交互。
友盟 SDK 改为隐私同意后再初始化;宣传页标签新增滑块位移动画,超过 5 个时选中项自动滚动居中。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-03 09:23:15 +08:00

4.8 KiB
Raw Blame History

Core 模块业务逻辑

模块职责

Core 模块提供跨业务复用的基础能力,包括网络请求、缓存存储和通用设计常量。业务页面不应直接重复实现这些能力。

主要子模块:

  • Networking:统一 API 请求、响应解析、错误处理和 token 注入。
  • Storage:统一登录 token、账号快照和 App 偏好的本地存储。
  • Design:统一颜色、字号、间距、控件尺寸和圆角。
  • Upload:统一阿里云 OSS 上传、图片压缩、上传策略和 Kingfisher 网络图片展示。

Networking

APIClient 是统一网络客户端,负责:

  • 根据 APIRequest 生成 URLRequest
  • 注入公共 HeaderContent-TypeAccept、App 版本和系统类型。
  • 通过 token provider 或 tokenOverride 注入登录 token。
  • 发送请求并处理 URLSession 错误。
  • 校验 HTTP 状态码。
  • 解码后端统一 APIEnvelope
  • 将 HTTP 错误、业务错误、解析错误转成 APIError

业务模块只应该封装自己的 API 类,例如 AuthAPIProfileAPI,然后调用 APIClient.send。页面和 ViewModel 不应直接拼接 URL 或处理原始响应体。

响应约定

后端响应通过 APIEnvelope<Response> 解包:

  • code 表示业务状态。
  • msg 表示业务提示。
  • data 是真正业务数据。

APIEnvelope.isSuccess 为 false 时,APIClient 抛出 APIError.serverCode

token 失效判断

APIError.isAuthenticationExpired 用于判断是否需要清空登录态:

  • HTTP 401 / 403 视为登录失效。
  • 业务码 200001 视为登录失效。
  • 错误文案包含 token、过期、登录失效、重新登录、unauthorized、验证失败等关键词时视为登录失效。

Storage

本地缓存按安全级别拆分:

  • SessionTokenStore:使用 UserDefaults 保存正式 token。
  • AccountSnapshotStore:使用 UserDefaults 保存非敏感账号快照。
  • AppPreferencesStore:使用 UserDefaults 保存上次手机号、协议同意状态等偏好。

缓存边界:

  • 正式 token 由 SessionTokenStore 写入 UserDefaults。
  • 临时 token 只放内存。
  • 密码、验证码、OSS STS token、一次性扫码结果和错误提示不落盘。
  • 头像、证件照等图片缓存交给 KingfisherCore 不保存图片 Data。
  • 隐私协议同意状态属于非敏感偏好,用于控制高德、友盟统计和 U-APM 等第三方 SDK 的初始化时机;退出登录时保留,清空登录页偏好时移除。

AccountSnapshot 保存可重建的账号展示和业务上下文:

  • AccountProfile
  • 账号类型和业务账号 ID
  • 当前角色 ID
  • 景区作用域和门店作用域
  • 当前景区 ID 和当前门店 ID

Design

AppDesign 管理跨页面颜色。AppMetrics 管理常用字号、间距、控件尺寸、行距和圆角。

新增页面时优先使用 AppMetricsAppDesign。只有明显属于单个页面的特殊尺寸,才保留在页面本地。

全局 Loading

GlobalLoadingCenter 是全局 Loading 的命令中心,只负责展示加载状态,不保存业务数据。业务 View 只能通过 Environment 获取它并调用 showhideupdateMessagewithLoadingwithOptionalLoading,不要在 body 中读取 isVisiblemessage 等展示状态。

Loading 的可观察状态只在 GlobalLoadingOverlayHost 内部订阅,并由 RootView 挂载到应用根部。这样切换 Loading 显隐时,只会刷新根部 Overlay不会让当前页面、Tab 根视图或业务子视图形成观察依赖。

当前全局 Loading 默认只展示动画;调用方传入 showsMessage: true 时,才会在动画下方展示 message 文案(如位置上报的「获取定位中」)。

全局 Loading 只用于阻塞型等待,例如冷启动恢复、登录、首屏加载、提交表单和核销。列表加载更多、上传进度、按钮内局部反馈继续保留在页面局部状态中。

全局 Toast

ToastCenter 只用于展示轻量提示文案,业务页面通过 toastCenter.show(...) 发出提示命令,不直接读取 Toast 展示状态。

Toast UI 是屏幕中央的黑色半透明圆角卡片,左侧带警告图标,文案 16pt以透明度淡入淡出无关闭按钮默认 2.2 秒自动隐藏。新的 Toast 会覆盖旧 Toast 并重新计时。

Upload

UploadAPI 通过 /api/app/config/get-sts-token 获取阿里云 OSS 临时上传配置。OSSUploadService 负责校验文件、生成 objectKey、调用 AlibabaCloudOSS SDK 并返回最终文件 URL。

上传模块只保存内存状态:

  • STS token 不写入 UserDefaults。
  • 用户选择的本地图片 Data 不落盘。
  • 上传进度只用于当前页面展示。

网络图片统一使用 RemoteImage / RemoteAvatarImage,内部由 Kingfisher 负责下载和缓存。业务页面不要再直接使用 AsyncImage 加载网络图片。