Skip to content

正式合并 iOS kmp/cmp 进 dev,包括二级页面跳转下沉等相关配置 - #596

Merged
985892345 merged 35 commits into
developfrom
guoxiangrui/feature/ios_cmp
Sep 6, 2026
Merged

正式合并 iOS kmp/cmp 进 dev,包括二级页面跳转下沉等相关配置#596
985892345 merged 35 commits into
developfrom
guoxiangrui/feature/ios_cmp

Conversation

@985892345

Copy link
Copy Markdown
Member

No description provided.

985892345 and others added 30 commits May 31, 2026 00:40
# Conflicts:
#	cyxbs-applications/pro/iosApp/CyxbsMobile2019_iOS.xcodeproj/project.pbxproj
#	cyxbs-pages/home/src/iosMain/kotlin/com/cyxbs/pages/home/mobile/ui/MobileHomePage.ios.kt
SportServiceImpl.ios.kt#jumpSportDetail 之前是 TODO(),iOS 上从体育打卡 feed
点进去会崩溃。按项目里 iOS 平台能力反向注入的标准模式(IOSHomeViewPager / IOSToast
同款),把这条跳转接通:

- sport iosMain 新增 SportIosPlatform 接口(小能力契约)
- jumpSportDetail() actual 改为 SportIosPlatform::class.implOrNull()?.jumpSportDetail()
  ?: toast("暂不支持跳转"),与其他 NavPlatform 兜底行为一致
- IOSKmpInterface 加 jumpSportDetail();IOSKmpInterfaceLink 通过
  @ImplProvider(SportIosPlatform::class) 适配
- KmpInterfaceImpl.swift 实现 jumpSportDetail():找 top UINavigationController
  → push SportAttendanceViewController(hidesBottomBarWhenPushed=true)
- AppDelegate.setupWindow 给 CMP rootVC 包 CustomNavigationController(自带
  isNavigationBarHidden + 修过 isNavigationBarHidden 下边缘右滑返回手势失效的问题)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
TodoFeedViewModel.ios.kt 之前只有空 actual class,iOS 上点击邮子清单 feed 完全
没反应。沿用 Step 1 体育打卡跳转桥的同款模式接通"点击整张卡片 → push 原生 ToDoVC":

- todo iosMain 新增 TodoIosPlatform 接口(小能力契约)
- TodoFeedViewModel.ios.kt override onCardClick:
  TodoIosPlatform::class.implOrNull()?.jumpTodoMain() ?: toast("暂不支持跳转")
- IOSKmpInterface 加 jumpTodoMain();IOSKmpInterfaceLink 通过
  @ImplProvider(TodoIosPlatform::class) 适配
- KmpInterfaceImpl.swift 实现 jumpTodoMain():push ToDoVC(hidesBottomBarWhenPushed=true)

refresh / onItemClick / onItemCheck 显式 override 留空(不是漏写):
iOS 端原生数据源 TodoSyncTool 暂未接入 KMP,feed 列表保持基类 Empty 默认状态,
体验上等同于「主页 feed 显示空态文案 + 用户点空白处进 ToDoVC 看完整列表」。
待 todo 模块整体 cmp 化后再对齐 Android 实现。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
DiscoverFunctions 的 5 个 click 在 commonMain 默认为 toast("该平台未实现"),
iOS 上对齐旧版 FinderToolsView.push(to:) 的跳转映射接通到原生 VC:

- clickNoClass        → WeDateVC
- clickSchoolCalendar → CalendarViewController
- clickTodo           → ToDoVC(复用 IOSKmpInterface.jumpTodoMain)
- clickSport          → SportAttendanceViewController(复用 IOSKmpInterface.jumpSportDetail)
- clickExam           → TestArrangeViewController

clickFindCourse / clickMap / clickSchoolCar / clickEmptyRoom 已通过对应
NavArgument 走 cmp 内部导航,无需 override。

实现:

