Browse Source

[1001725]增加订单界面显示

zk 1 year ago
parent
commit
61b39b0892
24 changed files with 926 additions and 38 deletions
  1. 8 2
      app/src/main/java/com/datarecovery/master/data/api/AtmobApi.java
  2. 93 0
      app/src/main/java/com/datarecovery/master/data/api/bean/OrderBean.java
  3. 17 0
      app/src/main/java/com/datarecovery/master/data/api/request/OrderPageRequest.java
  4. 32 0
      app/src/main/java/com/datarecovery/master/data/api/response/OrderPageResponse.java
  5. 35 0
      app/src/main/java/com/datarecovery/master/data/repositories/PayRepository.java
  6. 6 0
      app/src/main/java/com/datarecovery/master/dialog/CommonLoadingDialog.java
  7. 18 15
      app/src/main/java/com/datarecovery/master/module/homepage/HomePageViewModel.java
  8. 41 3
      app/src/main/java/com/datarecovery/master/module/imgrecover/ImageRecoverActivity.java
  9. 77 9
      app/src/main/java/com/datarecovery/master/module/imgrecover/ImageRecoverViewModel.java
  10. 37 0
      app/src/main/java/com/datarecovery/master/module/order/OrderFragment.java
  11. 95 0
      app/src/main/java/com/datarecovery/master/module/order/OrderItemAdapter.java
  12. 64 0
      app/src/main/java/com/datarecovery/master/module/order/OrderViewModel.java
  13. BIN
      app/src/main/res/drawable-xxhdpi/bg_example.webp
  14. BIN
      app/src/main/res/drawable-xxhdpi/icon_order.webp
  15. BIN
      app/src/main/res/drawable-xxhdpi/icon_order_no_data.webp
  16. 5 0
      app/src/main/res/drawable/bg_order_card.xml
  17. 5 0
      app/src/main/res/drawable/bg_order_copy.xml
  18. 11 0
      app/src/main/res/drawable/bg_order_header.xml
  19. 1 1
      app/src/main/res/layout/activity_image_recover.xml
  20. 5 4
      app/src/main/res/layout/dialog_common_loading.xml
  21. 147 4
      app/src/main/res/layout/fragment_order.xml
  22. 211 0
      app/src/main/res/layout/item_order.xml
  23. 13 0
      app/src/main/res/values/strings.xml
  24. 5 0
      app/src/main/res/values/style.xml

+ 8 - 2
app/src/main/java/com/datarecovery/master/data/api/AtmobApi.java

@@ -3,8 +3,10 @@ package com.datarecovery.master.data.api;
 
 
 import com.atmob.app.lib.base.BaseResponse;
 import com.atmob.app.lib.base.BaseResponse;
 import com.datarecovery.master.data.api.request.LoginRequest;
 import com.datarecovery.master.data.api.request.LoginRequest;
+import com.datarecovery.master.data.api.request.OrderPageRequest;
 import com.datarecovery.master.data.api.request.SendCodeRequest;
 import com.datarecovery.master.data.api.request.SendCodeRequest;
 import com.datarecovery.master.data.api.response.LoginResponse;
 import com.datarecovery.master.data.api.response.LoginResponse;
+import com.datarecovery.master.data.api.response.OrderPageResponse;
 
 
 import atmob.reactivex.rxjava3.core.Single;
 import atmob.reactivex.rxjava3.core.Single;
 import atmob.retrofit2.http.Body;
 import atmob.retrofit2.http.Body;
@@ -13,9 +15,13 @@ import atmob.retrofit2.http.POST;
 public interface AtmobApi {
 public interface AtmobApi {
 
 
 
 
-    @POST("/s/v1/user/code")
+    @POST("/project/recover/v1/user/code")
     Single<BaseResponse<Object>> loginSendCode(@Body SendCodeRequest request);
     Single<BaseResponse<Object>> loginSendCode(@Body SendCodeRequest request);
 
 
-    @POST("/s/v1/user/login")
+    @POST("/project/recover/v1/user/login")
     Single<BaseResponse<LoginResponse>> loginUserLogin(@Body LoginRequest request);
     Single<BaseResponse<LoginResponse>> loginUserLogin(@Body LoginRequest request);
+
+    @POST("/project/recover/v1/order/page")
+    Single<BaseResponse<OrderPageResponse>> orderPage(@Body OrderPageRequest request);
+
 }
 }

+ 93 - 0
app/src/main/java/com/datarecovery/master/data/api/bean/OrderBean.java

