Files
2026-09-15 15:44:13 +07:00

14 KiB
Raw Permalink Blame History

项目名称, 一级部门, 二级部门, DMP编码, 项目类型, 开发语言, 项目负责人, 运维负责人, 产品负责人, 项目成员, 项目状态, 项目级别, 核心分支, 代码仓库, 最后审计人, 最后审计时间, 告警群, 备注
项目名称 一级部门 二级部门 DMP编码 项目类型 开发语言 项目负责人 运维负责人 产品负责人 项目成员 项目状态 项目级别 核心分支 代码仓库 最后审计人 最后审计时间 告警群 备注
91porn 北斗 瑞升 APP Dart DN5368 DN9460,DN9651,DN4792 YY1145,YY1208 DN5368,DN1180 开发中 main
ssh://git@bd-git-sh.jsyyds.com:8082/ruisheng/jha-204-91pron/frontend/91porn-android-client.git
DN5368 2026-08-06 tg://blibli-alert-group Flutter 客户端(Android + iOS 双端),当前版本 1.12.1Android 包名 com.noporn.newchatone_twelve_one(版本号变更需同步替换)

1. 项目说明

91porn 移动客户端(Android + iOS 同一套代码),基于 Flutter 3.38.3 + Dart 3.10.0,面向 C 端用户的视频/社区/AI/暗网综合内容 APP。

核心模块:

  • 首页 (hj_page/home/):视频/短视频/漫画/动漫等多 Tab 内容流,含搜索、片库、排行
  • 发现 (hj_page/find/):榜单、分类、片单
  • AI (hj_page/mine/ai/):AI 换脸、AI 脱衣、文生图、图生视频、文生小说等付费功能
  • 会员/支付 (hj_page/mine/mine_vip/hj_page/pre_sale/):VIP 购买、金币充值、代理充值、预售
  • 个人中心 (hj_page/user_center_page/hj_page/mine/):用户主页、客服、QA、设置
  • 社区 (hj_page/community/):帖子、评论、互动
  • IM (im_manager/):自研私信/会话,无三方 IM SDK(会话列表、聊天详情、消息通知、聊天页广告位)
  • 暗网 (hj_page/darkweb/):分类专区,独立入口与 VIP 体系
  • 直播 (hj_page/live/):直播入口
  • 在线客服 (hj_page/zaixiankefu/)H5 客服对接
  • 播放器:基于 video_player + ffmpeg_kit_flutter_new_https + 自研 m3u8_downloader
  • 视频下载Android 走 m3u8_downloader 原生 isolateiOS 走 IOSVideoDownloader(用 ffmpeg 拉远程 m3u8 转 mp4 自动入相册,命令 -c copy -bsf:a aac_adtstoasc -movflags +faststart,不重编码)

技术栈:

  • 状态管理:GetX (GetxController + GetBuilder) + Provider(全局状态)
  • 网络:Dio + 自研 httpManager + RSA 请求加密
  • 屏幕适配:flutter_screenutil(设计稿 428×927
  • 路由:GetX 路由
  • 本地存储:MMKV + shared_preferences
  • 视频下载:m3u8_downloader-master(本仓库内)
  • 调试工具:ume_core + ume_kit_dio / ume_kit_perf / ume_kit_ui(均取自 pub,不再本地维护)

项目目录结构:

hgdj/
├── lib/
│   ├── alert/                # 全局弹窗
│   ├── assets_tool/          # 颜色、图片、资源路径
│   ├── config/               # 配置常量(域名、版本、AB 等)
│   ├── extension/            # Dart 扩展方法
│   ├── hj_model/             # 数据模型(手写 fromJson
│   ├── hj_page/              # 业务页面(按模块分目录)
│   ├── hj_utils/             # 工具方法 + API service
│   ├── im_manager/           # 自研 IM(会话/聊天页/通知)
│   ├── routers/              # 路由定义与跳转
│   ├── tools_base/           # 基础工具(网络/事件/loading/toast/refresh/缓存)
│   ├── track_event_manager/  # 设备信息 / 请求头 sid 会话
│   └── main.dart             # 入口
├── android/                  # Android 工程
├── ios/                      # iOS 工程
├── assets/                   # 静态资源(图片/flare/字体)
├── m3u8_downloader-master/   # 自研 m3u8 下载库
├── third_party/              # 三方原生库
├── dist/                     # 打包产物输出目录
├── build_apk.sh              # 双端打包脚本(apk / ipa
└── pubspec.yaml

2. 基础设施与中间件

  • 后端服务:91porn-serverGo,独立仓库)— 提供 APP API、Web 管理、Skd 任务
  • CDN:视频/图片/动漫资源分发(Cloudfront + 自有域名多线路)
  • 推送:Telegram Bot 客服群对接
  • 客户端依赖:
    • DioHTTP 网络层
    • cached_network_image:图片缓存
    • mmkv / shared_preferences:本地 KV
    • ffmpeg_kit_flutter_new_https:视频处理(社区维护 fork,自托管二进制带 SSL,原 minimal 包二进制已下架)
    • flutter_inappwebviewH5 嵌入(充值/客服/活动页)
    • permission_handler:权限申请
    • device_info_plus / package_info_plus:设备信息
    • flutter_native_image / image_pickers:图片选择压缩