- discover iosMain 新增 DiscoverFunctionsIosPlatform 接口(含全 5 个 jump 方法)。
  jumpTodoMain / jumpSportDetail 与 TodoIosPlatform / SportIosPlatform 行为一致,
  因 discover 模块只依赖 todo.api / sport.api 而无法跨模块复用那两个接口,此处
  重复声明;IOSKmpInterfaceLink 中靠 Kotlin 多接口同名同签名方法的合并 override
  共享单一实现,转发到 IOSKmpInterface 上已有的 jumpTodoMain / jumpSportDetail。
- PlatformDiscoverFunctions.ios.kt 5 个 click override 通过桥实现缺失时降级到
  super(基类 toast 提示),避免崩溃。
- IOSKmpInterface 新增 jumpWeDate / jumpSchoolCalendar / jumpTestArrange 三个方法;
  IOSKmpInterfaceLink 加 @ImplProvider(DiscoverFunctionsIosPlatform::class) 适配。
- KmpInterfaceImpl.swift 实现三个 push(hidesBottomBarWhenPushed = true)。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
CMP 主页 + Step 1~2.5 的跳转桥已经接管 iOS 端发现 / 邮乐园 / 我的三 tab 的全部
入口与跳转,这里把旧的 iOS 入口代码删干净。

删除文件(23 个,-2743 行):

- TabBar/:TabBar.swift / TabBarHeaderView.swift / TabBarPresentationViewController.swift
  / TabBarController.swift / UITabBarItem+TabBar.swift
  (CustomNavigationController.swift 保留:AppDelegate 用它包 CMP rootVC,
   保留位置先在 TabBar/ 不动,后续清理 TabBar/ 空目录时再挪 Common/)
- Center/Carnie/:RYCarnieViewController.swift / RYCarnieHeaderView.swift / RYCarnieEntryView.swift
  (PersonModel.swift 保留:被 UpdatePersonModelTool / RYLoginVC / Common/UserModel 跨模块用)
- MineMainPage/:Controller/MineViewController.{h,m} + View/Mine{TopBlurView,SignView,MSSEnterBtn,TableViewCell}.{h,m}
  + Model/MineUserInfoModel.{h,m}
  (PersonalMainPage/ 子树保留:EditMyInfoVC 等还没 cmp 化;MineMainPage/Source/MineMainPageHeader.h
   保留:纯 API 宏,被 EditMyInfoModel + Marco 用)
- Discover_MainPage/Discover_SportAttendanceForMainPage/Alert/:SAAlertController.swift /
  NoticeItem.swift / NoticeView.swift
  (Step 3 推过来的 —— 它们被 TabBarController.showSANotice 用,跟 TabBar 一起删才不悬空。
   SportAttendanceForMainPage/ 剩下的 Controller/PopUpController/View/ 留到 Step 3 一起处理)

代码改动:

- IOSKmpInterface / IOSHomeViewPager 删除 createTabBarController():原来 Swift 端
  return TabBarController(),删 TabBar 后 Swift 实现无处可指;扫了一遍这个方法
  也根本没有任何业务调用方。
- IOSKmpInterfaceLink 同步删 override。
- pro / multiplatform 两个 KmpInterfaceImpl.swift 同步删 createTabBarController 实现。
- AppDelegate 清两处 TabBarController 死注释;KmpInterfaceImpl.topNavigationController()
  里关于"iOS TabBarController 混合阶段"的过时注释 + 解 TabBar.selectedVC 那一步同步清掉
  (CMP rootVC 已由 CustomNavigationController 直接包裹,nav 在根上就能拿到)。
- EditMyInfoViewController.m 删废 import "MineViewController.h"(实际从未使用)。
- Bridging-Header.h 删 import "MineViewController.h"。
- pbxproj 清理 80 行:23 个被删文件的 PBXBuildFile / PBXFileReference / PBXGroup /
  PBXSourcesBuildPhase 引用,用 sed 按 "/* <Name>[ *]" 精确 pattern 批量清除并校验残留为 0。

跨步过渡修复:

- RYFinderHeaderView.swift#request 里 tabBarItem.needShowBadgePoint = ... 一行注释掉。
  needShowBadgePoint 是被本 commit 删掉的 UITabBarItem+TabBar.swift 扩展。
  Finder/ 目录整体属于 Step 3 即将删除范围;本 commit 仅做最小注释让工程编译通过,
  不删整行(也不动周围 message_system_user_msgHasRead 网络请求),Step 3 整个文件会删。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
