Sfoglia il codice sorgente

[new]新增意见建议和投诉举报界面

Destiny 1 anno fa
parent
commit
5ba6639897

BIN
assets/images/icon_complaint_and_report.webp


BIN
assets/images/icon_opinion_and_suggestion.webp


+ 6 - 8
assets/string/base/string.xml

@@ -24,6 +24,7 @@
     <string name="user_agreement">用户协议</string>
     <string name="main_drawer_check_updates">检查更新</string>
     <string name="main_drawer_complaint_and_report">投诉举报</string>
+    <string name="main_drawer_opinion_and_suggestion">意见建议</string>
     <string name="main_drawer_logout">退出登录</string>
     <string name="main_drawer_logoff">注销账号</string>
     <string name="main_drawer_record_number">备案号216545885</string>
@@ -42,8 +43,7 @@
     <string name="talk_rename_title_hint">请输入谈话记录标题</string>
     <string name="talk_rename_success">修改成功</string>
     <string name="talk_rename_fail">修改失败</string>
-    <string name="talk_rename_delete_prompt">是否删除“%s”模板?该谈话包含您的待办事项,将一并删除。
-    </string>
+    <string name="talk_rename_delete_prompt">是否删除“%s”模板?该谈话包含您的待办事项,将一并删除。</string>
     <string name="talk_delete_success">删除成功</string>
     <string name="talk_delete_fail">删除失败</string>
     <string name="talk_tab_summary">谈话总结</string>
@@ -58,6 +58,7 @@
     <string name="talk_analyse_fail">分析失败</string>
     <string name="talk_analyse_low_toast">小听电量太低,不足以分析这段谈话</string>
     <string name="talk_analyse_summary_fail">谈话分析失败,点击去</string>
+    <string name="talk_analyse_fail_feedback">反馈问题</string>
     <string name="talk_todo_title">待办事项</string>
     <string name="talk_todo_item">项</string>
     <string name="talk_todo_all">所有待办</string>
@@ -66,8 +67,7 @@
     <string name="record_status_pending">准备开始录音</string>
     <string name="record_status_recording">我正在听...</string>
     <string name="record_status_paused">录音已暂停</string>
-    <string name="talk_traffic_remind_title">您未在WIFI环境中,此次分析约消耗%s的流量,请问是否继续?
-    </string>
+    <string name="talk_traffic_remind_title">您未在WIFI环境中,此次分析约消耗%s的流量,请问是否继续?</string>
     <string name="talk_traffic_remind_tips">以后不再提示</string>
     <string name="talk_upload_file_not_exist">文件不存在</string>
     <string name="talk_audio_loading">音频正在加载中</string>
@@ -87,8 +87,7 @@
     <string name="load_failed">加载失败</string>
     <string name="talk_analysis_success">谈话分析已完成</string>
     <string name="talk_analysis_success_btn_txt">查看</string>
-    <string name="account_logout_tips">确定要注销此账号吗?一旦注销,账号信息将永久消失,无法恢复。
-    </string>
+    <string name="account_logout_tips">确定要注销此账号吗?一旦注销,账号信息将永久消失,无法恢复。</string>
     <string name="account_logout_success">注销成功</string>
     <string name="error_code_no_login">账号未登录</string>
     <string name="record_notification_channel_id">record</string>
@@ -136,8 +135,7 @@
     <string name="recording_duration_cannot_less_than_3s">录音时长不能低于3秒</string>
     <string name="audio_not_support_type">不支持该格式</string>
     <string name="add_desktop_shortcut">添加快听到桌面</string>
-    <string name="add_desktop_shortcut_tips">想更快打开录音吗?\n添加“快听”到桌面,让小听更快听见
-    </string>
+    <string name="add_desktop_shortcut_tips">想更快打开录音吗?\n添加“快听”到桌面,让小听更快听见</string>
     <string name="add_desktop_shortcut_btn_txt">立即添加</string>
     <string name="desktop_shortcut_record_name">小听快听</string>
     <string name="dialog_send_friend">发送给朋友</string>

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

