Browse Source

[feat]亲密度分析,对接获取亲密配置接口

hezihao 7 months ago
parent
commit
631b310df7

+ 7 - 0
lib/data/api/atmob_api.dart

@@ -36,6 +36,7 @@ import 'package:keyboard/data/api/response/chat_prologue_response.dart';
 import 'package:keyboard/data/api/response/chat_super_reply_response.dart';
 import 'package:keyboard/data/api/response/chat_super_speak_response.dart';
 import 'package:keyboard/data/api/response/config_response.dart';
+import 'package:keyboard/data/api/response/intimacy_analyze_config_response.dart';
 import 'package:keyboard/data/api/response/item_list_response.dart';
 import 'package:keyboard/data/api/response/item_retention_response.dart';
 import 'package:keyboard/data/api/response/keyboard_character_list_response.dart';
@@ -251,4 +252,10 @@ abstract class AtmobApi {
   Future<BaseResponse<ChatPrologueResponse>> chatPrologue(
     @Body() ChatPrologueRequest request,
   );
+
+  /// 获取亲密度配置
+  @POST("/project/keyboard/v1/intimacy/analyze/config")
+  Future<BaseResponse<IntimacyAnalyzeConfigResponse>> getIntimacyAnalyzeConfig(
+    @Body() AppBaseRequest request,
+  );
 }

+ 38 - 0
lib/data/api/atmob_api.g.dart

@@ -1165,6 +1165,44 @@ class _AtmobApi implements AtmobApi {
     return _value;
   }
 
