فهرست منبع

修改意见反馈,新增意见反馈记录

Pq 1 سال پیش
والد
کامیت
f8fd6ad2a6
60فایلهای تغییر یافته به همراه2500 افزوده شده و 18 حذف شده
  1. 8 0
      BaseLibrary/src/main/java/com/cooleshow/base/interfaces/IFilterData.java
  2. 10 0
      BaseLibrary/src/main/java/com/cooleshow/base/interfaces/IFilterViewData.java
  3. 2 0
      BaseLibrary/src/main/java/com/cooleshow/base/router/RouterPath.kt
  4. 18 0
      BaseLibrary/src/main/java/com/cooleshow/base/utils/DateUtil.java
  5. 65 0
      BaseLibrary/src/main/java/com/cooleshow/base/utils/DeviceUtils.java
  6. 13 0
      BaseLibrary/src/main/java/com/cooleshow/base/utils/GlideUtils.kt
  7. 22 3
      BaseLibrary/src/main/java/com/cooleshow/base/utils/JumpUtils.java
  8. 10 0
      BaseLibrary/src/main/java/com/cooleshow/base/utils/UiUtils.java
  9. BIN
      BaseLibrary/src/main/res/drawable-xhdpi/icon_arrow_down4.png
  10. BIN
      BaseLibrary/src/main/res/drawable-xhdpi/icon_arrow_top_blue.png
  11. BIN
      BaseLibrary/src/main/res/drawable-xxhdpi/icon_arrow_down4.png
  12. BIN
      BaseLibrary/src/main/res/drawable-xxhdpi/icon_arrow_top_blue.png
  13. 5 0
      BaseLibrary/src/main/res/drawable/shape_2dc7aa_22dp.xml
  14. 5 0
      BaseLibrary/src/main/res/drawable/shape_f2f2f2_6dp.xml
  15. 5 0
      BaseLibrary/src/main/res/drawable/shape_f6f6f6_4dp.xml
  16. 98 0
      BaseLibrary/src/main/res/layout/pickerview_select_options_layout.xml
  17. 1 0
      BaseLibrary/src/main/res/values/colors.xml
  18. 6 1
      chatModule/src/main/AndroidManifest.xml
  19. 5 0
      chatModule/src/main/java/com/cooleshow/chatmodule/ui/PhotoPreviewActivity.java
  20. 1 1
      institution/src/main/java/com/cooleshow/institution/stu/ui/main/MineFragment.java
  21. 1 1
      rong_im/common_im_ui/src/main/AndroidManifest.xml
  22. 2 2
      student/build.gradle
  23. 1 1
      student/src/main/java/com/cooleshow/student/ui/main/MineFragment.java
  24. 1 1
      student/src/main/java/com/cooleshow/student/ui/mine/FeedBackActivity.java
  25. 1 1
      student/src/main/java/com/cooleshow/student/ui/mine/SettingActivity.java
  26. 2 2
      teacher/build.gradle
  27. 1 1
      teacher/src/main/java/com/cooleshow/teacher/ui/main/MineFragment.java
  28. 1 1
      teacher/src/main/java/com/cooleshow/teacher/ui/mine/FeedBackActivity.java
  29. 1 1
      teacher/src/main/java/com/cooleshow/teacher/ui/mine/SettingActivity.java
  30. 12 0
      usercenter/src/main/AndroidManifest.xml
  31. 54 0
      usercenter/src/main/java/com/cooleshow/usercenter/adapter/FeedBackAddPhotoListAdapter.java
  32. 113 0
      usercenter/src/main/java/com/cooleshow/usercenter/adapter/FeedBackRecordAdapter.java
  33. 45 0
      usercenter/src/main/java/com/cooleshow/usercenter/adapter/FeedBackRecordFilterTypeAdapter.java
  34. 26 0
      usercenter/src/main/java/com/cooleshow/usercenter/adapter/FeedBackRecordImgListAdapter.java
  35. 12 0
      usercenter/src/main/java/com/cooleshow/usercenter/bean/FeedBackRecordListBean.java
  36. 194 0
      usercenter/src/main/java/com/cooleshow/usercenter/bean/FeedBackTypeBean.java
  37. 42 2
      usercenter/src/main/java/com/cooleshow/usercenter/data/api/UserApi.kt
  38. 103 0
      usercenter/src/main/java/com/cooleshow/usercenter/presenter/FeedBackPresenter.java
  39. 80 0
      usercenter/src/main/java/com/cooleshow/usercenter/presenter/FeedBackRecordPresenter.java
  40. 23 0
      usercenter/src/main/java/com/cooleshow/usercenter/presenter/contract/FeedBackContract.java
  41. 25 0
      usercenter/src/main/java/com/cooleshow/usercenter/presenter/contract/FeedBackRecordContract.java
  42. 398 0
      usercenter/src/main/java/com/cooleshow/usercenter/ui/activity/setting/FeedBackActivity.java
  43. 223 0
      usercenter/src/main/java/com/cooleshow/usercenter/ui/activity/setting/FeedBackRecordActivity.java
  44. 313 0
      usercenter/src/main/java/com/cooleshow/usercenter/widget/FeedBackRecordFilterView.java
  45. 5 0
      usercenter/src/main/res/color/selector_333333_to_2dc7aa.xml
  46. BIN
      usercenter/src/main/res/drawable-xhdpi/icon_del_img.png
  47. BIN
      usercenter/src/main/res/drawable-xhdpi/icon_feed_back_type_tag.png
  48. BIN
      usercenter/src/main/res/drawable-xhdpi/icon_feedback_add_img.png
  49. BIN
      usercenter/src/main/res/drawable-xxhdpi/icon_del_img.png
  50. BIN
      usercenter/src/main/res/drawable-xxhdpi/icon_feed_back_type_tag.png
  51. BIN
      usercenter/src/main/res/drawable-xxhdpi/icon_feedback_add_img.png
  52. 6 0
      usercenter/src/main/res/drawable/selector_feedback_record_filter_item.xml
  53. 36 0
      usercenter/src/main/res/layout/ac_feed_back_record_layout.xml
  54. 130 0
      usercenter/src/main/res/layout/activity_feedback_layout.xml
  55. 8 0
      usercenter/src/main/res/layout/item_feed_back_img_layout.xml
  56. 143 0
      usercenter/src/main/res/layout/item_feed_back_record_layout.xml
  57. 32 0
      usercenter/src/main/res/layout/item_feedback_photo_list_item.xml
  58. 21 0
      usercenter/src/main/res/layout/item_feedback_record_type_filter_text_layout.xml
  59. 169 0
      usercenter/src/main/res/layout/view_feed_back_record_filter_layout.xml
  60. 2 0
      usercenter/src/main/res/values/strings.xml

+ 8 - 0
BaseLibrary/src/main/java/com/cooleshow/base/interfaces/IFilterData.java

@@ -0,0 +1,8 @@
+package com.cooleshow.base.interfaces;
+
+/**
+ * Author by pq, Date on 2023/2/20.
+ */
+public interface IFilterData {
+    String getFilterViewText();
+}

+ 10 - 0
BaseLibrary/src/main/java/com/cooleshow/base/interfaces/IFilterViewData.java

@@ -0,0 +1,10 @@
+package com.cooleshow.base.interfaces;
+
+/**
+ * Author by pq, Date on 2023/4/12.
+ */
+public interface IFilterViewData {
+    String getDataId();
+
+    String getShowName();
+}

+ 2 - 0
BaseLibrary/src/main/java/com/cooleshow/base/router/RouterPath.kt

@@ -62,6 +62,8 @@ object RouterPath {
             const val UPDATE_PASSWORD = "/userCenter/UpdatePasswordActivity"
             const val FORGET_PASSWORD = "/userCenter/ForgetPasswordActivity"
             const val MINE_MODIFY_PASSWORD = "/userCenter/ModifyPasswordActivity"
+            const val MINE_FEEDBACK = "/userCenter/MINE_FEEDBACK"
+            const val MINE_FEEDBACK_RECORD = "/userCenter/FeedBackRecordActivity"
         }
     }
 

+ 18 - 0
BaseLibrary/src/main/java/com/cooleshow/base/utils/DateUtil.java

@@ -1164,4 +1164,22 @@ public class DateUtil {
         return 0;
     }
 
+    public static Date getZero(Date date){
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        calendar.set(Calendar.HOUR_OF_DAY, 0);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.SECOND, 0);
+        return calendar.getTime();
+    }
+
+    public static Date getEnd(Date date){
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        calendar.set(Calendar.HOUR_OF_DAY, 23);
+        calendar.set(Calendar.MINUTE, 59);
+        calendar.set(Calendar.SECOND, 59);
+        return calendar.getTime();
+    }
+
 }

+ 65 - 0
BaseLibrary/src/main/java/com/cooleshow/base/utils/DeviceUtils.java

@@ -550,4 +550,69 @@ public final class DeviceUtils {
         wm.getDefaultDisplay().getSize(point);
         return point.y;
     }
+
+    /**
+     * 获取厂商名
+     **/
+    public static String getDeviceManufacturer() {
+        return android.os.Build.MANUFACTURER;
+    }
+
+    /**
+     * 获取产品名
+     **/
+    public static String getDeviceProduct() {
+        return android.os.Build.PRODUCT;
+    }
+
+    /**
+     * 获取手机品牌
+     */
+    public static String getDeviceBrand() {
+        return android.os.Build.BRAND;
+    }
+
+    /**
+     * 获取手机型号
+     */
+    public static String getDeviceModel() {
+        return android.os.Build.MODEL;
+    }
+
+    /**
+     * 设备名
+     **/
+    public static String getDeviceDevice() {
+        return android.os.Build.DEVICE;
+    }
+
+    /**
+     * 获取手机Android 系统SDK
+     *
+     * @return
+     */
+    public static int getDeviceSDK() {
+        return android.os.Build.VERSION.SDK_INT;
+    }
+
+    /**
+     * 获取手机Android 版本
+     *
+     * @return
+     */
+    public static String getDeviceAndroidVersion() {
+        return android.os.Build.VERSION.RELEASE;
+    }
+
+    public static String getCustomDeviceInfo() {
+        StringBuilder stringBuilder = new StringBuilder();
+        stringBuilder.append(getDeviceBrand());
+        stringBuilder.append("_");
+        stringBuilder.append(getDeviceModel());
+        stringBuilder.append("_");
+        stringBuilder.append(getDeviceSDK());
+        stringBuilder.append("_");
+        stringBuilder.append(getDeviceAndroidVersion());
+        return stringBuilder.toString();
+    }
 }

+ 13 - 0
BaseLibrary/src/main/java/com/cooleshow/base/utils/GlideUtils.kt

@@ -7,9 +7,11 @@ import android.graphics.drawable.Drawable
 import android.widget.ImageView
 import com.bumptech.glide.Glide
 import com.bumptech.glide.load.MultiTransformation
+import com.bumptech.glide.load.engine.DiskCacheStrategy
 import com.bumptech.glide.request.RequestOptions
 import com.cooleshow.base.R
 import com.cooleshow.base.widgets.transformation.GlideRoundTransform
+import com.cooleshow.base.widgets.transformation.RadiusTransformation
 import jp.wasabeef.glide.transformations.BlurTransformation
 
 /*
@@ -91,4 +93,15 @@ object GlideUtils {
             .load(videoUrl)
             .into(view)
     }
+
+    fun loadRoundImageFitCenter(context: Context, url: String?, imageView: ImageView,radius: Int){
+        var options = RequestOptions()
+            .placeholder(-1)
+            .error(-1) //.priority(Priority.HIGH)
+            .transform(RadiusTransformation(context, radius))
+            .diskCacheStrategy(DiskCacheStrategy.NONE)
+            .fitCenter()
+
+        com.bumptech.glide.Glide.with(context).load(url).apply(options).into(imageView)
+    }
 }

+ 22 - 3
BaseLibrary/src/main/java/com/cooleshow/base/utils/JumpUtils.java

@@ -1,5 +1,9 @@
 package com.cooleshow.base.utils;
 
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Parcelable;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -13,6 +17,8 @@ import com.cooleshow.base.router.RouterPath;
 
 import org.json.JSONObject;
 
+import java.util.ArrayList;
+
 /**
  * Author by pq, Date on 2022/6/29.
  */