CMP 主页 + Step 1~2.5 + Step 4 的跳转桥已经接管发现 tab,本次清掉 iOS 端发现 tab
入口的原生实现:

删除文件(39 个,-3344 行):

- Finder/:11 个 .swift —— 整目录删除(RYFinderViewController 入口 + Header / Banner
  / News / Tools 四块及配套 cell/model;Tools/FinderTools 这个 Resource 文本文件
  也一并删除)
- Discover/Discover_MainPage/Discover_Electric/:12 个 .h/.m —— 整目录删除
  (ElectricViewController / PickerDormitoryViewController / ElectricityView /
   ElectricFeeModel / ElectricFeeItem / PickerDormitoryModel)
- Discover/Discover_MainPage/Discover_SportAttendanceForMainPage/:剩余 6 个 .h/.m
  (DiscoverSAVC 入口 + popUpViewController 体育说明弹层 + DataContentView 三列数据视图。
   Alert/ 子目录已在 Step 4 删除)
- Discover/Discover_ToDo/FinderChild/:8 个 .swift —— 整目录删除(ToDoFinderVC + 7 个
  ToDo*ForFinder Cell)
- Discover/Source/ElectricHeader.h:电费 API 宏头,电费已 cmp 化,iOS 这边
  ElectricViewController 也删了,此头已无人真用

代码改动(3 个文件):

- Marco/CyxbsMobilePathAndKey.h 删 #import "ElectricHeader.h" 一行
- Bridging-Header.h 删 #import "ElectricViewController.h" 和
  #import "DiscoverSAVC.h" 两行
- pbxproj 清理 130 行(每个 .swift/.m 4 行、.h 2 行)+ ElectricHeader.h 2 行 +
  FinderTools Resource 4 行,共 136 行。sed 按 "/* <Name>[ *]" 精确 pattern 批量
  清除并校验残留为 0
  (pbxproj 里剩 4 行是 ElectricBill / PickerDormitoryModel 两个空 PBXGroup 节点,
   不影响编译,Xcode Project Navigator 仅显示空文件夹,留待后续清理)

剩余孤儿资源(.xcassets 里的 finder_* / carnie_* / TabBar_* / mineBackImg / 消息中心 /
邮票 / 活动中心 / 意见与反馈 / learnmore 等)不在本 commit 删除范围,对编译/功能无影响,
留待所有 Step 完成后统一清理 ipa size。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
DiscoverNavPlatform 在项目里只有 Android 端 @ImplProvider 实现,iOS 端拿到的是 null,
导致发现页消息中心 / 签到 icon / Banner / 教务在线公告点击都走 toast("暂不支持跳转")
兜底。沿用 Step 1/2/2.5 同款模式,把 5 个跳转都接通:

- launchNotification         → push MineMessageVC
- jumpCheckIn                → present 全屏 CheckInViewController
                               (对齐原 RYFinderHeaderView.attendanceBtnTouched)
- jumpJwNewsList             → toast "教务新闻功能暂时停止服务"
- jumpJwNewsItem(newId)      → 同上
                               (对齐原 FinderNewsView 显示的停服文案,
                                原 didSelectItemAt 本就是空实现)
- onBannerClick(url, keyword) → UIApplication.shared.open(url) 交给 Safari
                               (对齐原 FinderBannerView.didSelectItemAt 行为;
                                Android 端那段 TrackingUtils 埋点是 Android 专属,不带过来)

实现:

- discover iosMain 新增 DiscoverIosPlatform 接口(5 个跳转方法的能力契约)。
- 新增 @ImplProvider object DiscoverNavPlatformIosImpl : DiscoverNavPlatform,
  转发到 DiscoverIosPlatform,实现缺失时 toast 兜底(同款 Step 5 之前的设计)。
- IOSKmpInterface 加 5 个方法;IOSKmpInterfaceLink 通过
  @ImplProvider(DiscoverIosPlatform::class) 适配。