3. 运维部署

客户端通过 build_apk.sh 本地打包后分发,不走 K8S/CI 流水线

发布流程:

  1. 切到 main 分支,更新 pubspec.yaml 版本号 + Config.innerVersion + local.properties + applicationId(按版本号转换规则)

  2. 确认 Config.isDebug = false(开发分支常年为 true,最容易漏)

  3. 打包(脚本自动检测 FVM PATH,产物统一复制至 dist/):

    sh build_apk.sh <target> [mode] [export_method] [export_options_plist] [sign_mode]
      target               a(android) | i(ios) | all
      mode                 release(默认) | debug | profile
      export_method (iOS)  app-store(默认) | ad-hoc | development | enterprise
      export_options_plist ExportOptions.plist 路径,留空用默认
      sign_mode     (iOS)  codesign(默认) | nocodesign
    

    常用:sh build_apk.sh aAndroid releasearm64 单 ABI)、sh build_apk.sh i release ad-hociOS 内测包)、sh build_apk.sh all

  4. 产物命名(APP_NAME 取自 pubspec.yamlname,即 hgdj):

    • Androidhgdj_<mode>_<version>_<MMdd-HHmm>.apk
    • iOShgdj_<mode>_<exportMethod>_<version>_<MMdd-HHmm>.ipa,如 hgdj_release_adhoc_1.12.1_0806-0925.ipa
  5. Android 发版前跑 VirusTotal 包毒检测

  6. 上传到分发平台(落地页 / 蒲公英 / 自有 CDN),Telegram 告警群通知

真机调试(不出正式包):flutter build ios --release && flutter install --release -d <deviceId>Xcode 自动签名,Team NWP977LR25

回滚方案:

  • 仅客户端无服务端回滚概念
  • 旧版本安装包保留在分发平台,用户可重新下载
  • 服务端通过 Config.dns 接口下发动态域名实现服务端切换

