소스 검색

[feat]亲密度分析,截图回复-识图回复,回复模式列表数据,对接配置接口

hezihao 7 달 전
부모
커밋
f24be4a2ea

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

@@ -14,6 +14,7 @@ import 'package:keyboard/data/api/request/chat_super_speak_request.dart';
 import 'package:keyboard/data/api/request/complaint_submit_request.dart';
 import 'package:keyboard/data/api/request/config_request.dart';
 import 'package:keyboard/data/api/request/intimacy_analyze_request.dart';
+import 'package:keyboard/data/api/request/intimacy_reply_analyze_request.dart';
 import 'package:keyboard/data/api/request/keyboard_character_list_request.dart';
 import 'package:keyboard/data/api/request/keyboard_character_update_request.dart';
 import 'package:keyboard/data/api/request/keyboard_choose_request.dart';
@@ -281,6 +282,12 @@ abstract class AtmobApi {
   Future<BaseResponse<IntimacyAnalyzeReplyConfigResponse>>
   getIntimacyAnalyzeReplyConfig(@Body() AppBaseRequest request);
 
+  /// 识图回复
+  @POST("/project/keyboard/v1/intimacy/reply/analyze")
+  Future<BaseResponse> intimacyReplyAnalyze(
+    @Body() IntimacyReplyAnalyzeRequest request,
+  );
+
   // 获取星座梗语与解读
   @POST("/project/keyboard/v1/keyboard/memeExplain")
   Future<BaseResponse<KeyboardMemeExplainResponse>> getKeyboardMemeExplain(

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

@@ -1312,6 +1312,39 @@ class _AtmobApi implements AtmobApi {
   }
 
   @override
+  Future<BaseResponse<dynamic>> intimacyReplyAnalyze(
+    IntimacyReplyAnalyzeRequest 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<dynamic>>(
+      Options(method: 'POST', headers: _headers, extra: _extra)
+          .compose(
+            _dio.options,
+            '/project/keyboard/v1/intimacy/reply/analyze',
+            queryParameters: queryParameters,
+            data: _data,
+          )
+          .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
+    );
+    final _result = await _dio.fetch<Map<String, dynamic>>(_options);
+    late BaseResponse<dynamic> _value;
+    try {
+      _value = BaseResponse<dynamic>.fromJson(
+        _result.data!,
+        (json) => json as dynamic,
+      );
+    } on Object catch (e, s) {
+      errorLogger?.logError(e, s, _options);
+      rethrow;
+    }
+    return _value;
+  }
+
+  @override
   Future<BaseResponse<KeyboardMemeExplainResponse>> getKeyboardMemeExplain(
     KeyboardMemeExplainRequest request,
   ) async {

+ 25 - 0
lib/data/api/request/intimacy_reply_analyze_request.dart

@@ -0,0 +1,25 @@
+import 'package:json_annotation/json_annotation.dart';
+import 'package:keyboard/base/app_base_request.dart';
+
+part 'intimacy_reply_analyze_request.g.dart';
+
+/// 识图回复的请求
+@JsonSerializable()
+class IntimacyReplyAnalyzeRequest extends AppBaseRequest {
+  /// 图片地址列表,不加cdn前缀
+  @JsonKey(name: "imageList")
+  List<String> imageList;
+
+  /// 语气标题
+  @JsonKey(name: "title")
+  String title;
+
+  /// 模式
+  @JsonKey(name: "mode")
+  String mode;
+
+  IntimacyReplyAnalyzeRequest(this.imageList, this.title, this.mode);
+
+  @override
+  Map<String, dynamic> toJson() => _$IntimacyReplyAnalyzeRequestToJson(this);
+}

+ 76 - 0
lib/data/api/request/intimacy_reply_analyze_request.g.dart

@@ -0,0 +1,76 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'intimacy_reply_analyze_request.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+IntimacyReplyAnalyzeRequest _$IntimacyReplyAnalyzeRequestFromJson(
+  Map<String, dynamic> json,
+) =>
+    IntimacyReplyAnalyzeRequest(
+        (json['imageList'] as List<dynamic>).map((e) => e as String).toList(),
+        json['title'] as String,
+        json['mode'] as String,
+      )
+      ..appPlatform = (json['appPlatform'] as num).toInt()
+      ..os = json['os'] as String
+      ..osVersion = json['osVersion'] as String
+      ..packageName = json['packageName'] as String?
+      ..appVersionName = json['appVersionName'] as String?
+      ..appVersionCode = (json['appVersionCode'] as num?)?.toInt()
+      ..channelName = json['channelName'] as String?
+      ..appId = (json['appId'] as num?)?.toInt()
+      ..tgPlatform = (json['tgPlatform'] as num?)?.toInt()
+      ..oaid = json['oaid'] as String?
+      ..aaid = json['aaid'] as String?
+      ..androidId = json['androidId'] as String?
+      ..imei = json['imei'] as String?
+      ..simImei0 = json['simImei0'] as String?
+      ..simImei1 = json['simImei1'] as String?
+      ..mac = json['mac'] as String?
+      ..idfa = json['idfa'] as String?
+      ..idfv = json['idfv'] as String?
+      ..machineId = json['machineId'] as String?
+      ..brand = json['brand'] as String?
+      ..model = json['model'] as String?
+      ..wifiName = json['wifiName'] as String?
+      ..region = json['region'] as String?
+      ..locLng = (json['locLng'] as num?)?.toDouble()
+      ..locLat = (json['locLat'] as num?)?.toDouble()
+      ..authToken = json['authToken'] as String?;
+
+Map<String, dynamic> _$IntimacyReplyAnalyzeRequestToJson(
+  IntimacyReplyAnalyzeRequest instance,
+) => <String, dynamic>{
+  'appPlatform': instance.appPlatform,
+  'os': instance.os,
+  'osVersion': instance.osVersion,
+  'packageName': instance.packageName,
+  'appVersionName': instance.appVersionName,
+  'appVersionCode': instance.appVersionCode,
+  'channelName': instance.channelName,
+  'appId': instance.appId,
+  'tgPlatform': instance.tgPlatform,
+  'oaid': instance.oaid,
+  'aaid': instance.aaid,
+  'androidId': instance.androidId,
+  'imei': instance.imei,
+  'simImei0': instance.simImei0,
+  'simImei1': instance.simImei1,
+  'mac': instance.mac,
+  'idfa': instance.idfa,
+  'idfv': instance.idfv,
+  'machineId': instance.machineId,
+  'brand': instance.brand,
+  'model': instance.model,
+  'wifiName': instance.wifiName,
+  'region': instance.region,
+  'locLng': instance.locLng,
+  'locLat': instance.locLat,
+  'authToken': instance.authToken,
+  'imageList': instance.imageList,
+  'title': instance.title,
+  'mode': instance.mode,
+};

+ 6 - 1
lib/data/api/response/intimacy_analyze_reply_config_response.dart

@@ -5,6 +5,7 @@ import 'package:keyboard/data/api/response/tone_bean.dart';
 
 import '../../bean/ai_model.dart';
 import '../../bean/intimacy_analyze_direction.dart';
+import '../../bean/reply_mode.dart';
 
 part 'intimacy_analyze_reply_config_response.g.dart';
 
@@ -15,7 +16,11 @@ class IntimacyAnalyzeReplyConfigResponse {
   @JsonKey(name: 'tones')
   List<ToneBean>? tones;
 
-  IntimacyAnalyzeReplyConfigResponse(this.tones);
+  /// 模式
+  @JsonKey(name: "modes")
+  List<ReplyMode> modes;
+
+  IntimacyAnalyzeReplyConfigResponse(this.tones, this.modes);
 
   factory IntimacyAnalyzeReplyConfigResponse.fromJson(
     Map<String, dynamic> json,

+ 4 - 1
lib/data/api/response/intimacy_analyze_reply_config_response.g.dart

@@ -12,8 +12,11 @@ IntimacyAnalyzeReplyConfigResponse _$IntimacyAnalyzeReplyConfigResponseFromJson(
   (json['tones'] as List<dynamic>?)
       ?.map((e) => ToneBean.fromJson(e as Map<String, dynamic>))
       .toList(),
+  (json['modes'] as List<dynamic>)
+      .map((e) => ReplyMode.fromJson(e as Map<String, dynamic>))
+      .toList(),
 );
 
 Map<String, dynamic> _$IntimacyAnalyzeReplyConfigResponseToJson(
   IntimacyAnalyzeReplyConfigResponse instance,
-) => <String, dynamic>{'tones': instance.tones};
+) => <String, dynamic>{'tones': instance.tones, 'modes': instance.modes};

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

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

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

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

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

@@ -10,6 +10,7 @@ import '../../utils/atmob_log.dart';
 import '../../utils/http_handler.dart';
 import '../api/atmob_api.dart';
 import '../api/request/intimacy_analyze_request.dart';
+import '../api/request/intimacy_reply_analyze_request.dart';
 import '../api/response/intimacy_analyze_chat_config_response.dart';
 import '../api/response/intimacy_analyze_config_response.dart';
 import '../api/response/intimacy_analyze_reply_config_response.dart';
@@ -111,4 +112,13 @@ class IntimacyAnalyzeRepository {
   ) {
     return atmobApi.getIntimacyAnalyze(request).then(HttpHandler.handle(true));
   }
+
+  // /// 识图回复
+  // Future<Object> intimacyReplyAnalyze(
+  //   IntimacyReplyAnalyzeRequest request,
+  // ) {
+  //   return atmobApi
+  //       .intimacyReplyAnalyze(request)
+  //       .then(HttpHandler.handle(true));
+  // }
 }

+ 9 - 8
lib/module/intimacy_analyse/intimacy_analyse_upload/popup/reply_mode_select_popup.dart

@@ -3,11 +3,12 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
 import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
 import 'package:keyboard/resource/colors.gen.dart';
 
+import '../../../../data/bean/reply_mode.dart';
 import '../../../../resource/assets.gen.dart';
 import '../../../../widget/gradient_text.dart';
 
 /// 选择新的Ai模型时回调
-typedef OnChooseReplyModeCallback = void Function(String newMode);
+typedef OnChooseReplyModeCallback = void Function(ReplyMode newMode);
 
 /// 回复模式选择,Popup锚点弹窗
 class ReplyModeSelectPopup {
@@ -30,8 +31,8 @@ class ReplyModeSelectPopup {
   static void show(
     GlobalKey anchorBtnKey,
     BuildContext context, {
-    required List<String> modeList,
-    required String currentMode,
+    required List<ReplyMode> modeList,
+    required ReplyMode currentMode,
     required OnChooseReplyModeCallback onChooseReplyModeCallback,
   }) {
     if (_isShowing) {
@@ -109,7 +110,7 @@ class ReplyModeSelectPopup {
                   padding: EdgeInsets.zero,
                   itemCount: modeList.length,
                   itemBuilder: (BuildContext context, int index) {
-                    String itemData = modeList[index];
+                    ReplyMode itemData = modeList[index];
                     return _buildListItem(
                       index,
                       itemData,
@@ -149,7 +150,7 @@ class ReplyModeSelectPopup {
   /// 列表项
   static Widget _buildListItem(
     int index,
-    String itemData,
+    ReplyMode itemData,
     bool isSelected,
     OnChooseReplyModeCallback onChooseReplyModeCallback,
   ) {
@@ -170,7 +171,7 @@ class ReplyModeSelectPopup {
           ),
           child: Center(
             child: Text(
-              itemData,
+              itemData.name ?? "",
               style: TextStyle(
                 color: ColorName.black80,
                 fontSize: 14.sp,
@@ -184,7 +185,7 @@ class ReplyModeSelectPopup {
   }
 
   /// 当前选中项
-  static Widget _buildCurrentSelectItem(String currentSelect) {
+  static Widget _buildCurrentSelectItem(ReplyMode currentSelect) {
     return GestureDetector(
       onTap: () {
         dismiss();
@@ -202,7 +203,7 @@ class ReplyModeSelectPopup {
                 ColorName.aiModelSwitchBtnColor2,
               ],
               child: Text(
-                currentSelect,
+                currentSelect.name ?? "",
                 style: TextStyle(fontSize: 14.sp, fontWeight: FontWeight.w500),
               ),
             ),

+ 19 - 4
lib/module/intimacy_analyse/screenshot_reply/scan_image_reply/scan_image_reply_controller.dart

@@ -10,6 +10,7 @@ import 'package:wechat_assets_picker/wechat_assets_picker.dart';
 
 import '../../../../data/bean/option_select_config.dart';
 import '../../../../data/bean/option_select_item.dart';
+import '../../../../data/bean/reply_mode.dart';
 import '../../../../utils/image_picker_util.dart';
 import '../../../../utils/intimacy_analyze_config_helper.dart';
 import '../../../../utils/upload/upload_file_manager.dart';
@@ -41,10 +42,10 @@ class ScanImageReplyController extends BaseController {
   Rxn<UploadInfo> uploadInfo = Rxn();
 
   /// Ai模型列表
-  RxList<String> replyModelList = <String>['评论模式', '搭讪模式'].obs;
+  RxList<ReplyMode> replyModelList = <ReplyMode>[].obs;
 
   /// 当前应用的Ai模型
-  Rx<String> currentReplyMode = '评论模式'.obs;
+  Rxn<ReplyMode> currentReplyMode = Rxn();
 
   /// 回复语气列表
   RxList<String> replyToneList = <String>["真好", "真好看", "真的很好看~"].obs;
@@ -58,9 +59,10 @@ class ScanImageReplyController extends BaseController {
   void onReady() {
     super.onReady();
     _initReplyToneOptionSelectConfigList();
+    _initReplyModeList();
   }
 
-  /// 回复语气列表
+  /// 初始化回复语气列表
   void _initReplyToneOptionSelectConfigList() {
     // 语气列表
     var toneList =
@@ -80,6 +82,19 @@ class ScanImageReplyController extends BaseController {
     }
   }
 
+  /// 初始化回复模式
+  void _initReplyModeList() {
+    var modeList = intimacyAnalyzeConfigHelper.intimacyAnalyzeReplyConfig.value?.modes ?? [];
+    replyModelList.addAll(modeList);
+    replyModelList.refresh();
+
+    // 默认选中第一个模式
+    if (modeList.isNotEmpty) {
+      currentReplyMode.value = replyModelList[0];
+      currentReplyMode.refresh();
+    }
+  }
+
   /// 选中回复语气的选项
   void selectReplyToneOption(
     OptionSelectConfig rowConfig,
@@ -101,7 +116,7 @@ class ScanImageReplyController extends BaseController {
   }
 
   /// 切换回复模型
-  void switchReplyMode(String newMode) {
+  void switchReplyMode(ReplyMode newMode) {
     currentReplyMode.value = newMode;
   }
 

+ 4 - 3
lib/module/intimacy_analyse/screenshot_reply/scan_image_reply/scan_image_reply_view.dart

@@ -6,6 +6,7 @@ import 'package:keyboard/data/bean/upload_info.dart';
 import '../../../../data/bean/image_viewer_item.dart';
 import '../../../../data/bean/option_select_config.dart';
 import '../../../../data/bean/option_select_item.dart';
+import '../../../../data/bean/reply_mode.dart';
 import '../../../../resource/assets.gen.dart';
 import '../../../../resource/colors.gen.dart';
 import '../../../../resource/string.gen.dart';
@@ -545,8 +546,8 @@ class ScanImageReplyView extends BaseView<ScanImageReplyController> {
               _replyModeSwitchBtnAnchorKey,
               context,
               modeList: controller.replyModelList.toList(),
-              currentMode: controller.currentReplyMode.value,
-              onChooseReplyModeCallback: (String newMode) {
+              currentMode: controller.currentReplyMode.value!,
+              onChooseReplyModeCallback: (ReplyMode newMode) {
                 controller.switchReplyMode(newMode);
               },
             );
@@ -574,7 +575,7 @@ class ScanImageReplyView extends BaseView<ScanImageReplyController> {
                       ColorName.aiModelSwitchBtnColor2,
                     ],
                     child: Text(
-                      controller.currentReplyMode.value,
+                      controller.currentReplyMode.value?.name ?? "",
                       style: TextStyle(
                         fontSize: 14.sp,
                         fontWeight: FontWeight.w500,