- pro/iosApp 的 KmpInterfaceImpl.swift 实现 5 个方法,同时新增 topViewController()
  工具方法(jumpCheckIn 用 present 而非 push,要顶层 VC 而非 Nav;topNavigationController
  内部改为复用它)。
- multiplatform/iosApp/iosApp/KmpInterfaceImpl.swift 是 multiplatform 独立测试 stub,
  原本从 Step 1 起就缺 jumpSportDetail / jumpTodoMain / jumpWeDate /
  jumpSchoolCalendar / jumpTestArrange 五个方法的空实现(实际未必被构建过,但理论上
  IOSKmpInterface 协议必须完整),本次一次性把 10 个新方法的空实现都补齐。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
FairgroundNavPlatform 在项目里没有任何 @ImplProvider 实现(Android 端也没有),
iOS 端拿到的是 null,邮乐园两个入口点击都走 toast("暂不支持跳转") 兜底。
沿用 Step 1/2/2.5/5 同款模式接通这两个跳转:

- jumpQaEntry         → push QAMainVC(对齐原 RYCarnieViewController.tapStatementEntry)
- jumpUfieldMainEntry → push ActivityMainViewController(对齐原 tapEventEntry)

实现:

- ufield iosMain 新增 FairgroundIosPlatform 接口(2 个跳转方法的能力契约)。
- 新增 @ImplProvider object FairgroundNavPlatformIosImpl : FairgroundNavPlatform,
  转发到 FairgroundIosPlatform,实现缺失时 toast 兜底。
- IOSKmpInterface 加 jumpQaEntry / jumpUfieldMainEntry;IOSKmpInterfaceLink 通过
  @ImplProvider(FairgroundIosPlatform::class) 适配。
- pro/iosApp 的 KmpInterfaceImpl.swift 实现两个 push(hidesBottomBarWhenPushed = true)。
  QAMainVC / ActivityMainViewController 都是 Swift 类,无需 bridging-header import。
- multiplatform/iosApp/iosApp/KmpInterfaceImpl.swift 同步加 2 个空实现。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
MineNavPlatform 在项目里没有任何 @ImplProvider 实现(Android 端也没有),
iOS 端拿到的是 null,「我的」主页所有跳转都走 toast("暂不支持跳转") 兜底。
沿用 Step 1/2/2.5/5 同款模式接通:

- launchNotification    → push MineMessageVC
                          (与 DiscoverIosPlatform.launchNotification 同名同行为,
                           IOSKmpInterfaceLink 中靠 Kotlin 多接口合并 override 共享单一实现)
- jumpStore             → push StampCenterVC
- jumpFeedbackCenter    → push FeedBackMainPageViewController
- jumpSign              → push CheckInViewController(对齐原 MineViewController.signViewClicked)
                          注意与 DiscoverIosPlatform.jumpCheckIn 不同:
                          原版我的页是 push、发现页 attendanceBtnTouched 是 present 全屏 modal
- jumpSetting           → push MineSettingViewController
- jumpActivityCenter    → push ActivityCenterVC

unreadCount: StateFlow<Int> 是 MineNavPlatform 上唯一非方法成员,iOS 端返回
MutableStateFlow(0) 兜底——红点 / 未读数功能在 iOS 端是有意省略的(iOS 旧版从未
对齐 Android 的 INotificationService 红点逻辑,与 feedback-skill-capture-nudges
memory 中"红点是故意移除的"决策一致)。

实现:

- mine iosMain 新增 MineIosPlatform 接口(6 个跳转方法的能力契约)。
- 新增 @ImplProvider object MineNavPlatformIosImpl : MineNavPlatform,转发到
  MineIosPlatform,实现缺失时 toast 兜底。unreadCount 直接持有 MutableStateFlow(0)。
- IOSKmpInterface 加 5 个方法(jumpStore / jumpFeedbackCenter / jumpSign /
  jumpSetting / jumpActivityCenter;launchNotification 在 Step 5 加发现页时已存在)。
  IOSKmpInterfaceLink 通过 @ImplProvider(MineIosPlatform::class) 适配。