4. 风险说明

  • 包名风险com.noporn.newchatone_twelve_one 与版本号强绑定,每次升版需替换 applicationId(数字转英文单词规则),遗漏会导致 push/支付失败
  • 加密密钥风险Config.encryptKey / ANTI_REPLAY_ATTACK_KEY / Config.appId = JHA-204 泄漏会被刷接口
  • 包毒检测:APK 容易被部分杀毒软件误报,需走 VirusTotal 检测后再分发
  • 包体积:当前接入 ffmpeg_kit_flutter_new_https(带 SSL,比 minimal 大 +5~10MB/ video_player / 多个三方 SDK,需定期 analyze-size 控制体积
  • iOS 最低系统版本Podfile + Runner.xcodeproj 锁定 15.0Xcode 16+ 要求 + ffmpeg 7.x 要求),低于此版本无法安装
  • Android SDK 版本minSdk 24 / targetSdk 36targetSdk 升级需重新验证权限与后台限制
  • 三方依赖image_pickers / m3u8_downloader 为内部维护,Flutter 升级时需同步适配
  • 原生插件升级flutter pub get + flutter analyze 全过也不代表能用,含原生代码的插件必须真机 build 验证(audioplayers 升 v6 即栽在这里)
  • release-only 缺陷:混淆 + strip + 独立 manifest 让 release 有一整类 debug 不复现的问题(详见第 5 节),每次发版必须真机跑 release 包,不能只测 debug
  • 域名兜底Config.dns = 91porn.zmnchs.com 走运维下发,运维接口挂掉会导致 APP 启动失败
  • Flutter 版本锁定3.38.3 强制 fvm,避免系统 SDK 切换触发 flutter_ume / leak_tracker 冲突
  • 暗网模块Config.darkWebEnable 通过运维下发开关,下发异常会暴露入口
  • DEBUG 标志Config.isDebug 切换会影响 lineList 兜底线路与日志输出,正式包必须 false(开发分支当前为 true

5. 历史事故(可选)

5.1 release 包专有(debug 一律不复现,最贵的一类)

debug 与 release 在混淆、符号 strip、manifest 合并三处行为不同,以下问题只能靠真机 release 包发现:

现象 根因 修复
iOS 启动卡死 / 本地存储静默读不到 FFIMMKV)符号被 strip 掉,运行时找不到 STRIP_INSTALLED_PRODUCT = NO(只设 STRIP_STYLE = non-global 不够)
Android 安装后直接闪退(SIGSEGV 含 native 方法的插件(ffmpeg-kit)被 R8 混淆,RegisterNatives 失败 proguard 补 -keep新增带 JNI 的插件都要补
启动弹「线路检测失败」,host lookup errno=7 INTERNET 权限只声明在 debug/profile 的 manifestsrc/main 漏了 权限写进 src/main/AndroidManifest.xml,别指望三方插件替你声明
页面灰屏 / 列表静默空白 T.toString() == '类名' 做分支,混淆后类名变了必然失配 一律改 T == 类型(比较 Type 对象,不碰名字字符串)

5.2 其他

  • 视频下载进度不刷新(退出重进才更新):本仓库内 m3u8_downloadercallbackDispatcher@pragma('vm:entry-point'),后台 isolate 起不来。教训:本地插件不是黑盒,出问题要读它的源码
  • 刷新控制器双重释放崩溃refreshCtrCustomRefreshView 释放,logic / 子 widget 又 dispose 一次 → headerMode! 空断言崩在 unmount 阶段 → 中断整棵树的卸载并连带泄漏。规则:只释放自己 new 的
  • dio 5.9 偶发 DioException[unknown] Null check operator:仅 CDN 接口偶发,根因不可复现(已证伪 adapter / FusedTransformer 两个方向),用幂等 GET 的 RetryInterceptor 自愈
  • 截图保存「提示成功但相册没有」RepaintBoundary 套在 SingleChildScrollView 内被裁剪,截出空图。改用 Center + FittedBox 完整渲染,且调用处必须 await 判断结果
  • 设置锁屏密码当次不生效、重启后才生效:把内部可变 list 直接交给未 await 的异步回调,回调在 await 之后读到的已是被 clear 的空 list(内存态空、持久化态有值)。传副本 List<int>.of(x) 修复
  • audioplayers 无法升 v6pub get / analyze 全过但 Android 侧 build 挂(5.2.1 与 platform_interface 7.1.1 错配 + Kotlin 2.1),已停在 v5.2.1
  • pull_to_refresh 升级后回弹手感夸张Flutter 3.16.8 → 3.38.3):改 pull_refresh.dart 参数解决;不迁移 EasyRefresh——logic 层有 305 处依赖 SmartRefresher 专有 API
  • 华为多任务卡片隐私遮盖失败:系统截快照早于 Flutter 生命周期回调,任何遮盖层(View / 独立 Window)都盖不住,也无法把黑屏换成自定义图。结论:只能用 FLAG_SECURE

6. 交接说明(可选)

  • Flutter 版本:必须使用 fvm flutter,版本锁定 3.38.3(见 .fvmrc),build_apk.sh 已内置 FVM PATH 检测
  • 打包build_apk.sh a 打 Androidbuild_apk.sh i 打 iOSbuild_apk.sh all 双端;完整参数见第 3 节
  • applicationId 规则com.noporn.newchat + <major>_<minor>_<patch>(数字转英文),如 1.12.1 → com.noporn.newchatone_twelve_one
  • 版本号同步点pubspec.yaml / Config.innerVersion / android/local.properties / android/app/build.gradle 四处必须一致
  • 加密密钥RSA 公私钥位于 Android 端 native 层 + Dart 层,调整时需双端同步
  • AB 配置Config 类中集中维护(aiSwitchConf / showAbTestAd 等),新增 AB 需走运维下发
  • 客服地址/customer/url 接口动态下发完整 URL,前端不再拼 baseHost
  • provider 注入main.dartMultiProvider 注入若干 ChangeNotifier,新增全局状态走该处
  • 图片资源assets_tool/ 统一管理路径扩展(.commonImgPath / .homePath / .darkWebPath 等)
  • 域名错误兜底DNS 接口失败时降级到 Config.LINE_LIST 本地兜底
  • 网络层异常约定dio 异常已被网络层吞成 BaseRespBean(业务层不要写 DioException catch),但请求前的签名加密会抛,需 try 兜底;拦截器只在「有响应但失败」时弹 toast,超时/断网(code 2001-2003)不弹,要各自兜底
  • 列表分页:统一继承 tools_base/base_list_controller.dartListBaseLogic(配 pullYsRefresh),别自己重写分页
  • 支付下单:走 PayManager().buy / buyVip(含 loading、余额不足跳充值、回调、source 透传),不要直接调 BuyService
  • 弹窗:提示类统一用 tools_base/widget/common_alert.dart;「停留 N 分钟后满足条件才弹」走 TimedPopupManageronClose 必须 cancel,否则泄漏)
  • 包毒检测:发版前必须用 /check-apk-virus 跑 VirusTotal
  • 包体积分析:使用 apk-analyzer skill 跑 flutter build apk --analyze-size