import 'package:dio/dio.dart'; import '../models/app_version.dart'; import '../models/tv_app.dart'; import 'api_client.dart'; import '../utils/session_org_scope.dart'; /// 应用管理服务:APP 版本管理与 TV 应用管理。 /// /// 对接真实「爱视后台」: /// - APP 版本:/api/device/orgGroupAppVersion/* /// - TV 应用:/api/theme/tvapp/* class AppService { AppService({Dio? dio}) : _dio = dio ?? ApiClient.instance.dio; final Dio _dio; // ================ APP 版本管理 ================ /// 获取 APP 版本列表(分页,可按组织/分组筛选)。 /// /// GET /device/orgGroupAppVersion/list?page=&limit=&orgId=&groupId= Future> getAppVersionList({ int page = 1, int limit = 20, String? orgId, String? groupId, }) async { final effectiveOrgId = orgId ?? (SessionOrgScope.instance.enabled ? SessionOrgScope.instance.currentOrgId : null); final response = await _dio.get( '/device/orgGroupAppVersion/list', queryParameters: { 'page': page, 'limit': limit, if (effectiveOrgId != null) 'orgId': effectiveOrgId, if (groupId != null) 'groupId': groupId, }, ); final list = _extractList(response.data); return list .whereType>() .map(AppVersion.fromJson) .toList(); } /// 按 orgId 查询该组织直接配置的版本(单体)。 /// /// 对齐 Web 端 `searchAppVersion`:每个 scope=ORG 的组织至多一条版本配置, /// 有则返回当前版本(进入编辑流程)、无则返回 null(走新增流程)。 /// /// GET /device/orgGroupAppVersion/search?orgId= /// /// 注意:拦截器已解包 `{code,msg,data}` 信封,`response.data` 即内层 data; /// 兼容 data 为 `{appVersion: {...}}`、版本对象直接返回、或 null(无配置)三种形态。 Future?> searchAppVersion({ required String orgId, String? groupId, }) async { if (orgId.isEmpty && groupId == null) { throw const ApiException(400, 'orgId 与 groupId 需二选一'); } final response = await _dio.get( '/device/orgGroupAppVersion/search', queryParameters: { if (orgId.isNotEmpty) 'orgId': orgId, if (groupId != null) 'groupId': groupId, }, ); final data = response.data; if (data == null) return null; if (data is Map) { final appVersion = data['appVersion']; if (appVersion is Map) { return Map.from(appVersion); } // 直接是版本对象(含 id 或 versionName)。 if (data.containsKey('id') || data.containsKey('versionName')) { return data; } } return null; } /// 获取 APP 版本详情。 /// /// GET /device/orgGroupAppVersion/info/{id} Future getAppVersionInfo(String id) async { final response = await _dio.get('/device/orgGroupAppVersion/info/$id'); final data = response.data; if (data is! Map) { throw ApiException(500, 'APP 版本信息加载失败:$id'); } return AppVersion.fromJson(data); } /// 新增 APP 版本。 /// /// POST /device/orgGroupAppVersion/save,body 为版本数据。 Future saveAppVersion(Map data) async { await _dio.post( '/device/orgGroupAppVersion/save', data: data, ); } /// 修改 APP 版本。 /// /// POST /device/orgGroupAppVersion/update,body 为版本数据(含 id)。 Future updateAppVersion(Map data) async { await _dio.post( '/device/orgGroupAppVersion/update', data: data, ); } /// 批量删除 APP 版本。 /// /// POST /device/orgGroupAppVersion/delete,body 为 `{ids: [...]}`。 Future deleteAppVersion(List ids) async { await _dio.post( '/device/orgGroupAppVersion/delete', data: {'ids': ids}, ); } // ================ TV 应用管理 ================ /// 获取 TV 应用列表(分页,可按名称/组织/分组筛选)。 /// /// GET /theme/tvapp/list?page=&limit=&appName=&orgId=&groupId= Future> getTvAppList({ int page = 1, int limit = 20, String? appName, String? orgId, String? groupId, }) async { final effectiveOrgId = orgId ?? (SessionOrgScope.instance.enabled ? SessionOrgScope.instance.currentOrgId : null); final response = await _dio.get( '/theme/tvapp/list', queryParameters: { 'page': page, 'limit': limit, if (appName != null) 'appName': appName, if (effectiveOrgId != null) 'orgId': effectiveOrgId, if (groupId != null) 'groupId': groupId, }, ); final list = _extractList(response.data); return list .whereType>() .map(TvApp.fromJson) .toList(); } /// 获取 TV 应用详情。 /// /// GET /theme/tvapp/info/{id} Future getTvAppInfo(String id) async { final response = await _dio.get('/theme/tvapp/info/$id'); final data = response.data; if (data is! Map) { throw ApiException(500, 'TV 应用信息加载失败:$id'); } return TvApp.fromJson(data); } /// 新增或修改 TV 应用。 /// /// POST /theme/tvapp/save,body 为应用数据。 Future saveTvApp(Map data) async { await _dio.post('/theme/tvapp/save', data: data); } /// 批量删除 TV 应用。 /// /// POST /theme/tvapp/delete,body 为 `{ids: [...]}`。 Future deleteTvApp(List ids) async { await _dio.post( '/theme/tvapp/delete', data: {'ids': ids}, ); } // ================ 工具方法 ================ /// 兼容列表响应的三种形态: /// `{list: [...], totalCount}` / `{page: {list, totalCount}}` / 直接数组。 static List _extractList(dynamic data) { if (data is List) { return data; } if (data is Map) { final list = data['list']; if (list is List) { return list; } final page = data['page']; if (page is Map && page['list'] is List) { return page['list'] as List; } } return const []; } }