- pro/iosApp 的 KmpInterfaceImpl.swift 实现 5 个 push(hidesBottomBarWhenPushed = true)。
- multiplatform/iosApp/iosApp/KmpInterfaceImpl.swift 同步加 5 个空实现。
- Bridging-Header.h 加 3 个 OC 类 import:StampCenterVC.h /
  FeedBackMainPageViewController.h / MineSettingViewController.h。
  (ActivityCenterVC / CheckInViewController / MineMessageVC 之前已暴露)

已知遗留(不在本 commit 范围内):StampCenterVC / ActivityCenterVC push 进去后
无法用左边缘右滑返回——它们内部的 UICollectionView / JXSegmentedListContainerView
panGesture 跟 interactivePopGestureRecognizer 竞争时赢得手势。QAMainVC 用
contentPanGesture.require(toFail: popGesture) 解决了同款问题,这俩 VC 没加。
这是 iOS 原版线上已有问题(原版 TabBarController.createVC 用的也是同款
CustomNavigationController),跟本次 cmp 迁移无关,不在本次修复范围。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
CMP 端 cyxbs-pages/mine/about/AboutNavEntry 已完整覆盖核心功能(版本更新 /
版本信息 / 产品官网 / 分享 / 用户协议 / 隐私政策 / ICP 备案),且原 iOS 里
LearnMoreViewController 的入口在 MineAboutContentView 中已被注释,
IntroductionController 是已废弃的功能介绍页,均无需移植。
CMP 端 cyxbs-pages/mine/edit/EditInfoNavEntry 已完整覆盖 PersonalMainPage
的 EditMyInformation:头像 / 昵称 / 性别 / 生日 / 个人简介。

附带处理:
- MineMainPage/ 整目录删除,含 PMPBasic*/PMPTools/SQLCodeCreater/Source 等
  PersonalMainPage 内部专用工具类(已逐个确认无外部引用)。
- MineMainPageHeader.h 内 8 个 API 宏,除 PersonInfo/UploadAvatar 用于
  EditMyInfoModel 外,其余在 Step 4 删 OldMineMainPage 后已无引用,
  从 CyxbsMobilePathAndKey.h 一并移除 import。
- StampCenterVC.jumpToProfile 原本 present EditMyInfoViewController,
  改为 toast 提示"请到「我的」-「编辑资料」中完善信息"。StampCenter 自身
  还是 iOS 原生页,待整体迁 CMP 后再统一接入 EditInfoNavArgument。
EmptyClass:CMP 端 cyxbs-pages/emptyroom 已完整覆盖(EmptyRoomNavEntry/
ViewModel/ApiService/Bean),iOS 端 EmptyClass 所有类只在 Discover_EmptyClass
内部互引,无外部依赖,包含 EmptyClassUnavailableViewController(对应 CMP
EmptyRoomViewModel 错误态展示)一并清理。

Discover_ToolPage:FinderToolViewController 是 2019 年老 Discover tab 的
「工具页面」网格视图,Step 3 删 Finder/ 时漏删但已无入口可达,且引用了
EmptyClass / ScheduleInquiry / SchoolBus / Map 等 4 个后续要删的目标,
顺手清理避免重复打补丁。
FindScheduleInquiry:CMP 端 cyxbs-pages/course/find 已完整覆盖
(FindCourseNavEntry/Screen/ViewModel + SearchResultList/LinkCard/IdleContent
+ FindStuBean/FindStuHistoryEntity + FindApiService + FindHistoryRepository),
覆盖按学号/姓名搜索课表 + 历史 + 同学消歧的完整流程。

附带处理(死代码):
- Discover_WeDate/Controller/WeDateViewController.m(Stove 2020)是没课约
  最初的单次拼人查空闲版本,2023 年被 coin 重写成 Swift 的 WeDateVC(群组化
  管理)后已无人 push(KmpInterface 和 StampCenter 都是 push Swift 版)。
- Discover_WeDate/View/{ChoosePeopleListView,PeopleListTableViewCell} 仅被
  上述死 ObjC 版引用,Swift 新版用自己的 UI 组件。