@@ -0,0 +1,93 @@
+package com.datarecovery.master.data.api.bean;
+
+import com.google.gson.annotations.SerializedName;
+
+public class OrderBean {
+    @SerializedName("itemName")
+    private String itemName;
+    @SerializedName("amount")
+    private int amount;
+    @SerializedName("outTradeNo")
+    private String outTradeNo;
+    @SerializedName("id")
+    private int id;
+    @SerializedName("authCode")
+    private String authCode;
+    @SerializedName("startTimestamp")
+    private long startTimestamp;
+    @SerializedName("endTimestamp")
+    private long endTimestamp;
+    @SerializedName("permanent")
+    private boolean permanent;
+
+    @SerializedName("tutorialLink")
+    private String tutorialLink;
+
+    public String getTutorialLink() {
+        return tutorialLink;
+    }
+
+    public String getItemName() {
+        return itemName;
+    }
+
+    public void setItemName(String itemName) {
+        this.itemName = itemName;
+    }
+
+    public int getAmount() {
+        return amount;
+    }
+
+    public void setAmount(int amount) {
+        this.amount = amount;
+    }
+
+    public String getOutTradeNo() {
+        return outTradeNo;
+    }
+
+    public void setOutTradeNo(String outTradeNo) {
+        this.outTradeNo = outTradeNo;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public String getAuthCode() {
+        return authCode;
+    }
+
+    public void setAuthCode(String authCode) {
+        this.authCode = authCode;
+    }
+
+    public long getStartTimestamp() {
+        return startTimestamp;
+    }
+
+    public void setStartTimestamp(long startTimestamp) {
+        this.startTimestamp = startTimestamp;
+    }
+
+    public long getEndTimestamp() {
+        return endTimestamp;
+    }
+
+    public void setEndTimestamp(long endTimestamp) {
+        this.endTimestamp = endTimestamp;
+    }
+
+    public boolean isPermanent() {
+        return permanent;
+    }
+
+    public void setPermanent(boolean permanent) {
+        this.permanent = permanent;
+    }
+}

+ 17 - 0
app/src/main/java/com/datarecovery/master/data/api/request/OrderPageRequest.java

@@ -0,0 +1,17 @@
+package com.datarecovery.master.data.api.request;
+
+import com.google.gson.annotations.SerializedName;
+
+public class OrderPageRequest extends BaseRequest {
+
+    @SerializedName("limit")
+    private final int limit;
+
+    @SerializedName("offset")
+    private final int offset;
+
+    public OrderPageRequest(int limit, int offset) {
+        this.limit = limit;
+        this.offset = offset;
+    }
+}

+ 32 - 0
app/src/main/java/com/datarecovery/master/data/api/response/OrderPageResponse.java

@@ -0,0 +1,32 @@
+package com.datarecovery.master.data.api.response;
+
+import com.datarecovery.master.data.api.bean.OrderBean;
+import com.google.gson.annotations.SerializedName;
+
+import java.util.List;
+
+public class OrderPageResponse {
+
+
+    @SerializedName("list")
+    private List<OrderBean> list;
+    @SerializedName("count")
+    private int count;
+
+    public List<OrderBean> getList() {
+        return list;
+    }
+
+    public void setList(List<OrderBean> list) {
+        this.list = list;
+    }
+
+    public int getCount() {
+        return count;
+    }
+
+    public void setCount(int count) {
+        this.count = count;
+    }
+
+}

+ 35 - 0
app/src/main/java/com/datarecovery/master/data/repositories/PayRepository.java

@@ -0,0 +1,35 @@
+package com.datarecovery.master.data.repositories;
+
+
+import com.atmob.app.lib.handler.RxHttpHandler;
+import com.datarecovery.master.data.api.AtmobApi;
+import com.datarecovery.master.data.api.request.OrderPageRequest;
+import com.datarecovery.master.data.api.response.OrderPageResponse;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import atmob.reactivex.rxjava3.annotations.NonNull;
+import atmob.reactivex.rxjava3.core.Single;
+import atmob.reactivex.rxjava3.core.SingleObserver;
+import atmob.reactivex.rxjava3.disposables.Disposable;
+import atmob.rxjava.utils.RxJavaUtil;
+
+@Singleton
+public class PayRepository {
+
+
+    private final AtmobApi atmobApi;
+
+    @Inject
+    public PayRepository(AtmobApi atmobApi) {
+        this.atmobApi = atmobApi;
+    }
+
+
+    public Single<OrderPageResponse> orderPage(int offset, int limit) {
+        return atmobApi.orderPage(new OrderPageRequest(offset, limit))
+                .compose(RxHttpHandler.handle(true))
+                .compose(RxJavaUtil.SingleSchedule.io2Main());
+    }
+}

+ 6 - 0
app/src/main/java/com/datarecovery/master/dialog/CommonLoadingDialog.java

@@ -3,6 +3,7 @@ package com.datarecovery.master.dialog;
 import static com.atmob.app.lib.base.BaseDialog.*;
 import static com.atmob.app.lib.base.BaseDialog.*;
 
 
 import android.content.Context;
 import android.content.Context;
+import android.view.View;
 
 
 import androidx.annotation.NonNull;
 import androidx.annotation.NonNull;
 import androidx.annotation.StringRes;
 import androidx.annotation.StringRes;
@@ -28,4 +29,9 @@ public class CommonLoadingDialog extends BaseDialog<DialogCommonLoadingBinding>
     protected boolean useQueue() {
     protected boolean useQueue() {
         return false;
         return false;
     }
     }
+
+    public CommonLoadingDialog setMessageGone() {
+        binding.commonLoadingText.setVisibility(View.GONE);
+        return this;
+    }
 }
 }

+ 18 - 15
app/src/main/java/com/datarecovery/master/module/homepage/HomePageViewModel.java

