hyapp-server/docs/ExploreTab-Flutter-App对接文档.md
2026-05-26 01:02:12 +08:00

5.9 KiB
Raw Permalink Blame History

Explore tab Flutter App 对接文档

本文档定义 App 端 Explore 页 H5 tab 的读取接口。后台在 HYApp 管理平台 / APP配置 / Explore配置 维护 tab 名称和 H5 链接App 只读取已启用配置并按服务端返回顺序展示。

基础约定

本地网关地址:

http://127.0.0.1:13000

所有 /api/v1 业务接口使用统一响应外壳:

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

客户端成功判断:

HTTP 200 && code == "OK"

失败时保留 request_id,用于后端排查日志。

App 标识 Header

Explore tab 按 App 隔离,接口没有 query/body 形式的 app_code 参数。gateway 通过 Header 解析 App

Header 必填 说明
X-App-Code 推荐 内部 App code例如 lalu
X-HY-App-Code X-App-Code 的兼容别名。
X-App-Package 推荐二选一 App 包名,例如 com.org.laluparty。传包名时 gateway 可解析到内部 app_code
X-App-Platform 包名解析时推荐 平台,例如 androidios

当前开发默认 app_codelalu。Flutter 仍建议显式传 X-App-CodeX-App-Package,避免多 App 环境串配置。

获取 Explore tab 列表

接口地址:

GET /api/v1/app/explore-tabs

完整本地地址:

http://127.0.0.1:13000/api/v1/app/explore-tabs

鉴权:

不需要 Bearer token

服务端行为:

  • 只返回当前 App 已启用的 Explore tabs。
  • 后台关闭的 tab 不下发给 App。
  • 返回顺序为后台 sort_order 升序,同排序时按较新的记录优先。

请求 Header

X-App-Code: lalu

或:

X-App-Package: com.org.laluparty
X-App-Platform: android

Query 参数

无。

Request Body

无。

curl 示例

curl -X GET 'http://127.0.0.1:13000/api/v1/app/explore-tabs' \
  -H 'X-App-Code: lalu'

包名解析方式:

curl -X GET 'http://127.0.0.1:13000/api/v1/app/explore-tabs' \
  -H 'X-App-Package: com.org.laluparty' \
  -H 'X-App-Platform: android'

成功响应

{
  "code": "OK",
  "message": "ok",
  "request_id": "req_xxx",
  "data": {
    "items": [
      {
        "id": 7,
        "app_code": "lalu",
        "tab": "Farm",
        "h5_url": "https://www.baidu.com",
        "enabled": true,
        "sort_order": 1,
        "updated_at_ms": 1700000000000
      }
    ],
    "total": 1
  }
}

data 字段

字段 类型 说明
items array Explore tab 列表。
total int 本次返回数量。

items[] 字段

字段 类型 说明
id int 后台配置记录 ID只用于排查或本地缓存 key不作为业务路由。
app_code string tab 所属 App例如 lalu
tab string App 展示的 tab 文案。
h5_url string 点击 tab 后加载的 H5 地址。
enabled bool 是否启用。App 接口只返回 true 的记录。
sort_order int 展示排序,数值越小越靠前。
updated_at_ms int 更新时间Unix epoch milliseconds。

空列表响应

当后台没有启用的 Explore tab 时,返回空数组,不是错误:

{
  "code": "OK",
  "message": "ok",
  "request_id": "req_xxx",
  "data": {
    "items": [],
    "total": 0
  }
}

错误响应

配置读取异常时:

{
  "code": "UPSTREAM_ERROR",
  "message": "upstream service error",
  "request_id": "req_xxx"
}

客户端处理建议:

  • UPSTREAM_ERROR:展示空态或保留上一次本地缓存。
  • OK:不要使用 data
  • 记录 request_id 到客户端日志,便于问题排查。

Flutter 数据模型

class ExploreTabList {
  final List<ExploreTabItem> items;
  final int total;

  ExploreTabList({
    required this.items,
    required this.total,
  });

  factory ExploreTabList.fromJson(Map<String, dynamic> json) {
    final rawItems = json['items'] as List<dynamic>? ?? const [];
    return ExploreTabList(
      items: rawItems
          .map((e) => ExploreTabItem.fromJson(e as Map<String, dynamic>))
          .toList(),
      total: json['total'] as int? ?? rawItems.length,
    );
  }
}

class ExploreTabItem {
  final int id;
  final String appCode;
  final String tab;
  final String h5Url;
  final bool enabled;
  final int sortOrder;
  final int updatedAtMs;

  ExploreTabItem({
    required this.id,
    required this.appCode,
    required this.tab,
    required this.h5Url,
    required this.enabled,
    required this.sortOrder,
    required this.updatedAtMs,
  });

  factory ExploreTabItem.fromJson(Map<String, dynamic> json) {
    return ExploreTabItem(
      id: json['id'] as int? ?? 0,
      appCode: json['app_code'] as String? ?? '',
      tab: json['tab'] as String? ?? '',
      h5Url: json['h5_url'] as String? ?? '',
      enabled: json['enabled'] as bool? ?? false,
      sortOrder: json['sort_order'] as int? ?? 0,
      updatedAtMs: json['updated_at_ms'] as int? ?? 0,
    );
  }
}

Flutter Dio 示例

Future<ExploreTabList> fetchExploreTabs(Dio dio) async {
  final response = await dio.get(
    '/api/v1/app/explore-tabs',
    options: Options(
      headers: {
        'X-App-Code': 'lalu',
      },
    ),
  );

  final body = response.data as Map<String, dynamic>;
  if (body['code'] != 'OK') {
    throw Exception('${body['code']}: ${body['message']} request_id=${body['request_id']}');
  }

  return ExploreTabList.fromJson(body['data'] as Map<String, dynamic>);
}

展示和跳转规则

  • App 按 items 返回顺序展示,不需要二次排序。
  • tab 为空或 h5_url 为空时,建议 App 跳过该项,避免展示不可点击入口。
  • 点击 tab 后打开 h5_url,由 H5 页面自身处理内部导航。
  • 如果接口失败App 可以使用本地缓存的上一版 tabs没有缓存时展示空态。