- Discover_FindScheduleInquiry/model/{ClassmatesList,ClassmateItem} 同样
  只被死 ObjC WeDateVC 引用(Swift 新版无依赖),可一并清理。
CMP 端 cyxbs-pages/schoolcar 比 iOS 原版功能更全:
- 自实现 mapcompose 模块(地图/相机/手势/标记),不依赖第三方
- 完整 UI:MapLayer / SchoolCarMap / MarkerIcon / CarInfoButtonSheet /
  LineSelector / RouteList / DownLoadingDialog / SchoolCarDetailCompose
- 完整 Bean / Repository / Api / Utils(Md5/MapInfo/ImageFile/String)

iOS 端 SchoolBus 33 文件全部内部互引,0 外部依赖。SchoolBusHeader.h
(Discover_POST_schoolBus_API 等校车 API 宏)仅在 SchoolBus 内部用,
一并清理。

顺手修旧 bug:Bridging-Header.h:228 有个硬编码老 URL 的重复
Discover_POST_schoolBus_API 宏(Swift 端 0 引用),删除。
校车 iOS 原生代码(含所有 MAMapKit/AMapLocation 使用点)已在前一 commit
随 Discover_SchoolBus 删除,全工程对高德 SDK 0 源码引用,可以拿掉 pod。

Podfile:
- 删 pod 'AMapLocation-NO-IDFA' / 'AMap3DMap-NO-IDFA'
- post_install 的 fat framework arm64-sim patch 数组去掉 3 个 AMap 三元组,
  只剩 Bugly(Bugly 仍在用,patch 逻辑保留)
- 注释里 "AMap / Bugly" → "Bugly"

pod install 自动副作用:
- Pods/AMap{3DMap,Foundation,Location}-NO-IDFA 目录删除
- CyxbsMobile2019_iOS.xcodeproj 去掉 [CP] Copy Pods Resources build phase
  (AMap 是唯一带 bundle resource 的 pod,没有别的 pod 用到这个阶段)

SchoolCarViewModel.ios.kt:补一段 KDoc 说明未来要给 iOS 加校车定位的方案。
不要把高德 pod 加回来,按以下方案走:
  1. CoreLocation 取 WGS-84 经纬度
  2. 客户端做 WGS-84 → GCJ-02 转换(公开算法,约 50 行)
  3. 转换后喂给 commonMain 的 GeoLocation.toUserLocation 线性公式
  4. 角度用 CLHeading 或 CoreMotion(Android 端罗盘本来也是系统传感器)
  5. 1500 米外自动关定位的距离判断复用 commonMain 已有的 Haversine 实现
CMP 端 cyxbs-pages/map 已覆盖地图核心能力:MapNavEntry / MapSheetNavEntry /
MapShowPictureNavEntry,以及搜索、地点详情、图片预览、收藏/历史、上传图片、
地图更新、下载进度和失败弹窗。

iOS 原生 CQUPTMap* 系列已无活跃引用:
- Discover tab 已迁 CMP,入口由 DiscoverFunctions.clickMap 走 MapNavArgument
- 旧 iOS 课表也已迁 CMP,旧课表里的“点教室跳地图”先禁用,等旧课表整体删除时
  一并移除;CMP 课表后续如需跳地图应直接走 MapNavArgument(placeSearch = ...)

附带处理:
- FYHCycleLabel 不是地图业务,只是滚动 label widget,被旧课表 FakeTabBar /
  ClassScheduleTabBarView 仍引用,因此从 Discover_Map/View 移到
  Tools/Encapsulation/TextCycleView 保留。
- 删除 CyxbsMobileLibraryHeader / Bridging-Header 里的 CQUPTMapPlaceRect /
  CQUPTMapViewController 全局 import。
CMP 端 cyxbs-pages/food 已覆盖核心能力:FoodNavEntry / FoodViewModel /
FoodRepository / FoodApiService / FoodDialog / TagSelector,以及 FoodMain /
Refresh / Result / Praise 等 bean。