+  @override
+  Future<BaseResponse<IntimacyAnalyzeConfigResponse>> getIntimacyAnalyzeConfig(
+    AppBaseRequest request,
+  ) async {
+    final _extra = <String, dynamic>{};
+    final queryParameters = <String, dynamic>{};
+    final _headers = <String, dynamic>{};
+    final _data = <String, dynamic>{};
+    _data.addAll(request.toJson());
+    final _options =
+        _setStreamType<BaseResponse<IntimacyAnalyzeConfigResponse>>(
+          Options(method: 'POST', headers: _headers, extra: _extra)
+              .compose(
+                _dio.options,
+                '/project/keyboard/v1/intimacy/analyze/config',
+                queryParameters: queryParameters,
+                data: _data,
+              )
+              .copyWith(
+                baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl),
+              ),
+        );
+    final _result = await _dio.fetch<Map<String, dynamic>>(_options);
+    late BaseResponse<IntimacyAnalyzeConfigResponse> _value;
+    try {
+      _value = BaseResponse<IntimacyAnalyzeConfigResponse>.fromJson(
+        _result.data!,
+        (json) => IntimacyAnalyzeConfigResponse.fromJson(
+          json as Map<String, dynamic>,
+        ),
+      );
+    } on Object catch (e, s) {
+      errorLogger?.logError(e, s, _options);
+      rethrow;
+    }
+    return _value;
+  }
+
   RequestOptions _setStreamType<T>(RequestOptions requestOptions) {
     if (T != dynamic &&
         !(requestOptions.responseType == ResponseType.bytes ||

+ 46 - 4
lib/data/api/response/intimacy_analyze_config_response.dart

@@ -1,16 +1,58 @@
 import 'package:json_annotation/json_annotation.dart';
 
-import '../../bean/intimacy_analyze_config.dart';
+import '../../bean/ai_model.dart';
+import '../../bean/intimacy_analyze_direction.dart';
 
 part 'intimacy_analyze_config_response.g.dart';
 
+/// 亲密度配置
 @JsonSerializable()
 class IntimacyAnalyzeConfigResponse {
-  @JsonKey(name: "config")
-  late final IntimacyAnalyzeConfig config;
+  /// 默认分析结果,markdown格式
+  @JsonKey(name: 'defaultContent')
+  String? defaultContent;
 
-  IntimacyAnalyzeConfigResponse({required this.config});
+  /// 最大图片上传数
+  @JsonKey(name: 'maxImageCount')
+  int? maxImageCount;
+
+  /// 最小图片上传数
+  @JsonKey(name: 'minImageCount')
+  int? minImageCount;
+
+  /// 是否可以自定义方向
+  @JsonKey(name: 'custom')
+  bool? custom;
+
+  /// 最大自定义字符数
+  @JsonKey(name: 'maxCustomWords')
+  int? maxCustomWords;
+
+  /// 最小自定义字符数
+  @JsonKey(name: 'minCustomWords')
+  int? minCustomWords;
+
+  /// 预测方向
+  @JsonKey(name: 'direction')
+  List<IntimacyAnalyzeDirection>? direction;
+
+  /// 模型选项列表
+  @JsonKey(name: 'modes')
+  List<AiModel>? modes;
+
+  IntimacyAnalyzeConfigResponse(
+    this.defaultContent,
+    this.maxImageCount,
+    this.minImageCount,
+    this.custom,
+    this.maxCustomWords,
+    this.minCustomWords,
+    this.direction,
+    this.modes,
+  );
 
   factory IntimacyAnalyzeConfigResponse.fromJson(Map<String, dynamic> json) =>
       _$IntimacyAnalyzeConfigResponseFromJson(json);
+
+  Map<String, dynamic> toJson() => _$IntimacyAnalyzeConfigResponseToJson(this);
 }

+ 22 - 4
lib/data/api/response/intimacy_analyze_config_response.g.dart

@@ -9,11 +9,29 @@ part of 'intimacy_analyze_config_response.dart';
 IntimacyAnalyzeConfigResponse _$IntimacyAnalyzeConfigResponseFromJson(
   Map<String, dynamic> json,
 ) => IntimacyAnalyzeConfigResponse(
-  config: IntimacyAnalyzeConfig.fromJson(
-    json['config'] as Map<String, dynamic>,
-  ),
+  json['defaultContent'] as String?,
+  (json['maxImageCount'] as num?)?.toInt(),
+  (json['minImageCount'] as num?)?.toInt(),
+  json['custom'] as bool?,
+  (json['maxCustomWords'] as num?)?.toInt(),
+  (json['minCustomWords'] as num?)?.toInt(),
+  (json['direction'] as List<dynamic>?)
+      ?.map((e) => IntimacyAnalyzeDirection.fromJson(e as Map<String, dynamic>))
+      .toList(),
+  (json['modes'] as List<dynamic>?)
+      ?.map((e) => AiModel.fromJson(e as Map<String, dynamic>))
+      .toList(),
 );
 
 Map<String, dynamic> _$IntimacyAnalyzeConfigResponseToJson(
   IntimacyAnalyzeConfigResponse instance,
-) => <String, dynamic>{'config': instance.config};
+) => <String, dynamic>{
+  'defaultContent': instance.defaultContent,
+  'maxImageCount': instance.maxImageCount,
+  'minImageCount': instance.minImageCount,
+  'custom': instance.custom,
+  'maxCustomWords': instance.maxCustomWords,
+  'minCustomWords': instance.minCustomWords,
+  'direction': instance.direction,
+  'modes': instance.modes,
+};

+ 22 - 0
lib/data/bean/ai_model.dart

@@ -0,0 +1,22 @@
+import 'package:json_annotation/json_annotation.dart';
+
+part 'ai_model.g.dart';
+
+/// Ai模型实体类
+@JsonSerializable()
+class AiModel {
+  /// 模型名称
+  @JsonKey(name: "name")
+  String? name;
+
+  /// 实际发送给服务端的值
+  @JsonKey(name: "value")
+  String? value;
+
+  AiModel(this.name, this.value);
+
+  factory AiModel.fromJson(Map<String, dynamic> json) =>
+      _$AiModelFromJson(json);
+
+  Map<String, dynamic> toJson() => _$AiModelToJson(this);
+}

+ 15 - 0
lib/data/bean/ai_model.g.dart

@@ -0,0 +1,15 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'ai_model.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+AiModel _$AiModelFromJson(Map<String, dynamic> json) =>
+    AiModel(json['name'] as String?, json['value'] as String?);
+
+Map<String, dynamic> _$AiModelToJson(AiModel instance) => <String, dynamic>{
+  'name': instance.name,
+  'value': instance.value,
+};

+ 0 - 57
lib/data/bean/intimacy_analyze_config.dart

@@ -1,57 +0,0 @@
-import 'package:json_annotation/json_annotation.dart';
-
-import 'intimacy_analyze_direction.dart';
-
-part 'intimacy_analyze_config.g.dart';
-
-/// 亲密度配置
-@JsonSerializable()
-class IntimacyAnalyzeConfig {
-  // 默认分析结果,markdown格式
-  @JsonKey(name: 'defaultContent')
-  String? defaultContent;
-
-  // 最大图片上传数
-  @JsonKey(name: 'maxImageCount')
-  int? maxImageCount;
-
-  // 最小图片上传数
-  @JsonKey(name: 'minImageCount')
-  int? minImageCount;
-
-  // 是否可以自定义方向
-  @JsonKey(name: 'custom')
-  bool? custom;
-
-  // 最大自定义字符数
-  @JsonKey(name: 'maxCustomWords')
-  int? maxCustomWords;
-
-  // 最小自定义字符数
-  @JsonKey(name: 'minCustomWords')
-  int? minCustomWords;
-
-  // 预测方向
-  @JsonKey(name: 'direction')
-  List<IntimacyAnalyzeDirection>? direction;
-
-  // 模型选项
-  @JsonKey(name: 'models')
-  List<String>? models;
-
-  IntimacyAnalyzeConfig(
-    this.defaultContent,
-    this.maxImageCount,
-    this.minImageCount,
-    this.custom,
-    this.maxCustomWords,
-    this.minCustomWords,
-    this.direction,
-    this.models,
-  );
-
-  factory IntimacyAnalyzeConfig.fromJson(Map<String, dynamic> json) =>
-      _$IntimacyAnalyzeConfigFromJson(json);
-
-  Map<String, dynamic> toJson() => _$IntimacyAnalyzeConfigToJson(this);
-}

+ 0 - 35
lib/data/bean/intimacy_analyze_config.g.dart

@@ -1,35 +0,0 @@
-// GENERATED CODE - DO NOT MODIFY BY HAND
-
-part of 'intimacy_analyze_config.dart';
-
-// **************************************************************************
-// JsonSerializableGenerator
-// **************************************************************************
-
-IntimacyAnalyzeConfig _$IntimacyAnalyzeConfigFromJson(
-  Map<String, dynamic> json,
-) => IntimacyAnalyzeConfig(
-  json['defaultContent'] as String?,
-  (json['maxImageCount'] as num?)?.toInt(),
-  (json['minImageCount'] as num?)?.toInt(),
-  json['custom'] as bool?,
-  (json['maxCustomWords'] as num?)?.toInt(),
-  (json['minCustomWords'] as num?)?.toInt(),
-  (json['direction'] as List<dynamic>?)
-      ?.map((e) => IntimacyAnalyzeDirection.fromJson(e as Map<String, dynamic>))
-      .toList(),
-  (json['models'] as List<dynamic>?)?.map((e) => e as String).toList(),
-);
-
-Map<String, dynamic> _$IntimacyAnalyzeConfigToJson(
-  IntimacyAnalyzeConfig instance,
-) => <String, dynamic>{
-  'defaultContent': instance.defaultContent,
-  'maxImageCount': instance.maxImageCount,
-  'minImageCount': instance.minImageCount,
-  'custom': instance.custom,
-  'maxCustomWords': instance.maxCustomWords,
-  'minCustomWords': instance.minCustomWords,
-  'direction': instance.direction,
-  'models': instance.models,
-};

+ 48 - 0
lib/data/repository/intimacy_analyze_repository.dart

@@ -0,0 +1,48 @@
+import 'package:get/get_rx/src/rx_types/rx_types.dart';
+import 'package:injectable/injectable.dart';
+import 'package:keyboard/base/app_base_request.dart';
+
+import '../../di/get_it.dart';
+import '../../utils/async_util.dart';
+import '../../utils/atmob_log.dart';
+import '../../utils/http_handler.dart';
+import '../api/atmob_api.dart';
+import '../api/response/intimacy_analyze_config_response.dart';
+
+/// 亲密度分析Repository层
+@LazySingleton()
+class IntimacyAnalyzeRepository {
+  final String tag = "IntimacyAnalyzeRepository";
+
+  final AtmobApi atmobApi;
+
+  /// 亲密度配置
+  Rxn<IntimacyAnalyzeConfigResponse> intimacyAnalyzeConfig = Rxn<IntimacyAnalyzeConfigResponse>();
+
+  IntimacyAnalyzeRepository(this.atmobApi) {
+    AtmobLog.d(tag, '$tag...init');
+    // 初始化时,刷新配置
+    refreshIntimacyAnalyzeConfig();
+  }
+
+  /// 从Getx的依赖注入中,获取实例,适合在没有依赖注入上下文的地方使用
+  IntimacyAnalyzeRepository getInstance() {
+    return getIt.get<IntimacyAnalyzeRepository>();
+  }
+
+  /// 刷新亲密度配置
+  void refreshIntimacyAnalyzeConfig() {
+    AsyncUtil.retry(() => requestIntimacyAnalyzeConfig(), Duration(seconds: 3),
+      maxRetry: 100,).then((IntimacyAnalyzeConfigResponse configResponse) {
+      AtmobLog.d(tag, "获取亲密度配置成功: ${configResponse.toJson()}");
+      intimacyAnalyzeConfig.value = configResponse;
+    });
+  }
+
+  /// 获取亲密度配置
+  Future<IntimacyAnalyzeConfigResponse> requestIntimacyAnalyzeConfig() {
+    return atmobApi
+        .getIntimacyAnalyzeConfig(AppBaseRequest())
+        .then(HttpHandler.handle(true));
+  }
+}

+ 9 - 3
lib/di/get_it.config.dart

@@ -21,6 +21,7 @@ import '../data/repository/account_repository.dart' as _i83;
 import '../data/repository/characters_repository.dart' as _i421;
 import '../data/repository/chat_repository.dart' as _i425;
 import '../data/repository/config_repository.dart' as _i50;
+import '../data/repository/intimacy_analyze_repository.dart' as _i283;
 import '../data/repository/keyboard_repository.dart' as _i274;
 import '../data/repository/store_repository.dart' as _i987;
 import '../dialog/content/character_add_tab_controller.dart' as _i991;
@@ -90,9 +91,6 @@ extension GetItInjectableX on _i174.GetIt {
     gh.factory<_i859.ChangeNicknameController>(
       () => _i859.ChangeNicknameController(),
     );
-    gh.factory<_i987.IntimacyAnalyseReportController>(
-      () => _i987.IntimacyAnalyseReportController(),
-    );
     gh.factory<_i1071.ImageViewerController>(
       () => _i1071.ImageViewerController(),
     );
@@ -150,6 +148,9 @@ extension GetItInjectableX on _i174.GetIt {
     gh.lazySingleton<_i274.KeyboardRepository>(
       () => _i274.KeyboardRepository(gh<_i243.AtmobApi>()),
     );
+    gh.lazySingleton<_i283.IntimacyAnalyzeRepository>(
+      () => _i283.IntimacyAnalyzeRepository(gh<_i243.AtmobApi>()),
+    );
     gh.factoryParam<
       _i293.CharacterTabGroupContentController,
       _i96.CharacterGroupInfo,
@@ -257,6 +258,11 @@ extension GetItInjectableX on _i174.GetIt {
         gh<_i50.ConfigRepository>(),
       ),
     );
+    gh.factory<_i987.IntimacyAnalyseReportController>(
+      () => _i987.IntimacyAnalyseReportController(
+        gh<_i283.IntimacyAnalyzeRepository>(),
+      ),
+    );
     gh.factory<_i1059.CharacterCustomListController>(
       () => _i1059.CharacterCustomListController(
         gh<_i421.CharactersRepository>(),

+ 23 - 20
lib/module/intimacy_analyse/analyse_report/intimacy_analyse_report_view.dart

@@ -1,5 +1,6 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_screenutil/flutter_screenutil.dart';
+import 'package:get/get.dart';
 import 'package:keyboard/base/base_view.dart';
 import '../../../resource/assets.gen.dart';
 import '../../../resource/colors.gen.dart';
@@ -27,26 +28,28 @@ class IntimacyAnalyseReportView
             width: double.infinity,
             height: double.infinity,
             child: SingleChildScrollView(
-              child: Column(
-                children: [
-                  SizedBox(height: 35.h),
-                  // 亲密度档案
-                  Row(
-                    mainAxisAlignment: MainAxisAlignment.center,
-                    children: [_buildIntimacyArchives()],
-                  ),
-                  SizedBox(height: 12.h),
-                  // 切换亲密度
-                  _buildIntimacyArchivesSwitchLayout(),
-                  SizedBox(height: 18.h),
-                  // 报告预览
-                  IntimacyAnalyseReportWidget(
-                    reportContent: controller.reportPreviewData.value,
-                    isPreview: true,
-                  ),
-                  SizedBox(height: 120.h),
-                ],
-              ),
+              child: Obx(() {
+                return Column(
+                  children: [
+                    SizedBox(height: 35.h),
+                    // 亲密度档案
+                    Row(
+                      mainAxisAlignment: MainAxisAlignment.center,
+                      children: [_buildIntimacyArchives()],
+                    ),
+                    SizedBox(height: 12.h),
+                    // 切换亲密度
+                    _buildIntimacyArchivesSwitchLayout(),
+                    SizedBox(height: 18.h),
+                    // 报告预览
+                    IntimacyAnalyseReportWidget(
+                      reportContent: controller.reportPreviewData.value,
+                      isPreview: true,
+                    ),
+                    SizedBox(height: 120.h),
+                  ],
+                );
+              }),
             ),
           ),
         ),

+ 30 - 17
lib/module/intimacy_analyse/analyse_report/intimacy_analyse_report_view_controller.dart

@@ -3,35 +3,48 @@ import 'package:get/get.dart';
 import 'package:injectable/injectable.dart';
 import 'package:keyboard/base/base_controller.dart';
 import 'package:wechat_assets_picker/wechat_assets_picker.dart';
+import '../../../data/api/response/intimacy_analyze_config_response.dart';
+import '../../../data/repository/intimacy_analyze_repository.dart';
 import '../../../utils/image_picker_util.dart';
 import '../intimacy_analyse_upload/intimacy_analyse_upload_page.dart';
 
 /// 亲密度分析-分析报告Tab-Controller
 @injectable
 class IntimacyAnalyseReportController extends BaseController {
-  /// 报告预览数据
-  RxString reportPreviewData =
-      '''
-  **性格匹配度**
+  /// 亲密度分析Repository
+  IntimacyAnalyzeRepository intimacyAnalyzeRepository;
+
+  /// 亲密度配置
+  Rxn<IntimacyAnalyzeConfigResponse> get intimacyAnalyzeConfig =>
+      intimacyAnalyzeRepository.intimacyAnalyzeConfig;
 
-  ● 互补型:一方外向活泼,另一方沉稳内敛,形成动态平衡。
-  ● 相似型:三观一致,兴趣重叠,减少摩擦但需警惕新鲜感流失。
-  ● 关键结论:差异是火花的来源,但核心价值观需一致(如家庭观、金钱观)。
+  /// 报告预览数据
+  RxString reportPreviewData = "".obs;
 
-  **沟通模式分析**
+  /// 报告预览-气泡文本
+  RxString reportPreviewBubbleText = '报告还有2565字未显示,点击按钮查看完整报告'.obs;
 
-  ● 语言风格:幽默调侃型 vs 理性分析型 → 需找到共同表达方式。
-  ● 冲突解决:回避型 vs 直面型 → 建议建立“冷静-沟通”机制。
-  ● 情感需求:一方需要高频互动,另一方偏好独立空间 → 需协商平衡点。
+  IntimacyAnalyseReportController(this.intimacyAnalyzeRepository);
 
-  **爱情语言测试**
+  @override
+  void onInit() {
+    super.onInit();
+    ever<IntimacyAnalyzeConfigResponse?>(intimacyAnalyzeConfig, (config) {
+      updateIntimacyAnalyzeConfig(config);
+    });
+  }
 
-  ● 根据盖瑞·查普曼的“五种爱之语”理论,分析双方的情感表达偏好:
-  ● 你的主要爱语:肯定的言辞(如情话、鼓励)
-  '''.obs;
+  @override
+  void onReady() {
+    super.onReady();
+    updateIntimacyAnalyzeConfig(intimacyAnalyzeConfig.value);
+  }
 
-  /// 报告预览-气泡文本
-  RxString reportPreviewBubbleText = '报告还有2565字未显示,点击按钮查看完整报告'.obs;
+  /// 更新亲密度配置
+  void updateIntimacyAnalyzeConfig(IntimacyAnalyzeConfigResponse? config) {
+    // 给页面的响应式变量赋值
+    reportPreviewData.value = (config != null ? config.defaultContent : "")!;
+  }
 
   /// 切换亲密档案
   void clickIntimacyArchivesSwitch() {}