@@ -50,7 +56,7 @@ public class JumpUtils {
                     if (TextUtils.equals(routeBean.pageTag, RouteConstants.PAGE_TAG_LIVE_CLASS)) {
                         //我的课表 -> 直播课
                         ARouter.getInstance().build(RouterPath.CourseCenter.TEACHER_MINE_COURSE)
-                                .withInt("selectPosition",1)
+                                .withInt("selectPosition", 1)
                                 .navigation();
                         return true;
                     }
@@ -58,7 +64,7 @@ public class JumpUtils {
                     if (TextUtils.equals(routeBean.pageTag, RouteConstants.PAGE_TAG_VIDEO_CLASS)) {
                         //我的课表 -> 视频课
                         ARouter.getInstance().build(RouterPath.CourseCenter.TEACHER_MINE_COURSE)
-                                .withInt("selectPosition",2)
+                                .withInt("selectPosition", 2)
                                 .navigation();
                         return true;
                     }
@@ -175,10 +181,23 @@ public class JumpUtils {
                 .navigation();
     }
 
-    public static void jumpJGMainAndSelectChild(int i,int childPos) {
+    public static void jumpJGMainAndSelectChild(int i, int childPos) {
         ARouter.getInstance().build(RouterPath.JGCenter.PATH_HOME)
                 .withInt(Constants.MAIN_PAGE_SELECT_POTION_KEY, i)
                 .withInt(Constants.MAIN_PAGE_SELECT_CHILD_POTION_KEY, childPos)
                 .navigation();
     }
+
+    public static void startPhotoPreview(Activity context, ArrayList<? extends Parcelable> list, int position, int requestCode) {
+        if (context == null || list == null || list.size() == 0) {
+            return;
+        }
+        Intent intent = new Intent();
+        intent.setAction("com.cooleshow.chatmodule.ui.PhotoPreviewActivity");
+        if (position != -1) {
+            intent.putExtra("position", position);
+        }
+        intent.putParcelableArrayListExtra("list", list);
+        context.startActivityForResult(intent, requestCode);
+    }
 }

+ 10 - 0
BaseLibrary/src/main/java/com/cooleshow/base/utils/UiUtils.java

@@ -384,4 +384,14 @@ public class UiUtils {
             });
         });
     }
+
+    public static void refreshFilterTextStyle(boolean isShow, TextView textView) {
+        if (textView == null) {
+            return;
+        }
+        textView.setTextColor(textView.getContext().getResources().getColor(isShow ? R.color.color_2dc7aa : R.color.color_333333));
+        int drawableRight = 0;
+        drawableRight = isShow ? R.drawable.icon_arrow_top_blue : R.drawable.icon_arrow_down3;
+        textView.setCompoundDrawablesWithIntrinsicBounds(0, 0, drawableRight, 0);
+    }
 }

BIN
BaseLibrary/src/main/res/drawable-xhdpi/icon_arrow_down4.png


BIN
BaseLibrary/src/main/res/drawable-xhdpi/icon_arrow_top_blue.png


BIN
BaseLibrary/src/main/res/drawable-xxhdpi/icon_arrow_down4.png


BIN
BaseLibrary/src/main/res/drawable-xxhdpi/icon_arrow_top_blue.png


+ 5 - 0
BaseLibrary/src/main/res/drawable/shape_2dc7aa_22dp.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/color_ff2dc7aa"/>
+    <corners android:radius="22dp"/>
+</shape>

+ 5 - 0
BaseLibrary/src/main/res/drawable/shape_f2f2f2_6dp.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/color_f2f2f2"/>
+    <corners android:radius="6dp"/>
+</shape>

+ 5 - 0
BaseLibrary/src/main/res/drawable/shape_f6f6f6_4dp.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="#f6f6f6" />
+    <corners android:radius="4dp" />
+</shape>

+ 98 - 0
BaseLibrary/src/main/res/layout/pickerview_select_options_layout.xml

@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:background="@drawable/bg_white_top_10dp"
+    android:orientation="vertical">
+
+    <RelativeLayout
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        android:id="@+id/rl_top"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+
+
+        <TextView
+            android:padding="14dp"
+            android:id="@+id/tv_cancel"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:layout_marginLeft="6dp"
+            android:text="取消"
+            android:textColor="@color/color_666666"
+            android:textSize="@dimen/dp_16" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerInParent="true"
+            android:text=""
+            android:textColor="@color/color_1a1a1a"
+            android:textSize="18dp" />
+
+        <TextView
+            android:id="@+id/tv_finish"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentRight="true"
+            android:layout_centerVertical="true"
+            android:layout_marginRight="6dp"
+            android:padding="14dp"
+            android:text="确定"
+            android:textColor="@color/color_2dc7aa"
+            android:textSize="@dimen/dp_16" />
+
+    </RelativeLayout>
+
+    <View
+        android:layout_marginEnd="13dp"
+        android:layout_marginStart="13dp"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintBottom_toBottomOf="@+id/optionspicker"
+        app:layout_constraintTop_toTopOf="@+id/optionspicker"
+        android:background="@drawable/shape_f2f2f2_6dp"
+        android:layout_width="match_parent"
+        android:layout_height="44dp"/>
+
+    <View
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/rl_top"
+        android:id="@+id/view_line"
+        style="@style/line_style"
+        android:layout_marginEnd="13dp"
+        android:layout_marginStart="13dp"/>
+    <!--此部分需要完整复制过去,删减或者更改ID会导致初始化找不到内容而报空-->
+    <LinearLayout
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/view_line"
+        android:id="@+id/optionspicker"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/dp_250"
+        android:gravity="center"
+        android:minHeight="150dp"
+        android:orientation="horizontal">
+
+        <com.contrarywind.view.WheelView
+            android:id="@+id/options1"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1" />
+
+        <com.contrarywind.view.WheelView
+            android:id="@+id/options2"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1" />
+
+        <com.contrarywind.view.WheelView
+            android:id="@+id/options3"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1" />
+    </LinearLayout>
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 1 - 0
BaseLibrary/src/main/res/values/colors.xml

@@ -201,5 +201,6 @@
     <color name="color_777777">#777777</color>
     <color name="color_eb6363">#EB6363</color>
     <color name="color_ff8057">#ff8057</color>
+    <color name="color_e6ffffff">#e6ffffff</color>
 
 </resources>

+ 6 - 1
chatModule/src/main/AndroidManifest.xml

@@ -31,7 +31,12 @@
         <activity
             android:name=".ui.PhotoPreviewActivity"
             android:configChanges="orientation|screenSize|keyboardHidden|fontScale|smallestScreenSize|screenLayout"
-            android:screenOrientation="portrait" />
+            android:screenOrientation="portrait" >
+            <intent-filter>
+                <action android:name="com.cooleshow.chatmodule.ui.PhotoPreviewActivity" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
 
         <activity
             android:name=".ui.JoinGroupApplyActivity"

+ 5 - 0
chatModule/src/main/java/com/cooleshow/chatmodule/ui/PhotoPreviewActivity.java

@@ -125,6 +125,11 @@ public class PhotoPreviewActivity extends BaseActivity<TcActivityPhotoPreviewBin
     }
 
 
