Files
suixinkan_ios_new/suixinkan/Features/Profile/Profile.md
汉秋 5ab9b1b324 修复账号切换后「我的」页当前账号展示错误,并统一举报摄影师首页 URI。
切换账号时以用户选中账号为准写入展示标题与业务作用域,避免沿用旧门店名称;同时将首页举报摄影师入口 URI 对齐为 report_photographer。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-01 17:21:04 +08:00

7.1 KiB
Raw Blame History

Profile 模块业务逻辑

模块职责

Profile 模块负责“我的/个人信息”页面及其二级页面,包括用户资料展示、昵称编辑、账号切换、密码修改、实名认证、系统设置、协议页和退出登录。

首页“空间设置”入口对应的是摄影师当前景区下的个人空间配置,已拆到 ProfileSpace 模块;Profile 模块只保留账号级个人资料能力。

该模块聚焦个人资料业务:

  • 拉取用户基础资料。
  • 拉取实名认证信息。
  • 展示头像、昵称、UID、手机号、账号状态和实名认证状态。
  • 修改昵称和头像。
  • 修改密码。
  • 切换当前景区/门店业务账号。
  • 提交实名认证基础资料。
  • 展示系统设置、版本号、下载链接和协议 H5 页面。
  • 退出登录入口。

登录态清理和缓存清理由 App 模块的 AuthSessionCoordinator 统一处理。

DEBUG 构建下,“我的”列表会额外展示“首页调试”入口,进入 DebugHomeMenuPreviewView 后可查看并跳转所有已知首页菜单,不读取角色权限。该入口只用于迁移预览和调试,不进入 Release 包。

核心对象

  • ProfileView:个人信息页 UI负责展示资料、编辑入口、密码弹窗和退出确认。
  • ProfileViewModel:维护资料加载状态、编辑状态、保存状态和展示文案。
  • ProfileRoute:个人中心二级页面路由。
  • AccountSwitchView / AccountSwitchViewModel:账号切换页面和状态逻辑。
  • RealNameAuthView / RealNameAuthViewModel:实名认证页面和表单逻辑。
  • SettingsCenterView / AgreementView:设置中心和协议 H5 页面。
  • DebugHomeMenuPreviewViewDEBUG 专用首页菜单预览页,不参与正式业务流程。
  • ProfileAPI:封装用户资料、实名认证和资料更新接口。
  • OSSUploadService:上传头像和实名认证证件图片,返回可提交给业务接口的 OSS URL。
  • UserInfoResponse:用户基础资料。
  • RealNameInfoResponse / RealNameInfo:实名认证信息。
  • UpdateInfoRequest:昵称、密码或头像更新请求体。
  • RealNameAuthRequest:实名认证提交请求体。

basic_info 首页权限入口继续进入 ProfileViewspace_settings 进入 ProfileSpaceView,两者不共用页面状态。

加载流程

  1. ProfileView.task 进入页面时调用 reloadProfile()
  2. 下拉刷新时同样调用 reloadProfile(),成功后不展示 Toast。
  3. ProfileViewModel.reload 并发请求:
    • ProfileAPI.userInfo
    • ProfileAPI.realNameInfo
  4. 请求成功后更新 userInforealNameInfo
  5. ProfileView 将最新 userInfo 交给 AuthSessionCoordinator.refreshCachedProfile
  6. 协调器更新 AccountContext.profile,并同步刷新账号快照。

资料编辑流程

  1. 用户点击编辑按钮。
  2. ProfileViewModel.beginEditing 进入编辑状态,并把当前昵称写入编辑框。
  3. 用户点击头像时通过 PhotosPicker 选择本地图片。
  4. AvatarImageProcessor 将头像压缩为 JPEG并暂存在内存中。
  5. 用户提交后,ProfileViewModel.saveProfile 校验昵称非空。
  6. 头像变化时先调用 OSSUploadService.uploadUserAvatar 上传到 OSS。
  7. 头像上传成功后调用 ProfileAPI.updateUserAvatarURL 回写头像 URL。
  8. 昵称变化时调用 ProfileAPI.updateUserInfo(nickname:)
  9. 接口成功后本地更新 userInfo.nicknameuserInfo.avatar
  10. ProfileView 刷新全局账号资料和账号快照。

