# 需求进度 ## 当前总目标 - 控制当前 Flutter Android 发包体积,持续定位冗余组件、超大资源和不合理构建配置,并把每一步处理结果落盘记录。 ## 本轮启动优化(非网络) - 已移除启动页固定 `6` 秒倒计时,改为最短约 `900ms` 展示后继续路由判断,避免人为等待直接拉长入 app 时间。 - 已将 Firebase / Crashlytics 从 `runApp` 前阻塞初始化改为首帧后后台预热,并补充“未就绪时仅本地打印”的异常兜底,减少首屏前平台初始化阻塞。 - 已将 `SocialChatAuthenticationManager`、`SocialChatUserProfileManager` 改为按需创建,避免 splash 阶段就提前触发 Google Sign-In / Firebase 会话检查。 - 已将 deep link、设备信息、缓存目录创建等非首帧必需动作延后到首帧后执行,降低首屏竞争。 - 已优化本地语言初始化:启动时不再重复写入 `SharedPreferences` 并触发一次无意义的 `notifyListeners`。 - 已优化首页容器与 Home 首屏:去掉首次进入时“先 loading 再建 tab”的本地跳变,并将首页 page 列表、底部导航项从 `build` 阶段的重复重建改为复用。 - 本轮按需求暂未处理网络链路上的启动等待,例如审核态检查或远端启动页配置请求。 ## 已完成模块 - 已修复礼物页幸运礼物发送链路:当前 `gift_page` 会按礼物类型分流,普通礼物继续走 `/gift/batch`,`LUCKY_GIFT/LUCK/MAGIC` 改走已存在的 `/gift/give/lucky-gift`;幸运/魔法礼物成功后不再本地伪造普通 `GIFT` 消息,而是改发房间内 `LUCK_GIFT_ANIM_OTHER` 动画消息,避免和后端幸运礼物开奖/补发逻辑打架;同时送礼失败已补用户提示,且对 `standardId` 缺失的幸运礼物增加了前置拦截,避免继续点发送却只有日志没有反馈。 - 已继续补齐幸运礼物前端可见反馈:根据真机日志确认 `giveLuckyGift` 和腾讯 IM 房间消息发送都已成功,当前问题收敛为发送端没有本地回显、且 `LUCK_GIFT_ANIM_OTHER` 收到后未真正接入房间礼物动画;现已在发送成功后先本地触发一轮房间礼物上飘反馈,并把收到的 `LUCK_GIFT_ANIM_OTHER` 直接接入现有房间礼物动画 listener,确保发送端和房间内其它端都能看到即时反应。排障期间临时加过的发送并发锁已在后续需求确认后撤回,不再限制幸运礼物连点。 - 已按最新确认调整幸运礼物点击策略:撤回前一轮为排障临时加上的发送并发锁,恢复幸运礼物可连续点击;当前连点时每次请求仍走 `/gift/give/lucky-gift`,并继续通过本地回显 + `LUCK_GIFT_ANIM_OTHER` 接入现有房间礼物动画 listener 的方式提供与普通礼物一致的即时播报体验。 - 已继续优化房间礼物播报 UI:礼物上飘条目高度与内部约束已重新收紧,修复底部 `bottom overflow`;同时为幸运礼物新增 10/20/50/100/200/300 连击特殊样式,这些档位的连击数字会以更大的“霸气金”渐变字显示,普通礼物与非里程碑连击保持原样式。 - 已修复 `Me -> Friends/Fans 列表 -> 他人主页 -> 返回 Me` 后个人资料串号的问题:`MePage2` 现只读取当前登录用户资料,`SocialChatUserProfileManager.userProfile` 继续只承载“当前查看中的详情页用户”,同时移除了 `syncCurrentUserProfile()` 对详情态的覆盖,避免查看他人资料后把 `Me` 页错误渲染成对方信息。 - 已按本轮动效替换需求完成首页底部 tab 动效接入,并同步将本轮新增本地 `.svga` 资源统一改成项目命名风格:当前 `Home / Explore / Message / Me` 已分别使用 `sc_icon_home_anim.svga / sc_icon_explore_anim.svga / sc_icon_message_anim.svga / sc_icon_me_anim.svga`,并继续保留原有 png 作为失败兜底;后续新增本地动效资源默认也按 `sc_icon_*_anim` 规则命名。 - 已将语言房右侧 `game` 悬浮入口从 emoji 占位替换为本地动效资源,并按最新反馈移除外层圆形 `container`:当前直接使用 `sc_icon_room_game_entry_anim.svga` 本体作为入口展示,尺寸与原入口占位一致;若 SVGA 加载失败,会自动回退到项目原有 `sc_icon_botton_game.png`。 - 已按最新反馈撤回语言房房间麦位声波的 SVGA 替换,当前已恢复为项目原有展示:VIP3/4/5/6 继续使用原先的 `webp` 声波资源,普通麦位回到原来的纯色圆形扩散效果;说话触发阈值与错峰扩散逻辑保持不变。 - 已修复语言房顶部左侧房间榜单入口出现 `right overflowed` 的问题:当前贡献值区域已改为约束宽度 + 自适应缩放文本,不再因为积分位数变长把右箭头顶出容器。 - 已根据最新确认回退首页 Party 区的 `recommend_rank_top` 三个素材替换:财富榜、房间榜、魅力榜前三头像现已恢复为原先版本,不再在该位置叠加 `recommend_rank_top` 动态头像框;相关素材仍保留在工程内并已按规范重命名,后续待确认真正使用位置。 - 已新增通用本地 SVGA 资源组件 `lib/ui_kit/widgets/svga/sc_svga_asset_widget.dart`,用于统一处理本地 assets 解码、内存缓存、单次播放/循环播放和失败兜底;当前首页底部 tab 和语言房 game 按钮已复用这套实现,便于后续继续接入其它本地动效资源。 - 已按最新语言房底部栏视觉需求完成 UI 重构:底部 5 个入口现改为同一水平基线布局,移除礼物按钮原先的中间悬浮 `Stack` 结构,并按最新顺序调整为“输入入口、礼物、麦克风、菜单、消息”;其中消息入口已移动到最右侧,且在麦克风隐藏时,礼物、菜单、消息 3 个入口会自动向右收拢成一组,避免中间留空。 - 已将语言房左侧输入入口改为独立组件:当前已撤回自绘聊天气泡图标方案,直接恢复使用项目原有的 `sc_images/room/icon_room_input_t.png` 资源作为左侧输入 icon,并继续放入约三分之一屏宽的圆角矩形中,右侧保留多语言问候文案 `roomBottomGreeting`,避免继续在自绘气泡尾巴形态上反复调整。 - 已将语言房礼物入口拆成独立组件:礼物图标缩小后当前尺寸只略大于右侧 3 个圆按钮,并保留常驻轻量摇晃动画;根据最新反馈,当前已移除礼物按钮的粒子特效,并进一步去掉礼物入口外层 `container`,直接使用与原先按钮壳同尺寸的礼物图片本体作为可点击 UI,避免额外底壳干扰观感。 - 已统一语言房其余四个入口的按钮壳样式:输入入口、消息、菜单、麦克风现统一使用淡色半透明背景 container,消息红点计数、菜单弹窗、消息跳转和麦克风开关等原有功能逻辑保持不变,本轮只调整 UI 展示与布局层。 - 已继续强化语言房右侧消息与麦克风入口的识别度:消息图标已替换为项目内更明显的信封样式资源 `sc_icon_send_user_message.png`,麦克风图标则在不改变按钮壳尺寸的前提下放大到更接近其它入口的可视大小,减少“图标偏小、不够醒目”的问题。 - 已按最新交互要求调整麦克风隐藏态布局:当第 4 个图标(麦克风)可见时,底部栏保持当前 5 个槽位的位置不变;当麦克风隐藏时,不再为其保留空槽位,礼物、消息、菜单 3 个入口会自动向右收拢成一组,避免右侧中间出现空位。 - 已排查语言房“双设备、不同账号进入同一房间,上麦后无声”的直接原因:当前 RTC 进房时统一以 Agora `Audience` 身份加入频道,见 `lib/services/audio/rtc_manager.dart` 中 `joinChannel()` 的 `clientRoleType: clientRoleAudience`;而本地麦克风开关 `isMic` 默认值为 `true`(当前语义实际是“闭麦”),上麦 `shangMai()` 后只有在 `!isMic` 时才会切到 `Broadcaster` 并取消本地静音,所以“只上麦、不点底部麦克风按钮”时不会发声。 - 已补充语言房当前真实交互结论:现有实现里“上麦”和“开麦”是两个动作。用户点空麦位后只是占麦;还需要再点击底部麦克风按钮,触发 `lib/ui_kit/widgets/room/room_bottom_widget.dart` 中的角色切换,才能真正开始向房间发送音频。 - 已同步补充该需求的后续决策点:如果产品预期是“上麦即能说话”,则需要单独改需求并调整实现为“上麦成功后自动切 `Broadcaster` 且自动开麦”;如果继续保留当前双步骤交互,则至少要补一条明确提示文案/引导,并把“双设备不同账号同房,上麦后需手动开麦才能互听”加入验收用例,避免测试误判为 RTC 故障。 - 已重新收敛语言房无声修复方案:撤回上一轮会影响进房的较大改动后,当前改为只做最小行为修补,不触碰进房和 token/join 链路;已在“底部麦克风点开”和“麦位解除静音且本人处于开麦态”两条路径上补齐 `muteLocalAudioStream(false)`,修正 UI 显示已开麦但 Agora 本地音频流仍保持静音的问题。 - 已按测试收尾要求移除语言房 RTC 诊断面板:该组件仅用于当前无声问题的真机排查,现已从房间页和相关临时诊断代码中整体删除,不作为正式功能保留。 - 已为语言房页面补充右下方 `game` 悬浮入口:入口位于聊天区右下侧、距右侧约 `15.w`、位于底部操作栏上方约 `100.w`,当前先使用代码绘制的 `🎮` 占位图标,并已在实现处标注后续替换为正式 UI 图片资源。 - 已新增语言房游戏底部弹窗:点击 `game` 入口后会从底部弹出约三分之一屏高的面板,采用房间页现有半透明磨砂风格,便于后续继续沿用当前视觉体系。 - 已补齐语言房游戏列表占位结构:弹窗内部先用静态游戏数据驱动,并按“`ListView` 可上下滑动 + 每行 `5` 个图标位”的方式实现,后续只需替换入口图、列表图标和真实接口数据即可继续开发。 - 已排查语言房游戏 H5 无法正常加载的直接原因:当前房内 BAISHUN 游戏页把“加载完成”几乎完全绑定在 H5 主动回调 `gameLoaded` 上,同时 `window.NativeBridge` 又是在 WebView `onPageFinished` 后才注入;真实 H5 若在更早的启动阶段就尝试读取桥接配置或判定 NativeBridge 是否存在,就会错过这次注入,表现为页面一直停留在 `Waiting for gameLoaded...`,因此问题核心更接近“App 与 H5 的桥接初始化时序不稳 + 加载态过度依赖 H5 回调”,而不只是单纯的页面 URL 无法访问。 - 已对语言房游戏 H5 链路补齐客户端兜底:房内游戏页现在会在页面启动阶段提前并重复尝试注入 BAISHUN bridge,不再只等首个 `onPageFinished`;同时加载遮罩已增加超时收口,不会因为 H5 没有及时回调 `gameLoaded` 就无限卡住。桥接侧也已补充 `getConfigSync`、全局配置缓存和 `baishunBridgeReady/baishunConfig` 事件分发,降低 H5 初始化阶段拿不到配置的概率,便于继续和 H5 联调确认其最终采用的接入方式。 - 已按《BAISHUN 游戏对接文档 1.3.2》重新核对客户端桥接协议:文档里的核心要求并不只是 `NativeBridge` 存在,还包括 `getConfig` 入参携带 `jsCallback`、客户端回调指定 JS 函数、以及 Flutter 章节单独列出的 `getConfig / destroy / gameRecharge / gameLoaded` 四个通道名;当前房内游戏桥接已补充这些文档协议的兼容层,便于直接验证真实 H5 当前到底走的是哪一条调用路径。 - 已新增 BAISHUN 临时调试面板,并封装为独立组件 `lib/modules/room_game/views/baishun_debug_panel.dart`:面板会展示 `entryUrl`、桥接注入次数、最近一次 `jsCallback`、最后一条桥接消息及日志列表,并提供 `Reload / Inject / ReplayConfig / Wallet / ClearLogs` 操作,专门用于这次房内游戏 H5 真机联调;该面板不是正式功能,后续调试完成后需要整块删除。 - 已根据 BAISHUN 文档中“`code` 为一次性参数且唯一”的约束继续收紧客户端下发策略:当前房内游戏页在 bootstrap / `pageFinished` 阶段只注入桥接方法,不再主动把完整配置反复推给 H5;真正含 `code` 的配置现在只会在 H5 明确调用 `getConfig` 后回一次,避免因为重复下发一次性 `code` 导致 BAISHUN 后续拉取 `sstoken / user_info` 失败。调试面板也已补充 `ConfigSend` 计数和最近一次配置摘要,便于真机确认是否存在重复下发。 - 已继续增强 BAISHUN 临时调试面板的排障能力:当前已在 H5 侧临时注入 `fetch / XMLHttpRequest / window.onerror / unhandledrejection` 日志回传,相关失败请求、状态码和响应片段会直接显示在 `Recent Logs`,专门用于继续定位当前 `get user info failed` 是否发生在百顺后续拉取 `sstoken / user_info` 的网络链路;这同样只是联调用临时能力,后续调试完成后需要删除。 - 已根据《BAISHUN 游戏对接文档 1.3.2》补齐 `language` 字段兼容:文档表 3 要求传给游戏的语言值是字符串数字枚举(如英文 `2`、阿语 `7`、土耳其语 `10`),而当前客户端真实下发值曾是 `en`;现已在房内游戏页发送配置前统一转换为 BAISHUN 约定值,并把 `raw -> normalized` 结果记录进调试日志,便于继续确认 `get user info failed` 是否由协议字段不匹配导致。 - 已根据最新真机日志继续收敛 BAISHUN 问题边界:当前调试面板已确认 `ConfigSend=1`、`language=2(raw=en)`、`getConfig_1_complete` 与 `gameLoaded_1_complete` 都已正常走通,说明 Flutter 侧桥接、语言字段和“一次性 code 重复下发”目前都不是主要矛盾;同时 `Recent Logs` 里未出现浏览器侧 `fetch/XHR` 失败,但仍出现 `get user info failed` 弹窗与 H5 内部 `InvalidStateError`,因此当前更倾向于 BAISHUN 服务端继续调用商户侧 `/v1/api/get_sstoken` / `/v1/api/get_user_info` 的链路失败,或其返回内容不符合文档要求,H5 页面里的报错更像后续症状而非首因。 - 已继续增强 BAISHUN 临时调试能力用于下一轮真机排障:当前除了原有 `fetch/XHR/window.onerror/unhandledrejection` 外,还会额外回传 H5 的 `console.log/info/warn/error` 与资源加载失败信息,并把本地日志保留条数放宽到 `80` 条、面板日志区适当加高;这些都只服务当前联调,不属于正式功能,问题定位完成后需要一并删除。 - 已通过 2026-04-16 真机最新控制台日志拿到更直接的证据:H5 侧明确打印了 `{"msgId":"Connect","errCode":1015,"errMsg":"1015-SSToken接口错误","data":null}`,并伴随 `WebSocket Error / WebSocket Close / Reconnect` 日志,说明当前问题已可进一步收敛为百顺游戏在建立长连接前获取 `SSToken` 失败;这表明主要矛盾已经不在 Flutter 容器桥接,而在百顺服务端访问商户侧 `/v1/api/get_sstoken` 的链路、该接口的业务结果、或其返回格式与文档约定不一致。 - 已继续定位“游戏画面可见但触摸无响应”的 Flutter 侧原因:当前实现此前一直把 BAISHUN H5 页面放在 `showGeneralDialog` 底部弹层里承载,同时 App 启动时又全局锁定了 `portraitUp`;对于 `FishingStar` 这类横版游戏,这会叠加出“平台视图在弹层容器中的命中不稳定 + iPhone 端实际不支持横屏”的问题。现已改为用独立路由承载 BAISHUN 游戏页,并按启动数据里的 `orientation` 动态切换横竖屏;同时 iOS `Info.plist` 已补充手机横屏支持,便于继续验证横版游戏触摸是否恢复。上述调整仍属于本轮 BAISHUN 联调修正,不是新的正式产品交互。 - 已按最新联调反馈回撤 BAISHUN 页面的横屏适配:当前后续不会接横屏游戏,因此已去掉游戏页按 `orientation` 切换系统方向的逻辑,并撤回 iPhone 端新增的横屏声明,只保留独立路由承载 BAISHUN 页面这一项 Flutter 容器修正。同时已继续增强临时调试,在 H5 侧补充 `pointerdown / touchstart / mousedown / click` 事件回传,用于下一轮真机直接确认“点击是否真的进到了 H5 DOM”;这些输入事件日志依旧只用于本轮排障,后续需要删除。 - 已按当前收尾需求移除 BAISHUN 临时调试面板:`BS DEBUG` 组件和相关调试入口现已从游戏页删除,不再作为正式功能保留;同时游戏页展示高度已恢复为接近半屏的底部弹出样式,回到最初设定的房内游戏视觉形态。 - 已继续微调 BAISHUN 游戏页高度:由于真实 H5 内容本身就是接近半屏,且顶部还需要预留拖拽条和标题栏空间,当前底部游戏页容器高度已从上一版的 `0.56` 屏高上调到 `0.62`,避免视觉上看起来比预期半屏更矮。 - 创建并持续维护进度跟踪文件。 - 已继续排查语言房 gift 动画链路:确认送礼后会同时走本地房间消息、滚屏礼物条和大额礼物全局飘屏三条路径,并修复动画管理器在控制器尚未绑定完成时提前消费队列导致后续动画不再播放的问题。 - 已定位并修复语言房礼物飘屏资源引用错误:代码里误写 `sc_icon_gift_flosc_bg` / `sc_icon_luck_gift_flosc_*`,实际资源文件名为 `float`,导致点击送礼后飘屏背景图加载失败,相关动画无法正常显示。 - 已继续定位语言房礼物特效不播放的根因:后端礼物配置返回的特效标记为 `ANIMATION`,而前端历史代码只识别拼写错误的 `ANIMSCION`,导致送礼后直接跳过全屏/半屏特效播放;现已改为同时兼容两种标记。 - 已继续优化语言房礼物特效播放性能:将礼物资源预热改为“后台串行预加载 + 选中礼物高优先级预加载 + 播放阶段复用同一解码/下载任务”,避免送礼时重复下载或重复解码同一个 `.svga/.mp4`;同时为全屏播放器增加 `RepaintBoundary`,并改为按原始比例渲染、关闭越界绘制,减少整页重绘和过度放大带来的卡顿。 - 已继续优化礼物二级页首屏与翻页加载体验:礼物配置改为会话内复用,避免每次打开礼物面板都重新拉列表;首屏与翻页页卡增加整页骨架态,页面图片预热改为“当前页并发预热 + 下一页提前预热”,并增加“最短可感知骨架时长 + 最长骨架保护窗口”,避免整页骨架一闪而过;超过上限后再切换到真实卡片,并让单个礼物继续使用小 `loading` 占位补齐,整体交互对齐常见直播 app 的礼物面板体验。 - 已修复首页房间封面显示链路:兼容接口 `roomCover/cover` 双字段,并补齐编辑房间成功后的封面内存回写。 - 已继续修复房间设置保存封面后丢失的问题:房间保存接口改为兼容提交 `id/roomId` 与 `roomCover/cover`,并在保存成功后优先保留刚提交的封面、名称、公告,避免被空响应覆盖。 - 已新增按房间 ID 的本地房间资料缓存兜底:首页、我的房间、历史/关注、搜索和再次进入房间都会优先回填最近一次本地保存的封面;同时已将房间封面空态图替换为新的 `sc_no_data.png`。 - 已确认房间封面上传接口与 `PUT /room/profile` 保存接口都返回了正确图片地址,并修正首页/重进房间的取值优先级,避免被列表接口短时间返回的旧封面或无效封面重新覆盖。 - 已继续完善个人主页头像与滚动表现:顶部小头像保持纯头像,主头像恢复头像框叠加;同时将个人主页背景并入可滚动 header,修复滑动时内容与背景不同步的问题。 - 已进一步统一头像框方案:共享头像组件改为“头像居中 + 头像框包边”结构,并对这类静态头像框资源增加白底去除处理,不再简单把头像框整张盖在头像上;个人主页主头像与房间麦位头像现已同步采用这一展示方式。 - 已修复静态头像框透明区域误变黑的问题:调整头像框白底透明化公式后,进入房间时不再出现只有头像附近有颜色、其余房间背景被黑块覆盖的现象。 - 已修复个人主页首屏黑屏与内容区多余圆角问题:为个人页补充稳定的底图/底色占位,避免进入页面时先出现黑屏;同时移除资料内容区顶部多余圆角。 - 已将个人主页首屏占位升级为骨架屏:进入个人页时会先按真实版式展示头像、昵称、计数区、Tab 和资料内容的骨架块,不再先露默认背景等待约 1 秒。 - 已为首页 Party 页补齐首屏骨架屏:顶部 H5 榜单现按三列奖杯卡位展示头像/标题骨架,下方房间区改为双列房卡骨架,并采用深绿底 + 金色描边的项目内风格;同时拆分榜单与房间列表加载态,仅在“首屏无内容加载”时展示骨架,避免下拉刷新时整页闪烁。 - 已为首页 My 板块补齐首屏骨架屏:`My room` 顶部房间卡片改为独立加载态,避免首屏把“正在加载我的房间”误显示成“去创建房间”;`Recent/Followed` 两个子页也已改成同风格双列房卡骨架,进入 tab 时会先展示完整结构占位,再按真实数据切换。 - 已为 `Me` 入口下的 `Store / Bag` 页面补齐首屏骨架屏:四类 `store` 商品页和四类 `bag` 物品页在“首屏空数据加载”阶段都会先展示同风格的三列卡片骨架,不再只显示小菊花;同时已为商品/物品名称补齐宽度约束与省略号处理,避免超长文案顶出卡片。 - 已将通用图片加载占位从静态 `loading` 图片升级为代码绘制的环形转点组件:礼物二级页单卡封面、`Store / Bag` 商品图以及复用共享图片组件的网络图,在“加载中”阶段都会显示动态转圈效果;而图片失败或 `no data` 时仍保持原有占位图,不混淆加载态与空态。 - 已继续细化首页房卡体验:`My` 板块房卡骨架数量已从 `4` 个补齐到 `6` 个,与首页 Party 首屏保持一致;同时将房卡右下角原本的静态绿色“直播中”图片替换为代码驱动的三段式动态音频条,首页、我的、搜索结果和房间浮窗现都会展示跳动效果,不再依赖静态资源图;最新已把动效调整为“单周期完整峰谷 + A/B/C 错峰起伏”的连续波形,观感更接近直播音频电平。 - 已继续微调首页房卡信息密度:房卡底部房名与在线人数字号已统一调小,和动态音频条更协调;同时已移除 `My` 板块顶部 `my room` 标题及其占位,让房间卡片整体上移,对齐更紧凑。 - 已继续微调首页视觉细节:房卡底栏房名再次缩小并轻微上移,和国旗、动态音频条、人数的中线更一致;首页顶部排行骨架也已简化为“3 个圆形头像 + 1 根文本条”,更贴近真实卡片结构。 - 已补回首页 Party 顶部 banner 展示链路:顶部现优先显示原有 `explore` banner,并在该分组为空时自动兜底使用首页 `home` banner,避免整块区域消失;同时首屏 banner 空数据加载阶段已补充同风格骨架占位,不再直接塌陷为零高度。 - 已继续微调首页 Party 顶部 banner 体验:banner 与下方排行组件之间已补齐接近房卡区的纵向间距;当 banner 只有 `1` 张时,会关闭无限轮播与横向回弹,左右滑动不再弹回中间。 - 已继续收窄首页 Party 顶部 banner 骨架样式:banner 骨架现改为更干净的整块占位,不再在中间叠加长方形白条,首屏观感更接近真实 banner 的整体加载。 - 已优化语言房顶部成员入口的点击范围:右上角在线成员区域现已将左侧头像堆叠区与右侧成员图标统一为同一点击热区,用户点击头像区也可直接打开成员列表页。 - 已继续修复房间封面跨用户不同步问题:当列表或进房返回空封面时,客户端会自动补拉 `room/profile/specific` 详情并缓存真实封面;同时房主保存房间资料后会向房间内其他用户派发资料刷新消息,避免只有自己能看到新封面、其他用户仍显示 `no data`。 - 已修复个人主页编辑页头像上传后无变化的问题:上传成功后会先本地回写新头像地址并立即提交;资料更新接口现同时兼容 `userAvatar/avatar` 字段,且不再被紧接着的旧资料回拉覆盖,返回个人主页后头像会即时更新。 - 已进一步定位图片 `no data` 根因并修复客户端加载链:日志确认房间封面详情接口可返回正确公网 `media...` 地址,但用户头像接口会返回 `jvapi.../external/oss/local/...` 这类受保护资源地址;共享图片组件现已对这类地址自动补齐鉴权请求头,避免其它用户侧加载时直接失败为 `no data`。 - 已直接校验头像异常地址的服务端返回:`jvapi.../external/oss/local/...` 当前会返回 `500 local disk file does not exist`,并非单纯鉴权缺失;前端现已在编辑资料成功后与本人资料回拉时优先保留刚上传成功的公网头像,避免再次被这类坏地址覆盖,同时修复了房间消息用户资料缓存未真正失效的笔误。 - 已继续修正个人资料更新接口的提交结构:排查发现注册接口使用嵌套 `profile`,而资料更新接口此前只发扁平字段;现已改为同时提交 `id + 扁平字段 + profile`,并在 `profile` 内同步带上 `userAvatar/avatar`,用于兼容后端可能按嵌套对象取值的情况。 - 已按最新联调结果再次收窄个人资料更新参数:日志已证明后端能收到请求但会忽略新头像地址,当前已改为头像相关只提交单一 `userAvatar` 字段,并移除 `avatar/profile` 冗余结构,便于继续验证后端是否对字段名或重复参数敏感。 - 已继续将个人页头像上传链路与通用资料提交拆开:上传成功后当前会单独触发一次仅含 `userAvatar` 的更新请求,不再混带昵称、性别、年龄、国家等字段,便于排除其它参数对头像更新接口的干扰。 - 已继续收敛个人主页资料编辑页提交行为:当前已移除资料列表页中的 `country` 条目及对应跳转/提交逻辑,并将昵称、性别、生日、Bio、Hobby、头像改为“改哪项只提交哪项”的增量更新;同时修正生日弹窗只会在确认且日期真实变更后才触发提交,避免取消或未改动时误发请求。 - 完成仓库结构、依赖引用、资源体积和 APK 组成的第一轮排查。 - 移除 4 个当前未在业务层直接使用的插件依赖:`loading_indicator_view_plus`、`social_sharing_plus`、`flutter_foreground_task`、`on_audio_query`,并清理相关平台声明。 - 修补 `image_cropper 5.0.1` Android 兼容问题,切换到本地 path 依赖以恢复构建。 - 完成 Android release 签名回退配置,解决仓库缺少 `yumi.jks` / `yumi_debug.jks` 时无法继续本地构建分析的问题。 - 完成 release 包体分析,确认 universal APK 过大主要由多 ABI 与 Agora/Tencent 原生 so 导致。 - 去除 Gradle 中与 Flutter 冲突的硬编码 `abiFilters`,确认 `--split-per-abi` 可以正常产出分架构 APK。 - 完成 TinyPNG 环境核查,并接入可执行的 Ruby 批量压缩脚本。 - 已完成 TinyPNG 第一轮批量压缩,`sc_images + assets` 总量已从 `47.25 MB` 降到 `22.54 MB`。 - 已增强 TinyPNG 脚本,支持断点续跑、单文件目标和失败项重试。 - 已完成 TinyPNG 网络失败项补跑,6 张 `SSL_connect` 异常图片已全部压缩成功。 - 已完成图片压缩后的 release 复测,确认分 ABI APK 体积继续显著下降。 - 已切换 Android `release` 为真正的瘦身模式:开启 `minify`、`shrinkResources`、`zipAlign`。 - 已完成开启瘦身配置后的 Android release 复测,并接入 `split-debug-info` 保存 Dart symbols。 - 已生成统一的 Python 打包脚本 `scripts/build_release.py`,开始接管 `AAB`、分 ABI APK 与 iOS 包流程。 - 已完成 `scripts/build_release.py` 的 Android / iOS 真机冒烟验证,产物归档目录与 manifest 均已生成。 - 已按当前需求再次完成正式 `AAB` 出包。 - 已定位 Google Play 上传阻塞点:当前 `AAB` 使用的是 `Android Debug` 证书签名,不是正式 upload key。 - 已确认当前项目属于“首次上架的新应用”,后续应走 Play App Signing 首发流程,而不是兼容老签名迁移流程。 - 已梳理 Google Play 首次上架所需的 `Play App Signing`、`upload key`、重新打包与提审步骤。 - 已澄清首次生成 `upload keystore` 时的“密钥库口令”是本地自行设置的密码,与 Google 提供的 `deployment_cert.der` 证书文件无关。 - 已为新应用生成正式 `upload keystore`,并接入工程的 release 签名配置。 - 已重新打出正式 `AAB`,并确认其签名已经从 `Android Debug` 切换到新的 upload key。 - 已定位 `FOREGROUND_SERVICE_MEDIA_PROJECTION` 的来源为 Agora `full-screen-sharing` 依赖,并开始从主 Manifest 覆盖移除。 - 已移除 `FOREGROUND_SERVICE_MEDIA_PROJECTION` 相关声明并重新打出正式 `AAB`。 - 已按当前需求打出正式 `arm64-v8a` 单架构 `APK`。 - 已将新的 `google-services.json` 替换进工程,准备重新打包验证。 ## 进行中模块 - 评估 iOS 正式签名参数接入后导出 `.ipa` 的流程。 - 继续评估 Agora 扩展 so 与 release shrink 策略是否还能进一步裁剪。 - 评估 12 张 TinyPNG 不支持解码的特殊 `webp` 是否需要改格式或换工具处理。 ## 关键技术决策 - 先做高置信度瘦身:优先清理未使用插件、ABI 配置和超大图片,暂不贸然删除核心业务能力。 - 避开仓库中用户已有未提交改动,只改必要文件并持续把结果写入本文件。 - 包体分析聚焦 release 产物,不被 `build/`、iOS 中间产物等本地缓存误导。 - Android 架构裁剪交给 Flutter 构建命令驱动,不再在 Gradle 中硬编码 `abiFilters`。 - 对 `image_cropper` 采用本地 path 依赖加最小补丁策略,避免升级带来的业务回归面。 - Android 签名配置采用条件回退:正式 keystore 不存在时自动回退到 debug 签名,仅用于本地分析验证。 - 图片压缩优先走 TinyPNG,以尽量保持画质稳定;失败项按原因分流处理。 - TinyPNG 的 `SSL_connect` 视为可重试网络抖动;`Image could not be decoded` 视为 TinyPNG 对特殊/动图 WebP 的能力边界,先记录不阻塞其余压缩。 ## 已改动文件 - `需求进度.md` - `lib/shared/data_sources/models/enum/sc_gift_type.dart` - `lib/shared/tools/sc_network_image_utils.dart` - `lib/shared/tools/sc_gift_vap_svga_manager.dart` - `lib/services/general/sc_app_general_manager.dart` - `lib/ui_kit/widgets/room/floating/floating_gift_screen_widget.dart` - `lib/ui_kit/widgets/room/floating/floating_luck_gift_screen_widget.dart` - `lib/services/room/rc_room_manager.dart` - `lib/services/audio/rtc_manager.dart` - `lib/modules/room/edit/room_edit_page.dart` - `lib/modules/user/edit/edit_user_info_page2.dart` - `lib/shared/data_sources/sources/repositories/sc_user_repository_impl.dart` - `lib/shared/data_sources/sources/repositories/sc_room_repository_imp.dart` - `lib/shared/tools/sc_room_profile_cache.dart` - `lib/shared/business_logic/models/res/room_res.dart` - `lib/shared/business_logic/models/res/follow_room_res.dart` - `lib/shared/business_logic/models/res/my_room_res.dart` - `lib/shared/business_logic/models/res/sc_edit_room_info_res.dart` - `lib/shared/business_logic/models/res/join_room_res.dart` - `lib/ui_kit/components/sc_compontent.dart` - `lib/ui_kit/components/sc_float_ichart.dart` - `lib/modules/index/index_page.dart` - `lib/modules/room/seat/sc_seat_item.dart` - `lib/ui_kit/widgets/room/room_head_widget.dart` - `lib/ui_kit/widgets/room/room_game_bottom_sheet.dart` - `lib/ui_kit/widgets/svga/sc_svga_asset_widget.dart` - `lib/modules/room/detail/room_detail_page.dart` - `lib/modules/home/popular/party/sc_home_party_page.dart` - `lib/modules/home/popular/mine/sc_home_mine_skeleton.dart` - `lib/modules/home/popular/follow/sc_room_follow_page.dart` - `lib/modules/home/popular/history/sc_room_history_page.dart` - `lib/modules/home/popular/mine/sc_home_mine_page.dart` - `lib/ui_kit/widgets/room/room_live_audio_indicator.dart` - `lib/modules/search/sc_search_page.dart` - `lib/modules/store/headdress/store_headdress_page.dart` - `lib/modules/store/mountains/store_mountains_page.dart` - `lib/modules/store/theme/store_theme_page.dart` - `lib/modules/store/chatbox/store_chatbox_page.dart` - `lib/modules/user/my_items/headdress/bags_headdress_page.dart` - `lib/modules/user/my_items/mountains/bags_mountains_page.dart` - `lib/modules/user/my_items/chatbox/bags_chatbox_page.dart` - `lib/modules/user/my_items/theme/bags_theme_page.dart` - `lib/ui_kit/widgets/store/store_bag_page_helpers.dart` - `sc_images/general/sc_no_data.png` - `.gitignore` - `android/key.properties` - `pubspec.yaml` - `pubspec.lock` - `lib/ui_kit/components/dialog/dialog.dart` - `android/app/src/main/AndroidManifest.xml` - `android/app/google-services.json` - `ios/Runner/Info.plist` - `scripts/tinypng_batch.rb` - `scripts/build_release.py` - `tinypng-progress.json` - `tinypng-report.json` - `local_packages/image_cropper-5.0.1-patched/android/src/main/java/vn/hunghd/flutter/plugins/imagecropper/ImageCropperPlugin.java` - `local_packages/image_cropper-5.0.1-patched/` - `android/app/build.gradle.kts` - `android/app/upload-keystore.jks` - `android/app/upload_certificate.pem` - `build/symbols/android/` - `build/symbols/ios/` - `dist/release/smoke-android/` - `dist/release/smoke-ios/` - `sc_images/` - `assets/` ## 已验证结果 - 已通过代码与资源目录交叉核对确认:房内礼物飘屏当前报错 `Unable to load asset: "sc_images/room/sc_icon_gift_flosc_bg.png"` 的根因是资源名拼写错误,而不是消息未下发;工程内实际存在的资源文件为 `sc_icon_gift_float_bg.png`、`sc_icon_luck_gift_float_bg1~5.png`、`sc_icon_luck_gift_float_n_bg.png`。 - 已确认当前“点击赠送没有动画”至少包含一类前端资源问题:大额礼物/幸运礼物飘屏 widget 已进入渲染,但因为背景图 asset 路径写错而无法显示;全屏 `SVGA/VAP` 特效是否播放仍取决于具体礼物是否带有 `giftSourceUrl`,且 `special` 包含 `ANIMSCION/ANIMATION/GLOBAL_GIFT` 之一。 - 已完成一轮针对卡顿的代码级优化:礼物列表现在只会对真正需要全屏特效的礼物做受控预热;用户选中礼物时会立即高优先级预热该礼物;播放器播放时优先复用内存里的 `MovieEntity` 或同一路径的在途任务,不再重复发起网络下载/重复解码;渲染层也已改为独立重绘边界以减少房间整页跟随重绘。 - 已通过 GiftFX 调试日志确认:示例礼物 `阿拉伯舞蹈` 实际返回 `giftSourceUrl=.svga` 且 `special=ANIMATION`,此前前端因为不识别该标记而输出 `skip local play because special does not include ANIMSCION/GLOBAL_GIFT`;本轮已补齐 `ANIMATION` 兼容判断。 - 礼物二级页当前已按“整页骨架 + 当前页并发预热 + 下一页提前预热 + 单卡小 loading 占位”的方式重构首屏加载策略:首次进入和翻页时不会再直接暴露 `noData` 图,且整页骨架会保留一个可感知时长,不再一闪而过;当前页礼物封面会并发预热而不是等每个格子各自串行体感加载。 - 当前工作区存在用户已有未提交改动,后续处理均避开覆盖。 - 首页 `party/follow/history/mine` 以及房间详情使用的房间封面模型已兼容 `roomCover` 与 `cover` 两种返回字段,上传封面后不会再因为字段名不一致掉回空占位。 - 房间设置保存封面时,前端现在会同时兼容提交和读取两套字段,并在 `PUT /room/profile` 响应或紧接着的房间详情刷新返回空封面时保留刚上传的封面,不再被空值冲掉。 - 已新增本地房间封面兜底缓存:即使服务端短时间仍返回空封面,首页列表、我的房间、搜索结果、房间头部、房间详情和再次进入房间也会继续显示最近一次本地成功保存的封面。 - 已通过实际请求日志确认:`POST /external/oss/upload`、`PUT /room/profile` 和随后 `GET /room/profile/specific` 都已返回正确封面 URL;本轮问题的根因已收敛为首页/列表链路仍可能使用接口短时间回传的旧值,因此本地成功保存的封面现已提升为更高优先级。 - 房间封面空态图已切换为新的 `sc_images/general/sc_no_data.png`,其资源尺寸为 `288x288`。 - 房间资料卡与个人主页使用的用户资料链路已重新对齐:个人页现兼容 `avatar` 别名;顶部小头像不叠加头像框,但主头像会继续叠加头像框资源,且个人页背景已随 header 一起滚动,不再出现内容先滑动、背景停留不动的现象。 - 头像框显示逻辑已改为“框在外、头像在内”的常见样式;针对当前这类带白底的静态头像框资源,已增加白底透明化处理,因此个人主页主头像与房间麦位头像都不会再留下明显白边。 - 静态头像框的透明区域现已保持透明,不会再被错误算成黑色;房间麦位头像、个人主页主头像和其它复用 `head()` 的头像组件进入房间后不会再出现大块黑底遮罩。 - 个人主页现在在数据加载前也会先展示默认背景和底色,不会再闪黑;“About me / Giftwall” 内容区顶部边缘已改为直角,不再额外出现一个圆角缺口。 - 个人主页当前已接入贴合页面结构的骨架屏,占位期间不会先看到背景图单独显示;资料接口返回后再无缝切到真实内容,首屏观感更平滑。 - 首页 Party 页当前已接入贴合真实版式的骨架屏:进入首页首屏时会先看到三张排行卡位与双列房卡占位,骨架配色已跟随页面深绿+鎏金主视觉,不再只显示居中的白色 `loading`;且排行榜与房间区会按各自请求结果独立切换,先返回的区域会先显示真实内容。 - 首页 My 板块当前已接入贴合真实版式的骨架屏:顶部 `My room` 现区分“首次加载中”和“确实未创建房间”,不会再先闪出创建房间卡;`Recent/Followed` 在首屏空数据加载时也会先展示双列房卡骨架,不再只显示小菊花或局部空白。 - `Me` 入口下的 `Store / Bag` 页面当前也已接入深绿主题的三列卡片骨架:首次进入并且列表尚未返回时,会先显示与正式卡片比例一致的占位;接口返回后再切到真实商品/物品卡片。`store` 与 `bag` 卡片标题现都带宽度约束和单行省略,类似截图里的长名称不会再横向撑破布局。 - 图片加载态与空态当前已拆分:共享网络图组件和礼物二级页单卡封面加载时会显示代码绘制的环形转点,不再继续复用 `sc_icon_loading.png`;若图片失败或确实无数据,仍旧保留原先那张占位图,避免把 `loading` 和 `no data` 看成同一种状态。 - 首页与搜索等房卡右下角的在线状态图标当前已改为代码绘制的动态音频条:三根绿条会按不同相位走完整的波峰波谷周期,错峰连续起伏,视觉上更接近直播/语聊房的实时状态;`My` 板块骨架数量也已与 Party 页对齐为 `6` 个。 - 首页房卡底部信息当前已进一步收紧:房名和人数文字比上一版更小,底栏与动态音频条的视觉重心更一致;`My` 页顶部 `my room` 标题也已移除,下方卡片和 tab 会自然上移填充。 - 首页顶部排行骨架当前已进一步收窄为单条标题占位,不再保留两条文本骨架;房卡底栏房名也已再次缩一号并做轻微上移,对齐更贴近设计稿观感。 - 目录体积排查显示:`build/` 约 `4.7G`、`.dart_tool/` 约 `347M`、`ios/` 约 `250M`、`sc_images/` 约 `48M`、`local_packages/` 约 `6.1M`。 - 当前包体过大的主要原因已经确认: - universal APK 带入了 `arm64-v8a`、`armeabi-v7a`、`x86_64` 三套 ABI。 - Agora 与腾讯 IM 原生 so 很大,其中 `libagora-rtc-sdk.so` 合计约 `79.4MB`,`libImSDK.so` 合计约 `10.2MB`。 - 资源目录中 `sc_images/index`、`sc_images/room`、`sc_images/person`、`sc_images/splash` 是最主要的大图来源。 - `flutter build apk --release --target-platform android-arm64 --analyze-size` 已成功执行,当前 universal release APK 约 `271MB`。 - `flutter build apk --release --split-per-abi` 已成功执行,压缩前分架构 APK 约为: - `app-arm64-v8a-release.apk` 约 `161.4MB` - `app-armeabi-v7a-release.apk` 约 `138.8MB` - `app-x86_64-release.apk` 约 `148.6MB` - `loading_indicator_view_plus`、`social_sharing_plus`、`flutter_foreground_task`、`on_audio_query` 已从当前依赖链路中移除。 - 当前图片资源统计为 `412` 张,TinyPNG 两轮处理后总量已从 `47.25 MB` 降到 `22.27 MB`,累计节省约 `24.99 MB`。 - 当前 TinyPNG 已成功压缩 `400` 张图片,剩余失败 `12` 张。 - 当前压缩收益最大的图片包括: - `sc_images/person/sc_icon_edit_userinfo_bg.png`:`2640776 -> 436823`,节省约 `2.10 MB` - `sc_images/splash/sc_splash.png`:`2373335 -> 379804`,节省约 `1.90 MB` - `sc_images/room/sc_icon_room_defaut_bg.png`:`2243222 -> 704696`,节省约 `1.47 MB` - `sc_images/index/sc_icon_index_bg.png`:`1422169 -> 420635`,节省约 `0.96 MB` - 失败项已分型: - `12` 张为 TinyPNG 无法解码的特殊/动图 `webp` - 当前 TinyPNG 进度与统计文件已落盘:`tinypng-progress.json`、`tinypng-report.json` - 图片压缩后再次执行 `flutter build apk --release --split-per-abi`,当前分架构 APK 已下降到: - `app-arm64-v8a-release.apk` 约 `135.2MB`,比压缩前少 `26.2MB` - `app-armeabi-v7a-release.apk` 约 `112.6MB`,比压缩前少 `26.2MB` - `app-x86_64-release.apk` 约 `122.4MB`,比压缩前少 `26.2MB` - 可以确认:这轮图片压缩带来的资源收益已经真实反映到最终 APK 体积中。 - 在开启 `minify`、`shrinkResources`、`zipAlign` 并追加 `--split-debug-info=build/symbols/android` 后,Android release 继续下降为: - `app-release.aab` 约 `181.8MB` - `app-arm64-v8a-release.apk` 约 `128.7MB`,比上一轮 `135.2MB` 再少 `6.5MB` - `app-armeabi-v7a-release.apk` 约 `105.8MB`,比上一轮 `112.6MB` 再少 `6.8MB` - `app-x86_64-release.apk` 约 `115.8MB`,比上一轮 `122.4MB` 再少 `6.6MB` - `build/symbols/android` 已生成 3 份符号文件,总计约 `14MB`,后续可用于 Dart 堆栈还原。 - `scripts/build_release.py --platform android --output-dir dist/release/smoke-android` 已验证通过,归档结果为: - `android/google-play/` 下输出 `yumi-v1.0.0-b1-google-play.aab` 与 Dart symbols - `android/local/` 下输出 `arm64-v8a.apk` 与 `armeabi-v7a.apk` - `android/testing/` 下单独输出 `x86_64-test.apk` - 同时生成 `build_manifest.json`,已记录产物路径、大小和 `sha256` - `scripts/build_release.py --platform ios --output-dir dist/release/smoke-ios` 已验证通过,当前无签名模式下输出: - `ios/archive/yumi-v1.0.0-b1.xcarchive` - `ios/symbols/app.ios-arm64.symbols` - 当前 iOS 无签名构建会跳过 `.ipa` 导出;如需正式 `.ipa`,脚本需追加 `--ios-codesign` - 已将 `dist/` 加入 `.gitignore`,避免打包产物持续污染工作区状态 - 本轮按需执行 `flutter build appbundle --release --split-debug-info=build/symbols/android` 已成功,产物为: - `build/app/outputs/bundle/release/app-release.aab` - 当前 AAB 体积约 `181.8MB` - 本地校验 `app-release.aab` 证书后确认: - 证书所有者为 `C=US, O=Android, CN=Android Debug` - 当前 AAB 的 `SHA1` 为 `6B:72:BF:6F:D1:7A:F2:99:CD:F3:14:EE:18:A6:29:67:F8:05:E6:B4` - 这说明当前 release 构建仍在回退使用 debug signing,无法直接作为 Google Play 正式发布包 - 已生成新的 upload 证书文件: - `android/app/upload-keystore.jks` - `android/app/upload_certificate.pem` - 新 upload key 当前指纹为: - `SHA1: C1:80:AF:BF:6E:1F:F2:F4:49:58:72:87:A2:BC:54:07:E7:D2:D9:A3` - `SHA256: 81:D6:3A:43:31:FA:83:87:0E:C3:5B:52:B8:C1:05:7C:3A:32:EC:24:37:0B:11:E4:2F:8C:62:4E:D4:AC:0C:3B` - release 构建已改为从 `android/key.properties` 读取正式 upload keystore,不再依赖当前的 debug 回退配置 - `flutter build appbundle --release --split-debug-info=build/symbols/android` 已重新执行,当前正式产物仍为: - `build/app/outputs/bundle/release/app-release.aab` - 当前 AAB 体积约 `181.8MB` - 重新校验该 AAB 后,签名者已变为: - `CN=Yumi Upload, OU=Mobile, O=Yumi, L=Shanghai, ST=Shanghai, C=CN` - `deployment_cert.der` 已核实为 Google 侧 app signing 证书,指纹为: - `SHA1: 3F:E1:78:DC:C3:29:4F:74:20:DF:27:54:CF:AF:46:46:D6:A1:94:78` - `SHA256: F9:BF:D0:89:F9:D7:FD:B2:53:24:A7:DB:59:E1:52:6F:54:A3:93:95:4E:88:7F:1C:4B:D6:03:66:E7:1A:1F:85` - 已确认当前存在两套不同证书: - 本地 `upload key`:用于你上传 AAB 到 Google Play - Google `app signing key`:用于 Google Play 最终给用户分发签名包 - `FOREGROUND_SERVICE_MEDIA_PROJECTION` 在当前 release 合并报告中的来源已确认是 `io.agora.rtc:full-screen-sharing:4.5.2` - 该依赖同时还带入了: - `io.agora.rtc2.extensions.MediaProjectionMgr$LocalScreenCaptureAssistantActivity` - `io.agora.rtc2.extensions.MediaProjectionMgr$LocalScreenSharingService` - 主 Manifest 已添加 `tools:node="remove"` 覆盖规则,准备重新打包验证最终合并结果 - 重新打包后,release manifest merger 报告已显示: - `uses-permission#android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION` - `REJECTED from [io.agora.rtc:full-screen-sharing:4.5.2]` - 当前 release 中已不再检测到以下声明: - `android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION` - `io.agora.rtc2.extensions.MediaProjectionMgr$LocalScreenCaptureAssistantActivity` - `io.agora.rtc2.extensions.MediaProjectionMgr$LocalScreenSharingService` - 新的正式产物已重新生成: - `build/app/outputs/bundle/release/app-release.aab` - 当前 AAB 体积仍约 `181.8MB` - 新 AAB 证书仍为本地 upload key: - `SHA1: C1:80:AF:BF:6E:1F:F2:F4:49:58:72:87:A2:BC:54:07:E7:D2:D9:A3` - 本轮按需执行 `flutter build apk --release --split-per-abi --target-platform android-arm64 --split-debug-info=build/symbols/android` 已成功,产物为: - `build/app/outputs/flutter-apk/app-arm64-v8a-release.apk` - 当前 `arm64-v8a` APK 体积约 `128.7MB` - 已核对新旧 `google-services.json`: - 原文件与新文件都匹配包名 `com.org.yumi` - 下载文件已成功覆盖到 `android/app/google-services.json` - 当前工程内文件 `SHA256` 为: - `a1706496a01f74d27e6c60598144cecc978934b02a87567e1ced887b5b0185d5` ## 已知问题 - `ios/Podfile.lock` 还保留旧插件记录,因为本轮未执行 `pod install`;但 Flutter 当前依赖链路已经不再包含已移除插件。 - universal APK 仍然会非常大;当前正确发包方式应优先使用 `--split-per-abi` 或直接产出 `aab`。 - 仍有 `12` 张 `webp` 被 TinyPNG 拒绝解码,推测是动画或特殊编码格式,不能继续直接走 TinyPNG 常规压缩。 - `split-debug-info` 会把 Dart symbols 额外落到构建目录,发包时需要和正式包一起留档,不能丢。 - iOS 当前验证走的是 `--no-codesign`,因此只产出 `.xcarchive`,不会自动导出可直接分发的 `.ipa`。 - Flutter/Xcode 当前给出两条 iOS 提醒: - 未来 iOS 版本将要求 `UIScene` 生命周期支持 - Launch image 仍是默认占位资源,提交前建议替换 - `android/key.properties` 保存了本地 upload keystore 口令,必须自行妥善备份,且不要提交到仓库 - 由于已显式移除 Agora 本地屏幕共享相关组件,如果业务后续要启用“屏幕共享/录屏推流”,需要再单独恢复相关 manifest 声明 ## 下一步要做什么 - 将新的 `AAB` 上传到 Play Console,并在首发流程中继续使用 Google 管理的 app signing key。 - 在需要配置 Google 登录、Firebase、支付等生产环境指纹时,优先登记 Google 的 `deployment_cert.der` 指纹;如平台要求上传者证书,再额外登记本地 upload key 指纹。 - 如果需要正式 iOS 分发包,为 `scripts/build_release.py` 补入 `--ios-codesign` 所需签名参数并导出 `.ipa`。 - 继续评估 Agora 扩展库是否都需要,优先核查 `lip sync`、`spatial audio`、`clear vision`、`segmentation`、`face capture` 等扩展 so 能否裁剪。 - 决定是否处理剩余 12 张特殊 `webp`:改格式、换压缩工具,或维持现状。