Browse Source

fix: 地址生成和下载

cjwen 1 year ago
parent
commit
83eacb84cb

+ 27 - 0
front/admin-front/src/api/adress.js

@@ -0,0 +1,27 @@
+import request from '@/utils/request'
+
+export const baseUrl = process.env.VUE_APP_BASEURL;
+
+
+export function pageAddress(data) {
+  return request({
+    url: '/ams/address/page',
+    method: 'post',
+    data
+  })
+}
+
+export function batchAddress(data) {
+  return request({
+    url: '/ams/address/generate/batch-address',
+    method: 'post',
+    data
+  })
+}
+export function downloadAddress(data) {
+  return request({
+    url: '/ams/address/download/batch-keystore',
+    method: 'post',
+    data
+  })
+}

+ 1 - 2
front/admin-front/src/layout/components/AppMain.vue

@@ -21,10 +21,9 @@ export default {
 .app-main {
   /*50 = navbar  */
   min-height: calc(100vh - 50px);
-  width: 100%;
   position: relative;
   overflow: hidden;
-  margin: 48px;
+  margin: 96px ;
 }
 .fixed-header+.app-main {
   padding-top: 50px;

+ 46 - 7
front/admin-front/src/styles/sidebar.scss

@@ -14,7 +14,7 @@
     width: $sideBarWidth !important;
     background-color: $menuBg;
     position: fixed;
-    font-size: 0px;
+    font-size: 0;
     top: 40px;
     bottom: 40px;
     left: 40px;
@@ -30,7 +30,7 @@
       display: flex;
       flex-direction: column;
       align-items: flex-start;
-      padding: 0px;
+      padding: 0;
       gap: 28px;
 
       position: absolute;
@@ -53,7 +53,7 @@
       display: flex;
       flex-direction: column;
       align-items: flex-start;
-      padding: 0px;
+      padding: 0;
       gap: 28px;
 
       position: absolute;
@@ -68,7 +68,7 @@
     }
 
     .el-scrollbar__bar.is-vertical {
-      right: 0px;
+      right: 0;
       width: 0;
     }
 
@@ -200,7 +200,7 @@
   // mobile responsive
   .mobile {
     .main-container {
-      margin-left: 0px;
+      margin-left: 0;
     }
 
     .sidebar-container {
@@ -304,7 +304,7 @@
 }
 
 .serach-box .el-input__inner {
-  font-family: 'HONOR Sans CN';
+  font-family: 'HONOR Sans CN', serif;
   font-style: normal;
   font-weight: 400;
   font-size: 12px;
@@ -326,4 +326,43 @@
   color: #000000 !important;
   text-align: center;
   margin-top: -8px;
-}
+}
+
+.totalCount-number {
+  font-family: 'HONOR Sans CN';
+  font-style: normal;
+  font-weight: 700;
+  font-size: 21px;
+  line-height: 28px;
+  color: #181818;
+}
+
+.totalCount-text {
+  font-family: 'HONOR Sans CN';
+  font-style: normal;
+  font-weight: 700;
+  font-size: 12px;
+  line-height: 16px;
+  color: #222222;
+  opacity: 0.5;
+}
+
+.btn-add {
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  padding: 16px 32px;
+  gap: 4px;
+
+  background: #4A76FF;
+  border-radius: 10px;
+}
+
+.block-title {
+  font-family: 'HONOR Sans CN';
+  font-style: normal;
+  font-weight: 700;
+  font-size: 21px;
+  line-height: 28px;
+}

+ 1 - 1
front/admin-front/src/utils/request.js

@@ -22,7 +22,7 @@ const service = axios.create({
   // axios中请求配置有baseURL选项,表示请求URL公共部分
   baseURL: process.env.VUE_APP_BASE_API,
   // 超时
-  timeout: 10000
+  // timeout: 100000
 })
 // request interceptor
 service.interceptors.request.use(

+ 159 - 0
front/admin-front/src/views/address/SaveOrUpdate.vue

@@ -0,0 +1,159 @@
+<template>
+  <div>
+    <el-drawer
+      :wrapperClosable="false"
+      size="700px"
+      :visible.sync="addressModal"
+      :withHeader="false"
+      :modal-append-to-body="false"
+    >
+      <el-row style="padding-top: 20px; border-bottom: 1px solid #f0f0f0">
+        <el-col :span="13" class="mb-18">
+          <span
+            class="block-title"
+            style="line-height: 2.5;margin:20px"
+            >生成地址</span
+          >
+        </el-col>
+        <el-col :span="10">
+          <el-button
+            type="danger"
+            plain
+            class="float-right mg-l-r-10 close-btn"
+            @click="close"
+            >关闭
+          </el-button>
+          <el-button
+            class="float-right mg-l-r-10 confirm-btn pd-2"
+            @click="generateAddress"
+            >确认</el-button
+          >
+        </el-col>
+      </el-row>
+
+      <el-form
+        :model="ruleForm"
+        status-icon
+        :rules="rules"
+        ref="ruleForm"
+        label-width="100px"
+        style="margin: 40px 0;width: 600px"
+      >
+        <el-form-item label="地址组名称" prop="groupName">
+          <el-input v-model="ruleForm.groupName" autocomplete="off"  ></el-input>
+        </el-form-item>
+        <el-form-item label="生成数量" prop="numWallet">
+          <el-input v-model="ruleForm.numWallet" autocomplete="off"></el-input>
+        </el-form-item>
+        <el-form-item label="密码" prop="password">
+          <el-input
+            type="password"
+            v-model="ruleForm.password"
+            autocomplete="off"
+          ></el-input>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="generateAddress('ruleForm')">提交</el-button
+          >
+          <el-button @click="resetForm('ruleForm')">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </el-drawer>
+  </div>
+</template>
+<style scope>
+.upload__text {
+  font-size: 12px;
+  font-family: MiSans, MiSans-Normal;
+  font-weight: Normal;
+  text-align: LEFT;
+  color: #888888;
+  line-height: 12px;
+  position: absolute;
+  bottom: 30px;
+  left: 23px;
+}
+
+.avatar-uploader .el-upload {
+  background: #f7f7f7;
+  border-radius: 10px;
+  cursor: pointer;
+  position: relative;
+  overflow: hidden;
+}
+
+.avatar-uploader .el-upload:hover {
+  border-color: #409eff;
+}
+
+.avatar-uploader-icon {
+  font-size: 28px;
+  color: #8c939d;
+  width: 156px;
+  height: 156px;
+  line-height: 156px;
+  text-align: center;
+}
+
+.el-upload-dragger {
+  width: 156px;
+  height: 156px;
+}
+.avatar {
+  width: 156px;
+  height: 156px;
+}
+</style>
+
+<script>
+import { pageAddress, batchAddress } from "@/api/adress";
+export const baseUrl = process.env.VUE_APP_BASEURL;
+export default {
+  data() {
+    return {
+      url: process.env.VUE_APP_BASEURL,
+      addressModal: false,
+      isSave: false,
+      ruleForm: {
+        password: undefined,
+        groupName: undefined,
+        numWallet: undefined,
+      },
+      rules: {},
+    };
+  },
+  methods: {
+    resetForm() {
+      this.ruleForm.groupName = undefined;
+      this.ruleForm.password = undefined;
+      this.ruleForm.numWallet = undefined;
+    },
+    resetField() {
+      this.$refs["ruleForm"].clearValidate();
+    },
+    close() {
+      this.addressModal = false;
+      this.resetForm();
+    },
+    generateAddress() {
+      this.$refs["ruleForm"].validate((valid) => {
+        if (valid) {
+          batchAddress(JSON.stringify(this.ruleForm), {
+            headers: {
+              "content-type": "application/json",
+            },
+          }).then((res) => {
+            this.$message.success("生成成功");
+            this.addressModal = false;
+            this.resetForm();
+            this.$parent.getAddresses();
+          });
+        } else {
+          this.$message.error("请填写必填字段!");
+        }
+      });
+    },
+  },
+  created() {},
+};
+</script>

+ 195 - 0
front/admin-front/src/views/address/download.vue

@@ -0,0 +1,195 @@
+<template>
+  <div>
+    <el-drawer
+      :wrapperClosable="false"
+      size="700px"
+      :visible.sync="downloadModal"
+      :withHeader="false"
+      :modal-append-to-body="false"
+    >
+      <el-row style="padding-top: 20px; border-bottom: 1px solid #f0f0f0">
+        <el-col :span="13" class="mb-18">
+          <span class="block-title" style="line-height: 2.5; margin: 20px"
+            >下载地址</span
+          >
+        </el-col>
+        <el-col :span="7" :offset="2">
+          <el-button
+            type="danger"
+            plain
+            class="float-right mg-l-r-10 close-btn"
+            @click="close"
+            >关闭
+          </el-button>
+          <el-button
+            class="float-right mg-l-r-10 confirm-btn pd-2"
+            @click="downloadAddress"
+            >确认</el-button
+          >
+        </el-col>
+      </el-row>
+
+      <el-form
+        :model="ruleForm"
+        status-icon
+        :rules="rules"
+        ref="ruleForm"
+        label-width="100px"
+        style="margin: 40px 0; width: 600px"
+      >
+        <el-form-item label="地址组名称" prop="groupName">
+          <el-input v-model="ruleForm.groupName" autocomplete="off"></el-input>
+        </el-form-item>
+        <!-- <el-form-item label="生成数量" prop="numWallet">
+          <el-input v-model="ruleForm.numWallet" autocomplete="off"></el-input>
+        </el-form-item> -->
+        <el-form-item label="密码" prop="password">
+          <el-input
+            type="password"
+            v-model="ruleForm.password"
+            autocomplete="off"
+          ></el-input>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="downloadAddress('ruleForm')"
+            >提交</el-button
+          >
+          <el-button @click="resetForm('ruleForm')">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </el-drawer>
+  </div>
+</template>
+<style scope>
+.upload__text {
+  font-size: 12px;
+  font-family: MiSans, MiSans-Normal;
+  font-weight: Normal;
+  text-align: LEFT;
+  color: #888888;
+  line-height: 12px;
+  position: absolute;
+  bottom: 30px;
+  left: 23px;
+}
+
+.avatar-uploader .el-upload {
+  background: #f7f7f7;
+  border-radius: 10px;
+  cursor: pointer;
+  position: relative;
+  overflow: hidden;
+}
+
+.avatar-uploader .el-upload:hover {
+  border-color: #409eff;
+}
+
+.avatar-uploader-icon {
+  font-size: 28px;
+  color: #8c939d;
+  width: 156px;
+  height: 156px;
+  line-height: 156px;
+  text-align: center;
+}
+
+.el-upload-dragger {
+  width: 156px;
+  height: 156px;
+}
+.avatar {
+  width: 156px;
+  height: 156px;
+}
+</style>
+
+<script>
+import Axios from "axios";
+import AES from "@/utils/aes";
+import { Message } from "element-ui";
+export default {
+  data() {
+    return {
+      url: process.env.VUE_APP_BASEURL,
+      downloadModal: false,
+      isSave: false,
+      ruleForm: {
+        password: undefined,
+        groupName: undefined,
+        address: undefined,
+      },
+      rules: {},
+    };
+  },
+  methods: {
+    resetForm() {
+      this.ruleForm.groupName = undefined;
+      this.ruleForm.password = undefined;
+      this.ruleForm.address = undefined;
+    },
+    resetField() {
+      this.$refs["ruleForm"].clearValidate();
+    },
+    close() {
+      this.downloadModal = false;
+      this.resetForm();
+    },
+    downloadAddress() {
+      this.$refs["ruleForm"].validate((valid) => {
+        if (valid) {
+          console.log("url:::" + this.url);
+          Axios.post(
+            this.url + "ams/address/download/batch-keystore",
+            {
+              groupName: this.ruleForm.groupName,
+              password: AES.encryptAes(this.ruleForm.password),
+            },
+            {
+              responseType: "arraybuffer",
+              headers: {
+                "Conntent-Type": "application/json; application/octet-stream;",
+              },
+            }
+          )
+            .then((response) => {
+              console.log(response.data);
+              let buffer = response.data;
+              let view = new DataView(buffer);
+
+              let str = "";
+              for (let i = 0; i < view.byteLength; i++) {
+                str += String.fromCharCode(view.getUint8(i));
+              }
+              if (str.includes(".json")) {
+                console.log(str.includes(".json"));
+                this.downloadFile(response.data);
+              } else {
+                const data = JSON.parse(str);
+                console.log(data);
+                console.log(data.message);
+                this.$message.error(data.message);
+              }
+            })
+            .catch((e) => {
+              alert(e);
+            });
+        } else {
+          this.$message.error("请填写必填字段!");
+        }
+      });
+    },
+
+    downloadFile(data) {
+      let blob = new Blob([data], { type: "application/zip" });
+      let url = window.URL.createObjectURL(blob);
+      const link = document.createElement("a"); // 创建a标签
+      link.href = url;
+      link.download = this.ruleForm.groupName + ".zip";
+      link.click();
+      URL.revokeObjectURL(url); // 释放内存
+    },
+  },
+  created() {},
+};
+</script>

+ 91 - 92
front/admin-front/src/views/address/index.vue

@@ -1,113 +1,112 @@
 <template>
-  <div class="el-container">
-    <el-form
-      :model="ruleForm"
-      status-icon
-      :rules="rules"
-      ref="ruleForm"
-      label-width="100px"
-      class="demo-ruleForm"
-      style="margin: auto"
+  <div class="">
+    <el-row style="margin: 0 0 48px 0">
+      <el-col :span="2">
+        <div class="">
+          <div class="totalCount-number">{{ this.totalCount }}</div>
+          <div class="totalCount-text">地址数量</div>
+        </div>
+      </el-col>
+
+      <el-col :span="3" :offset="15">
+        <el-button type="primary" class="btn-add" @click="generateAddress">
+          批量生成地址
+        </el-button>
+      </el-col>
+      <el-col :span="3">
+        <el-button type="primary" class="btn-add" @click="downloadAddress">
+          批量下载地址
+        </el-button>
+      </el-col>
+    </el-row>
+
+    <div class="block-title">用户管理</div>
+    <el-table :data="tableData" style="width: 100%">
+      <el-table-column prop="address" label="地址账号" width="420">
+        <template slot-scope="{ row }">
+          {{row.groupName}} <span style="margin-left:10px"></span> {{row.address}}
+        </template>
+      </el-table-column>
+
+      <!-- <el-table-column prop="groupName" label="地址组"> </el-table-column> -->
+      <el-table-column prop="" label="gas消耗"> </el-table-column>
+      <el-table-column prop="" label="地址余额"> </el-table-column>
+      <el-table-column prop="addressType" label="地址类型">
+        <template slot-scope="{ row }">
+          <el-tag v-if="row.addressType === 1" type="info">批量号</el-tag>
+          <el-tag v-else>精品号</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column prop="createTime" label="创建时间"> </el-table-column>
+    </el-table>
+    <el-pagination
+      @size-change="handleSizeChange"
+      @current-change="handleCurrentChange"
+      :current-page.sync="page"
+      :page-sizes="[10, 15, 25, 35]"
+      :page-size.sync="pageSize"
+      layout="total, sizes, prev, pager, next, jumper"
+      :total="totalCount"
     >
-      <el-form-item label="密码" prop="password">
-        <el-input
-          type="password"
-          v-model="ruleForm.password"
-          autocomplete="off"
-        ></el-input>
-      </el-form-item>
-      <el-form-item label="地址组名称" prop="groupName">
-        <el-input v-model="ruleForm.groupName" autocomplete="off"></el-input>
-      </el-form-item>
-      <el-form-item>
-        <el-button type="primary" @click="submitForm('ruleForm')"
-          >提交</el-button
-        >
-        <el-button @click="resetForm('ruleForm')">重置</el-button>
-      </el-form-item>
-    </el-form>
+    </el-pagination>
+    <SaveOrUpdate ref="SaveOrUpdate" />
+    <download ref="download"></download>
   </div>
 </template>
 <script>
-import AES from "@/utils/aes";
-import Axios from "axios";
-import { Message } from "element-ui";
+import { pageAddress, batchAddress } from "@/api/adress";
+import SaveOrUpdate from "./SaveOrUpdate.vue";
+import Download from "./download.vue";
 export default {
+  components: { SaveOrUpdate, Download },
   data() {
     return {
       url: process.env.VUE_APP_BASE_API,
-      ruleForm: {
-        password: "",
-        groupName: "",
-        address: "",
+      address: {
+        password: undefined,
+        groupName: undefined,
+        numWallet: undefined,
       },
-      rules: {},
+      tableData: [],
+      page: 1,
+      pageSize: 10,
+      totalCount: 0,
     };
   },
+  created() {
+    this.getAddresses();
+  },
   methods: {
-    submitForm(formName) {
-      this.$refs[formName].validate((valid) => {
-        if (valid) {
-          Axios.post(
-            this.url + "ams/address/download/batch-keystore",
-            {
-              groupName: this.ruleForm.groupName,
-              password: AES.encryptAes(this.ruleForm.password),
-            },
-            {
-              responseType: "arraybuffer",
-              headers: {
-                "Conntent-Type": "application/json; application/octet-stream;",
-              },
-            }
-          )
-            .then((response) => {
-              console.log(response.data);
-              let buffer = response.data;
-              let view = new DataView(buffer);
-
-              let str = "";
-              for (let i = 0; i < view.byteLength; i++) {
-                str += String.fromCharCode(view.getUint8(i));
-              }
-              if (str.includes(".json")) {
-                console.log(str.includes(".json")); 
-                this.downloadFile(response.data);
-              }else{
-                const data = JSON.parse(str)
-                console.log(data);
-                console.log(data.message);
-                 this.$message.error(data.message);
-              }
-            })
-            .catch((e) => {
-              console.log(e);
-            });
-        } else {
-          Message.error("download error!!");
-          return false;
-        }
-      });
+    generateAddress() {
+      this.$refs.SaveOrUpdate.addressModal = true;
+      this.$refs.SaveOrUpdate.resetField();
+      this.$refs.SaveOrUpdate.resetUserForm();
+    },
+    downloadAddress() {
+      this.$refs.download.downloadModal = true;
+      this.$refs.download.resetField();
+      this.$refs.download.resetUserForm();
     },
-    downloadFile(data) {
-      let blob = new Blob([data], {
-        type: "application/zip",
+    getAddresses() {
+      pageAddress({
+        page: this.page,
+        pageSize: this.pageSize,
+      }).then((res) => {
+        this.tableData = res.records;
+        this.totalCount = res.total;
       });
-      let url = window.URL.createObjectURL(blob);
-      const link = document.createElement("a"); // 创建a标签
-      link.href = url;
-      link.download = this.ruleForm.groupName + ".zip";
-      link.click();
-      URL.revokeObjectURL(url); // 释放内存
     },
-    resetForm(formName) {
-      this.$refs[formName].resetFields();
+
+    handleSizeChange(val) {
+      this.pageSize = val;
+      this.page = 1;
+      this.getAddresses();
     },
-  },
-  computed: {
-    saveAs() {
-      return saveAs;
+    handleCurrentChange(val) {
+      this.page = val;
+      this.getAddresses();
     },
   },
+  computed: {},
 };
 </script>

+ 13 - 3
src/main/java/com/ichaoj/ams/controller/AddressController.java

@@ -3,10 +3,13 @@ package com.ichaoj.ams.controller;
 import cn.hutool.core.util.StrUtil;
 import com.ichaoj.ams.request.address.BatchAddressRequest;
 import com.ichaoj.ams.request.address.BatchKeyStoreRequest;
+import com.ichaoj.ams.request.address.PageAddressRequest;
 import com.ichaoj.ams.request.address.SubscribeAddressRequest;
+import com.ichaoj.ams.response.address.AddressResponse;
 import com.ichaoj.ams.service.IAmsAddressAccountService;
 import com.ichaoj.common.annotation.AuthResource;
 import com.ichaoj.common.exception.ErrorServiceException;
+import com.ichaoj.common.model.PublicPage;
 import com.ichaoj.common.model.PublicResult;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -19,9 +22,7 @@ import java.math.BigDecimal;
 import java.util.List;
 
 /**
- * @author 焦竞健
- * @description TODO
- * @date 2022/4/15 10:37
+ * @author cjwen
  */
 @RestController
 @RequestMapping("/address")
@@ -72,4 +73,13 @@ public class AddressController {
         return PublicResult.success();
     }
 
+    @Operation(summary = "分页查询地址")
+    @PostMapping("/page")
+    @AuthResource
+    public PublicResult<PublicPage<AddressResponse>> pageAddress(@RequestBody PageAddressRequest pageAddressRequest) {
+        PublicPage<AddressResponse> result = addressService.pageAddress(pageAddressRequest);
+        return PublicResult.success(result);
+    }
+
+
 }

+ 21 - 0
src/main/java/com/ichaoj/ams/request/address/PageAddressRequest.java

@@ -0,0 +1,21 @@
+package com.ichaoj.ams.request.address;
+
+import com.ichaoj.ams.response.address.AddressResponse;
+import com.ichaoj.common.model.PublicPage;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * @author : cjwen
+ * @date : 2023/05/11 17:18
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+@Schema(title = "分页查询地址")
+public class PageAddressRequest extends PublicPage<AddressResponse> {
+
+    @Schema(title = "当前地址组名称")
+    private String groupName;
+
+}

+ 0 - 9
src/main/java/com/ichaoj/ams/response/address/AddressResponse.java

@@ -26,15 +26,6 @@ public class AddressResponse {
      */
     private Integer addressType;
 
-    /**
-     * keystore文件
-     */
-    private String keystore;
-    /**
-     * keystore文件位置
-     */
-    private String keystoreLocation;
-
     /**
      * 地址组名称
      */

+ 10 - 0
src/main/java/com/ichaoj/ams/service/IAmsAddressAccountService.java

@@ -3,6 +3,9 @@ package com.ichaoj.ams.service;
 import com.ichaoj.ams.entity.AmsAddressAccount;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ichaoj.ams.request.address.BatchAddressRequest;
+import com.ichaoj.ams.request.address.PageAddressRequest;
+import com.ichaoj.ams.response.address.AddressResponse;
+import com.ichaoj.common.model.PublicPage;
 
 import javax.servlet.http.HttpServletResponse;
 import java.util.List;
@@ -48,4 +51,11 @@ public interface IAmsAddressAccountService extends IService<AmsAddressAccount> {
      * @return 是否创建
      */
     boolean checkGroupName(String groupName, String userId);
+
+    /**
+     * 分页查询地址信息
+     * @param pageAddressRequest 分页参数
+     * @return 分页结果
+     */
+    PublicPage<AddressResponse> pageAddress(PageAddressRequest pageAddressRequest);
 }

+ 20 - 51
src/main/java/com/ichaoj/ams/service/impl/AmsAddressAccountServiceImpl.java

@@ -1,9 +1,12 @@
 package com.ichaoj.ams.service.impl;
 
+import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.StrUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ichaoj.ams.common.bean.Wallet;
 import com.ichaoj.ams.common.util.EthWalletPrivate;
@@ -12,13 +15,17 @@ import com.ichaoj.ams.entity.AmsAddressAccount;
 import com.ichaoj.ams.mapper.AmsAddressAccountMapper;
 import com.ichaoj.ams.request.address.BatchAddressRequest;
 import com.ichaoj.ams.request.address.BatchKeyStoreRequest;
+import com.ichaoj.ams.request.address.PageAddressRequest;
+import com.ichaoj.ams.response.address.AddressResponse;
 import com.ichaoj.ams.service.IAmsAddressAccountService;
 import com.ichaoj.ams.service.ZipService;
 import com.ichaoj.common.exception.ErrorServiceException;
+import com.ichaoj.common.model.PublicPage;
 import com.ichaoj.common.model.PublicResult;
 import com.ichaoj.common.model.PublicUserInfo;
 import com.ichaoj.disk.provider.client.DiskClient;
 import com.ichaoj.disk.provider.resp.FileResponse;
+import com.ichaoj.mybatis.service.SuperWhaleServiceImpl;
 import com.ichaoj.web.context.SuperWhaleContext;
 import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
@@ -49,7 +56,7 @@ import static com.ichaoj.ams.constant.AmsConstant.WALLET_FILE_PATH;
  */
 @Service
 @Slf4j
-public class AmsAddressAccountServiceImpl extends ServiceImpl<AmsAddressAccountMapper, AmsAddressAccount> implements IAmsAddressAccountService {
+public class AmsAddressAccountServiceImpl extends SuperWhaleServiceImpl<AmsAddressAccountMapper, AmsAddressAccount> implements IAmsAddressAccountService {
 
     @Autowired(required = false)
     private AmsAddressAccountMapper baseMapper;
@@ -112,6 +119,16 @@ public class AmsAddressAccountServiceImpl extends ServiceImpl<AmsAddressAccountM
         return this.count(wrapper) > 0;
     }
 
+    @Override
+    public PublicPage<AddressResponse> pageAddress(PageAddressRequest pageAddressRequest) {
+        LambdaQueryWrapper<AmsAddressAccount> wrapper = Wrappers.lambdaQuery();
+        wrapper.eq(StrUtil.isNotBlank(pageAddressRequest.getGroupName()), AmsAddressAccount::getGroupName, pageAddressRequest.getGroupName())
+                .orderByDesc(AmsAddressAccount::getCreateTime);
+
+        Page<AmsAddressAccount> result = this.page(this.buildPageObj(pageAddressRequest), wrapper);
+        return this.convertPublicPage(result, resp -> BeanUtil.copyProperties(resp, AddressResponse.class));
+    }
+
     private String getLocation(String fileId) {
         PublicResult<FileResponse> result = diskClient.getFileById(fileId);
         FileResponse data = result.getData();
@@ -135,7 +152,7 @@ public class AmsAddressAccountServiceImpl extends ServiceImpl<AmsAddressAccountM
 
     @Override
     @SneakyThrows
-    public void batchKeystore(String groupName,String password, HttpServletResponse response) {
+    public void batchKeystore(String groupName, String password, HttpServletResponse response) {
         String userId = SuperWhaleContext.getContext(PublicUserInfo.class).getUserId();
         boolean existGroup = this.checkGroupName(groupName, userId);
         if (!existGroup) {
@@ -175,61 +192,13 @@ public class AmsAddressAccountServiceImpl extends ServiceImpl<AmsAddressAccountM
         InputStream inputStream = new FileInputStream(zipFile);
         byte[] buffer = new byte[1024];
         OutputStream outputStream = response.getOutputStream();
-        int len = 0;
+        int len;
         while ((len = inputStream.read(buffer)) > 0) {
             outputStream.write(buffer, 0, len);
         }
         inputStream.close();
         outputStream.close();
     }
-
-    /**
-     * 批量下载keystore文件
-     *
-     * @param keyStoreRequest 请求参数
-     * @param response
-     */
-
-    public void batchKeystoreTemp(BatchKeyStoreRequest keyStoreRequest, HttpServletResponse response) {
-        try {
-            String userId = SuperWhaleContext.getContext(PublicUserInfo.class).getUserId();
-            boolean existGroup = this.checkGroupName(keyStoreRequest.getGroupName(), userId);
-            if (!existGroup) {
-                throw new ErrorServiceException("The address group name is incorrect");
-            }
-            Set<File> files = new HashSet<>();
-            List<String> addresses = keyStoreRequest.getAddresses();
-            if (CollectionUtil.isEmpty(addresses)) {
-                LambdaQueryWrapper<AmsAddressAccount> wrapper = Wrappers.lambdaQuery();
-                wrapper.eq(AmsAddressAccount::getUserId, userId)
-                        .eq(AmsAddressAccount::getGroupName, keyStoreRequest.getGroupName());
-                List<AmsAddressAccount> list = this.list(wrapper);
-                if (CollectionUtil.isNotEmpty(list)) {
-                    getFiles(keyStoreRequest, files, list);
-                }
-            } else {
-                LambdaQueryWrapper<AmsAddressAccount> wrapper = Wrappers.lambdaQuery();
-                wrapper.eq(AmsAddressAccount::getUserId, userId)
-                        .eq(AmsAddressAccount::getGroupName, keyStoreRequest.getGroupName())
-                        .in(AmsAddressAccount::getAddress, addresses);
-                List<AmsAddressAccount> list = this.list(wrapper);
-                if (CollectionUtil.isNotEmpty(list)) {
-                    getFiles(keyStoreRequest, files, list);
-                }
-            }
-            if (CollectionUtil.isNotEmpty(files)) {
-                zipService.create(
-                        userId,
-                        WALLET_FILE_PATH
-                        , WALLET_FILE_PATH
-                        , WalletUtil.getEncryptPwd(keyStoreRequest.getGroupName())
-                        , ".zip", response);
-            }
-        } catch (Exception e) {
-            log.error("batchKeystore 方法出错:{}", e.getMessage());
-        }
-    }
-
     private void getFiles(BatchKeyStoreRequest keyStoreRequest, Set<File> files, List<AmsAddressAccount> list) {
         try {
             String userId = SuperWhaleContext.getContext(PublicUserInfo.class).getUserId();