+    @Override
+    public void onBackPressed() {
+        initResult();
+    }
+
     private void initResult() {
         Intent intent = new Intent();
         intent.putParcelableArrayListExtra("list", (ArrayList<? extends Parcelable>) selectList);

+ 1 - 1
institution/src/main/java/com/cooleshow/institution/stu/ui/main/MineFragment.java

@@ -133,7 +133,7 @@ public class MineFragment extends BaseMVPFragment<FgMineLayoutBinding, MinePrese
 
         if (id == R.id.tv_feed_back) {
             //意见反馈
-            ARouter.getInstance().build(RouterPath.MineCenter.MINE_FEEDBACK)
+            ARouter.getInstance().build(RouterPath.UserCenter.MINE_FEEDBACK)
                     .navigation();
             return;
         }

+ 1 - 1
rong_im/common_im_ui/src/main/AndroidManifest.xml

@@ -38,7 +38,7 @@
             android:windowSoftInputMode="adjustPan"
             android:screenOrientation="portrait" />
         <activity
-            android:name="com.common.im.ui.activity.PhotoPreviewActivity"
+            android:name="com.cooleshow.base.ui.activity.tools.PhotoPreviewActivity"
             android:configChanges="orientation|screenSize|keyboardHidden"
             android:screenOrientation="portrait" />
         <activity

+ 2 - 2
student/build.gradle

@@ -18,8 +18,8 @@ android {
         applicationId "com.cooleshow.student"
         minSdkVersion 21
         targetSdkVersion 30
-        versionCode 150
-        versionName "1.5.0"
+        versionCode 152
+        versionName "1.5.2"
 
         ndk {
             abiFilters "armeabi-v7a", "arm64-v8a"

+ 1 - 1
student/src/main/java/com/cooleshow/student/ui/main/MineFragment.java

@@ -143,7 +143,7 @@ public class MineFragment extends BaseMVPFragment<FragmentMineLayoutBinding, Min
                 break;
             case R.id.tv_feedback:
                 //意见反馈
-                ARouter.getInstance().build(RouterPath.MineCenter.MINE_FEEDBACK)
+                ARouter.getInstance().build(RouterPath.UserCenter.MINE_FEEDBACK)
                         .navigation();
                 //事件埋点->点击意见反馈
                 EventHelper.addEvent(EventConstants.EVENT_ID_FEEDBACK);

+ 1 - 1
student/src/main/java/com/cooleshow/student/ui/mine/FeedBackActivity.java

@@ -33,7 +33,7 @@ import java.util.Map;
  * @author Ryan
  * 类说明:
  */
-@Route(path = RouterPath.MineCenter.MINE_FEEDBACK)
+@Deprecated
 public class FeedBackActivity extends BaseMVPActivity<ActivityFeedbackBinding, FeedBackPresenter> implements FeedBackContract.FeedBackView, View.OnClickListener {
     @Override
     public void onClick(View view) {

+ 1 - 1
student/src/main/java/com/cooleshow/student/ui/mine/SettingActivity.java

@@ -73,7 +73,7 @@ public class SettingActivity extends BaseMVPActivity<ActivitySettingBinding, Set
                 finish();
                 break;
             case R.id.cl_feedback:
-                ARouter.getInstance().build(RouterPath.MineCenter.MINE_FEEDBACK)
+                ARouter.getInstance().build(RouterPath.UserCenter.MINE_FEEDBACK)
                         .navigation();
                 break;
             case R.id.tv_sign_out_account:

+ 2 - 2
teacher/build.gradle

@@ -20,8 +20,8 @@ android {
         applicationId "com.cooleshow.teacher"
         minSdkVersion 21
         targetSdkVersion 30
-        versionCode 151
-        versionName "1.5.1"
+        versionCode 152
+        versionName "1.5.2"
         ndk {
             abiFilters "armeabi-v7a", "arm64-v8a"
         }

+ 1 - 1
teacher/src/main/java/com/cooleshow/teacher/ui/main/MineFragment.java

@@ -269,7 +269,7 @@ public class MineFragment extends BaseMVPFragment<FragmentMineLayoutBinding, Min
                 break;
             case R.id.tv_feedback:
                 //意见反馈
-                ARouter.getInstance().build(RouterPath.MineCenter.MINE_FEEDBACK)
+                ARouter.getInstance().build(RouterPath.UserCenter.MINE_FEEDBACK)
                         .navigation();
                 //事件埋点->意见反馈
                 EventHelper.addEvent(EventConstants.EVENT_ID_FEEDBACK_FOR_TEACHER);

+ 1 - 1
teacher/src/main/java/com/cooleshow/teacher/ui/mine/FeedBackActivity.java

@@ -31,7 +31,7 @@ import java.util.Map;
  * @author Ryan
  * 类说明:
  */
-@Route(path = RouterPath.MineCenter.MINE_FEEDBACK)
+@Deprecated
 public class FeedBackActivity extends BaseMVPActivity<ActivityFeedbackBinding, FeedBackPresenter> implements FeedBackContract.FeedBackView, View.OnClickListener {
     @Override
     public void onClick(View view) {

+ 1 - 1
teacher/src/main/java/com/cooleshow/teacher/ui/mine/SettingActivity.java

@@ -65,7 +65,7 @@ public class SettingActivity extends BaseMVPActivity<ActivitySettingBinding, Set
                     .withString(UserConstants.PHONE_NUM_KEY, UserHelper.getUserPhone())
                     .navigation();
         } else if (id == R.id.cl_feedback) {
-            ARouter.getInstance().build(RouterPath.MineCenter.MINE_FEEDBACK)
+            ARouter.getInstance().build(RouterPath.UserCenter.MINE_FEEDBACK)
                     .navigation();
         } else if (id == R.id.tv_sign_out_account) {
             ARouter.getInstance().build(RouterPath.UserCenter.SIGN_OUT_ACCOUNT)

+ 12 - 0
usercenter/src/main/AndroidManifest.xml

@@ -57,5 +57,17 @@
             android:name=".ui.activity.setting.UpdatePasswordActivity"
             android:configChanges="orientation|screenSize|keyboardHidden"
             android:screenOrientation="portrait" />
+
+        <activity
+            android:name=".ui.activity.setting.FeedBackActivity"
+            android:windowSoftInputMode="adjustPan"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:screenOrientation="portrait" />
+
+        <activity
+            android:name=".ui.activity.setting.FeedBackRecordActivity"
+            android:windowSoftInputMode="adjustPan"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:screenOrientation="portrait" />
     </application>
 </manifest>

+ 54 - 0
usercenter/src/main/java/com/cooleshow/usercenter/adapter/FeedBackAddPhotoListAdapter.java

@@ -0,0 +1,54 @@
+package com.cooleshow.usercenter.adapter;
+
+import android.view.View;
+import android.widget.ImageView;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.viewholder.BaseViewHolder;
+import com.cooleshow.base.utils.GlideUtils;
+import com.cooleshow.base.utils.SizeUtils;
+import com.cooleshow.base.utils.Utils;
+import com.cooleshow.base.utils.helper.QMUIDeviceHelper;
+import com.cooleshow.usercenter.R;
+import com.luck.picture.lib.entity.LocalMedia;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+/**
+ * 创建日期:2022/6/13 14:22
+ *
+ * @author Ryan
+ * 类说明:
+ */
+public class FeedBackAddPhotoListAdapter extends BaseQuickAdapter<LocalMedia, BaseViewHolder> {
+
+    private final boolean isTablet;
+
+    public FeedBackAddPhotoListAdapter() {
+        super(R.layout.item_feedback_photo_list_item);
+        addChildClickViewIds(R.id.iv_del);
+        isTablet = QMUIDeviceHelper.isTablet(Utils.getApp());
+    }
+
+    @Override
+    protected void convert(BaseViewHolder helper, LocalMedia item) {
+        View view = helper.getView(R.id.cs_root);
+        if (isTablet) {
+            int padding = SizeUtils.dp2px(14);
+            view.setPadding(padding, SizeUtils.dp2px(12), padding, 0);
+            RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) view.getLayoutParams();
+            layoutParams.width = RecyclerView.LayoutParams.WRAP_CONTENT;
+        }
+        ImageView ivIcon = helper.getView(R.id.iv_icon);
+        ImageView iv_del = helper.getView(R.id.iv_del);
+        if (item.getPath().equals("123")) {
+            iv_del.setVisibility(View.GONE);
+            ivIcon.setImageResource(R.drawable.icon_feedback_add_img);
+        } else {
+            iv_del.setVisibility(View.VISIBLE);
+            GlideUtils.INSTANCE.loadRoundImageFitCenter(getContext(), item.getPath(), ivIcon, SizeUtils.dp2px(5));
+        }
+
+    }
+
+}

+ 113 - 0
usercenter/src/main/java/com/cooleshow/usercenter/adapter/FeedBackRecordAdapter.java

@@ -0,0 +1,113 @@
+package com.cooleshow.usercenter.adapter;
+
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.alibaba.android.arouter.launcher.ARouter;
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.listener.OnItemChildClickListener;
+import com.chad.library.adapter.base.viewholder.BaseViewHolder;
+import com.cooleshow.base.router.RouterPath;
+import com.cooleshow.base.utils.JumpUtils;
+import com.cooleshow.base.utils.SizeUtils;
+import com.cooleshow.base.utils.Utils;
+import com.cooleshow.base.utils.helper.QMUIDisplayHelper;
+import com.cooleshow.usercenter.R;
+import com.cooleshow.usercenter.bean.FeedBackRecordListBean;
+import com.luck.picture.lib.entity.LocalMedia;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Locale;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+/**
+ * Author by pq, Date on 2023/12/26.
+ */
+public class FeedBackRecordAdapter extends BaseQuickAdapter<FeedBackRecordListBean.RowsBean, BaseViewHolder> {
+
+    private final int screenWidth;
+    private final int imgWidth = SizeUtils.dp2px(74);
+    private final int imgMargin = SizeUtils.dp2px(10);
+
+    public FeedBackRecordAdapter() {
+        super(R.layout.item_feed_back_record_layout);
+        screenWidth = QMUIDisplayHelper.getScreenWidth(Utils.getApp());
+    }
+
+    @Override
+    protected void convert(@NonNull BaseViewHolder holder, FeedBackRecordListBean.RowsBean bean) {
+        //类型
+        holder.setText(R.id.tv_type, bean.getSuggestionTypeName());
+        //反馈内容
+        holder.setText(R.id.tv_content, bean.getContent());
+        //图片
+        loadImg(holder, bean);
+        //回复
+        LinearLayout ll_reply = holder.getView(R.id.ll_reply);
+        boolean hasReply = !TextUtils.isEmpty(bean.getFeedbackContent());
+        ll_reply.setVisibility(hasReply ? View.VISIBLE : View.GONE);
+        holder.setText(R.id.tv_reply_content, bean.getFeedbackContent());
+    }
+
+    private void loadImg(@NonNull BaseViewHolder holder, FeedBackRecordListBean.RowsBean bean) {
+        RecyclerView recyclerView = holder.getView(R.id.recyclerView);
+        TextView tv_num_tip = holder.getView(R.id.tv_num_tip);
+        String[] imgUrls = getImgUrl(bean.getAttachmentUrls());
+        int imgScrollCount = imgUrls != null ? imgUrls.length : 0;
+        int imgScrollWidth = (imgWidth + imgMargin) * imgScrollCount;
+        recyclerView.setVisibility(imgScrollWidth == 0 ? View.GONE : View.VISIBLE);
+        if (imgScrollCount != 0) {
+            FeedBackRecordImgListAdapter imgListAdapter = new FeedBackRecordImgListAdapter();
+            imgListAdapter.setOnItemChildClickListener(bindImgPreviewClick());
+            recyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
+            recyclerView.setAdapter(imgListAdapter);
+            ArrayList<String> imgUrlList = new ArrayList<>(Arrays.asList(imgUrls));
+            imgListAdapter.setList(imgUrlList);
+        }
+        boolean isShowTip = imgScrollWidth > screenWidth * 0.9;
+        tv_num_tip.setVisibility(isShowTip ? View.VISIBLE : View.GONE);
+        tv_num_tip.setText(String.format(Locale.getDefault(), "共%d张", imgScrollCount));
+    }
+
+    private String[] getImgUrl(String imgUrls) {
+        if (TextUtils.isEmpty(imgUrls)) {
+            return null;
+        }
+        try {
+            String[] split = imgUrls.split(",");
+            return split;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    private OnItemChildClickListener bindImgPreviewClick() {
+        OnItemChildClickListener itemChildClickListener = new OnItemChildClickListener() {
+            @Override
+            public void onItemChildClick(@NonNull BaseQuickAdapter<?, ?> adapter, @NonNull View view, int position) {
+                if (position < adapter.getData().size()) {
+                    ArrayList<LocalMedia> list = new ArrayList<>();
+                    for (int i = 0; i < adapter.getData().size(); i++) {
+                        String imgUrl = (String) adapter.getData().get(i);
+                        LocalMedia localMedia = new LocalMedia();
+                        localMedia.setPath(imgUrl);
+                        list.add(localMedia);
+                    }
+                    ARouter.getInstance().build(RouterPath.ChatCenter.CHAT_PHOTO_PREVIEW)
+                            .withParcelableArrayList("list", list)
+                            .withInt("position", position)
+                            .withBoolean("isRemove", false)
+                            .navigation(getContext());
+                }
+            }
+        };
+        return itemChildClickListener;
+    }
+}

+ 45 - 0
usercenter/src/main/java/com/cooleshow/usercenter/adapter/FeedBackRecordFilterTypeAdapter.java

@@ -0,0 +1,45 @@
+package com.cooleshow.usercenter.adapter;
+
+import android.widget.TextView;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.viewholder.BaseViewHolder;
+import com.cooleshow.base.interfaces.IFilterViewData;
+import com.cooleshow.usercenter.R;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Author by pq, Date on 2023/4/12.
+ */
+public class FeedBackRecordFilterTypeAdapter extends BaseQuickAdapter<IFilterViewData, BaseViewHolder> {
+    private int selectPos = -1;
+
+    public FeedBackRecordFilterTypeAdapter() {
+        super(R.layout.item_feedback_record_type_filter_text_layout);
+    }
+
+    public void setSelectPos(int pos) {
+        if (selectPos == pos) {
+            selectPos = -1;
+        } else {
+            selectPos = pos;
+        }
+        notifyDataSetChanged();
+    }
+
+    public String getSelectDataId() {
+        if (selectPos != -1 && selectPos < getData().size()) {
+            return getData().get(selectPos).getDataId();
+        }
+        return "";
+    }
+
+    @Override
+    protected void convert(@NonNull BaseViewHolder holder, IFilterViewData skillSelectBean) {
+        holder.setText(R.id.tv_text, skillSelectBean.getShowName());
+        TextView tv_text = holder.getView(R.id.tv_text);
+        int pos = holder.getLayoutPosition();
+        tv_text.setSelected(pos == selectPos);
+    }
+}

+ 26 - 0
usercenter/src/main/java/com/cooleshow/usercenter/adapter/FeedBackRecordImgListAdapter.java

@@ -0,0 +1,26 @@
+package com.cooleshow.usercenter.adapter;
+
+import android.widget.ImageView;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.viewholder.BaseViewHolder;
+import com.cooleshow.base.utils.GlideImageLoaderUtils;
+import com.cooleshow.usercenter.R;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Author by pq, Date on 2023/12/26.
+ */
+public class FeedBackRecordImgListAdapter extends BaseQuickAdapter<String, BaseViewHolder> {
+    public FeedBackRecordImgListAdapter() {
+        super(R.layout.item_feed_back_img_layout);
+        addChildClickViewIds(R.id.img);
+    }
+
+    @Override
+    protected void convert(@NonNull BaseViewHolder holder, String s) {
+        ImageView view = holder.getView(R.id.img);
+        GlideImageLoaderUtils.getInstance().loadCustRoundCircleImage(getContext(), s, view, 5);
+    }
+}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 12 - 0
usercenter/src/main/java/com/cooleshow/usercenter/bean/FeedBackRecordListBean.java


+ 194 - 0
usercenter/src/main/java/com/cooleshow/usercenter/bean/FeedBackTypeBean.java

@@ -0,0 +1,194 @@
+package com.cooleshow.usercenter.bean;
+
+import android.text.TextUtils;
+
+import com.contrarywind.interfaces.IPickerViewData;
+import com.cooleshow.base.interfaces.IFilterViewData;
+
+import java.util.List;
+
+/**
+ * Author by pq, Date on 2023/8/31.
+ */
+public class FeedBackTypeBean {
+
+    /**
+     * next : true
+     * current : 0
+     * total : 0
+     * pages : 0
+     * extra : {"createBy":0,"createTime":"","updateBy":0,"updateTime":"","id":0,"delFlag":true,"type":""}
+     * prev : true
+     * limit : 0
+     * rows : [{"createBy":0,"createTime":"","updateBy":0,"updateTime":"","id":0,"delFlag":true,"type":""}]
+     */
+
+    private boolean next;
+    private int current;
+    private int total;
+    private int pages;
+    private boolean prev;
+    private int limit;
+    private List<RowsBean> rows;
+
+    public boolean isNext() {
+        return next;
+    }
+
+    public void setNext(boolean next) {
+        this.next = next;
+    }
+
+    public int getCurrent() {
+        return current;
+    }
+
+    public void setCurrent(int current) {
+        this.current = current;
+    }
+
+    public int getTotal() {
+        return total;
+    }
+
+    public void setTotal(int total) {
+        this.total = total;
+    }
+
+    public int getPages() {
+        return pages;
+    }
+
+    public void setPages(int pages) {
+        this.pages = pages;
+    }
+
+
+    public boolean isPrev() {
+        return prev;
+    }
+
+    public void setPrev(boolean prev) {
+        this.prev = prev;
+    }
+
+    public int getLimit() {
+        return limit;
+    }
+
+    public void setLimit(int limit) {
+        this.limit = limit;
+    }
+
+    public List<RowsBean> getRows() {
+        return rows;
+    }
+
+    public void setRows(List<RowsBean> rows) {
+        this.rows = rows;
+    }
+
+    public static class RowsBean implements IPickerViewData, IFilterViewData {
+        /**
+         * createBy : 0
+         * createTime :
+         * updateBy : 0
+         * updateTime :
+         * id : 0
+         * delFlag : true
+         * type :
+         */
+
+        private String createBy;
+        private String createTime;
+        private String updateBy;
+        private String updateTime;
+        private String id;
+        private boolean delFlag;
+        private String type;
+        private String name;
+
+        public String getText() {
+            return name;
+        }
+
+        public void setText(String text) {
+            this.name = text;
+        }
+
+        public String getCreateBy() {
+            return createBy;
+        }
+
+        public void setCreateBy(String createBy) {
+            this.createBy = createBy;
+        }
+
+        public String getCreateTime() {
+            return createTime;
+        }
+
+        public void setCreateTime(String createTime) {
+            this.createTime = createTime;
+        }
+
+        public String getUpdateBy() {
+            return updateBy;
+        }
+
+        public void setUpdateBy(String updateBy) {
+            this.updateBy = updateBy;
+        }
+
+        public String getUpdateTime() {
+            return updateTime;
+        }
+
+        public void setUpdateTime(String updateTime) {
+            this.updateTime = updateTime;
+        }
+
+        public String getId() {
+            return id;
+        }
+
+        public void setId(String id) {
+            this.id = id;
+        }
+
+        public boolean isDelFlag() {
+            return delFlag;
+        }
+
+        public void setDelFlag(boolean delFlag) {
+            this.delFlag = delFlag;
+        }
+
+        public String getType() {
+            return type;
+        }
+
+        public void setType(String type) {
+            this.type = type;
+        }
+
+        @Override
+        public String getPickerViewText() {
+            String text = getText();
+            if (!TextUtils.isEmpty(text)) {
+                return text;
+            }
+            return "暂无内容";
+        }
+
+        @Override
+        public String getDataId() {
+            return getId();
+        }
+
+        @Override
+        public String getShowName() {
+            return getText();
+        }
+    }
+}

+ 42 - 2
usercenter/src/main/java/com/cooleshow/usercenter/data/api/UserApi.kt

@@ -2,8 +2,11 @@ package com.cooleshow.usercenter.data.api
 
 
 import com.cooleshow.base.bean.QueryParamsConfigBean
+import com.cooleshow.base.bean.ServiceContactBean
 import com.cooleshow.base.common.BaseConstant
 import com.cooleshow.base.data.net.BaseResponse
+import com.cooleshow.usercenter.bean.FeedBackRecordListBean
+import com.cooleshow.usercenter.bean.FeedBackTypeBean
 import com.cooleshow.usercenter.bean.StudentUserInfo
 import com.cooleshow.usercenter.bean.TeacherUserInfo
 import com.cooleshow.usercenter.bean.UserLoginInfo
@@ -227,6 +230,43 @@ interface UserApi {
     @POST(BaseConstant.AUTH_GROUP + "user/checkVerityCode")
     fun checkSmsCode(@Body body: RequestBody): Observable<BaseResponse<Any?>?>?
 
-    @POST("{group_name}"+"/user/updateImUserInfo")
-    fun notifyUserPushId(@Path("group_name") group_name :String,@Body body: RequestBody?): Observable<BaseResponse<Object>?>?
+    @POST("{group_name}" + "/user/updateImUserInfo")
+    fun notifyUserPushId(
+        @Path("group_name") group_name: String,
+        @Body body: RequestBody?
+    ): Observable<BaseResponse<Object>?>?
+
+    @POST(BaseConstant.AUTH_GROUP + "user/queryConfig")
+    fun getCustomerServiceContact(): Observable<BaseResponse<ServiceContactBean?>?>?
+
+    /**
+     * 意见反馈
+     *
+     * @param
+     * @return
+     */
+    @POST("{group_name}" + "/sysSuggestionType/page")
+    fun getSuggestionType(
+        @Body requestBody: RequestBody?,
+        @Path("group_name") group_name: String
+    ): Observable<BaseResponse<FeedBackTypeBean?>?>?
+
+
+    /**
+     * 意见反馈
+     *
+     * @param params
+     * @return
+     */
+    @POST("{group_name}" + "/sysSuggestionV2/save")
+    fun addSuggestion(
+        @Body requestBody: RequestBody,
+        @Path("group_name") group_name: String
+    ): Observable<BaseResponse<Any?>?>?
+
+    @POST("{group_name}" + "/sysSuggestionV2/page")
+    fun getSuggestionRecord(
+        @Body convertToRequestBodyJson: RequestBody?,
+        @Path("group_name") group_name: String
+    ): Observable<BaseResponse<FeedBackRecordListBean?>?>?
 }

+ 103 - 0
usercenter/src/main/java/com/cooleshow/usercenter/presenter/FeedBackPresenter.java

@@ -0,0 +1,103 @@
+package com.cooleshow.usercenter.presenter;
+
+import android.text.TextUtils;
+
+import com.cooleshow.base.bean.ServiceContactBean;
+import com.cooleshow.base.common.BaseConstant;
+import com.cooleshow.base.presenter.BasePresenter;
+import com.cooleshow.base.rx.BaseObserver;
+import com.cooleshow.base.utils.DeviceUtils;
+import com.cooleshow.base.utils.RequestBodyUtil;
+import com.cooleshow.usercenter.bean.FeedBackTypeBean;
+import com.cooleshow.usercenter.data.api.UserApi;
+import com.cooleshow.usercenter.helper.UserHelper;
+import com.cooleshow.usercenter.presenter.contract.FeedBackContract;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * 创建日期:2022/5/18 16:26
+ *
+ * @author Ryan
+ * 类说明:
+ */
+public class FeedBackPresenter extends BasePresenter<FeedBackContract.FeedBackView> implements FeedBackContract.Presenter {
+    public void addSuggestion(String content, String mobileNo, String typeId, String imgUrls) {
+        if (getView() != null) {
+            getView().showLoading();
+        }
+        JSONObject jsonObject = new JSONObject();
+        try {
+            if (TextUtils.isEmpty(mobileNo)) {
+                mobileNo = UserHelper.getUserPhone();
+            }
+
+            jsonObject.put("clientType", "Android");
+            jsonObject.put("content", content);
+            jsonObject.put("mobileNo", mobileNo);
+            jsonObject.put("type", "APP");
+            jsonObject.put("title", "");//传空值
+            jsonObject.put("suggestionTypeId", typeId);
+            jsonObject.put("userAgent", getDeviceInfo());
+            if (!TextUtils.isEmpty(imgUrls)) {
+                jsonObject.put("attachmentUrls", imgUrls);
+            }
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+        addSubscribe(create(UserApi.class).addSuggestion(RequestBodyUtil.convertToRequestBodyJson(jsonObject.toString()),BaseConstant.CLIENT_API_GROUP_NAME), new BaseObserver<Object>(getView()) {
+            @Override
+            protected void onSuccess(Object data) {
+                if (getView() != null) {
+                    getView().addSuggestionSuccess(data);
+                }
+            }
+        });
+    }
+
+    private String getDeviceInfo() {
+        try {
+            StringBuilder stringBuilder = new StringBuilder();
+            String androidID = DeviceUtils.getAndroidID();
+            String deviceType = DeviceUtils.getCustomDeviceInfo();
+            stringBuilder.append("AndroidDeviceId=" + androidID);
+            stringBuilder.append(";");
+            stringBuilder.append("DeviceType=" + deviceType);
+            return stringBuilder.toString();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return "";
+    }
+
+    public void getSuggestionType() {
+        JSONObject jsonObject = new JSONObject();
+        try {
+            jsonObject.put("rows", Integer.MAX_VALUE);
+            jsonObject.put("page", 1);
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+        addSubscribe(create(UserApi.class).getSuggestionType(RequestBodyUtil.convertToRequestBodyJson(jsonObject.toString()), BaseConstant.CLIENT_API_GROUP_NAME), new BaseObserver<FeedBackTypeBean>(getView()) {
+            @Override
+            protected void onSuccess(FeedBackTypeBean data) {
+                if (getView() != null) {
+                    getView().getSuggestionTypeSuccess(data);
+                }
+            }
+        });
+    }
+
+    public void getCustomerServiceContact() {
+        addSubscribe(create(UserApi.class).getCustomerServiceContact(), new BaseObserver<ServiceContactBean>(getView()) {
+            @Override
+            protected void onSuccess(ServiceContactBean data) {
+                if (getView() != null) {
+                    getView().getCustomerServiceContactSuccess(data);
+                }
+            }
+        });
+    }
+
+}

+ 80 - 0
usercenter/src/main/java/com/cooleshow/usercenter/presenter/FeedBackRecordPresenter.java

@@ -0,0 +1,80 @@
+package com.cooleshow.usercenter.presenter;
+
+
+import android.text.TextUtils;
+
+import com.cooleshow.base.common.BaseConstant;
+import com.cooleshow.base.constanst.Constants;
+import com.cooleshow.base.presenter.BasePresenter;
+import com.cooleshow.base.rx.BaseObserver;
+import com.cooleshow.base.utils.RequestBodyUtil;
+import com.cooleshow.usercenter.bean.FeedBackRecordListBean;
+import com.cooleshow.usercenter.bean.FeedBackTypeBean;
+import com.cooleshow.usercenter.data.api.UserApi;
+import com.cooleshow.usercenter.presenter.contract.FeedBackRecordContract;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * 创建日期:2022/5/18 16:26
+ *
+ * @author Ryan
+ * 类说明:
+ */
+public class FeedBackRecordPresenter extends BasePresenter<FeedBackRecordContract.FeedBackView> implements FeedBackRecordContract.Presenter {
+
+    public void getFeedBackRecord(int page,String typeId,String startTime,String endTime) {
+        JSONObject jsonObject = new JSONObject();
+        try {
+            jsonObject.put("rows", Constants.DEFAULT_DATA_SIZE);
+            jsonObject.put("page", page);
+            if(!TextUtils.isEmpty(typeId)){
+                jsonObject.put("suggestionTypeId", typeId);
+            }
+            if(!TextUtils.isEmpty(startTime)){
+                jsonObject.put("startTime", startTime);
+            }
+            if(!TextUtils.isEmpty(endTime)){
+                jsonObject.put("endTime", endTime);
+            }
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+        addSubscribe(create(UserApi.class).getSuggestionRecord(RequestBodyUtil.convertToRequestBodyJson(jsonObject.toString()),BaseConstant.CLIENT_API_GROUP_NAME), new BaseObserver<FeedBackRecordListBean>(getView()) {
+            @Override
+            protected void onSuccess(FeedBackRecordListBean data) {
+                if (getView() != null) {
+                    getView().getSuggestionRecordSuccess(page,data);
+                }
+            }
+
+            @Override
+            public void onError(Throwable e) {
+                super.onError(e);
+                if(getView()!=null){
+                    getView().getSuggestionRecordError(page);
+                }
+            }
+        });
+    }
+
+    public void getSuggestionType() {
+        JSONObject jsonObject = new JSONObject();
+        try {
+            jsonObject.put("rows", Integer.MAX_VALUE);
+            jsonObject.put("page", 1);
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+        addSubscribe(create(UserApi.class).getSuggestionType(RequestBodyUtil.convertToRequestBodyJson(jsonObject.toString()), BaseConstant.CLIENT_API_GROUP_NAME), new BaseObserver<FeedBackTypeBean>(getView()) {
+            @Override
+            protected void onSuccess(FeedBackTypeBean data) {
+                if (getView() != null) {
+                    getView().getSuggestionTypeSuccess(data);
+                }
+            }
+        });
+    }
+
+}

+ 23 - 0
usercenter/src/main/java/com/cooleshow/usercenter/presenter/contract/FeedBackContract.java

@@ -0,0 +1,23 @@
+package com.cooleshow.usercenter.presenter.contract;
+
+import com.cooleshow.base.bean.ServiceContactBean;
+import com.cooleshow.base.presenter.view.BaseView;
+import com.cooleshow.usercenter.bean.FeedBackTypeBean;
+
+/**
+ * 创建日期:2022/5/18 16:26
+ *
+ * @author Ryan
+ * 类说明:
+ */
+public interface FeedBackContract {
+    interface FeedBackView extends BaseView {
+        void addSuggestionSuccess(Object object);
+
+        void getCustomerServiceContactSuccess(ServiceContactBean data);
+
+        void getSuggestionTypeSuccess(FeedBackTypeBean data);
+    }
+    interface Presenter {
+    }
+}

+ 25 - 0
usercenter/src/main/java/com/cooleshow/usercenter/presenter/contract/FeedBackRecordContract.java

@@ -0,0 +1,25 @@
+package com.cooleshow.usercenter.presenter.contract;
+
+import com.cooleshow.base.presenter.view.BaseView;
+import com.cooleshow.usercenter.bean.FeedBackRecordListBean;
+import com.cooleshow.usercenter.bean.FeedBackTypeBean;
+
+/**
+ * 创建日期:2022/5/18 16:26
+ *
+ * @author Ryan
+ * 类说明:
+ */
+public interface FeedBackRecordContract {
+    interface FeedBackView extends BaseView {
+
+        void getSuggestionRecordSuccess(int page , FeedBackRecordListBean data);
+
+        void getSuggestionTypeSuccess(FeedBackTypeBean data);
+
+        void getSuggestionRecordError(int page);
+
+    }
+    interface Presenter {
+    }
+}

+ 398 - 0
usercenter/src/main/java/com/cooleshow/usercenter/ui/activity/setting/FeedBackActivity.java

@@ -0,0 +1,398 @@
+package com.cooleshow.usercenter.ui.activity.setting;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.Intent;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.TextView;
+
+import com.alibaba.android.arouter.facade.annotation.Route;
+import com.alibaba.android.arouter.launcher.ARouter;
+import com.bigkoo.pickerview.builder.OptionsPickerBuilder;
+import com.bigkoo.pickerview.view.OptionsPickerView;
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.listener.OnItemChildClickListener;
+import com.chad.library.adapter.base.listener.OnItemClickListener;
+import com.cooleshow.base.bean.ServiceContactBean;
+import com.cooleshow.base.constanst.StyleConfig;
+import com.cooleshow.base.constanst.UploadConstants;
+import com.cooleshow.base.router.RouterPath;
+import com.cooleshow.base.ui.activity.BaseMVPActivity;
+import com.cooleshow.base.utils.JumpUtils;
+import com.cooleshow.base.utils.ToastUtil;
+import com.cooleshow.base.utils.helper.GlideEngine;
+import com.cooleshow.base.utils.helper.QMUIDeviceHelper;
+import com.cooleshow.base.utils.helper.QMUIStatusBarHelper;
+import com.cooleshow.base.utils.helper.upload.UploadHelper;
+import com.cooleshow.usercenter.R;
+import com.cooleshow.usercenter.adapter.FeedBackAddPhotoListAdapter;
+import com.cooleshow.usercenter.bean.FeedBackTypeBean;
+import com.cooleshow.usercenter.databinding.ActivityFeedbackLayoutBinding;
+import com.cooleshow.usercenter.presenter.FeedBackPresenter;
+import com.cooleshow.usercenter.presenter.contract.FeedBackContract;
+import com.luck.picture.lib.PictureSelector;
+import com.luck.picture.lib.config.PictureConfig;
+import com.luck.picture.lib.config.PictureMimeType;
+import com.luck.picture.lib.entity.LocalMedia;
+import com.tbruyelle.rxpermissions3.RxPermissions;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+/**
+ * 创建日期:2022/5/18 16:25
+ *
+ * @author Ryan
+ * 类说明:
+ */
+@Route(path = RouterPath.UserCenter.MINE_FEEDBACK)
+public class FeedBackActivity extends BaseMVPActivity<ActivityFeedbackLayoutBinding, FeedBackPresenter> implements FeedBackContract.FeedBackView, View.OnClickListener {
+    private OptionsPickerView pvOptions;
+    private int currentSelectTypePosition = -1;
+    private int maxSelectNum = 5;
+    private String currentSelectTypeId;
+
+    private ArrayList<FeedBackTypeBean.RowsBean> types = new ArrayList<>();
+    private FeedBackAddPhotoListAdapter mPhotoListAdapter;
+
+    List<String> urlList = new ArrayList<>();
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        StyleConfig.setTheme(this);
+        super.onCreate(savedInstanceState);
+        QMUIStatusBarHelper.setStatusBarLightMode(this);
+    }
+
+    @Override
+    public void onClick(View view) {
+        int id = view.getId();
+        if (id == R.id.tv_submit) {
+            String content = getContent();
+            if (TextUtils.isEmpty(content)) {
+                ToastUtil.getInstance().showShort("请输入您的反馈意见");
+                return;
+            }
+            if (TextUtils.isEmpty(currentSelectTypeId)) {
+                ToastUtil.getInstance().showShort("请选择反馈类型");
+                return;
+            }
+            int selectSize = getSelectSize();
+            if (selectSize > 0) {
+                uploadImg(selectSize);
+            } else {
+                presenter.addSuggestion(content, "", currentSelectTypeId, "");
+            }
+//            String mobileNo = viewBinding.etConnect.getText().toString().trim();
+//            if (TextUtils.isEmpty(mobileNo)) {
+//                mobileNo = UserHelper.getUserPhone();
+////                ToastUtil.getInstance().showShort("请输入您的邮箱或手机号");
+////                return;
+//            }
+//            boolean mobile = PhoneUtils.isMobile(mobileNo);
+//            boolean email = RegexUtils.isEmail(mobileNo);
+//            if (mobile || email) {
+//                presenter.addSuggestion(content, mobileNo);
+//            } else {
+//                ToastUtil.getInstance().showShort("请输入正确的邮箱或手机号");
+//            }
+            return;
+        }
+
+        if (id == R.id.cs_type) {
+            showTypeFilter();
+            return;
+        }
+
+        if (id == com.cooleshow.base.R.id.tv_right_text) {
+            ARouter.getInstance().build(RouterPath.UserCenter.MINE_FEEDBACK_RECORD)
+                    .navigation();
+            return;
+        }
+    }
+
+    @Override
+    protected void initView() {
+        initMidTitleToolBar(viewBinding.toolbarInclude.toolbar, "意见反馈");
+        viewBinding.toolbarInclude.tvRightText.setVisibility(View.VISIBLE);
+        viewBinding.toolbarInclude.tvRightText.setText("反馈记录");
+        viewBinding.toolbarInclude.tvRightText.setOnClickListener(this);
+        viewBinding.tvSubmit.setOnClickListener(this);
+        viewBinding.csType.setOnClickListener(this);
+        mPhotoListAdapter = new FeedBackAddPhotoListAdapter();
+        RecyclerView.LayoutManager layoutManager;
+        if(QMUIDeviceHelper.isTablet(getApplicationContext())){
+            layoutManager =new LinearLayoutManager(this, RecyclerView.HORIZONTAL,false);
+        }else{
+            layoutManager = new GridLayoutManager(this, 4);
+        }
+        viewBinding.recyclerView.setLayoutManager(layoutManager);
+        addNewEmpty();
+        viewBinding.recyclerView.setAdapter(mPhotoListAdapter);
+    }
+
+    @Override
+    public void initData() {
+        super.initData();
+        initListener();
+    }
+
+    private void uploadImg(int enableSelectSize) {
+        urlList.clear();
+        for (int i = 0; i < mPhotoListAdapter.getData().size(); i++) {
+            String compressPath = mPhotoListAdapter.getData().get(i).getCompressPath();
+            if (!TextUtils.isEmpty(compressPath)) {
+                upLoadVideo(this, compressPath, enableSelectSize);
+            }
+        }
+    }
+
+    private void initListener() {
+        mPhotoListAdapter.setOnItemClickListener(new OnItemClickListener() {
+            @Override
+            public void onItemClick(@NonNull BaseQuickAdapter<?, ?> adapter, @NonNull View view, int position) {
+                LocalMedia item = (LocalMedia) adapter.getItem(position);
+                if (item.getPath().equals("123")) {
+                    toSelectPic();
+                } else {
+                    JumpUtils.startPhotoPreview(FeedBackActivity.this,getImages(),position,100);
+                }
+            }
+        });
+
+        mPhotoListAdapter.setOnItemChildClickListener(new OnItemChildClickListener() {
+            @Override
+            public void onItemChildClick(@NonNull BaseQuickAdapter<?, ?> adapter, @NonNull View view, int position) {
+                if (position < mPhotoListAdapter.getData().size()) {
+                    LocalMedia localMedia = mPhotoListAdapter.getData().get(position);
+                    if (view.getId() == R.id.iv_del) {
+                        mPhotoListAdapter.remove(localMedia);
+                        addNewEmpty();
+                        return;
+                    }
+                }
+            }
+        });
+    }
+
+    private void toSelectPic() {
+        new RxPermissions(this)
+                .request(Manifest.permission.CAMERA,
+                        Manifest.permission.READ_EXTERNAL_STORAGE,
+                        Manifest.permission.WRITE_EXTERNAL_STORAGE)
+                .subscribe(granted -> {
+                    if (granted) {
+                        goAlbum();
+                    } else {
+                        ToastUtil.getInstance().show(this, "请打开存储和相机权限!");
+                    }
+                });
+    }
+
+    private void goAlbum() {
+        PictureSelector.create(FeedBackActivity.this)
+                .openGallery(PictureMimeType.ofImage())//全部.PictureMimeType.ofAll()、图片.ofImage()、视频.ofVideo()、音频.ofAudio()
+                .loadImageEngine(GlideEngine.createGlideEngine())
+                .theme(com.cooleshow.base.R.style.picture_daya_style)// 主题样式设置 具体参考 values/styles   用法:R.style.picture.white.style
+                .selectionMode(PictureConfig.MULTIPLE)// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE
+                .maxSelectNum(maxSelectNum + 1 - mPhotoListAdapter.getData().size())//多一个添加的
+                .compress(true)// 是否压缩 true or false
+                .forResult(PictureConfig.CHOOSE_REQUEST);
+    }
+
+
+    public int getSelectSize() {
+        int count = 0;
+        for (int i = 0; i < mPhotoListAdapter.getData().size(); i++) {
+            LocalMedia localMedia = mPhotoListAdapter.getData().get(i);
+            if (!TextUtils.isEmpty(localMedia.getCompressPath())) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    private void addNewEmpty() {
+        if (hasEmpty()) {
+            return;
+        }
+        LocalMedia localMedia = new LocalMedia();
+        localMedia.setPath("123");
+        mPhotoListAdapter.getData().add(localMedia);
+    }
+
+    private boolean hasEmpty() {
+        for (int i = 0; i < mPhotoListAdapter.getData().size(); i++) {
+            LocalMedia localMedia = mPhotoListAdapter.getData().get(i);
+            if (TextUtils.equals(localMedia.getPath(), "123")) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void upLoadVideo(Activity activity, String filePath, int enableSelectSize) {
+        UploadHelper uploadHelper = new UploadHelper(activity, UploadConstants.UPLOAD_TYPE_OTHER);
+        uploadHelper.uploadFile(new File(filePath));
+        uploadHelper.setUpLoadCallBack(new UploadHelper.UpLoadCallBack() {
+            @Override
+            public void onSuccess(String url) {
+                urlList.add(url);
+                if (urlList.size() == enableSelectSize) {
+                    StringBuilder stringBuilder = new StringBuilder();
+                    for (int i = 0; i < urlList.size(); i++) {
+                        stringBuilder.append(urlList.get(i));
+                        if (i != urlList.size() - 1) {
+                            stringBuilder.append(",");
+                        }
+                    }
+                    presenter.addSuggestion(getContent(), "", currentSelectTypeId, stringBuilder.toString());
+                    urlList.clear();
+                }
+            }
+
+            @Override
+            public void onFailure() {
+                ToastUtil.getInstance().showShort("上传失败,请重试");
+            }
+        });
+    }
+
+    private String getContent() {
+        return viewBinding.etContent.getText().toString().trim();
+    }
+
+    @Override
+    protected ActivityFeedbackLayoutBinding getLayoutView() {
+        return ActivityFeedbackLayoutBinding.inflate(getLayoutInflater());
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        presenter.getCustomerServiceContact();
+        presenter.getSuggestionType();
+    }
+
+    @Override
+    protected FeedBackPresenter createPresenter() {
+        return new FeedBackPresenter();
+    }
+
+    @Override
+    public void addSuggestionSuccess(Object object) {
+        ToastUtil.getInstance().showShort("提交成功");
+        finish();
+    }
+
+    @Override
+    public void getCustomerServiceContactSuccess(ServiceContactBean data) {
+        if (!checkActivityExist()) {
+            return;
+        }
+        if (data != null) {
+            viewBinding.tvContactText.setText(getString(R.string.custom_service_tip, data.getPhone(), data.getEmail()));
+        }
+    }
+
+    @Override
+    public void getSuggestionTypeSuccess(FeedBackTypeBean data) {
+        if (!checkActivityExist()) {
+            return;
+        }
+        if (data != null && data.getRows() != null) {
+            types.clear();
+            types.addAll(data.getRows());
+        }
+    }
+
+
+    private void showTypeFilter() {
+        if (types.isEmpty()) {
+            return;
+        }
+        pvOptions = new OptionsPickerBuilder(this, (options1, options2, options3, v) -> {
+            this.currentSelectTypePosition = options1;
+            FeedBackTypeBean.RowsBean rowsBean = types.get(options1);
+            viewBinding.tvFeedbackType.setText(rowsBean.getText());
+            viewBinding.tvFeedbackType.setTextColor(getResources().getColor(com.cooleshow.base.R.color.color_333333));
+            currentSelectTypeId = rowsBean.getId();
+        }).setLayoutRes(com.cooleshow.base.R.layout.pickerview_options_default_layout, v -> {
+                    //自定义布局中的控件初始化及事件处理
+                    final TextView tvSubmit = (TextView) v.findViewById(com.cooleshow.base.R.id.tv_finish);
+                    TextView ivCancel = (TextView) v.findViewById(com.cooleshow.base.R.id.tv_cancel);
+                    tvSubmit.setOnClickListener(v12 -> {
+                        pvOptions.returnData();
+                        pvOptions.dismiss();
+                    });
+                    ivCancel.setOnClickListener(v1 -> pvOptions.dismiss());
+
+                }).setDividerColor(Color.TRANSPARENT)
+                .setBgColor(Color.TRANSPARENT).isDialog(false).build();
+
+        pvOptions.setPicker(types);
+        if (currentSelectTypePosition != -1 && currentSelectTypePosition < types.size()) {
+            pvOptions.setSelectOptions(currentSelectTypePosition);
+        }
+        pvOptions.show();
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        if (resultCode == RESULT_OK) {
+            switch (requestCode) {
+                case PictureConfig.CHOOSE_REQUEST:
+                    // 图片、视频、音频选择结果回调
+                    List<LocalMedia> list = PictureSelector.obtainMultipleResult(data);
+                    mPhotoListAdapter.getData().addAll(0, list);
+                    if (mPhotoListAdapter.getData().size() > maxSelectNum) {
+                        mPhotoListAdapter.getData().remove(maxSelectNum);
+                    }
+                    mPhotoListAdapter.notifyDataSetChanged();
+
+                    // 例如 LocalMedia 里面返回三种path
+                    // 1.media.getPath(); 为原图path
+                    // 2.media.getCutPath();为裁剪后path,需判断media.isCut();是否为true  注意:音视频除外
+                    // 3.media.getCompressPath();为压缩后path,需判断media.isCompressed();是否为true  注意:音视频除外
+                    // 如果裁剪并压缩了,以取压缩路径为准,因为是先裁剪后压缩的
+                    //                    GlideImageLoaderUtils.getInstance().loadCircleImage(this,selectList.get(0).getCutPath(),ivPortrait);
+
+                    break;
+                case 100:
+                    // 图片、视频、音频选择结果回调
+                    List<LocalMedia> list1 = data.getParcelableArrayListExtra("list");
+                    mPhotoListAdapter.getData().clear();
+                    mPhotoListAdapter.getData().addAll(list1);
+                    if (mPhotoListAdapter.getData().size() < maxSelectNum) {
+                        addNewEmpty();
+                    }
+                    mPhotoListAdapter.notifyDataSetChanged();
+                    break;
+
+            }
+        }
+    }
+
+    private ArrayList<LocalMedia> getImages() {
+        ArrayList<LocalMedia> list = new ArrayList<>();
+        for (int i = 0; i < mPhotoListAdapter.getData().size(); i++) {
+            LocalMedia localMedia = mPhotoListAdapter.getData().get(i);
+            if (!TextUtils.isEmpty(localMedia.getCompressPath())) {
+                list.add(localMedia);
+            }
+        }
+        return list;
+    }
+}

+ 223 - 0
usercenter/src/main/java/com/cooleshow/usercenter/ui/activity/setting/FeedBackRecordActivity.java

@@ -0,0 +1,223 @@
+package com.cooleshow.usercenter.ui.activity.setting;
+
+import android.os.Bundle;
+import android.view.View;
+
+import com.alibaba.android.arouter.facade.annotation.Route;
+import com.cooleshow.base.constanst.Constants;
+import com.cooleshow.base.router.RouterPath;
+import com.cooleshow.base.ui.activity.BaseMVPActivity;
+import com.cooleshow.base.utils.SizeUtils;
+import com.cooleshow.base.utils.UiUtils;
+import com.cooleshow.base.utils.helper.QMUIStatusBarHelper;
+import com.cooleshow.base.widgets.CommonBottomItemDecoration;
+import com.cooleshow.base.widgets.EmptyViewLayout;
+import com.cooleshow.usercenter.adapter.FeedBackRecordAdapter;
+import com.cooleshow.usercenter.bean.FeedBackRecordListBean;
+import com.cooleshow.usercenter.bean.FeedBackTypeBean;
+import com.cooleshow.usercenter.databinding.AcFeedBackRecordLayoutBinding;
+import com.cooleshow.usercenter.presenter.FeedBackRecordPresenter;
+import com.cooleshow.usercenter.presenter.contract.FeedBackRecordContract;
+import com.cooleshow.usercenter.widget.FeedBackRecordFilterView;
+import com.scwang.smart.refresh.footer.ClassicsFooter;
+import com.scwang.smart.refresh.layout.api.RefreshLayout;
+import com.scwang.smart.refresh.layout.listener.OnLoadMoreListener;
+import com.scwang.smart.refresh.layout.listener.OnRefreshListener;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.LinearLayoutManager;
+
+/**
+ * Author by pq, Date on 2023/12/26.
+ */
+@Route(path = RouterPath.UserCenter.MINE_FEEDBACK_RECORD)
+public class FeedBackRecordActivity extends BaseMVPActivity<AcFeedBackRecordLayoutBinding, FeedBackRecordPresenter> implements FeedBackRecordContract.FeedBackView, View.OnClickListener {
+
+    private FeedBackRecordAdapter mAdapter;
+    private int currentPage = 1;
+
+    private boolean hasNext = true;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        QMUIStatusBarHelper.setStatusBarLightMode(this);
+    }
+
+    @Override
+    protected void initView() {
+        initMidTitleToolBar(viewBinding.toolbarInclude.toolbar, "反馈记录");
+        viewBinding.toolbarInclude.tvRightText.setVisibility(View.VISIBLE);
+        viewBinding.toolbarInclude.tvRightText.setText("筛选");
+        viewBinding.toolbarInclude.tvRightText.setOnClickListener(this);
+        viewBinding.toolbarInclude.tvRightText.setCompoundDrawablePadding(SizeUtils.dp2px(4));
+        UiUtils.refreshFilterTextStyle(false, viewBinding.toolbarInclude.tvRightText);
+    }
+
+    @Override
+    public void initData() {
+        super.initData();
+        mAdapter = new FeedBackRecordAdapter();
+        CommonBottomItemDecoration bottomItemDecoration = new CommonBottomItemDecoration(0, 0, SizeUtils.dp2px(12), 0);
+        EmptyViewLayout emptyViewLayout = new EmptyViewLayout(this);
+        emptyViewLayout.setContent(com.cooleshow.base.R.drawable.icon_empty_content, "暂无内容");
+        mAdapter.setEmptyView(emptyViewLayout);
+        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
+        viewBinding.recyclerView.addItemDecoration(bottomItemDecoration);
+        viewBinding.recyclerView.setLayoutManager(linearLayoutManager);
+        viewBinding.recyclerView.setAdapter(mAdapter);
+        viewBinding.refreshLayout.setRefreshFooter(new ClassicsFooter(this).setDrawableSize(20));
+        initListener();
+
+        getData();
+    }
+
+    private void initListener() {
+        viewBinding.refreshLayout.setOnRefreshListener(new OnRefreshListener() {
+            @Override
+            public void onRefresh(@NonNull RefreshLayout refreshLayout) {
+                currentPage = 1;
+                getData();
+            }
+
+        });
+
+        viewBinding.refreshLayout.setOnLoadMoreListener(new OnLoadMoreListener() {
+            @Override
+            public void onLoadMore(@NonNull RefreshLayout refreshLayout) {
+                //上拉加载
+                if (hasNext) {
+                    currentPage++;
+                    getData();
+                } else {
+                    viewBinding.refreshLayout.finishLoadMoreWithNoMoreData();
+                }
+            }
+        });
+
+        viewBinding.filterView.setOnEventListener(new FeedBackRecordFilterView.OnEventListener() {
+            @Override
+            public void onDismiss() {
+                changeFilterViewVisibility();
+            }
+
+            @Override
+            public void onQuery(String typeId, String startTime, String endTime) {
+                cTypeId = typeId;
+                cStartTime = startTime;
+                cEndTime = endTime;
+                currentPage = 1;
+                getData();
+                changeFilterViewVisibility();
+            }
+        });
+    }
+
+    private String cTypeId;
+    private String cStartTime;
+    private String cEndTime;
+
+    private void getData() {
+        if (presenter != null) {
+            presenter.getFeedBackRecord(currentPage, cTypeId, cStartTime, cEndTime);
+        }
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        presenter.getSuggestionType();
+    }
+
+    @Override
+    protected AcFeedBackRecordLayoutBinding getLayoutView() {
+        return AcFeedBackRecordLayoutBinding.inflate(getLayoutInflater());
+    }
+
+    @Override
+    protected FeedBackRecordPresenter createPresenter() {
+        return new FeedBackRecordPresenter();
+    }
+
+    @Override
+    public void getSuggestionRecordSuccess(int page, FeedBackRecordListBean data) {
+        if (!checkActivityExist()) {
+            return;
+        }
+        if (mAdapter != null) {
+            if (page == 1) {
+                viewBinding.refreshLayout.finishRefresh();
+                mAdapter.getData().clear();
+                mAdapter.notifyDataSetChanged();
+                if (data != null && data.getRows() != null && data.getRows().size() > 0) {
+                    checkHasNext(data.getRows().size());
+                    mAdapter.setNewInstance(data.getRows());
+                }
+            } else {
+                if (data != null && data.getRows() != null && data.getRows().size() > 0) {
+                    viewBinding.refreshLayout.finishLoadMore();
+                    mAdapter.addData(data.getRows());
+                    checkHasNext(data.getRows().size());
+                } else {
+                    viewBinding.refreshLayout.finishLoadMoreWithNoMoreData();
+                }
+            }
+        }
+    }
+
+    @Override
+    public void getSuggestionTypeSuccess(FeedBackTypeBean data) {
+        if (!checkActivityExist()) {
+            return;
+        }
+        viewBinding.filterView.setData(data);
+    }
+
+    @Override
+    public void getSuggestionRecordError(int page) {
+        if (!checkActivityExist()) {
+            return;
+        }
+        if (page == 1) {
+            viewBinding.refreshLayout.finishRefresh();
+        } else {
+            if (mAdapter != null) {
+                currentPage--;
+                viewBinding.refreshLayout.finishLoadMore(false);
+            }
+        }
+    }
+
+
+    @Override
+    public void onClick(View v) {
+        int id = v.getId();
+        if (id == com.cooleshow.base.R.id.tv_right_text) {
+            changeFilterViewVisibility();
+            return;
+        }
+    }
+
+    private void changeFilterViewVisibility() {
+        int visibility = viewBinding.filterView.getVisibility();
+        if (visibility == View.VISIBLE) {
+            viewBinding.filterView.setVisibility(View.GONE);
+            UiUtils.refreshFilterTextStyle(false, viewBinding.toolbarInclude.tvRightText);
+        } else {
+            viewBinding.filterView.setVisibility(View.VISIBLE);
+            UiUtils.refreshFilterTextStyle(true, viewBinding.toolbarInclude.tvRightText);
+        }
+    }
+
+
+    /**
+     * 检查是否还有下一页
+     *
+     * @param dataSize
+     */
+    private void checkHasNext(int dataSize) {
+        hasNext = dataSize >= Constants.DEFAULT_DATA_SIZE;
+        viewBinding.refreshLayout.setNoMoreData(!hasNext);
+    }
+}

+ 313 - 0
usercenter/src/main/java/com/cooleshow/usercenter/widget/FeedBackRecordFilterView.java

@@ -0,0 +1,313 @@
+package com.cooleshow.usercenter.widget;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+
+import com.bigkoo.pickerview.builder.TimePickerBuilder;
+import com.bigkoo.pickerview.listener.CustomListener;
+import com.bigkoo.pickerview.view.TimePickerView;
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.listener.OnItemClickListener;
+import com.cooleshow.base.utils.DateUtil;
+import com.cooleshow.base.utils.ToastUtil;
+import com.cooleshow.base.utils.UiUtils;
+import com.cooleshow.usercenter.R;
+import com.cooleshow.usercenter.adapter.FeedBackRecordFilterTypeAdapter;
+import com.cooleshow.usercenter.bean.FeedBackTypeBean;
+
+import java.util.Calendar;
+import java.util.Date;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+/**
+ * Author by pq, Date on 2023/12/26.
+ */
+public class FeedBackRecordFilterView extends FrameLayout implements View.OnClickListener {
+
+    private RecyclerView mRecyclerView;
+    private TextView mTvStartTime;
+    private TextView mTvEndTime;
+    private View mViewLineStart;
+    private View mViewLineEnd;
+    private TextView mTvCancel;
+    private TextView mTvConfirm;
+    private FeedBackRecordFilterTypeAdapter mAdapter;
+
+    private OnEventListener mEventListener;
+    private String selectId;
+
+    private Date currentSelectStartDate;
+    private Date currentSelectEndDate;
+    private TimePickerView mPvTime;
+
+    private boolean isSelectStart = true;
+
+    public FeedBackRecordFilterView(@NonNull Context context) {
+        this(context, null);
+    }
+
+    public FeedBackRecordFilterView(@NonNull Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, -1);
+    }
+
+    public FeedBackRecordFilterView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        init();
+    }
+
+    private void init() {
+        LayoutInflater.from(getContext()).inflate(R.layout.view_feed_back_record_filter_layout, this);
+        initView();
+        initListener();
+    }
+
+
+    private void initView() {
+        mRecyclerView = findViewById(R.id.recyclerView);
+        mTvStartTime = findViewById(R.id.tv_start_time);
+        mTvEndTime = findViewById(R.id.tv_end_time);
+        mViewLineStart = findViewById(R.id.view_line_start);
+        mViewLineEnd = findViewById(R.id.view_line_end);
+        mTvCancel = findViewById(R.id.tv_cancel);
+        mTvConfirm = findViewById(R.id.tv_confirm);
+        findViewById(R.id.fl_root).setOnClickListener(this);
+        findViewById(R.id.cs_content).setOnClickListener(this);
+
+        mAdapter = new FeedBackRecordFilterTypeAdapter();
+        GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), 2);
+        mRecyclerView.setLayoutManager(gridLayoutManager);
+        mRecyclerView.setAdapter(mAdapter);
+    }
+
+    private void initListener() {
+        mTvCancel.setOnClickListener(this);
+        mTvConfirm.setOnClickListener(this);
+        mTvStartTime.setOnClickListener(this);
+        mTvEndTime.setOnClickListener(this);
+
+        mAdapter.setOnItemClickListener(new OnItemClickListener() {
+            @Override
+            public void onItemClick(@NonNull BaseQuickAdapter<?, ?> adapter, @NonNull View view, int position) {
+                if (position < mAdapter.getData().size()) {
+                    mAdapter.setSelectPos(position);
+                }
+            }
+        });
+    }
+
+
+    public void setData(FeedBackTypeBean data) {
+        if (mAdapter != null) {
+            if (data != null && data.getRows() != null && data.getRows().size() > 0) {
+                mAdapter.setList(data.getRows());
+            } else {
+                mAdapter.getData().clear();
+                mAdapter.notifyDataSetChanged();
+            }
+        }
+    }
+
+    @Override
+    public void onClick(View v) {
+        int id = v.getId();
+        if (id == R.id.fl_root) {
+            if (UiUtils.isFastClick(500)) {
+                return;
+            }
+            if (mEventListener != null) {
+                mEventListener.onDismiss();
+            }
+            return;
+        }
+        if (id == R.id.cs_content) {
+            return;
+        }
+        if (id == R.id.tv_confirm) {
+            if (UiUtils.isFastClick(500)) {
+                return;
+            }
+            handleConfirm();
+            return;
+        }
+
+        if (id == R.id.tv_start_time) {
+            isSelectStart = true;
+            showTimerPopu(currentSelectStartDate);
+            return;
+        }
+
+        if (id == R.id.tv_end_time) {
+            isSelectStart = false;
+            showTimerPopu(currentSelectEndDate);
+            return;
+        }
+        if (id == R.id.tv_cancel) {
+            resetCondition();
+            return;
+        }
+    }
+
+    private void handleConfirm() {
+        if (mEventListener != null) {
+            if (!checkParams()) {
+                return;
+            }
+            selectId = mAdapter.getSelectDataId();
+            String startTime = formatTime2(currentSelectStartDate, true);
+            String endTime = formatTime2(currentSelectEndDate, false);
+            mEventListener.onQuery(selectId, startTime, endTime);
+        }
+    }
+
+
+    private boolean checkParams() {
+        if (currentSelectStartDate == null && currentSelectEndDate == null) {
+            return true;
+        }
+        if (currentSelectStartDate == null || currentSelectEndDate == null) {
+            ToastUtil.getInstance().showShort("请选择正确的时间范围");
+            return false;
+        }
+//        if (currentSelectStartDate == null && currentSelectEndDate != null) {
+//            ToastUtil.getInstance().showShort("请选择正确的时间范围");
+//            return false;
+//        }
+        if (currentSelectEndDate.getTime() < currentSelectStartDate.getTime()) {
+            ToastUtil.getInstance().showShort("结束时间不可小于开始时间");
+            return false;
+        }
+        return true;
+    }
+
+    private void resetCondition() {
+        mAdapter.setSelectPos(-1);
+        mTvStartTime.setText("开始时间");
+        mTvEndTime.setText("结束时间");
+        currentSelectStartDate = null;
+        currentSelectEndDate = null;
+        changeTextStyle(false, true);
+        changeTextStyle(false, false);
+    }
+
+    public void setOnEventListener(OnEventListener onEventListener) {
+        this.mEventListener = onEventListener;
+    }
+
+    public interface OnEventListener {
+        void onDismiss();
+
+        void onQuery(String typeId, String startTime, String endTime);
+    }
+
+    private void showTimerPopu(Date currentDate) {
+        if (mPvTime == null) {
+            mPvTime = new TimePickerBuilder(getContext(), (d, v) -> {
+                if (d == null) {
+                    return;
+                }
+                setSelectDate(d);
+            }).setLayoutRes(com.cooleshow.base.R.layout.pickerview_default_layout, new CustomListener() {
+                        @Override
+                        public void customLayout(View v) {
+                            //自定义布局中的控件初始化及事件处理
+                            final TextView tvSubmit = (TextView) v.findViewById(R.id.tv_finish);
+                            TextView ivCancel = (TextView) v.findViewById(R.id.tv_cancel);
+                            tvSubmit.setOnClickListener(new OnClickListener() {
+                                @Override
+                                public void onClick(View v) {
+                                    mPvTime.returnData();
+                                    mPvTime.dismiss();
+                                }
+                            });
+                            ivCancel.setOnClickListener(new OnClickListener() {
+                                @Override
+                                public void onClick(View v) {
+                                    mPvTime.dismiss();
+                                }
+                            });
+
+                        }
+                    }).setType(new boolean[]{true, true, true, false
+                            , false, false})// 默认全部显示
+                    .setLineSpacingMultiplier(2.5f)
+                    .setDividerColor(Color.TRANSPARENT)
+                    .setBgColor(Color.TRANSPARENT)
+                    .setContentTextSize(16)
+                    .setType(new boolean[]{true, true, true, false, false, false})// 默认全部显示
+                    .setTextColorCenter(getResources().getColor(com.cooleshow.base.R.color.color_1a1a1a))//设置选中项的颜色
+                    .isDialog(false)//是否显示为对话框样式
+                    .setLabel("年", "月", "日", "", "", "")
+                    .build();
+        }
+        if (currentDate != null) {
+            Calendar calendar = Calendar.getInstance();
+            calendar.setTime(currentDate);
+            mPvTime.setDate(calendar);
+        }
+        mPvTime.show();
+    }
+
+    private String formatTime2(Date d, boolean isZeroTime) {
+        if (d == null) {
+            return "";
+        }
+        try {
+            Date date;
+            if (isZeroTime) {
+                date = DateUtil.getZero(d);
+            } else {
+                date = DateUtil.getEnd(d);
+            }
+            String s = DateUtil.date2Str(date);
+            return s;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return "";
+    }
+
+    private String formatTime(Date d) {
+        if (d == null) {
+            return "";
+        }
+        try {
+            String s = DateUtil.date2Str(d, "yyyy-MM-dd");
+            return s;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return "";
+    }
+
+    private void setSelectDate(Date d) {
+        String s = formatTime(d);
+        if (isSelectStart) {
+            currentSelectStartDate = d;
+            mTvStartTime.setText(s);
+            changeTextStyle(true, true);
+        } else {
+            currentSelectEndDate = d;
+            mTvEndTime.setText(s);
+            changeTextStyle(true, false);
+        }
+    }
+
+    private void changeTextStyle(boolean isLightMode, boolean isStart) {
+        if (isStart) {
+            mTvStartTime.setTextColor(getContext().getResources().getColor(isLightMode ? com.cooleshow.base.R.color.color_2dc7aa : com.cooleshow.base.R.color.color_aaaaaa));
+            mViewLineStart.setBackgroundColor(getContext().getResources().getColor(isLightMode ? com.cooleshow.base.R.color.color_2dc7aa : com.cooleshow.base.R.color.color_777777));
+        } else {
+            mTvEndTime.setTextColor(getContext().getResources().getColor(isLightMode ? com.cooleshow.base.R.color.color_2dc7aa : com.cooleshow.base.R.color.color_aaaaaa));
+            mViewLineEnd.setBackgroundColor(getContext().getResources().getColor(isLightMode ? com.cooleshow.base.R.color.color_2dc7aa : com.cooleshow.base.R.color.color_777777));
+        }
+    }
+}

+ 5 - 0
usercenter/src/main/res/color/selector_333333_to_2dc7aa.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="@color/color_2dc7aa" android:state_selected="true"/>
+    <item android:color="@color/color_333333"/>
+</selector>

BIN
usercenter/src/main/res/drawable-xhdpi/icon_del_img.png


BIN
usercenter/src/main/res/drawable-xhdpi/icon_feed_back_type_tag.png


BIN
usercenter/src/main/res/drawable-xhdpi/icon_feedback_add_img.png


BIN
usercenter/src/main/res/drawable-xxhdpi/icon_del_img.png


BIN
usercenter/src/main/res/drawable-xxhdpi/icon_feed_back_type_tag.png


BIN
usercenter/src/main/res/drawable-xxhdpi/icon_feedback_add_img.png


+ 6 - 0
usercenter/src/main/res/drawable/selector_feedback_record_filter_item.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/shape_f0fffc_16dp_border_2dc7aa_1dp" android:state_selected="true"/>
+    <item android:drawable="@drawable/shape_f2f2f2_16dp"/>
+
+</selector>

+ 36 - 0
usercenter/src/main/res/layout/ac_feed_back_record_layout.xml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <include
+        android:id="@+id/toolbar_include"
+        layout="@layout/common_toolbar_layout" />
+
+    <com.scwang.smart.refresh.layout.SmartRefreshLayout
+        android:id="@+id/refreshLayout"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/toolbar_include"
+        app:srlEnableLoadMore="true">
+
+
+        <androidx.recyclerview.widget.RecyclerView
+            android:id="@+id/recyclerView"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:overScrollMode="never"
+            android:scrollbars="none" />
+    </com.scwang.smart.refresh.layout.SmartRefreshLayout>
+
+    <com.cooleshow.usercenter.widget.FeedBackRecordFilterView
+        android:id="@+id/filter_view"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:visibility="gone"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/toolbar_include" />
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 130 - 0
usercenter/src/main/res/layout/activity_feedback_layout.xml

@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <include
+        android:id="@+id/toolbar_include"
+        layout="@layout/common_toolbar_layout" />
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/cs_type"
+        android:layout_width="match_parent"
+        android:layout_height="41dp"
+        android:layout_marginStart="14dp"
+        android:layout_marginTop="12dp"
+        android:layout_marginEnd="14dp"
+        android:background="@drawable/shape_10dp_white">
+
+        <TextView
+            android:id="@+id/tv_feedback_type"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:includeFontPadding="false"
+            android:paddingStart="12dp"
+            android:text="反馈类型(必选)"
+            android:textColor="@color/color_aaaaaa"
+            android:textSize="@dimen/sp_16"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintLeft_toLeftOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <ImageView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginEnd="12dp"
+            android:src="@drawable/icon_arrow_down2"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintRight_toRightOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="16dp"
+        android:layout_marginTop="15dp"
+        android:layout_marginRight="16dp"
+        android:paddingBottom="18dp"
+        android:background="@drawable/bg_white_10dp">
+
+        <EditText
+            android:theme="@style/MyEditText"
+            android:id="@+id/et_content"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/dp_166"
+            android:background="@color/transparent"
+            android:gravity="left"
+            android:hint="请输入您的反馈意见..."
+            android:paddingLeft="12dp"
+            android:paddingTop="14dp"
+            android:paddingRight="12dp"
+            android:paddingBottom="14dp"
+            android:textColor="@color/black_333"
+            android:textColorHint="@color/color_aaaaaa"
+            android:textSize="@dimen/sp_16"
+            app:layout_constraintLeft_toLeftOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <androidx.recyclerview.widget.RecyclerView
+            android:id="@+id/recycler_view"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:overScrollMode="never"
+            android:scrollbars="none"
+            app:layout_constraintLeft_toLeftOf="parent"
+            app:layout_constraintRight_toRightOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/et_content" />
+
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+    <com.cooleshow.base.widgets.ClearEditText
+        android:id="@+id/et_connect"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/dp_48"
+        android:layout_marginLeft="16dp"
+        android:layout_marginTop="8dp"
+        android:layout_marginRight="16dp"
+        android:background="@drawable/bg_white_10dp"
+        android:gravity="left"
+        android:hint="您的邮箱或手机号"
+        android:inputType="textEmailAddress"
+        android:maxLength="64"
+        android:paddingLeft="12dp"
+        android:paddingTop="14dp"
+        android:paddingRight="12dp"
+        android:paddingBottom="14dp"
+        android:textColor="@color/black_333"
+        android:textColorHint="@color/color_999999"
+        android:textSize="@dimen/sp_16"
+        android:visibility="gone" />
+
+    <TextView
+        android:id="@+id/tv_contact_text"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="17dp"
+        android:layout_marginTop="14dp"
+        android:layout_marginRight="17dp"
+        android:lineSpacingExtra="4dp"
+        android:text="或通过以下方式联系我们:\n客服电话:19212093904\n邮箱:schoolmusiclass@163.com"
+        android:textColor="@color/gray_777"
+        android:textSize="@dimen/sp_14" />
+
+    <TextView
+        android:id="@+id/tv_submit"
+        android:layout_width="match_parent"
+        android:layout_height="44dp"
+        android:layout_gravity="bottom"
+        android:layout_marginLeft="28dp"
+        android:layout_marginTop="53dp"
+        android:layout_marginRight="28dp"
+        android:background="?attr/klx_main_bt_background"
+        android:gravity="center"
+        android:text="确定"
+        android:textColor="@color/white"
+        android:textSize="@dimen/sp_16" />
+</LinearLayout>

+ 8 - 0
usercenter/src/main/res/layout/item_feed_back_img_layout.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="74dp"
+    android:id="@+id/img"
+    android:layout_marginEnd="10dp"
+    android:layout_height="74dp">
+
+</ImageView>

+ 143 - 0
usercenter/src/main/res/layout/item_feed_back_record_layout.xml

@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/cs_root"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_marginStart="13dp"
+    android:layout_marginTop="12dp"
+    android:layout_marginEnd="13dp"
+    android:background="@drawable/bg_white_10dp"
+    android:paddingStart="12dp"
+    android:paddingEnd="12dp"
+    android:paddingBottom="23dp">
+
+    <ImageView
+        android:id="@+id/iv_tag"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="15dp"
+        android:src="@drawable/icon_feed_back_type_tag"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <TextView
+        android:id="@+id/tv_type_title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:includeFontPadding="false"
+        android:paddingStart="4dp"
+        android:text="反馈类型"
+        android:textColor="@color/color_333333"
+        android:textSize="@dimen/sp_14"
+        android:textStyle="bold"
+        app:layout_constraintBottom_toBottomOf="@+id/iv_tag"
+        app:layout_constraintLeft_toRightOf="@+id/iv_tag"
+        app:layout_constraintTop_toTopOf="@+id/iv_tag" />
+
+    <TextView
+        android:id="@+id/tv_type"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:includeFontPadding="false"
+        android:paddingStart="4dp"
+        android:textColor="@color/color_333333"
+        android:textSize="@dimen/sp_14"
+        android:textStyle="bold"
+        app:layout_constraintBottom_toBottomOf="@+id/iv_tag"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="@+id/iv_tag"
+        tools:text="反馈类型" />
+
+    <View
+        android:id="@+id/view_line"
+        android:layout_width="match_parent"
+        android:layout_height="1px"
+        android:layout_marginTop="13dp"
+        android:background="@color/color_f2f2f2"
+        app:layout_constraintTop_toBottomOf="@+id/iv_tag" />
+
+    <TextView
+        android:id="@+id/tv_content"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:includeFontPadding="false"
+        android:paddingTop="9dp"
+        android:paddingBottom="13dp"
+        android:textColor="@color/color_333333"
+        android:textSize="@dimen/sp_14"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/view_line"
+        tools:text="我觉得使用不流畅,我觉得使用不流畅,我觉" />
+
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@+id/recyclerView"
+        android:layout_width="match_parent"
+        android:layout_height="74dp"
+        android:overScrollMode="never"
+        android:scrollbars="none"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/tv_content">
+
+    </androidx.recyclerview.widget.RecyclerView>
+
+    <TextView
+        android:id="@+id/tv_num_tip"
+        android:layout_width="37dp"
+        android:layout_height="0dp"
+        android:background="@color/color_e6ffffff"
+        android:gravity="center"
+        android:textColor="@color/color_777777"
+        android:textSize="@dimen/sp_12"
+        android:visibility="gone"
+        app:layout_constraintBottom_toBottomOf="@+id/recyclerView"
+        app:layout_constraintRight_toRightOf="@+id/recyclerView"
+        app:layout_constraintTop_toTopOf="@+id/recyclerView"
+        tools:text="共5张" />
+
+    <LinearLayout
+        android:layout_marginTop="12dp"
+        android:id="@+id/ll_reply"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="@drawable/shape_f6f6f6_4dp"
+        android:orientation="vertical"
+        android:paddingStart="10dp"
+        android:paddingEnd="10dp"
+        android:paddingBottom="13dp"
+        android:visibility="gone"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/recyclerView">
+
+        <TextView
+            android:id="@+id/tv_reply_title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:includeFontPadding="false"
+            android:paddingTop="6dp"
+            android:paddingBottom="6dp"
+            android:text="处理结果"
+            android:textColor="@color/color_333333"
+            android:textSize="@dimen/sp_14"
+            android:textStyle="bold"
+            app:layout_constraintLeft_toLeftOf="parent"
+            app:layout_constraintRight_toRightOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/view_line" />
+
+
+        <TextView
+            android:id="@+id/tv_reply_content"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:includeFontPadding="false"
+            android:textColor="@color/color_777777"
+            android:textSize="@dimen/sp_14"
+            tools:text="感谢您对音乐数字课堂的关注与支持,我们会认真处理您的反馈,下一版本会尽快优化,给您更好的使用体验,敬请期待哦~给您更好的使用体验,敬请期待哦~给您更好的使用体验,敬请期待哦~" />
+
+    </LinearLayout>
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 32 - 0
usercenter/src/main/res/layout/item_feedback_photo_list_item.xml

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:paddingTop="12dp"
+    android:id="@+id/cs_root"
+    android:layout_gravity="center"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+
+    <ImageView
+        android:id="@+id/iv_icon"
+        android:layout_width="68dp"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:qmui_corner_radius="5dp"
+        android:layout_height="68dp"
+        android:layout_gravity="center"
+        android:orientation="vertical"
+        android:src="@drawable/icon_feedback_add_img" />
+
+   <ImageView
+       android:visibility="gone"
+       android:id="@+id/iv_del"
+       android:layout_marginEnd="4dp"
+       android:layout_marginTop="4dp"
+       app:layout_constraintRight_toRightOf="@+id/iv_icon"
+       app:layout_constraintTop_toTopOf="@+id/iv_icon"
+       android:src="@drawable/icon_del_img"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content"/>
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 21 - 0
usercenter/src/main/res/layout/item_feedback_record_type_filter_text_layout.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_marginStart="5dp"
+    android:layout_marginEnd="5dp"
+    android:layout_marginTop="5dp"
+    android:layout_marginBottom="5dp"
+    android:layout_height="wrap_content">
+
+    <TextView
+        android:gravity="center"
+        android:id="@+id/tv_text"
+        android:layout_width="match_parent"
+        android:layout_height="34dp"
+        android:background="@drawable/selector_feedback_record_filter_item"
+        android:includeFontPadding="false"
+        android:textColor="@color/selector_333333_to_2dc7aa"
+        android:textSize="@dimen/sp_13"
+        tools:text="长笛" />
+</FrameLayout>

+ 169 - 0
usercenter/src/main/res/layout/view_feed_back_record_filter_layout.xml

@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/fl_root"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="#60000000">
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/cs_content"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="@color/white"
+        android:paddingBottom="18dp">
+
+        <TextView
+            android:id="@+id/tv_title1"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="13dp"
+            android:paddingTop="10dp"
+            android:paddingBottom="7dp"
+            android:text="反馈类型"
+            android:textColor="@color/color_333333"
+            android:textSize="@dimen/sp_15"
+            android:textStyle="bold"
+            android:visibility="visible"
+            app:layout_constraintLeft_toLeftOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            tools:visibility="visible" />
+
+        <androidx.recyclerview.widget.RecyclerView
+            android:id="@+id/recyclerView"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
+            android:overScrollMode="never"
+            android:scrollbars="none"
+            app:layout_constraintTop_toBottomOf="@+id/tv_title1" />
+
+        <TextView
+            android:id="@+id/tv_title2"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="13dp"
+            android:paddingTop="24dp"
+            android:paddingBottom="7dp"
+            android:text="时间选择"
+            android:textColor="@color/color_333333"
+            android:textSize="@dimen/sp_15"
+            android:textStyle="bold"
+            android:visibility="visible"
+            app:layout_constraintLeft_toLeftOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/recyclerView"
+            tools:visibility="visible" />
+
+
+        <TextView
+            android:id="@+id/tv_title3"
+            android:layout_width="wrap_content"
+            android:layout_height="35dp"
+            android:layout_marginTop="12dp"
+            android:gravity="center"
+            android:text="至"
+            android:textColor="@color/color_333333"
+            android:textSize="@dimen/sp_16"
+            android:textStyle="bold"
+            app:layout_constraintLeft_toLeftOf="parent"
+            app:layout_constraintRight_toRightOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/tv_title2" />
+
+        <TextView
+            android:id="@+id/tv_start_time"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="13dp"
+            android:gravity="center"
+            android:paddingTop="5dp"
+            android:paddingBottom="8dp"
+            android:text="开始时间"
+            android:textColor="@color/color_aaaaaa"
+            android:textSize="@dimen/sp_16"
+            app:layout_constraintBottom_toBottomOf="@+id/tv_title3"
+            app:layout_constraintLeft_toLeftOf="parent"
+            app:layout_constraintRight_toLeftOf="@+id/tv_title3"
+            app:layout_constraintTop_toTopOf="@+id/tv_title3" />
+
+
+        <TextView
+            android:id="@+id/tv_end_time"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginEnd="13dp"
+            android:gravity="center"
+            android:paddingTop="5dp"
+            android:paddingBottom="8dp"
+            android:text="结束时间"
+            android:textColor="@color/color_aaaaaa"
+            android:textSize="@dimen/sp_16"
+            app:layout_constraintBottom_toBottomOf="@+id/tv_title3"
+            app:layout_constraintLeft_toRightOf="@+id/tv_title3"
+            app:layout_constraintRight_toRightOf="parent"
+            app:layout_constraintTop_toTopOf="@+id/tv_title3" />
+
+        <View
+            android:id="@+id/view_line_start"
+            android:layout_width="0dp"
+            android:layout_height="2dp"
+            android:layout_marginStart="22dp"
+            android:layout_marginEnd="22dp"
+            android:background="@color/color_777777"
+            app:layout_constraintBottom_toBottomOf="@+id/tv_start_time"
+            app:layout_constraintLeft_toLeftOf="@+id/tv_start_time"
+            app:layout_constraintRight_toRightOf="@+id/tv_start_time" />
+
+        <View
+            android:id="@+id/view_line_end"
+            android:layout_width="0dp"
+            android:layout_height="2dp"
+            android:layout_marginStart="22dp"
+            android:layout_marginEnd="22dp"
+            android:background="@color/color_777777"
+            app:layout_constraintBottom_toBottomOf="@+id/tv_end_time"
+            app:layout_constraintLeft_toLeftOf="@+id/tv_end_time"
+            app:layout_constraintRight_toRightOf="@+id/tv_end_time" />
+
+
+        <View
+            android:id="@+id/view_line"
+            android:layout_width="match_parent"
+            android:layout_height="1px"
+            android:layout_marginTop="21dp"
+            android:background="@color/color_f2f2f2"
+            app:layout_constraintTop_toBottomOf="@+id/tv_title3" />
+
+        <TextView
+            android:id="@+id/tv_cancel"
+            android:layout_width="0dp"
+            android:layout_height="44dp"
+            android:layout_marginStart="13dp"
+            android:layout_marginTop="18dp"
+            android:background="@drawable/shape_border_dbdbdb_1dp_22dp"
+            android:gravity="center"
+            android:text="重置"
+            android:textColor="@color/color_333333"
+            android:textStyle="bold"
+            app:layout_constraintLeft_toLeftOf="parent"
+            app:layout_constraintRight_toLeftOf="@+id/tv_confirm"
+            app:layout_constraintTop_toBottomOf="@+id/view_line" />
+
+        <TextView
+            android:id="@+id/tv_confirm"
+            android:layout_width="0dp"
+            android:layout_height="44dp"
+            android:layout_marginStart="15dp"
+            android:layout_marginEnd="13dp"
+            android:background="@drawable/shape_2dc7aa_22dp"
+            android:gravity="center"
+            android:text="确定"
+            android:textColor="@color/white"
+            android:textSize="@dimen/sp_16"
+            android:textStyle="bold"
+            app:layout_constraintLeft_toRightOf="@+id/tv_cancel"
+            app:layout_constraintRight_toRightOf="parent"
+            app:layout_constraintTop_toTopOf="@+id/tv_cancel" />
+    </androidx.constraintlayout.widget.ConstraintLayout>
+</FrameLayout>

+ 2 - 0
usercenter/src/main/res/values/strings.xml

@@ -26,4 +26,6 @@
     <string name="str_sign_out_account_des3">3、账号一旦注销完成,将无法恢复;您与我们曾签署过的相关用户协议、授权协议等相应终止。</string>
     <string name="str_sign_out_account_des2">1、您将无法再以此账号登录/使用酷乐秀APP的相关服务。</string>
     <string name="str_sign_out_account_des2_detail">( 1 ) 该账号下的所有内容、信息、数据、记录、个人资料(例如:头像、昵称等)及绑定信息(例如:绑定手机号等);\n( 2 ) 该账号权益信息将被清除(例如:会员时长、购买单曲、专辑信息)。</string>
+
+    <string name="custom_service_tip">或通过以下方式联系我们:\n客服电话:%s\n邮箱:%s</string>
 </resources>

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است