@@ -85,7 +85,7 @@ public class HomePageViewModel extends BaseViewModel {
     }
     }
 
 
     public void onImgRecoveryClick() {
     public void onImgRecoveryClick() {
-        isCheckPermission(() -> ImageRecoverActivity.start(ActivityUtil.getTopActivity()));
+        isCheckPermission(() -> ImageRecoverActivity.start(ActivityUtil.getTopActivity(), ImageRecoverActivity.Type.RECOVER));
     }
     }
 
 
     /**
     /**
@@ -138,20 +138,23 @@ public class HomePageViewModel extends BaseViewModel {
         if (bean == null) {
         if (bean == null) {
             return;
             return;
         }
         }
-        // TODO: 2024/1/9 需要判断是否会员
-        switch (bean.getFunctionId()) {
-            case FunctionBean.AUDIO_RECOVERY:
-                AudioRecoverActivity.start(ActivityUtil.getTopActivity());
-                break;
-            case FunctionBean.FILE_RECOVERY:
-                FileRecoverActivity.start(ActivityUtil.getTopActivity());
-                break;
-            case FunctionBean.IMG_CLEARING:
-                break;
-            case FunctionBean.VIDEO_RECOVERY:
-                VideoRecoverActivity.start(ActivityUtil.getTopActivity());
-                break;
-        }
+        isCheckPermission(() -> {
+            // TODO: 2024/1/9 需要判断是否会员
+            switch (bean.getFunctionId()) {
+                case FunctionBean.AUDIO_RECOVERY:
+                    AudioRecoverActivity.start(ActivityUtil.getTopActivity());
+                    break;
+                case FunctionBean.FILE_RECOVERY:
+                    FileRecoverActivity.start(ActivityUtil.getTopActivity());
+                    break;
+                case FunctionBean.IMG_CLEARING:
+                    ImageRecoverActivity.start(ActivityUtil.getTopActivity(), ImageRecoverActivity.Type.DELETE);
+                    break;
+                case FunctionBean.VIDEO_RECOVERY:
+                    VideoRecoverActivity.start(ActivityUtil.getTopActivity());
+                    break;
+            }
+        });
     }
     }
 
 
     public interface NextStepCallback {
     public interface NextStepCallback {

+ 41 - 3
app/src/main/java/com/datarecovery/master/module/imgrecover/ImageRecoverActivity.java

@@ -7,6 +7,7 @@ import android.content.Intent;
 import android.os.Bundle;
 import android.os.Bundle;
 import android.view.KeyEvent;
 import android.view.KeyEvent;
 
 
+import androidx.annotation.IntDef;
 import androidx.annotation.NonNull;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.Nullable;
 import androidx.recyclerview.widget.ConcatAdapter;
 import androidx.recyclerview.widget.ConcatAdapter;
@@ -27,6 +28,8 @@ import com.datarecovery.master.utils.ImageDeepDetector;
 import com.google.android.material.tabs.TabLayout;
 import com.google.android.material.tabs.TabLayout;
 import com.gyf.immersionbar.ImmersionBar;
 import com.gyf.immersionbar.ImmersionBar;
 
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.List;
 import java.util.List;
 
 
 import dagger.hilt.android.AndroidEntryPoint;
 import dagger.hilt.android.AndroidEntryPoint;
@@ -36,6 +39,16 @@ import dagger.hilt.android.AndroidEntryPoint;
 public class ImageRecoverActivity extends BaseActivity<ActivityImageRecoverBinding> implements ImageItemAdapter.onItemClick {
 public class ImageRecoverActivity extends BaseActivity<ActivityImageRecoverBinding> implements ImageItemAdapter.onItemClick {
 
 
 
 
+    private ConcatAdapter concatAdapter;
+
+    @IntDef({Type.RECOVER, Type.DELETE})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Type {
+        int RECOVER = 1;
+        int DELETE = 2;
+    }
+
+    private static final String TYPE = "type";
     ImageRecoverViewModel imageRecoverViewModel;
     ImageRecoverViewModel imageRecoverViewModel;
 
 
     private final int[] tabTitle = {R.string.photo, R.string.wx, R.string.qq, R.string.other};
     private final int[] tabTitle = {R.string.photo, R.string.wx, R.string.qq, R.string.other};
@@ -49,21 +62,30 @@ public class ImageRecoverActivity extends BaseActivity<ActivityImageRecoverBindi
     private ImageItemAdapter otherAdapter;
     private ImageItemAdapter otherAdapter;
     private GridLayoutManager gridLayoutManager;
     private GridLayoutManager gridLayoutManager;
 
 
-    public static void start(Context context) {
+    public static void start(Context context, @Type int type) {
         Intent intent = new Intent(context, ImageRecoverActivity.class);
         Intent intent = new Intent(context, ImageRecoverActivity.class);
         if (!(context instanceof Activity)) {
         if (!(context instanceof Activity)) {
             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         }
         }
+        intent.putExtra(TYPE, type);
         context.startActivity(intent);
         context.startActivity(intent);
     }
     }
 
 
     @Override
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         super.onCreate(savedInstanceState);
+        initData();
         initView();
         initView();
         initObserver();
         initObserver();
     }
     }
 
 
+    private void initData() {
+        Intent intent = getIntent();
+        if (intent != null) {
+            imageRecoverViewModel.setOperationType(intent.getIntExtra(TYPE, Type.RECOVER));
+        }
+    }
+
     private void initView() {
     private void initView() {
         binding.toolBar.setNavigationOnClickListener(v -> onBackPressed());
         binding.toolBar.setNavigationOnClickListener(v -> onBackPressed());
         addTopStatusBarHeight(binding.toolBar);
         addTopStatusBarHeight(binding.toolBar);
@@ -88,7 +110,7 @@ public class ImageRecoverActivity extends BaseActivity<ActivityImageRecoverBindi
         otherAdapter = new ImageItemAdapter(ImageDeepDetector.ImageFile.CATEGORY_OTHER, this);
         otherAdapter = new ImageItemAdapter(ImageDeepDetector.ImageFile.CATEGORY_OTHER, this);
         otherAdapter.setOnItemClick(this);
         otherAdapter.setOnItemClick(this);
 
 
-        ConcatAdapter concatAdapter = new ConcatAdapter(
+        concatAdapter = new ConcatAdapter(
                 photoTitleAdapter,
                 photoTitleAdapter,
                 photoAdapter,
                 photoAdapter,
                 wxTitleAdapter,
                 wxTitleAdapter,
@@ -163,7 +185,15 @@ public class ImageRecoverActivity extends BaseActivity<ActivityImageRecoverBindi
 
 
     @Override
     @Override
     public void onItemClick(ImageDeepDetector.ImageFile imageFile) {
     public void onItemClick(ImageDeepDetector.ImageFile imageFile) {
-        imageRecoverViewModel.checkPreview(imageFile);
+        if (imageFile == null) {
+            return;
+        }
+        if (imageRecoverViewModel.getType() == Type.DELETE) {
+            imageRecoverViewModel.setItemCheck(imageFile);
+        } else {
+            imageRecoverViewModel.checkPreview(imageFile);
+        }
+
     }
     }
 
 
     private void initTabLayout() {
     private void initTabLayout() {
@@ -222,7 +252,14 @@ public class ImageRecoverActivity extends BaseActivity<ActivityImageRecoverBindi
         }
         }
     }
     }
 
 
+    @SuppressLint("NotifyDataSetChanged")
     private void initObserver() {
     private void initObserver() {
+        imageRecoverViewModel.getNotifyList().observe(this, o -> {
+            photoAdapter.notifyDataSetChanged();
+            wxAdapter.notifyDataSetChanged();
+            qqAdapter.notifyDataSetChanged();
+            otherAdapter.notifyDataSetChanged();
+        });
         imageRecoverViewModel.getShowScanDialogEvent().observe(this, this::showScanProgressDialog);
         imageRecoverViewModel.getShowScanDialogEvent().observe(this, this::showScanProgressDialog);
         imageRecoverViewModel.getDetectedPhotoImg().observe(this, list -> photoAdapter.submit(list));
         imageRecoverViewModel.getDetectedPhotoImg().observe(this, list -> photoAdapter.submit(list));
         imageRecoverViewModel.getDetectedWxImg().observe(this, list -> wxAdapter.submit(list));
         imageRecoverViewModel.getDetectedWxImg().observe(this, list -> wxAdapter.submit(list));
@@ -270,6 +307,7 @@ public class ImageRecoverActivity extends BaseActivity<ActivityImageRecoverBindi
         if (BoxingUtil.boxing(show)) {
         if (BoxingUtil.boxing(show)) {
             if (loadingDialog == null) {
             if (loadingDialog == null) {
                 loadingDialog = new CommonLoadingDialog(this);
                 loadingDialog = new CommonLoadingDialog(this);
+                loadingDialog.setMessage((imageRecoverViewModel.getType()) == Type.DELETE ? R.string.deleting : R.string.exporting);
             }
             }
             loadingDialog.show();
             loadingDialog.show();
         } else {
         } else {

+ 77 - 9
app/src/main/java/com/datarecovery/master/module/imgrecover/ImageRecoverViewModel.java

@@ -48,6 +48,7 @@ public class ImageRecoverViewModel extends BaseViewModel {
     private final SingleLiveEvent<?> detectedFinish = new SingleLiveEvent<>();
     private final SingleLiveEvent<?> detectedFinish = new SingleLiveEvent<>();
     private final SingleLiveEvent<Boolean> showScanDialogEvent = new SingleLiveEvent<>();
     private final SingleLiveEvent<Boolean> showScanDialogEvent = new SingleLiveEvent<>();
     private final SingleLiveEvent<Boolean> showLoadingEvent = new SingleLiveEvent<>();
     private final SingleLiveEvent<Boolean> showLoadingEvent = new SingleLiveEvent<>();
+    private final SingleLiveEvent<?> notifyList = new SingleLiveEvent<>();
     private final MutableLiveData<String> barTitle = new MutableLiveData<>();
     private final MutableLiveData<String> barTitle = new MutableLiveData<>();
     private final MutableLiveData<Boolean> checkAll = new MutableLiveData<>(false);
     private final MutableLiveData<Boolean> checkAll = new MutableLiveData<>(false);
     //总探测到的图片数量
     //总探测到的图片数量
@@ -56,6 +57,7 @@ public class ImageRecoverViewModel extends BaseViewModel {
     private final MutableLiveData<List<ImageDeepDetector.ImageFile>> selectedList = new MutableLiveData<>(new ArrayList<>());
     private final MutableLiveData<List<ImageDeepDetector.ImageFile>> selectedList = new MutableLiveData<>(new ArrayList<>());
     private LiveData<String> selectedCountTxt;
     private LiveData<String> selectedCountTxt;
     private Disposable scanDisposable;
     private Disposable scanDisposable;
+    private int type;
 
 
 
 
     @Inject
     @Inject
@@ -65,6 +67,10 @@ public class ImageRecoverViewModel extends BaseViewModel {
         initLiveData();
         initLiveData();
     }
     }
 
 
+    public LiveData<?> getNotifyList() {
+        return notifyList;
+    }
+
     public LiveData<Boolean> getShowLoadingEvent() {
     public LiveData<Boolean> getShowLoadingEvent() {
         return showLoadingEvent;
         return showLoadingEvent;
     }
     }
@@ -134,6 +140,9 @@ public class ImageRecoverViewModel extends BaseViewModel {
         return barTitle;
         return barTitle;
     }
     }
 
 
+    public int getType() {
+        return type;
+    }
 
 
     private void initLiveData() {
     private void initLiveData() {
         detectedPhotoTitle = Transformations.map(detectedPhotoImg, list ->
         detectedPhotoTitle = Transformations.map(detectedPhotoImg, list ->
@@ -144,13 +153,6 @@ public class ImageRecoverViewModel extends BaseViewModel {
                 ContextUtil.getContext().getString(R.string.qq_count, (list == null || list.isEmpty()) ? 0 : list.size()));
                 ContextUtil.getContext().getString(R.string.qq_count, (list == null || list.isEmpty()) ? 0 : list.size()));
         detectedOtherTitle = Transformations.map(detectedOtherImg, list ->
         detectedOtherTitle = Transformations.map(detectedOtherImg, list ->
                 ContextUtil.getContext().getString(R.string.other_count, (list == null || list.isEmpty()) ? 0 : list.size()));
                 ContextUtil.getContext().getString(R.string.other_count, (list == null || list.isEmpty()) ? 0 : list.size()));
-
-        selectedCountTxt = Transformations.map(selectedList, list -> {
-            if (list == null || list.isEmpty()) {
-                return ContextUtil.getContext().getString(R.string.export);
-            }
-            return ContextUtil.getContext().getString(R.string.export_count, list.size());
-        });
     }
     }
 
 
     public void onCheckAllClick(boolean isCheck) {
     public void onCheckAllClick(boolean isCheck) {
@@ -217,7 +219,7 @@ public class ImageRecoverViewModel extends BaseViewModel {
                         totalCount += imageFiles.size();
                         totalCount += imageFiles.size();
                         totalDetectedCount.setValue(totalCount);
                         totalDetectedCount.setValue(totalCount);
                         for (ImageDeepDetector.ImageFile imageFile : imageFiles) {
                         for (ImageDeepDetector.ImageFile imageFile : imageFiles) {
-                            MutableLiveData<List<ImageDeepDetector.ImageFile>> liveData = null;
+                            MutableLiveData<List<ImageDeepDetector.ImageFile>> liveData;
                             if (imageFile.getCategory() == ImageDeepDetector.ImageFile.CATEGORY_GALLERY) {
                             if (imageFile.getCategory() == ImageDeepDetector.ImageFile.CATEGORY_GALLERY) {
                                 liveData = detectedPhotoImg;
                                 liveData = detectedPhotoImg;
                             } else if (imageFile.getCategory() == ImageDeepDetector.ImageFile.CATEGORY_WECHAT) {
                             } else if (imageFile.getCategory() == ImageDeepDetector.ImageFile.CATEGORY_WECHAT) {
@@ -261,10 +263,56 @@ public class ImageRecoverViewModel extends BaseViewModel {
     }
     }
 
 
     public void checkPreview(@NonNull ImageDeepDetector.ImageFile imageFile) {
     public void checkPreview(@NonNull ImageDeepDetector.ImageFile imageFile) {
+        if (type == ImageRecoverActivity.Type.DELETE) {
+            return;
+        }
         //TODO 判断是否有会员
         //TODO 判断是否有会员
         previewEvent.setValue(imageFile);
         previewEvent.setValue(imageFile);
     }
     }
 
 
+    public void onOperationClick() {
+        if (type == ImageRecoverActivity.Type.DELETE) {
+            onDeleteClick();
+        } else {
+            onExportClick();
+        }
+    }
+
+    private void onDeleteClick() {
+        List<ImageDeepDetector.ImageFile> list = getList(selectedList);
+        if (list.size() == 0) {
+            return;
+        }
+        showLoadingEvent.setValue(true);
+        RxJavaUtil.doInBackground(() -> {
+            for (ImageDeepDetector.ImageFile item : list) {
+                item.delete();
+                MutableLiveData<List<ImageDeepDetector.ImageFile>> liveData;
+                if (item.getCategory() == ImageDeepDetector.ImageFile.CATEGORY_GALLERY) {
+                    liveData = detectedPhotoImg;
+                } else if (item.getCategory() == ImageDeepDetector.ImageFile.CATEGORY_WECHAT) {
+                    liveData = detectedWxImg;
+                } else if (item.getCategory() == ImageDeepDetector.ImageFile.CATEGORY_QQ) {
+                    liveData = detectedQQImg;
+                } else {
+                    liveData = detectedOtherImg;
+                }
+                List<ImageDeepDetector.ImageFile> itemList = getList(liveData);
+                itemList.remove(item);
+            }
+            return true;
+        }, o -> {
+            checkAll.setValue(false);
+            showLoadingEvent.setValue(false);
+            ToastUtil.show(R.string.delete_success, ToastUtil.LENGTH_SHORT);
+            list.clear();
+            notifyList.call();
+        }, throwable -> {
+            showLoadingEvent.setValue(false);
+            ToastUtil.show(R.string.delete_fail, ToastUtil.LENGTH_SHORT);
+        });
+    }
+
     public void onExportClick() {
     public void onExportClick() {
         List<ImageDeepDetector.ImageFile> list = getList(selectedList);
         List<ImageDeepDetector.ImageFile> list = getList(selectedList);
         if (list.size() == 0) {
         if (list.size() == 0) {
@@ -283,7 +331,6 @@ public class ImageRecoverViewModel extends BaseViewModel {
             showLoadingEvent.setValue(false);
             showLoadingEvent.setValue(false);
             ToastUtil.show(R.string.export_success, ToastUtil.LENGTH_SHORT);
             ToastUtil.show(R.string.export_success, ToastUtil.LENGTH_SHORT);
             list.clear();
             list.clear();
-            selectedList.setValue(list);
         }, throwable -> {
         }, throwable -> {
             showLoadingEvent.setValue(false);
             showLoadingEvent.setValue(false);
             ToastUtil.show(R.string.export_fail, ToastUtil.LENGTH_SHORT);
             ToastUtil.show(R.string.export_fail, ToastUtil.LENGTH_SHORT);
@@ -305,4 +352,25 @@ public class ImageRecoverViewModel extends BaseViewModel {
     }
     }
 
 
 
 
+    public void setOperationType(@ImageRecoverActivity.Type int type) {
+        this.type = type;
+        switch (type) {
+            case ImageRecoverActivity.Type.DELETE:
+                selectedCountTxt = Transformations.map(selectedList, list -> {
+                    if (list == null || list.isEmpty()) {
+                        return ContextUtil.getContext().getString(R.string.delete);
+                    }
+                    return ContextUtil.getContext().getString(R.string.delete_count, list.size());
+                });
+                break;
+            case ImageRecoverActivity.Type.RECOVER:
+                selectedCountTxt = Transformations.map(selectedList, list -> {
+                    if (list == null || list.isEmpty()) {
+                        return ContextUtil.getContext().getString(R.string.export);
+                    }
+                    return ContextUtil.getContext().getString(R.string.export_count, list.size());
+                });
+                break;
+        }
+    }
 }
 }

+ 37 - 0
app/src/main/java/com/datarecovery/master/module/order/OrderFragment.java

@@ -1,6 +1,12 @@
 package com.datarecovery.master.module.order;
 package com.datarecovery.master.module.order;
 
 
+import android.os.Bundle;
+import android.view.View;
+
 import androidx.annotation.NonNull;
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
 
 
 import com.atmob.app.lib.base.BaseFragment;
 import com.atmob.app.lib.base.BaseFragment;
 import com.datarecovery.master.databinding.FragmentOrderBinding;
 import com.datarecovery.master.databinding.FragmentOrderBinding;
@@ -12,6 +18,37 @@ import dagger.hilt.android.AndroidEntryPoint;
 public class OrderFragment extends BaseFragment<FragmentOrderBinding> {
 public class OrderFragment extends BaseFragment<FragmentOrderBinding> {
 
 
 
 
+    private OrderViewModel orderViewModel;
+
+    private OrderItemAdapter orderItemAdapter;
+
+
+    @Override
+    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        initView();
+        initObserver();
+    }
+
+    private void initView() {
+        orderItemAdapter = new OrderItemAdapter(getViewLifecycleOwner());
+        binding.ryOrder.setAdapter(orderItemAdapter);
+        binding.ryOrder.setLayoutManager(new LinearLayoutManager(getContext()));
+        binding.swiperLayout.setOnRefreshListener(() -> orderViewModel.refreshOrderPageList());
+    }
+
+    private void initObserver() {
+        orderViewModel.getOrderList().observe(getViewLifecycleOwner(), list -> orderItemAdapter.submit(list));
+        orderViewModel.getRefreshOrderListEvent().observe(getViewLifecycleOwner(), o -> binding.swiperLayout.setRefreshing(false));
+    }
+
+    @Override
+    protected void initViewModel() {
+        super.initViewModel();
+        orderViewModel = getViewModelProvider().get(OrderViewModel.class);
+        binding.setOrderViewModel(orderViewModel);
+    }
+
     @Override
     @Override
     protected void configImmersion(@NonNull ImmersionBar immersionBar) {
     protected void configImmersion(@NonNull ImmersionBar immersionBar) {
         immersionBar.statusBarDarkFont(true);
         immersionBar.statusBarDarkFont(true);

+ 95 - 0
app/src/main/java/com/datarecovery/master/module/order/OrderItemAdapter.java

@@ -0,0 +1,95 @@
+package com.datarecovery.master.module.order;
+
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.recyclerview.widget.AsyncListDiffer;
+import androidx.recyclerview.widget.DiffUtil;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.datarecovery.master.data.api.bean.OrderBean;
+import com.datarecovery.master.databinding.ItemOrderBinding;
+
+import java.util.List;
+import java.util.Objects;
+
+public class OrderItemAdapter extends RecyclerView.Adapter<OrderItemAdapter.ViewHolder> {
+
+
+    private final AsyncListDiffer<OrderBean> listDiffer;
+    private final LifecycleOwner lifecycleOwner;
+
+    public OrderItemAdapter(LifecycleOwner lifecycleOwner) {
+        this.lifecycleOwner = lifecycleOwner;
+        listDiffer = new AsyncListDiffer<>(this, new DiffUtil.ItemCallback<OrderBean>() {
+            @Override
+            public boolean areItemsTheSame(@NonNull OrderBean oldItem, @NonNull OrderBean newItem) {
+                return oldItem.getId() == newItem.getId();
+            }
+
+            @Override
+            public boolean areContentsTheSame(@NonNull OrderBean oldItem, @NonNull OrderBean newItem) {
+                if (!Objects.equals(oldItem.getOutTradeNo(), newItem.getOutTradeNo())) {
+                    return false;
+                }
+                if (!Objects.equals(oldItem.getItemName(), newItem.getItemName())) {
+                    return false;
+                }
+                if (!Objects.equals(oldItem.getAmount(), newItem.getAmount())) {
+                    return false;
+                }
+                if (!Objects.equals(oldItem.getAuthCode(), newItem.getAuthCode())) {
+                    return false;
+                }
+                if (!Objects.equals(oldItem.isPermanent(), newItem.isPermanent())) {
+                    return false;
+                }
+                if (!Objects.equals(oldItem.getTutorialLink(), newItem.getTutorialLink())) {
+                    return false;
+                }
+                return true;
+            }
+        });
+
+    }
+
+    @NonNull
+    @Override
+    public OrderItemAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+        ItemOrderBinding binding = ItemOrderBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
+        return new ViewHolder(binding);
+    }
+
+    @Override
+    public void onBindViewHolder(@NonNull OrderItemAdapter.ViewHolder holder, int position) {
+        holder.bind(listDiffer.getCurrentList().get(position));
+    }
+
+    @Override
+    public int getItemCount() {
+        return listDiffer.getCurrentList().size();
+    }
+
+    public void submit(List<OrderBean> list) {
+        listDiffer.submitList(list);
+    }
+
+    public class ViewHolder extends RecyclerView.ViewHolder {
+
+        private final ItemOrderBinding binding;
+
+        public ViewHolder(@NonNull ItemOrderBinding binding) {
+            super(binding.getRoot());
+            this.binding = binding;
+            binding.setLifecycleOwner(lifecycleOwner);
+        }
+
+        public void bind(OrderBean orderBean) {
+            binding.setOrderBean(orderBean);
+        }
+    }
+
+
+}

+ 64 - 0
app/src/main/java/com/datarecovery/master/module/order/OrderViewModel.java

@@ -0,0 +1,64 @@
+package com.datarecovery.master.module.order;
+
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MutableLiveData;
+
+import com.atmob.app.lib.base.BaseViewModel;
+import com.atmob.app.lib.livedata.SingleLiveEvent;
+import com.datarecovery.master.data.api.bean.OrderBean;
+import com.datarecovery.master.data.api.response.OrderPageResponse;
+import com.datarecovery.master.data.repositories.PayRepository;
+
+import java.util.List;
+
+import javax.inject.Inject;
+
+import atmob.reactivex.rxjava3.annotations.NonNull;
+import atmob.reactivex.rxjava3.core.SingleObserver;
+import atmob.reactivex.rxjava3.disposables.Disposable;
+import dagger.hilt.android.lifecycle.HiltViewModel;
+
+
+@HiltViewModel
+public class OrderViewModel extends BaseViewModel {
+
+
+    private final PayRepository payRepository;
+
+    private final MutableLiveData<List<OrderBean>> orderList = new MutableLiveData<>();
+    private final SingleLiveEvent<?> refreshOrderListEvent = new SingleLiveEvent<>();
+
+    @Inject
+    public OrderViewModel(PayRepository payRepository) {
+        this.payRepository = payRepository;
+        refreshOrderPageList();
+    }
+
+    public LiveData<List<OrderBean>> getOrderList() {
+        return orderList;
+    }
+
+    public LiveData<?> getRefreshOrderListEvent() {
+        return refreshOrderListEvent;
+    }
+
+    public void refreshOrderPageList() {
+        payRepository.orderPage(0, 100).subscribe(new SingleObserver<OrderPageResponse>() {
+            @Override
+            public void onSubscribe(@NonNull Disposable d) {
+
+            }
+
+            @Override
+            public void onSuccess(@NonNull OrderPageResponse orderPageResponse) {
+                orderList.setValue(orderPageResponse.getList());
+                refreshOrderListEvent.call();
+            }
+
+            @Override
+            public void onError(@NonNull Throwable e) {
+                refreshOrderListEvent.call();
+            }
+        });
+    }
+}

BIN
app/src/main/res/drawable-xxhdpi/bg_example.webp


BIN
app/src/main/res/drawable-xxhdpi/icon_order.webp


BIN
app/src/main/res/drawable-xxhdpi/icon_order_no_data.webp


+ 5 - 0
app/src/main/res/drawable/bg_order_card.xml

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

+ 5 - 0
app/src/main/res/drawable/bg_order_copy.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="#E4EFFF" />
+    <corners android:radius="2dp" />
+</shape>

+ 11 - 0
app/src/main/res/drawable/bg_order_header.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <corners
+        android:topLeftRadius="8dp"
+        android:topRightRadius="8dp" />
+    <gradient
+        android:centerColor="#FAFCFF"
+        android:endColor="#FFFFFF"
+        android:centerX="0.9"
+        android:startColor="#EEF5FF" />
+</shape>

+ 1 - 1
app/src/main/res/layout/activity_image_recover.xml

@@ -74,7 +74,7 @@
             android:layout_height="0dp"
             android:layout_height="0dp"
             android:background="@{imageRecoverViewModel.selectedList.size() > 0 ? @drawable/bg_common_btn : @drawable/bg_common_disable_btn}"
             android:background="@{imageRecoverViewModel.selectedList.size() > 0 ? @drawable/bg_common_btn : @drawable/bg_common_disable_btn}"
             android:gravity="center"
             android:gravity="center"
-            android:onClick="@{()->imageRecoverViewModel.onExportClick()}"
+            android:onClick="@{()->imageRecoverViewModel.onOperationClick()}"
             android:text="@{imageRecoverViewModel.selectedCountTxt}"
             android:text="@{imageRecoverViewModel.selectedCountTxt}"
             android:textColor="@color/white"
             android:textColor="@color/white"
             android:textSize="16sp"
             android:textSize="16sp"

+ 5 - 4
app/src/main/res/layout/dialog_common_loading.xml

@@ -19,29 +19,30 @@
         app:layout_constraintWidth_percent="0.3333333333333333" />
         app:layout_constraintWidth_percent="0.3333333333333333" />
 
 
     <ProgressBar
     <ProgressBar
+        android:id="@+id/common_loading_progress"
         android:layout_width="0dp"
         android:layout_width="0dp"
         android:layout_height="0dp"
         android:layout_height="0dp"
         android:indeterminate="true"
         android:indeterminate="true"
         android:indeterminateDrawable="@drawable/progress_common_loading"
         android:indeterminateDrawable="@drawable/progress_common_loading"
-        app:layout_constraintBottom_toBottomOf="@+id/common_loading_bg"
+        app:layout_constraintBottom_toTopOf="@+id/common_loading_text"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintEnd_toEndOf="@+id/common_loading_bg"
         app:layout_constraintEnd_toEndOf="@+id/common_loading_bg"
         app:layout_constraintStart_toStartOf="@+id/common_loading_bg"
         app:layout_constraintStart_toStartOf="@+id/common_loading_bg"
         app:layout_constraintTop_toTopOf="@+id/common_loading_bg"
         app:layout_constraintTop_toTopOf="@+id/common_loading_bg"
-        app:layout_constraintVertical_bias="0.3448275862068966"
+        app:layout_constraintVertical_chainStyle="packed"
         app:layout_constraintWidth_percent="0.0916666666666667" />
         app:layout_constraintWidth_percent="0.0916666666666667" />
 
 
     <TextView
     <TextView
         android:id="@+id/common_loading_text"
         android:id="@+id/common_loading_text"
         android:layout_width="wrap_content"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_height="wrap_content"
+        android:layout_marginTop="12dp"
         android:text="@string/loading_txt"
         android:text="@string/loading_txt"
         android:textColor="@color/white"
         android:textColor="@color/white"
         android:textSize="14sp"
         android:textSize="14sp"
         app:layout_constraintBottom_toBottomOf="@+id/common_loading_bg"
         app:layout_constraintBottom_toBottomOf="@+id/common_loading_bg"
         app:layout_constraintEnd_toEndOf="@+id/common_loading_bg"
         app:layout_constraintEnd_toEndOf="@+id/common_loading_bg"
         app:layout_constraintStart_toStartOf="@+id/common_loading_bg"
         app:layout_constraintStart_toStartOf="@+id/common_loading_bg"
-        app:layout_constraintTop_toTopOf="@+id/common_loading_bg"
-        app:layout_constraintVertical_bias="0.696969696969697" />
+        app:layout_constraintTop_toBottomOf="@+id/common_loading_progress" />
 
 
 </androidx.constraintlayout.widget.ConstraintLayout>
 </androidx.constraintlayout.widget.ConstraintLayout>

+ 147 - 4
app/src/main/res/layout/fragment_order.xml

@@ -1,6 +1,149 @@
 <?xml version="1.0" encoding="utf-8"?>
 <?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="match_parent">
+<layout 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">
 
 
-</androidx.constraintlayout.widget.ConstraintLayout>
+    <data>
+
+        <variable
+            name="orderViewModel"
+            type="com.datarecovery.master.module.order.OrderViewModel" />
+
+        <import type="com.atmob.common.ui.SizeUtil" />
+    </data>
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="#F8F8F8">
+
+        <ImageView
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:src="@drawable/bg_example"
+            app:layout_constraintDimensionRatio="1080:558"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <Space
+            android:id="@+id/space_status_bar"
+            android:layout_width="match_parent"
+            android:layout_height="@{SizeUtil.getStatusBarHeight(), default=@dimen/app_status_bar_height}"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <Space
+            android:id="@+id/space1"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            app:layout_constraintDimensionRatio="360:16"
+            app:layout_constraintTop_toBottomOf="@+id/space_status_bar" />
+
+        <ImageView
+            android:id="@+id/iv_example"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_marginStart="@dimen/app_common_page_horizontal_padding"
+            android:src="@drawable/icon_order"
+            app:layout_constraintDimensionRatio="246:60"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/space1"
+            app:layout_constraintWidth_percent="0.2" />
+
+        <Space
+            android:id="@+id/space2"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            app:layout_constraintDimensionRatio="360:22"
+            app:layout_constraintTop_toBottomOf="@+id/iv_example" />
+
+
+        <ImageView
+            android:id="@+id/iv_order_no_data"
+            isGone="@{orderViewModel.orderList.size() > 0}"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:src="@drawable/icon_order_no_data"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintDimensionRatio="260:160"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/space2"
+            app:layout_constraintVertical_bias="0.2351190476190476"
+            app:layout_constraintVertical_chainStyle="packed"
+            app:layout_constraintWidth_percent="0.7222222222222222" />
+
+        <TextView
+            android:id="@+id/tv_order_no_data"
+            isGone="@{orderViewModel.orderList.size() > 0}"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="16dp"
+            android:text="@string/order_no_data"
+            android:textColor="#404040"
+            android:textSize="16sp"
+            app:layout_constraintEnd_toEndOf="@+id/iv_order_no_data"
+            app:layout_constraintStart_toStartOf="@+id/iv_order_no_data"
+            app:layout_constraintTop_toBottomOf="@+id/iv_order_no_data" />
+
+
+        <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
+            android:id="@+id/swiper_layout"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintTop_toBottomOf="@id/space2">
+
+
+            <androidx.core.widget.NestedScrollView
+                android:layout_width="match_parent"
+                android:layout_height="match_parent">
+
+                <LinearLayout
+                    isGone="@{orderViewModel.orderList == null || orderViewModel.orderList.size() == 0}"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:orientation="vertical">
+
+                    <androidx.recyclerview.widget.RecyclerView
+                        android:id="@+id/ry_order"
+                        android:layout_width="match_parent"
+                        android:layout_height="match_parent"
+                        tools:listitem="@layout/item_order" />
+
+                    <LinearLayout
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:gravity="center"
+                        android:orientation="horizontal"
+                        android:paddingVertical="8dp">
+
+                        <View
+                            android:layout_width="12dp"
+                            android:layout_height="1dp"
+                            android:background="#CCCCCC" />
+
+                        <TextView
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:layout_marginHorizontal="4dp"
+                            android:text="@string/order_show_hint"
+                            android:textColor="#CCCCCC"
+                            android:textSize="12dp" />
+
+                        <View
+                            android:layout_width="12dp"
+                            android:layout_height="1dp"
+                            android:background="#CCCCCC" />
+
+
+                    </LinearLayout>
+
+                </LinearLayout>
+
+            </androidx.core.widget.NestedScrollView>
+
+
+        </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
+
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+</layout>

+ 211 - 0
app/src/main/res/layout/item_order.xml

@@ -0,0 +1,211 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout 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">
+
+    <data>
+
+        <variable
+            name="orderBean"
+            type="com.datarecovery.master.data.api.bean.OrderBean" />
+    </data>
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="8dp"
+        tools:background="@color/black10">
+
+
+        <View
+            android:background="@drawable/bg_order_card"
+            app:layout_constraintStart_toStartOf="@+id/order_header"
+            app:layout_constraintEnd_toEndOf="@+id/order_header"
+            app:layout_constraintTop_toTopOf="@+id/order_header"
+            app:layout_constraintBottom_toBottomOf="@+id/space6"
+            android:layout_width="0dp"
+            android:layout_height="0dp" />
+
+        <View
+            android:id="@+id/order_header"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_marginHorizontal="16dp"
+            android:background="@drawable/bg_order_header"
+            app:layout_constraintDimensionRatio="328:36"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <TextView
+            android:id="@+id/tv_order"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="12dp"
+            android:textColor="#202020"
+            android:textSize="14sp"
+            android:textStyle="bold"
+            app:layout_constraintBottom_toBottomOf="@+id/order_header"
+            app:layout_constraintStart_toStartOf="@+id/order_header"
+            app:layout_constraintTop_toTopOf="@+id/order_header"
+            tools:text="订单号:adfe21649518788" />
+
+        <TextView
+            android:id="@+id/tv_copy_order"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginEnd="12dp"
+            android:background="@drawable/bg_order_copy"
+            android:paddingHorizontal="10dp"
+            android:paddingVertical="2dp"
+            android:text="@string/order_copy"
+            android:textColor="@color/colorPrimary"
+            android:textSize="12sp"
+            app:layout_constraintBottom_toBottomOf="@+id/order_header"
+            app:layout_constraintEnd_toEndOf="@+id/order_header"
+            app:layout_constraintTop_toTopOf="@+id/order_header" />
+
+        <Space
+            android:id="@+id/space1"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            app:layout_constraintDimensionRatio="360:12"
+            app:layout_constraintTop_toBottomOf="@+id/order_header" />
+
+        <TextView
+            android:id="@+id/tv_order_buy_type"
+            style="@style/Order_List_Content_Txt"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/order_buy_type"
+            app:layout_constraintLeft_toLeftOf="@+id/tv_order"
+            app:layout_constraintTop_toBottomOf="@+id/space1" />
+
+        <TextView
+            style="@style/Order_List_Content_Txt"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="16dp"
+            app:layout_constraintBaseline_toBaselineOf="@+id/tv_order_buy_type"
+            app:layout_constraintStart_toEndOf="@+id/tv_order_buy_type"
+            tools:text="图片恢复" />
+
+        <Space
+            android:id="@+id/space2"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            app:layout_constraintDimensionRatio="360:8"
+            app:layout_constraintTop_toBottomOf="@+id/tv_order_buy_type" />
+
+        <TextView
+            android:id="@+id/tv_order_buy_time"
+            style="@style/Order_List_Content_Txt"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/order_buy_time"
+            app:layout_constraintLeft_toLeftOf="@+id/tv_order"
+            app:layout_constraintTop_toBottomOf="@+id/space2" />
+
+        <TextView
+            style="@style/Order_List_Content_Txt"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="16dp"
+            app:layout_constraintBaseline_toBaselineOf="@+id/tv_order_buy_time"
+            app:layout_constraintStart_toEndOf="@+id/tv_order_buy_time"
+            tools:text="2023-12-16" />
+
+
+        <Space
+            android:id="@+id/space3"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            app:layout_constraintDimensionRatio="360:8"
+            app:layout_constraintTop_toBottomOf="@+id/tv_order_buy_time" />
+
+
+        <TextView
+            android:id="@+id/tv_order_member_validity"
+            style="@style/Order_List_Content_Txt"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/order_member_validity"
+            app:layout_constraintLeft_toLeftOf="@+id/tv_order"
+            app:layout_constraintTop_toBottomOf="@+id/space3" />
+
+        <TextView
+            style="@style/Order_List_Content_Txt"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="16dp"
+            app:layout_constraintBaseline_toBaselineOf="@+id/tv_order_member_validity"
+            app:layout_constraintStart_toEndOf="@+id/tv_order_member_validity"
+            tools:text="永久有效" />
+
+
+        <Space
+            android:id="@+id/space4"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            app:layout_constraintDimensionRatio="360:12"
+            app:layout_constraintTop_toBottomOf="@+id/tv_order_member_validity" />
+
+        <View
+            android:id="@+id/v_line"
+            android:layout_width="0dp"
+            android:layout_height="1dp"
+            android:background="#F5F5F5"
+            app:layout_constraintEnd_toEndOf="@+id/tv_copy_order"
+            app:layout_constraintStart_toStartOf="@+id/tv_order"
+            app:layout_constraintTop_toBottomOf="@+id/space4" />
+
+        <Space
+            android:id="@+id/space5"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            app:layout_constraintDimensionRatio="360:8"
+            app:layout_constraintTop_toBottomOf="@+id/v_line" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textColor="#404040"
+            android:textSize="14sp"
+            app:layout_constraintBottom_toTopOf="@+id/space7"
+            app:layout_constraintLeft_toLeftOf="@+id/tv_order"
+            app:layout_constraintTop_toBottomOf="@+id/space5"
+            tools:text="金额:¥66" />
+
+
+        <TextView
+            android:id="@+id/tv_copy_link"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_marginEnd="12dp"
+            android:background="@drawable/bg_common_btn"
+            android:gravity="center"
+            android:text="@string/order_copy_link"
+            android:textColor="@color/white"
+            android:textSize="14sp"
+            android:textStyle="bold"
+            app:layout_constraintBottom_toTopOf="@+id/space6"
+            app:layout_constraintDimensionRatio="120:36"
+            app:layout_constraintEnd_toEndOf="@+id/order_header"
+            app:layout_constraintTop_toBottomOf="@+id/space5"
+            app:layout_constraintWidth_percent="0.3333333333333333" />
+
+        <Space
+            app:layout_constraintBottom_toTopOf="@+id/space6"
+            android:id="@+id/space7"
+            app:layout_constraintDimensionRatio="360:5"
+            android:layout_width="match_parent"
+            android:layout_height="0dp" />
+
+        <Space
+            android:id="@+id/space6"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintDimensionRatio="360:8" />
+
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+</layout>

+ 13 - 0
app/src/main/res/values/strings.xml

@@ -123,4 +123,17 @@
     <string name="away_a_week">一周前</string>
     <string name="away_a_week">一周前</string>
     <string name="a_month_ago">一个月前</string>
     <string name="a_month_ago">一个月前</string>
     <string name="a_year_ago">一个年前</string>
     <string name="a_year_ago">一个年前</string>
+    <string name="delete">立即清除</string>
+    <string name="delete_count">立即清除(%d)</string>
+    <string name="delete_success">清除成功</string>
+    <string name="delete_fail">清除失败</string>
+    <string name="exporting">正在导出…</string>
+    <string name="deleting">正在清除…</string>
+    <string name="order_no_data">暂无订单</string>
+    <string name="order_show_hint">已展示全部订单</string>
+    <string name="order_copy">复制</string>
+    <string name="order_buy_type">购买服务</string>
+    <string name="order_buy_time">购买时间</string>
+    <string name="order_member_validity">会员时效</string>
+    <string name="order_copy_link">复制教程链接</string>
 </resources>
 </resources>

+ 5 - 0
app/src/main/res/values/style.xml

@@ -57,5 +57,10 @@
         <item name="android:layout_gravity">center</item>
         <item name="android:layout_gravity">center</item>
     </style>
     </style>
 
 
+    <style name="Order_List_Content_Txt">
+        <item name="android:textSize">14sp</item>
+        <item name="android:textColor">#404040</item>
+    </style>
+
 
 
 </resources>
 </resources>