hyapp-h5/docs/Flutter-H5-排行榜对接文档.md
2026-05-26 02:56:37 +08:00

8.7 KiB
Raw Blame History

Flutter H5 排行榜对接文档

本文说明 Flutter App 如何打开 H5 排行榜、向 H5 传递登录态,以及接收 H5 通过 JSBridge 发回的导航事件。

入口地址

本地开发:

http://127.0.0.1:30000/rank/index.html?env=local&token={access_token}&app_code=lalu

测试环境:

https://{h5-test-domain}/rank/index.html?env=test&token={access_token}&app_code=lalu

线上环境:

https://{h5-domain}/rank/index.html?token={access_token}&app_code=lalu

env 规则:

参数 说明
不传 H5 请求 https://api.global-interaction.com/
env=test H5 请求 https://api-test.global-interaction.com/
env=local H5 请求 http://localhost:13000/,用于本机 gateway 联调

URL 参数

参数 必填 说明
token App 登录后拿到的 access token。H5 会作为 Authorization: Bearer <token> 调后端。
access_token token 的兼容别名。
accessToken token 的兼容别名。
app_code App 编码,当前传 lalu。H5 会作为 X-App-Code 请求头。
appCode app_code 的兼容别名。
env API 环境切换,见上表。

H5 启动后会调用:

GET /api/v1/users/me/overview
Authorization: Bearer <token>
X-App-Code: lalu

这个接口用于确认登录态并缓存当前用户信息。排行榜数据使用同一个 token 和 app code 请求。

H5 页面能力

排行榜页面地址:

/rank/index.html

页面内包含三个榜单,通过 tab 切换:

H5 Tab 后端 board_type 说明
Wealth sent 财富榜,按用户送礼总金币排行
Room room 房间榜,按房间收礼总金币排行
Charm received 魅力榜,按用户收礼总金币排行

时间维度:

H5 Tab 后端 period
Daily today
Weekly week
Monthly month

排行榜接口:

GET /api/v1/activities/user-leaderboards?board_type=sent&period=today&page=1&page_size=20
Authorization: Bearer <token>
X-App-Code: lalu

H5 会分页加载,page_size=20。如果无 token 或接口失败,页面会展示 Figma 默认占位数据,不阻塞页面打开。

Flutter JSBridge

H5 会按以下优先级尝试发送消息:

  1. window.flutter_inappwebview.callHandler("HyAppBridge", action, payload)
  2. window.HyAppBridgeChannel.postMessage(jsonString)
  3. window.FlutterBridge.postMessage(jsonString)
  4. window.webkit.messageHandlers.HyAppBridge.postMessage({ action, payload })

Flutter 只需要实现其中一种即可。推荐统一注册 HyAppBridge

消息格式

flutter_inappwebview.callHandlerpostMessage 的消息是 JSON 字符串:

{
    "action": "openUser",
    "payload": {
        "user_id": "10001"
    }
}

H5 发出的 action

action payload 触发场景 Flutter 行为
ready { "page": "rank" } H5 初始化完成 可关闭加载态
back {} 用户点击左上角返回 关闭 WebView 或返回上一页
openUser { "user_id": "10001" } 点击财富榜/魅力榜用户头像、榜单项 打开用户详情页
openRoom { "room_id": "room_id" } 点击房间榜房间头像、榜单项 进入或打开房间详情
openRankNote { "board_type": "sent" } 点击右上角问号 当前 H5 已内置说明页Flutter 可只打点,不需要跳转

board_type 取值:

说明
sent 财富榜
room 房间榜
received 魅力榜

Flutter 示例

flutter_inappwebview

final url = Uri.parse(
  'http://127.0.0.1:30000/rank/index.html'
  '?env=local'
  '&token=${Uri.encodeComponent(accessToken)}'
  '&app_code=lalu',
);

InAppWebView(
  initialUrlRequest: URLRequest(url: WebUri(url.toString())),
  onWebViewCreated: (controller) {
    controller.addJavaScriptHandler(
      handlerName: 'HyAppBridge',
      callback: (args) async {
        final action = args.isNotEmpty ? args[0] as String : '';
        final payload = args.length > 1 && args[1] is Map
            ? Map<String, dynamic>.from(args[1] as Map)
            : <String, dynamic>{};

        switch (action) {
          case 'ready':
            // 关闭 loading
            break;
          case 'back':
            Navigator.of(context).maybePop();
            break;
          case 'openUser':
            final userId = payload['user_id']?.toString() ?? '';
            if (userId.isNotEmpty) {
              // TODO: 打开用户详情页
            }
            break;
          case 'openRoom':
            final roomId = payload['room_id']?.toString() ?? '';
            if (roomId.isNotEmpty) {
              // TODO: 打开房间或房间详情页
            }
            break;
          case 'openRankNote':
            // H5 内部已展示说明页,这里可做埋点
            break;
        }
        return {'ok': true};
      },
    );
  },
)

webview_flutter JavaScriptChannel

如果使用 webview_flutter,可以注入 HyAppBridgeChannel

final controller = WebViewController()
  ..setJavaScriptMode(JavaScriptMode.unrestricted)
  ..addJavaScriptChannel(
    'HyAppBridgeChannel',
    onMessageReceived: (message) {
      final data = jsonDecode(message.message) as Map<String, dynamic>;
      final action = data['action']?.toString() ?? '';
      final payload = data['payload'] is Map
          ? Map<String, dynamic>.from(data['payload'] as Map)
          : <String, dynamic>{};

      switch (action) {
        case 'ready':
          break;
        case 'back':
          Navigator.of(context).maybePop();
          break;
        case 'openUser':
          final userId = payload['user_id']?.toString() ?? '';
          break;
        case 'openRoom':
          final roomId = payload['room_id']?.toString() ?? '';
          break;
      }
    },
  )
  ..loadRequest(Uri.parse(rankUrl));

后端依赖

H5 依赖以下 Gateway HTTP 接口:

接口 说明
GET /api/v1/users/me/overview 解析 token 后获取当前用户信息
GET /api/v1/activities/user-leaderboards 获取排行榜

业务接口返回 envelope

{
    "code": "OK",
    "message": "ok",
    "request_id": "req_xxx",
    "data": {}
}

H5 也兼容旧的 code: 0 成功格式。

本地联调

hyapp-h5 目录运行:

make run

默认打开:

http://127.0.0.1:30000/rank/index.html?env=local

Flutter 真机调本机服务时,env=local 对 H5 来说会请求 http://localhost:13000/。如果 WebView 运行在真机上,localhost 指向手机自身,不是开发机。真机联调建议:

  1. 使用测试环境 env=test
  2. 或把 H5/API 部署到同一局域网可访问地址。
  3. 或后续给 H5 增加可配置 api_base 参数。

验收点

  1. Flutter 打开 H5 时带上 tokenapp_code
  2. H5 首次加载后发出 ready
  3. 点击左上角返回Flutter 收到 back 并关闭 WebView。
  4. 点击财富榜/魅力榜用户Flutter 收到 openUser
  5. 点击房间榜房间Flutter 收到 openRoom
  6. 切换 Wealth / Room / CharmDaily / Weekly / MonthlyH5 正确请求排行榜接口。
  7. 点击右上角问号H5 展示说明页,返回后仍停留在排行榜页。