@@ -64,6 +64,10 @@ abstract class AtmobApi {
   @POST("/project/secretary/v1/user/info/update")
   Future<BaseResponse> updateUserInfo(@Body() UserInfoUpdateRequest request);
 
+  /// 投诉/建议
+  @POST("/project/secretary/v1/customer/complaint/submit")
+  Future<BaseResponse> complaintSubmit(@Body() AppBaseRequest request);
+
   /// 用户信息
   @POST("/project/secretary/v1/user/info")
   Future<BaseResponse<UserInfoResponse>> userInfo(

+ 18 - 0
lib/data/api/request/complaint_submit_request.dart

@@ -0,0 +1,18 @@
+import 'package:electronic_assistant/base/app_base_request.dart';
+import 'package:json_annotation/json_annotation.dart';
+
+part 'complaint_submit_request.g.dart';
+
+@JsonSerializable()
+class ComplaintSubmitRequest extends AppBaseRequest {
+  @JsonKey(name: "type")
+  int type;
+
+  @JsonKey(name: "content")
+  String content;
+
+  ComplaintSubmitRequest(this.type, this.content);
+
+  @override
+  Map<String, dynamic> toJson() => _$ComplaintSubmitRequestToJson(this);
+}

+ 14 - 0
lib/data/api/response/complaint_submit_response.dart

@@ -0,0 +1,14 @@
+import 'package:json_annotation/json_annotation.dart';
+
+part 'complaint_submit_response.g.dart';
+
+@JsonSerializable()
+class ComplaintSubmitResponse {
+  @JsonKey(name: 'code')
+  int code;
+
+  ComplaintSubmitResponse(this.code);
+
+  factory ComplaintSubmitResponse.fromJson(Map<String, dynamic> json) =>
+      _$ComplaintSubmitResponseFromJson(json);
+}

+ 1 - 2
lib/data/consts/constants.dart

@@ -1,4 +1,3 @@
-
 import 'package:electronic_assistant/utils/mmkv_util.dart';
 import 'package:flutter_umeng/flutter_umeng.dart';
 
@@ -7,7 +6,7 @@ import '../../utils/common_utils.dart';
 class Constants {
   Constants._();
 
-  static const String env = envProd;
+  static const String env = envTest;
 
   static const String envDev = 'dev';
 

+ 7 - 0
lib/data/repositories/account_repository.dart

@@ -2,6 +2,7 @@ import 'dart:async';
 
 import 'package:electronic_assistant/base/app_base_request.dart';
 import 'package:electronic_assistant/data/api/atmob_api.dart';
+import 'package:electronic_assistant/data/api/request/complaint_submit_request.dart';
 import 'package:electronic_assistant/data/repositories/task_repository.dart';
 import 'package:electronic_assistant/utils/async_util.dart';
 import 'package:electronic_assistant/utils/cancel_future.dart';
@@ -108,6 +109,12 @@ class AccountRepository {
     });
   }
 
+  Future<void> complaintSubmit(int type, String content) {
+    return atmobApi
+        .complaintSubmit(ComplaintSubmitRequest(type, content))
+        .then(HttpHandler.handle(true));
+  }
+
   void onLoginSuccess(String phone, String? token) {
     _token = token;
     _phone = phone;

+ 36 - 0
lib/module/main/drawer/complaint/controller.dart

@@ -0,0 +1,36 @@
+import 'package:electronic_assistant/base/base_controller.dart';
+import 'package:electronic_assistant/data/repositories/account_repository.dart';
+import 'package:electronic_assistant/utils/error_handler.dart';
+import 'package:electronic_assistant/utils/toast_util.dart';
+import 'package:get/get.dart';
+import 'package:retrofit/http.dart';
+
+class ComplaintOpinionController extends BaseController {
+  var title = ''.obs;
+
+  var numCount = 0.obs;
+
+  var content = "".obs;
+
+  @override
+  void onInit() {
+    super.onInit();
+
+    title.value = Get.arguments;
+  }
+
+  void requestSubmit() {
+    var type = 1;
+    if (title.value == "投诉举报") {
+      type = 2;
+    } else {
+      type = 1;
+    }
+    accountRepository.complaintSubmit(type, content.value).then((data) {
+      ToastUtil.showToast("发送成功");
+      Get.back();
+    }).catchError((error) {
+      ErrorHandler.toastError(error);
+    });
+  }
+}

+ 144 - 0
lib/module/main/drawer/complaint/view.dart

@@ -0,0 +1,144 @@
+import 'package:electronic_assistant/base/base_page.dart';
+import 'package:electronic_assistant/module/main/drawer/complaint/controller.dart';
+import 'package:electronic_assistant/resource/assets.gen.dart';
+import 'package:electronic_assistant/resource/colors.gen.dart';
+import 'package:electronic_assistant/utils/expand.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_screenutil/flutter_screenutil.dart';
+import 'package:get/get.dart';
+
+class ComplaintOpinionPage extends BasePage<ComplaintOpinionController> {
+  const ComplaintOpinionPage({super.key});
+
+  @override
+  bool immersive() {
+    return true;
+  }
+
+  // 点击空白处收起键盘
+  @override
+  void backgroundOnTapEvent() {
+    super.backgroundOnTapEvent();
+    FocusScope.of(Get.context!).requestFocus(FocusNode());
+  }
+
+  @override
+  Widget buildBody(BuildContext context) {
+    return Scaffold(
+      resizeToAvoidBottomInset: false,
+      backgroundColor: Colors.transparent,
+      appBar: AppBar(
+        systemOverlayStyle: SystemUiOverlayStyle.dark,
+        backgroundColor: Colors.transparent,
+        title: Obx(() => Text(controller.title.value,
+            style:
+                TextStyle(fontSize: 17.sp, color: ColorName.primaryTextColor))),
+        leading: IconButton(
+          icon: SizedBox(
+              width: 24.w, height: 24.w, child: Assets.images.iconBack.image()),
+          // Custom icon
+          onPressed: () {
+            Get.back();
+          },
+        ),
+      ),
+      body: _buildContentView(),
+    );
+  }
+
+  Widget _buildContentView() {
+    return SafeArea(
+      child: Container(
+        padding: EdgeInsets.symmetric(horizontal: 12.w),
+        child: Column(
+          crossAxisAlignment: CrossAxisAlignment.start,
+          children: [
+            Obx(
+              () => Text(
+                controller.title.value,
+                style: TextStyle(
+                  color: ColorName.secondaryTextColor,
+                  fontSize: 14.sp,
+                  fontWeight: FontWeight.w500,
+                ),
+              ),
+            ),
+            SizedBox(
+              height: 12.h,
+            ),
+            Container(
+              decoration: BoxDecoration(
+                color: "#E9E9E9".toColor(),
+                borderRadius: BorderRadius.circular(8),
+              ),
+              height: 260.h,
+              child: TextField(
+                maxLength: 200,
+                maxLines: null,
+                cursorColor: ColorName.colorPrimary,
+                style: TextStyle(
+                    fontSize: 15.sp, color: ColorName.primaryTextColor),
+                decoration: InputDecoration(
+                  counterText: '',
+                  border: InputBorder.none,
+                  fillColor: Colors.transparent,
+                  hintText: "请输入您的投诉内容",
+                  hintStyle: TextStyle(
+                      fontSize: 15.sp, color: ColorName.tertiaryTextColor),
+                  contentPadding: const EdgeInsets.all(12).w,
+                ),
+                onChanged: (value) {
+                  controller.numCount.value = value.length;
+                  controller.content.value = value;
+                },
+              ),
+            ),
+            SizedBox(
+              height: 13.h,
+            ),
+            Row(
+              mainAxisAlignment: MainAxisAlignment.end,
+              children: [
+                Obx(
+                  () => Text(
+                    "${controller.numCount}/200",
+                    style: TextStyle(
+                      color: ColorName.tertiaryTextColor,
+                      fontSize: 12.sp,
+                    ),
+                  ),
+                ),
+              ],
+            ),
+            const Spacer(),
+            GestureDetector(
+              onTap: () => controller.requestSubmit(),
+              child: Container(
+                height: 48.w,
+                alignment: Alignment.center,
+                decoration: BoxDecoration(
+                  gradient: LinearGradient(
+                    colors: ['#6177F2'.color, '#8B9DFF'.color],
+                    begin: Alignment.centerLeft,
+                    end: Alignment.centerRight,
+                    stops: const [0.0, 1.0],
+                  ),
+                  borderRadius: BorderRadius.circular(8.w),
+                ),
+                child: Text(
+                  "提交",
+                  style: TextStyle(
+                    fontWeight: FontWeight.bold,
+                    fontSize: 16.sp,
+                    color: Colors.white,
+                  ),
+                ),
+              ),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+}

+ 14 - 5
lib/module/main/drawer/view.dart

@@ -169,6 +169,20 @@ class MainDrawerView extends BasePage<MainDrawerController> {
             },
           ),
           buildOperationItem(
+            Assets.images.iconOpinionAndSuggestion.image(),
+            StringName.mainDrawerOpinionAndSuggestion.tr,
+            () {
+              Get.toNamed(RoutePath.complaintOpinion, arguments: "投诉举报");
+            },
+          ),
+          buildOperationItem(
+            Assets.images.iconComplaintAndReport.image(),
+            StringName.mainDrawerComplaintAndReport.tr,
+            () {
+              Get.toNamed(RoutePath.complaintOpinion, arguments: "意见建议");
+            },
+          ),
+          buildOperationItem(
             Assets.images.iconDrawerCheckUpdates.image(),
             StringName.mainDrawerCheckUpdates.tr,
             () {
@@ -180,11 +194,6 @@ class MainDrawerView extends BasePage<MainDrawerController> {
                   fontSize: 12.sp, color: ColorName.tertiaryTextColor),
             ),
           ),
-          // buildOperationItem(
-          //   Assets.images.iconComplaintAndReport.image(),
-          //   StringName.mainDrawerComplaintAndReport.tr,
-          //   () {},
-          // ),
           buildOperationItem(
             Assets.images.iconLogoff.image(),
             StringName.mainDrawerLogoff.tr,

+ 31 - 3
lib/module/talk/common_view.dart

@@ -1,4 +1,5 @@
 import 'package:electronic_assistant/data/bean/agenda_list_all_bean.dart';
+import 'package:electronic_assistant/router/app_pages.dart';
 import 'package:electronic_assistant/utils/expand.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
@@ -93,10 +94,37 @@ Widget getTalkFailView() {
             height: 100.w,
             child: Assets.images.iconTalkAnalyseFail.image()),
         SizedBox(height: 4.h),
-        Text(StringName.talkAnalyseFail.tr,
-            style:
-                TextStyle(fontSize: 15.sp, color: ColorName.primaryTextColor)),
+        Text(
+          StringName.talkAnalyseFail.tr,
+          style: TextStyle(
+            fontSize: 15.sp,
+            color: ColorName.primaryTextColor,
+            fontWeight: FontWeight.w500,
+          ),
+        ),
         SizedBox(height: 2.h),
+        Row(
+          mainAxisAlignment: MainAxisAlignment.center,
+          children: [
+            Text(StringName.talkAnalyseSummaryFail.tr,
+                style: TextStyle(
+                    fontSize: 12.sp, color: ColorName.secondaryTextColor)),
+            GestureDetector(
+              onTap: () {
+                Get.toNamed(RoutePath.complaintOpinion, arguments: "意见建议");
+              },
+              child: Text(
+                StringName.talkAnalyseFailFeedback.tr,
+                style: TextStyle(
+                  color: "#102FDE".toColor(),
+                  fontSize: 12.sp,
+                  decoration: TextDecoration.underline,
+                  decorationColor: "#102FDE".toColor(),
+                ),
+              ),
+            )
+          ],
+        ),
       ],
     ),
   );

+ 8 - 0
lib/router/app_pages.dart

@@ -6,6 +6,8 @@ import 'package:electronic_assistant/module/chat/start/controller.dart';
 import 'package:electronic_assistant/module/files/controller.dart';
 import 'package:electronic_assistant/module/files/search/controller.dart';
 import 'package:electronic_assistant/module/main/controller.dart';
+import 'package:electronic_assistant/module/main/drawer/complaint/controller.dart';
+import 'package:electronic_assistant/module/main/drawer/complaint/view.dart';
 import 'package:electronic_assistant/module/main/drawer/controller.dart';
 import 'package:electronic_assistant/module/record/controller.dart';
 import 'package:electronic_assistant/module/splash/controller.dart';
@@ -68,6 +70,8 @@ abstract class RoutePath {
   static const agendaDetail = '/agendaDetail';
 
   static const audioPicker = '/audioPicker';
+
+  static const complaintOpinion = '/complaintOpinion';
 }
 
 class AppBinding extends Bindings {
@@ -92,6 +96,7 @@ class AppBinding extends Bindings {
     lazyPut(() => MainDrawerController());
     lazyPut(() => AgendaDetailController());
     lazyPut(() => AudioPickerController());
+    lazyPut(() => ComplaintOpinionController());
   }
 
   void lazyPut<S>(InstanceBuilderCallback<S> builder) {
@@ -114,4 +119,7 @@ final generalPages = [
   GetPage(name: RoutePath.browser, page: () => const BrowserPage()),
   GetPage(name: RoutePath.agendaDetail, page: () => const AgendaDetailPage()),
   GetPage(name: RoutePath.audioPicker, page: () => const AudioPickerPage()),
+  GetPage(
+      name: RoutePath.complaintOpinion,
+      page: () => const ComplaintOpinionPage()),
 ];