密码修改流程

  1. 用户打开 PasswordUpdateSheet
  2. 输入新密码并点击完成。
  3. ProfileViewModel.updatePassword 校验密码至少 6 位。
  4. 校验通过后调用 ProfileAPI.updateUserInfo(password:)
  5. 成功后关闭弹窗并展示 Toast。

密码不会写入本地缓存。

账号切换流程

  1. 用户点击“当前账号”进入 AccountSwitchView
  2. AccountSwitchViewModel.load 调用 ProfileAPI.switchableAccounts,读取 /api/app/v9/accounts
  3. 页面展示景区账号和门店账号,优先选中后端标记的当前账号,否则选中第一项。
  4. 用户确认后调用 AuthAPI.setUser,使用 AccountSwitchAccount.toSetUserRequest() 生成请求体。
  5. 切换成功后调用 AuthSessionCoordinator.completeLogin,重新写入正式 token、账号快照、权限、景区和门店上下文。
  6. AppRouter.reset() 清空旧路由栈并回到首页。

实名认证流程

  1. 用户点击“认证状态”进入 RealNameAuthView
  2. RealNameAuthViewModel.load 调用 ProfileAPI.realNameInfo 并回填姓名、身份证号、证件有效期、图片 URL 和审核状态。
  3. 用户可发送短信验证码,接口为 /api/yf-handset-app/photog/real-name/sms-verify-code
  4. 用户通过图片卡片选择身份证人像面和国徽面。
  5. RealNameImageProcessor 将证件图片压缩为 JPEG并暂存在内存中。
  6. 提交前校验姓名、身份证号、短信验证码、证件图片和有效期。
  7. 校验通过后先调用 OSSUploadService.uploadRealNameImage 上传证件图片。
  8. 上传成功后把 OSS URL 写入 RealNameAuthRequest.frontUrl/backUrl
  9. 调用 /api/yf-handset-app/photog/real-name/submit 提交实名资料。
  10. 提交成功后重新加载实名认证信息。

证件图片的原始 Data、压缩 Data 和上传进度只保存在内存中,不写入本地缓存。

设置和协议流程

  1. 用户点击“系统设置”进入 SettingsCenterView
  2. 设置中心展示关于我们、系统版本、App 下载链接、用户协议和隐私政策。
  3. App 下载点击后复制 /h5/app/download 链接到剪贴板。
  4. 协议页使用 AgreementView 加载 APIEnvironment.current.baseURL 下的 H5 页面。

退出登录流程

  1. 用户点击退出登录。
  2. ProfileView 展示确认弹窗。
  3. 用户确认后调用 AuthSessionCoordinator.logout
  4. 协调器清空正式 token、账号快照、账号上下文、路由栈和 Toast。
  5. AppSession 切换为 loggedOut,根视图回到登录页。
  6. 上次手机号和协议状态等非敏感偏好保留。

状态展示规则

  • 进入个人信息页时,先用 AccountContext 中已恢复的本地缓存(AccountSnapshot)预填充昵称、手机号和头像;接口返回后再替换为最新数据。
  • 昵称为空时展示“未设置昵称”。
  • 真实姓名、手机号和账号状态为空时展示 --
  • 实名认证状态:
    • auditStatus == 2:已实名认证。
    • auditStatus == 3:审核不通过。
    • 其他状态:审核中。
    • 无实名认证信息时:点击去实名认证。
  • 账号切换失败只展示 Toast不清空登录态。
  • 实名认证失败只影响实名认证页面,不影响登录态和账号上下文。
  • 「当前账号」展示规则:
    • 门店账号(store_user)展示门店名称,不回退到景区名称。
    • 景区账号(scenic_user)展示景区名称。
    • 展示标题在登录/切换成功时写入 AccountContext.currentAccountDisplayTitle,切换账号时必须同步更新,不能沿用上一次账号名称。