iOS 原生 Food 22 文件已无活跃引用。唯一外部入口来自仍未迁 CMP 的
StampCenterVC.jumpToFood;这里改为 toast 提示用户从「邮乐园」进入美食,
与前面 jumpToProfile 的过渡处理一致,待 StampCenter 整体迁 CMP 后再统一接入。

FoodHeader.h 仅被 Food 模块内部使用,一并删除。
主页课表已迁移到 CMP(cyxbs-pages/course):MobileHomePage.ios.kt 直接用
CourseBottomSheetViewModel 默认展开课表,CourseNavEntry 提供课表单页。
iOS 端原 Curriculum/ 下的 Swift 壳(Details、Edit、Schedule/View、Schedule/ViewController)
已无任何活跃入口,删除。

保留以下文件继续供 CyxbsWidgetExtension 使用(Widget 的 ScheduleProvider 仍直接
请求课表并以旧 ScheduleModel Codable 写入 App Group 缓存):
- Curriculum/Schedule/Model/{ScheduleModel,CurriculumModel,SearchStudentModel}.swift
- Curriculum/Schedule/Filter/{ScheduleCalModel,ScheduleCalModel+EX,ScheduleDrawType,RYScheduleMaping,ScheduleDataFetch}.swift

抽出公共扩展:
- Tools/Encapsulation/UICollectionView+ElementKindSection.swift
  原本定义在 Curriculum/Schedule/ViewController/RYScheduleCollectionViewLayout.swift
  顶部,被 WeDate 的 ScheduleCollectionViewLayout / ScheduleFact 隐式依赖(项目自定义
  的 supplementary kind 命名空间,非系统 UIKit 类型)。删旧课表会把这个全局扩展一起
  抽掉,所以这里独立成文件,挂到 app target + WidgetExtension target。
- 同时把 Discover_WeDate/CourseSchedule/ScheduleFact.swift 里原本走旧 ry_layout
  全局计算属性的写法,就地改为 as? ScheduleCollectionViewLayout,不再依赖跨模块的
  隐式扩展属性。

下一步:在 CMP iOS 端实现 LessonRepository 课表请求成功后写一份 App Group
schedule/{stuNum} 缓存供 Widget 兜底,逐步把 Widget 数据源从旧 ScheduleModel
转为 CMP 来源。
主页课表已迁 CMP,但 CyxbsWidgetExtension 课表小组件仍读取 App Group 下旧
ScheduleModel Codable 缓存(路径 <AppGroup>/schedule/{stuNum})。新增一条
单向桥让 CMP 写盘后顺手把同一份数据同步给 Widget,Widget 端 0 改动。

cyxbs-pages/course commonMain:
- 新增 service/CourseIosPlatform 接口,仅 iOS 端实现;
  方法 onLessonUpdated(stuNum, nowWeek, stuLessonBeanJson)
- LessonRepository.requestLesson 在保存 AccountSettings 之后调用
  CourseIosPlatform::class.implOrNull()?.onLessonUpdated(...)
  传刚序列化好的 StuLessonBean JSON;Android 端 implOrNull 返回 null,
  不受影响。

cyxbs-applications/multiplatform iosMain:
- IOSKmpInterface 加 onLessonUpdated
- IOSKmpInterfaceLink 同时实现 CourseIosPlatform 并 @ImplProvider 注册

cyxbs-applications/pro/iosApp KmpInterfaceImpl.swift:
- 实现 onLessonUpdated:用 SwiftyJSON 解析 StuLessonBean JSON,按旧
  CurriculumModel(json:) 字段映射(hash_day / begin_lesson / week / course /
  classroom / type / course_num / rawWeek / teacher,与 StuLessonBean.StuLesson
  的 @SerialName 完全一致,零适配)重组旧 ScheduleModel;
- nowWeek 触发 didSet 复用旧逻辑算出学期 start 写入 UserModel.default.start;
- student 字段缺失时回读 .searchStudent(sno:) 老缓存;
- 最终用 CacheManager.cache(in: .schedule(sno:)) 写入 App Group 文件缓存,
  Widget 下次刷新即可命中新数据。
- IOSApp.kt: onLogout() 调用 IAccountEditService.onLogout() 后通过
  LoginNavArgument.navigate(HomeNavArgument(), clearStack = true) 跳转登录页
- LoginServiceImpl.ios.kt: jumpToLoginPage() 实现 CMP 导航跳转到登录页
- KmpInterfaceImpl.swift: 补全 onLessonUpdated 协议方法空实现
- 登录成功后同步 iOS 原生数据:通过 IAccountService.state 监听登录事件,
  通知 Swift 侧同步待办、用户信息、Person 模型、检查邮箱绑定
- 实现忘记密码功能:弹出输入框 → 查询绑定状态 → 跳转 ForgotViewController
- 实现用户协议/隐私政策链接点击:Safari 打开协议 URL
- 实现不同意用户协议退出 app:iOS 调用 exit(0)
- 新增 LoginIosPlatform 接口,遵循项目现有 KtProvider 桥接模式
- 清理 iOS 平台层已失效的导航接口,恢复 CMP Framework 编译
- 将版本缓存迁移提前到网络初始化之前,避免全新安装时 baseURL 被清空
- 统一新旧网络栈的环境切换,并为 Objective-C 公共请求入口增加非法 URL 防崩保护
- 已通过真机 Debug 构建、卸载重装及登录进主页验证,待办与用户信息接口均请求成功
- 合并 develop 的新版 schedule 与旧 todo 模块移除
- 将 iOS 发现页邮子清单入口切换到 CMP 日程主页
- 移除旧 ToDoVC 跳转桥接及 CMP 登录后的原生待办重复同步
- 解决登录 ViewModel、Compose Resources 构建脚本与旧 iOS todo 文件冲突
- 已通过 KMP iOS 编译、schedule iOS 测试及不签名真机 Xcode 构建
- 删除已由 schedule CMP 页面替代的原生清单源码与专用图片资源
- 清理 Xcode 工程引用、桥接头和旧待办接口封装
- 移除原生登录、退出时的旧 TodoSyncTool 同步调用
- 保留活动中心仍在使用的添加待办能力,并继续由 CMP 迁移旧服务端数据
- 已通过不签名 iOS 真机目标全工程构建
- 合并 develop 最新日程能力,包含跨模块 Compose ABI 修复与外部日程创建接口
- 增加 iOS 到 Schedule 的 KMP 桥接,并按 Android 规则映射活动截止时间、提醒和分类
- 活动详情成功创建本地日程后回写活动中心状态,回写失败不撤销已创建日程
- 验证:真机 Debug 全量 Xcode 构建通过,Kotlin/Native 导出与 Swift 调用签名兼容
- BottomSheet 首次展开前等待内容完成有效高度测量,避免以 0 作为动画目标
- 兼容 iOS CMP Dialog 先执行展开、后触发布局测量的平台时序,同时保持协程可取消
- 清理定位问题使用的 CourseSheetTrace 临时日志,不包含个人签名工程配置
- 验证 cyxbs-components:view 的 Android Main 与 iOS Arm64 编译通过
- 将 Schedule Room 数据库迁移到 Library/Application Support/schedule 标准持久化目录
- 停止读取旧 schedule-room3-production.db,避免旧版同版本结构触发 Room identity 校验失败
- 打开数据库前检查并创建父目录,兼容生产路径与测试注入路径
- 已通过 iOS 真机构建、冷启动、远端同步及本地修改写入验证
- 在 ComposeUIViewController 根入口统一消费超过 12dp 的底部导航栏安全区,避免页面产生过大留白。
- 保留 WindowInsets.navigationBars 原始值,兼容课表等直接读取系统 inset 参与布局计算的组件。
- 将处理放在 AppTheme 外层,避免页面重复嵌套主题时重复消费 navigation bar padding。
- 验证:IDE 诊断无错误,compileKotlinIosArm64 与 Xcode 真机构建均通过。
@985892345
985892345 merged commit 5184d9e into develop Sep 6, 2026
2 checks passed
@985892345
985892345 deleted the guoxiangrui/feature/ios_cmp branch September 6, 2026 17:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant