Parcourir la source

feature: u卡

ljc il y a 5 mois
Parent
commit
90a94a5a8a

+ 1 - 0
.env.development

@@ -3,3 +3,4 @@ NODE_ENV = 'development'
 
 # 本地环境接口地址
 VITE_APP_BASE_API = '/api'
+VITE_APP_ENV = 'development'

+ 1 - 0
src/config/index.ts

@@ -12,6 +12,7 @@ export const PRIMARY_COLOR = '#409eff'
 
 const ht = window.location.protocol
 const ho = window.location.host.split('.')[1]
+console.log(ho, 'ho')
 const c = import.meta.env.VITE_APP_ENV
 let Host00, Host85, Host05, Host80
 switch (c) {

+ 20 - 0
src/service/ucard.ts

@@ -335,6 +335,26 @@ class UCardService extends Service {
   async deleteBlockchain(params = {}) {
     return await this.post('/wasabi/card/blockchain/config/delete', params)
   }
+  // 区块链汇率列表
+  async getBlockchainRatePage(params = {}) {
+    return await this.post('/wasabi/card/blockchain/rate/config/page', params)
+  }
+  // 修改区块链汇率
+  async updateBlockchainRate(params = {}) {
+    return await this.post('/wasabi/card/blockchain/rate/config/update', params)
+  }
+  // 新增区块链汇率
+  async addBlockchainRate(params = {}) {
+    return await this.post('/wasabi/card/blockchain/rate/config/add', params)
+  }
+  // 删除区块链汇率
+  async deleteBlockchainRate(params = {}) {
+    return await this.post('/wasabi/card/blockchain/rate/config/delete', params)
+  }
+  // 加密货币交易记录列表
+  async getBlockchainTransactionPage(params = {}) {
+    return await this.post('/wasabi/encrypted/wallet/transaction/page', params)
+  }
 }
 
 export default new UCardService()

+ 520 - 3
src/views/card/CardBlockchainRate/index.vue

@@ -1,5 +1,522 @@
-<script setup lang="ts"></script>
+<template>
+  <div
+    id="card_Blockchain"
+    v-loading="pictLoading"
+    class="view"
+    :element-loading-background="'rgba(43, 48, 67, 0.65)'"
+    :element-loading-spinner="'el-icon-loading'"
+  >
+    <div class="crm_search">
+      <el-form ref="formRef" :model="search" label-width="">
+        <el-row>
+          <el-col :span="24" :md="24" :lg="24">
+            <el-form-item style="margin-right: 10px">
+              <el-input
+                v-model.trim="search.currency"
+                class="crm-border-radius-no"
+                clearable
+                :placeholder="t('Ucard.BlockchainRate.addP1')"
+                @keyup.enter="toSearch"
+              >
+              </el-input>
+            </el-form-item>
+            <el-form-item style="margin-right: 10px">
+              <el-input
+                v-model.trim="search.convertCurrency"
+                class="crm-border-radius-no"
+                clearable
+                :placeholder="t('Ucard.BlockchainRate.addP2')"
+                @keyup.enter="toSearch"
+              >
+              </el-input>
+            </el-form-item>
+            <el-form-item>
+              <el-select
+                v-model="search.enableStatus"
+                class="crm-border-radius-no"
+                clearable
+                :placeholder="t('Ucard.BlockchainRate.pageT3')"
+                @change="toSearch"
+              >
+                <el-option
+                  v-for="(value, key) in enableStatus"
+                  :key="key"
+                  :label="t(value)"
+                  :value="key"
+                />
+              </el-select>
+            </el-form-item>
+            <el-form-item>
+              <el-button
+                class="crm-border-radius-no crm-border-left-no"
+                :icon="Search"
+                @click="toSearch"
+              ></el-button>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item>
+          <el-button
+            v-if="display['R-Card-BlockchainRate-Add']?.show"
+            class=""
+            type="primary"
+            :icon="Plus"
+            @click="openAddDialog"
+          >
+            {{ t('R-Card-BlockchainRate-Add') }}
+          </el-button>
+          <el-button
+            v-if="display['R-Card-BlockchainRate-Delete']?.show"
+            :disabled="!multipleSelection.length"
+            :type="multipleSelection.length ? 'primary' : 'info'"
+            :icon="Minus"
+            @click="toDelete"
+          >
+            {{ t('R-Card-BlockchainRate-Delete') }}
+          </el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+    <el-table
+      :data="mock_tableData"
+      stripe
+      style="width: 100%"
+      @selection-change="handleSelectionChange"
+    >
+      <el-table-column align="left" type="selection" width="55"> </el-table-column>
+      <el-table-column prop="currency" align="left" :label="t('Ucard.BlockchainRate.pageT1')">
+        <template #default="{ row }">
+          {{ row.currency || '--' }}
+        </template>
+      </el-table-column>
+      <el-table-column
+        prop="convertCurrency"
+        align="left"
+        :label="t('Ucard.BlockchainRate.pageT2')"
+      >
+        <template #default="{ row }">
+          {{ row.convertCurrency || '--' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="exchangeRate" align="left" :label="t('Ucard.BlockchainRate.pageT4')">
+        <template #default="{ row }">
+          {{ row.exchangeRate || '--' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="enableStatus" align="left" :label="t('Ucard.BlockchainRate.pageT3')">
+        <template #default="{ row }">
+          <el-switch
+            v-model="row.enableStatus"
+            :disabled="!display['R-Card-BlockchainRate-Edit']?.show"
+            :active-text="t(enableStatus[1])"
+            :active-value="1"
+            :inactive-text="t(enableStatus[0])"
+            :inactive-value="0"
+            active-color="#368FEC"
+            inactive-color="#EB3F57"
+            class="crm_switch crm_switch_width"
+            @change="() => changeEnable(row)"
+          >
+          </el-switch>
+        </template>
+      </el-table-column>
+      <el-table-column prop="ctrl" align="center" :label="t('Label.Action')">
+        <template #default="{ row }">
+          <el-dropdown trigger="click" @command="handleCommand">
+            <span class="el-dropdown-link crm-cursor">
+              <i style="font-weight: bold; font-size: 20px" class="iconfont iconcaidan"></i>
+            </span>
+            <template #dropdown>
+              <el-dropdown-menu>
+                <el-dropdown-item
+                  v-if="display['R-Card-BlockchainRate-Edit']?.show"
+                  :command="{ type: 'editor', row: row }"
+                >
+                  <el-icon><Edit /></el-icon>
+                  <span>{{ t('R-Card-Blockchain-Edit') }}</span>
+                </el-dropdown-item>
+                <el-dropdown-item
+                  v-if="display['R-Card-BlockchainRate-Delete']?.show"
+                  :command="{ type: 'delete', row: row }"
+                >
+                  <el-icon><Delete /></el-icon>
+                  <span>{{ t('R-Card-Blockchain-Delete') }}</span>
+                </el-dropdown-item>
+              </el-dropdown-menu>
+            </template>
+          </el-dropdown>
+        </template>
+      </el-table-column>
+    </el-table>
+    <PagePagination
+      :pager-info="pagerInfo"
+      @current-change="handleCurrentChange"
+      @size-change="handleSizeChange"
+    />
 
-<template>1</template>
+    <!-- 新增 -->
+    <el-dialog
+      v-model="addDialogVisible"
+      :title="t(isEdit ? 'Ucard.BlockchainRate.title1' : 'Ucard.BlockchainRate.title2')"
+      width="500px"
+      :close-on-click-modal="false"
+    >
+      <el-form ref="addFormRef" :model="addForm" :rules="addRules" label-width="120px">
+        <el-form-item :label="`${t('Ucard.BlockchainRate.pageT1')}:`" prop="currency">
+          <el-input
+            v-model="addForm.currency"
+            :disabled="isEdit"
+            :placeholder="t('Ucard.BlockchainRate.addP1')"
+          ></el-input>
+        </el-form-item>
+        <el-form-item :label="`${t('Ucard.BlockchainRate.pageT2')}:`" prop="convertCurrency">
+          <el-input
+            v-model="addForm.convertCurrency"
+            :disabled="isEdit"
+            :placeholder="t('Ucard.BlockchainRate.addP2')"
+          ></el-input>
+        </el-form-item>
+        <el-form-item :label="`${t('Ucard.BlockchainRate.pageT4')}:`" prop="exchangeRate">
+          <el-input
+            v-model="addForm.exchangeRate"
+            type="number"
+            :placeholder="t('Ucard.BlockchainRate.addP4')"
+          ></el-input>
+        </el-form-item>
+        <el-form-item
+          style="text-align: left"
+          :label="`${t('Ucard.BlockchainRate.pageT3')}:`"
+          prop="enableStatus"
+        >
+          <el-switch
+            v-model="addForm.enableStatus"
+            :active-text="t(enableStatus[1])"
+            :active-value="1"
+            :inactive-text="t(enableStatus[0])"
+            :inactive-value="0"
+            active-color="#368FEC"
+            class="crm_switch crm_switch_width"
+            inactive-color="#EB3F57"
+          >
+          </el-switch>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="addDialogVisible = false">{{ t('Btn.Cancel') }} </el-button>
+          <el-button type="primary" :loading="addLoading" @click="handleAddConfirm"
+            >{{ t('Btn.Confirm') }}
+          </el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
 
-<style scoped lang="scss"></style>
+<script setup>
+  import { ref, reactive, computed, watch, onMounted, nextTick, inject } from 'vue'
+  import { useI18n } from 'vue-i18n'
+  import { ElMessage, ElMessageBox } from 'element-plus'
+  import Service from '@/service/ucard'
+  import Config from '@/config/index'
+  import { enableStatus } from '@/enum/enum'
+  import PagePagination from '@/components/pagePagination/index.vue'
+  import { Delete, Edit, Minus, Plus, Search } from '@element-plus/icons-vue'
+
+  const { t } = useI18n()
+  const { Code } = Config
+  const Session = inject('session')
+  const pigeon = inject('pigeon')
+
+  // 常量
+  const floatReg = /^\d+(\.\d{0,10})?$/
+
+  // 响应式数据
+  const pictLoading = ref(false)
+  const mock_tableData = ref([])
+  const formRef = ref(null)
+  const addFormRef = ref(null)
+  const addDialogVisible = ref(false)
+  const isEdit = ref(false)
+  const addLoading = ref(false)
+  const multipleSelection = ref([])
+
+  const search = reactive({
+    currency: '',
+    convertCurrency: '',
+    enableStatus: '',
+  })
+
+  const pagerInfo = reactive({
+    row: 10,
+    current: 1,
+    pageTotal: 0,
+    rowTotal: 0,
+  })
+
+  const addForm = reactive({
+    currency: '',
+    convertCurrency: '',
+    enableStatus: 0,
+    exchangeRate: '',
+  })
+
+  // 计算属性
+  const display = computed(() => {
+    return JSON.parse(Session.Get('display', true))
+  })
+
+  const addRules = computed(() => ({
+    currency: [
+      {
+        required: true,
+        message: t('Ucard.BlockchainRate.addP1'),
+        trigger: 'blur',
+      },
+    ],
+    convertCurrency: [
+      {
+        required: true,
+        message: t('Ucard.BlockchainRate.addP2'),
+        trigger: 'blur',
+      },
+    ],
+    exchangeRate: [
+      {
+        required: true,
+        validator: (rule, value, callback) => {
+          if (value) {
+            const test = floatReg.test(value)
+            if (test) {
+              return callback()
+            } else {
+              return callback(new Error(t('global.validator.v13')))
+            }
+          } else {
+            return callback(new Error(t('Ucard.BlockchainRate.addP4')))
+          }
+        },
+        trigger: ['change', 'blur'],
+      },
+    ],
+    enableStatus: [
+      {
+        required: true,
+        message: t('Ucard.BlockchainRate.addP3'),
+        trigger: 'blur',
+      },
+    ],
+  }))
+
+  // 监听器
+  watch(addDialogVisible, (val) => {
+    if (!val) {
+      Object.assign(addForm, {
+        currency: '',
+        convertCurrency: '',
+        enableStatus: 0,
+        exchangeRate: '',
+      })
+    }
+  })
+
+  // 生命周期
+  onMounted(() => {
+    searchFunc()
+  })
+
+  // 方法
+  const keyDown = () => {
+    console.log(1)
+  }
+
+  // 获取列表数据
+  const searchFunc = async () => {
+    pictLoading.value = true
+    if (!display.value['R-Card-BlockchainRate-Page']?.show) {
+      ElMessage.warning(t('Msg.NotDisplay'))
+      pictLoading.value = false
+      return
+    }
+
+    const res = await Service.getBlockchainRatePage({
+      ...search,
+      page: {
+        current: pagerInfo.current,
+        row: pagerInfo.row,
+      },
+    })
+
+    if (res.code == Code.StatusOK) {
+      mock_tableData.value = res.data
+      if (res.page != null) {
+        pagerInfo.rowTotal = res.page.rowTotal
+        pagerInfo.pageTotal = res.page.pageTotal
+      } else {
+        pagerInfo.rowTotal = 0
+      }
+      ElMessage.success(t('Msg.SearchSuccess'))
+    } else {
+      ElMessage.error(res.msg)
+    }
+    pictLoading.value = false
+  }
+
+  // 选择多项
+  const handleSelectionChange = (val) => {
+    multipleSelection.value = val.map((item) => item.id)
+  }
+
+  // 删除
+  const toDelete = () => {
+    handleDelete(multipleSelection.value)
+  }
+
+  // 搜索
+  const toSearch = () => {
+    pagerInfo.current = 1
+    searchFunc()
+  }
+
+  // 分页返回数据
+  const handleSizeChange = (val) => {
+    pagerInfo.row = val
+    searchFunc()
+  }
+
+  const handleCurrentChange = (val) => {
+    pagerInfo.current = val
+    searchFunc()
+  }
+
+  // 处理下拉菜单命令
+  const handleCommand = (command) => {
+    if (command.type === 'editor') {
+      Object.assign(addForm, command.row)
+      isEdit.value = true
+      addDialogVisible.value = true
+    } else if (command.type === 'delete') {
+      handleDelete([command.row.id])
+    }
+  }
+
+  // 打开新增对话框
+  const openAddDialog = () => {
+    Object.assign(addForm, {
+      currency: '',
+      convertCurrency: '',
+      enableStatus: 0,
+      exchangeRate: '',
+    })
+    isEdit.value = false
+    addDialogVisible.value = true
+
+    nextTick(() => {
+      // 新增 打开时清空一下
+      if (addFormRef.value) {
+        addFormRef.value.clearValidate()
+      }
+    })
+  }
+
+  // 修改启用状态
+  const changeEnable = async (row) => {
+    try {
+      const res = await Service.updateBlockchainRate({
+        id: row.id,
+        currency: row.currency,
+        convertCurrency: row.convertCurrency,
+        enableStatus: row.enableStatus,
+        exchangeRate: row.exchangeRate,
+      })
+
+      if (res.code == 200) {
+        ElMessage.success(t('card.Info.t27'))
+        searchFunc()
+      } else {
+        ElMessage.error(res.msg)
+      }
+    } catch (error) {
+      ElMessage.error(t('Msg.SystemError'))
+    }
+  }
+
+  // 确认新增/编辑
+  const handleAddConfirm = async () => {
+    if (!addFormRef.value) return
+
+    const valid = await addFormRef.value.validate()
+    if (!valid) return
+
+    addLoading.value = true
+    try {
+      const params = { ...addForm }
+      const res = isEdit.value
+        ? await Service.updateBlockchainRate(params)
+        : await Service.addBlockchainRate(params)
+
+      if (res.code == Code.StatusOK) {
+        ElMessage.success(t('Msg.SaveSuccess'))
+        addDialogVisible.value = false
+        searchFunc() // 刷新列表
+      } else {
+        ElMessage.error(res.msg)
+      }
+    } catch (error) {
+      ElMessage.error(t('Msg.SaveFail'))
+    } finally {
+      addLoading.value = false
+    }
+  }
+
+  // 删除
+  const handleDelete = async (ids) => {
+    try {
+      await ElMessageBox.confirm(
+        t('Ucard.Blockchain.deleteConfirm'),
+        t('Ucard.Blockchain.deleteTitle'),
+        {
+          confirmButtonText: t('Btn.Confirm'),
+          cancelButtonText: t('Btn.Cancel'),
+          type: 'warning',
+        }
+      )
+
+      const res = await Service.deleteBlockchainRate({ ids })
+      if (res.code == Code.StatusOK) {
+        ElMessage.success(t('Msg.DeleteSuccess'))
+        searchFunc() // 刷新列表
+      } else {
+        ElMessage.error(res.msg)
+      }
+    } catch (error) {
+      if (error !== 'cancel') {
+        ElMessage.error(t('Msg.DeleteFail'))
+      }
+    }
+  }
+</script>
+<style scoped lang="scss">
+  #card_Blockchain {
+    .crm_search {
+      .search_action_btn {
+        .delete {
+          background-color: #a1a1a1;
+        }
+
+        .delete.active {
+          background-color: #368fec;
+        }
+      }
+    }
+  }
+</style>
+<style lang="scss">
+  #card_Blockchain {
+    .dialog_header_w {
+      .crm_search_down {
+        width: 400px;
+      }
+    }
+  }
+</style>

+ 269 - 3
src/views/card/CardBlockchainTransaction/index.vue

@@ -1,5 +1,271 @@
-<script setup lang="ts"></script>
+<template>
+  <div
+    id="card_BlockchainTransaction"
+    v-loading="pictLoading"
+    class="view"
+    :element-loading-background="'rgba(43, 48, 67, 0.65)'"
+    :element-loading-spinner="'el-icon-loading'"
+  >
+    <div class="crm_search">
+      <el-form ref="formRef" :model="search" label-width="">
+        <el-row>
+          <el-col :span="24" :md="24" :lg="24">
+            <el-form-item>
+              <el-select
+                v-model="search.tag"
+                class="crm_search_down crm-border-radius-no"
+                :placeholder="t('Placeholder.Choose')"
+              >
+                <el-option
+                  v-for="option in tagOptions"
+                  :key="option.value"
+                  :label="option.label"
+                  :value="option.value"
+                />
+              </el-select>
+            </el-form-item>
+            <el-form-item style="margin-right: 10px">
+              <el-input
+                v-if="search.tag == 1"
+                v-model.trim="search.cId"
+                class="crm-border-left-no crm-border-radius-no"
+                clearable
+                :placeholder="t('Placeholder.Input')"
+                @keyup.enter="toSearch"
+              ></el-input>
+              <el-input
+                v-if="search.tag == 2"
+                v-model.trim="search.mobile"
+                class="crm-border-left-no crm-border-radius-no"
+                clearable
+                :placeholder="t('Placeholder.Input')"
+                @keyup.enter="toSearch"
+              ></el-input>
+              <el-input
+                v-if="search.tag == 3"
+                v-model.trim="search.email"
+                class="crm-border-left-no crm-border-radius-no"
+                clearable
+                :placeholder="t('Placeholder.Input')"
+                @keyup.enter="toSearch"
+              ></el-input>
+            </el-form-item>
+            <el-form-item style="margin-right: 10px">
+              <el-input
+                v-model.trim="search.address"
+                class="crm-border-radius-no"
+                clearable
+                :placeholder="t('Ucard.BlockchainTransaction.address')"
+                @keyup.enter="toSearch"
+              >
+              </el-input>
+            </el-form-item>
+            <el-form-item>
+              <el-input
+                v-model.trim="search.unit"
+                class="crm-border-radius-no"
+                clearable
+                :placeholder="t('Ucard.BlockchainTransaction.unit')"
+                @keyup.enter="toSearch"
+              >
+              </el-input>
+            </el-form-item>
+            <el-form-item>
+              <el-button
+                class="crm-border-radius-no crm-border-left-no"
+                icon="el-icon-search"
+                @click="toSearch"
+              ></el-button>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item>
+          <el-button
+            v-if="display['R-Card-BlockchainTransaction-Export']?.show"
+            type="primary"
+            style="margin-left: 8px"
+            :loading="exportLoading"
+            @click="exportList"
+          >
+            {{ t('Btn.Export') }}
+          </el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+    <el-table :data="mock_tableData" stripe style="width: 100%">
+      <el-table-column prop="" align="left" :label="t('Label.CidAccount')">
+        <template #default="{ row }">
+          <span>{{ row.cId || '--' }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column prop="name" align="left" :label="t('Label.Name')">
+        <template #default="{ row }">
+          <span v-if="row.firstName">
+            {{ row.firstName + ' ' }}
+          </span>
+          <span v-if="row.middle">{{ row.middle + ' ' }}</span>
+          <span v-if="row.lastName">{{ row.lastName }}</span>
+          <span v-if="!row.firstName && !row.lastName && !row.middle">{{ '--' }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column prop="email" align="left" :label="t('Label.Email')">
+        <template #default="{ row }">
+          {{ row.email || '--' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="mobile" align="left" :label="t('Label.Mobile')">
+        <template #default="{ row }"> {{ row.areaCode }} {{ row.mobile }} </template>
+      </el-table-column>
+      <el-table-column prop="blockchain" align="left" :label="t('Ucard.Blockchain.pageT2')">
+        <template #default="{ row }">
+          {{ row.blockchain || '--' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="country" align="left" :label="t('Ucard.DepositAddress.p1')">
+        <template #default="{ row }">
+          {{ row.country || '--' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="address" align="left" :label="t('Ucard.DepositAddress.p2')">
+        <template #default="{ row }">
+          {{ row.address || '--' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="unit" align="left" :label="t('Ucard.BlockchainTransaction.p1')">
+        <template #default="{ row }">
+          {{ row.unit || '--' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="amount" align="left" :label="t('Ucard.BlockchainTransaction.p2')">
+        <template #default="{ row }">
+          {{ row.amount || '--' }}
+        </template>
+      </el-table-column>
+    </el-table>
+    <PagePagination
+      :pager-info="pagerInfo"
+      @current-change="handleCurrentChange"
+      @size-change="handleSizeChange"
+    />
+  </div>
+</template>
 
-<template>1</template>
+<script setup>
+  import { ref, reactive, computed, onMounted, inject } from 'vue'
+  import { useI18n } from 'vue-i18n'
+  import { ElMessage } from 'element-plus'
+  import Service from '@/service/ucard'
+  import Config from '@/config/index'
+  import { exportExcel } from '@/utils/export'
+  import PagePagination from '@/components/pagePagination/index.vue'
 
-<style scoped lang="scss"></style>
+  const { t } = useI18n()
+  const { Code } = Config
+  const Session = inject('session')
+  const pigeon = inject('pigeon')
+
+  // 响应式数据
+  const pictLoading = ref(false)
+  const exportLoading = ref(false)
+  const mock_tableData = ref([])
+  const formRef = ref(null)
+
+  const search = reactive({
+    tag: 1,
+    cId: '',
+    email: '',
+    mobile: '',
+    address: '',
+    unit: '',
+  })
+
+  const pagerInfo = reactive({
+    row: 10,
+    current: 1,
+    pageTotal: 0,
+    rowTotal: 0,
+  })
+
+  // 计算属性
+  const display = computed(() => {
+    return JSON.parse(Session.Get('display', true))
+  })
+
+  const tagOptions = computed(() => [
+    { label: t('Label.CidAccount'), value: 1 },
+    { label: t('Ucard.KycAuth.item2'), value: 2 },
+    { label: t('Ucard.KycAuth.item3'), value: 3 },
+  ])
+
+  // 生命周期
+  onMounted(() => {
+    searchFunc()
+  })
+
+  // 方法
+  // 获取列表数据
+  const searchFunc = async () => {
+    pictLoading.value = true
+    if (!display.value['R-Card-BlockchainTransaction-Page']?.show) {
+      ElMessage.warning(t('Msg.NotDisplay'))
+      pictLoading.value = false
+      return
+    }
+
+    const res = await Service.getBlockchainTransactionPage({
+      ...search,
+      page: {
+        current: pagerInfo.current,
+        row: pagerInfo.row,
+      },
+    })
+
+    if (res.code == Code.StatusOK) {
+      mock_tableData.value = res.data
+      if (res.page != null) {
+        pagerInfo.rowTotal = res.page.rowTotal
+        pagerInfo.pageTotal = res.page.pageTotal
+      } else {
+        pagerInfo.rowTotal = 0
+      }
+      ElMessage.success(t('Msg.SearchSuccess'))
+    } else {
+      ElMessage.error(res.msg)
+    }
+    pictLoading.value = false
+  }
+
+  // 搜索
+  const toSearch = () => {
+    pagerInfo.current = 1
+    searchFunc()
+  }
+
+  // 分页返回数据
+  const handleSizeChange = (val) => {
+    pagerInfo.row = val
+    searchFunc()
+  }
+
+  const handleCurrentChange = (val) => {
+    pagerInfo.current = val
+    searchFunc()
+  }
+
+  // 导出
+  const exportList = async () => {
+    exportLoading.value = true
+    try {
+      await exportExcel(
+        pigeon,
+        '/wasabi/encrypted/wallet/transaction/list/export',
+        { ...search },
+        'Encrypted_Wallet_Transactions'
+      )
+    } catch (error) {
+      ElMessage.error(t('Msg.ExportFail'))
+    } finally {
+      exportLoading.value = false
+    }
+  }
+</script>

+ 285 - 3
src/views/card/CardWithdrawTransaction/index.vue

@@ -1,5 +1,287 @@
-<script setup lang="ts"></script>
+<template>
+  <div
+    id="card_BlockchainTransaction"
+    v-loading="pictLoading"
+    class="view"
+    :element-loading-background="loadingBackground"
+    element-loading-spinner="el-icon-loading"
+  >
+    <div class="crm_search">
+      <el-form ref="formRef" :model="search" label-width="">
+        <el-row>
+          <el-col :span="24" :md="24" :lg="24">
+            <el-form-item>
+              <el-select
+                v-model="search.tag"
+                class="crm_search_down crm-border-radius-no"
+                :placeholder="t('Placeholder.Choose')"
+              >
+                <el-option
+                  v-for="option in tagOptions"
+                  :key="option.value"
+                  :label="option.label"
+                  :value="option.value"
+                ></el-option>
+              </el-select>
+            </el-form-item>
+            <el-form-item style="margin-right: 10px">
+              <el-input
+                v-if="search.tag == 1"
+                v-model.trim="search.cId"
+                class="crm-border-left-no crm-border-radius-no"
+                clearable
+                :placeholder="t('Placeholder.Input')"
+                @keyup.enter="toSearch"
+              ></el-input>
+              <el-input
+                v-if="search.tag == 2"
+                v-model.trim="search.mobile"
+                class="crm-border-left-no crm-border-radius-no"
+                clearable
+                :placeholder="t('Placeholder.Input')"
+                @keyup.enter="toSearch"
+              ></el-input>
+              <el-input
+                v-if="search.tag == 3"
+                v-model.trim="search.email"
+                class="crm-border-left-no crm-border-radius-no"
+                clearable
+                :placeholder="t('Placeholder.Input')"
+                @keyup.enter="toSearch"
+              ></el-input>
+            </el-form-item>
+            <el-form-item style="margin-right: 10px">
+              <el-input
+                v-model.trim="search.address"
+                class="crm-border-radius-no"
+                clearable
+                :placeholder="t('Ucard.BlockchainTransaction.address')"
+                @keyup.enter="toSearch"
+              >
+              </el-input>
+            </el-form-item>
+            <el-form-item>
+              <el-input
+                v-model.trim="search.unit"
+                class="crm-border-radius-no"
+                clearable
+                :placeholder="t('Ucard.BlockchainTransaction.unit')"
+                @keyup.enter="toSearch"
+              >
+              </el-input>
+            </el-form-item>
+            <el-form-item>
+              <el-button
+                class="crm-border-radius-no crm-border-left-no"
+                :icon="Search"
+                @click="toSearch"
+              ></el-button>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item>
+          <el-button
+            v-if="display['R-Card-BlockchainTransaction-Export']?.show"
+            type="primary"
+            style="margin-left: 8px"
+            :loading="exportLoading"
+            @click="exportList"
+            >{{ t('Btn.Export') }}</el-button
+          >
+        </el-form-item>
+      </el-form>
+    </div>
+    <el-table :data="mock_tableData" stripe style="width: 100%">
+      <el-table-column prop="" align="left" :label="t('Label.CidAccount')">
+        <template #default="scope">
+          <span>{{ scope.row.cId || '--' }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column prop="name" align="left" :label="t('Label.Name')">
+        <template #default="scope">
+          <span v-if="scope.row.firstName">
+            {{ scope.row.firstName + ' ' }}
+          </span>
+          <span v-if="scope.row.middle">{{ scope.row.middle + ' ' }}</span>
+          <span v-if="scope.row.lastName">{{ scope.row.lastName }}</span>
+          <span v-if="!scope.row.firstName && !scope.row.lastName && !scope.row.middle">{{
+            '--'
+          }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column prop="email" align="left" :label="t('Label.Email')">
+        <template #default="scope">
+          {{ scope.row.email || '--' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="mobile" align="left" :label="t('Label.Mobile')">
+        <template #default="scope"> {{ scope.row.areaCode }} {{ scope.row.mobile }} </template>
+      </el-table-column>
+      <el-table-column prop="blockchain" align="left" :label="t('Ucard.Blockchain.pageT2')">
+        <template #default="scope">
+          {{ scope.row.blockchain || '--' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="country" align="left" :label="t('Ucard.DepositAddress.p1')">
+        <template #default="scope">
+          {{ scope.row.country || '--' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="address" align="left" :label="t('Ucard.DepositAddress.p2')">
+        <template #default="scope">
+          {{ scope.row.address || '--' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="unit" align="left" :label="t('Ucard.BlockchainTransaction.p1')">
+        <template #default="scope">
+          {{ scope.row.unit || '--' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="amount" align="left" :label="t('Ucard.BlockchainTransaction.p2')">
+        <template #default="scope">
+          {{ scope.row.amount || '--' }}
+        </template>
+      </el-table-column>
+    </el-table>
+    <PagePagination
+      :pager-info="pagerInfo"
+      @current-change="handleCurrentChange"
+      @size-change="handleSizeChange"
+    />
+  </div>
+</template>
 
-<template>1</template>
+<script setup>
+  import { ref, reactive, computed, onMounted, inject } from 'vue'
+  import { useI18n } from 'vue-i18n'
+  import Service from '@/service/ucard'
+  import Config from '@/config/index'
+  import { exportExcel } from '@/utils/export'
+  import PagePagination from '@/components/pagePagination/index.vue'
+  import { Search } from '@element-plus/icons-vue'
+  import { ElMessage } from 'element-plus'
 
-<style scoped lang="scss"></style>
+  const { t } = useI18n()
+  const { Code } = Config
+  const Session = inject('session')
+  const pigeon = inject('pigeon')
+
+  const pictLoading = ref(false)
+  const exportLoading = ref(false)
+  const formRef = ref(null)
+  const mock_tableData = ref([])
+  const loadingBackground = 'rgba(43, 48, 67, 0.65)'
+
+  const search = reactive({
+    tag: 1,
+    cId: '',
+    email: '',
+    mobile: '',
+    address: '',
+    unit: '',
+  })
+
+  const pagerInfo = reactive({
+    row: 10,
+    current: 1,
+    pageTotal: 0,
+    rowTotal: 0,
+  })
+
+  const display = computed(() => {
+    return JSON.parse(sessionStorage.getItem('display') || '{}')
+  })
+
+  const tagOptions = computed(() => [
+    { label: t('Label.CidAccount'), value: 1 },
+    { label: t('Ucard.KycAuth.item2'), value: 2 },
+    { label: t('Ucard.KycAuth.item3'), value: 3 },
+  ])
+
+  //获取列表数据
+  const searchFunc = async () => {
+    pictLoading.value = true
+    if (!display.value['R-Card-BlockchainTransaction-Page']?.show) {
+      // 假设有Message组件可用
+      ElMessage.warning(t('Msg.NotDisplay'))
+      pictLoading.value = false
+      return
+    }
+    let res = await Service.getBlockchainTransactionPage({
+      ...search,
+      page: {
+        current: pagerInfo.current,
+        row: pagerInfo.row,
+      },
+    })
+    if (res.code == Code.StatusOK) {
+      mock_tableData.value = res.data
+      if (res.page != null) {
+        pagerInfo.rowTotal = res.page.rowTotal
+        pagerInfo.pageTotal = res.page.pageTotal
+      } else {
+        pagerInfo.rowTotal = 0
+      }
+      ElMessage.success(t('Msg.SearchSuccess'))
+    } else {
+      ElMessage.error(res.msg)
+    }
+    pictLoading.value = false
+  }
+
+  //搜索
+  const toSearch = () => {
+    pagerInfo.current = 1
+    searchFunc()
+  }
+
+  //分页返回数据
+  const handleSizeChange = (val) => {
+    pagerInfo.row = val
+    searchFunc()
+  }
+
+  const handleCurrentChange = (val) => {
+    pagerInfo.current = val
+    searchFunc()
+  }
+
+  // 导出
+  const exportList = async () => {
+    exportExcel(
+      pigeon,
+      '/wasabi/encrypted/wallet/transaction/list/export',
+      { ...search },
+      'Encrypted_Wallet_Transactions'
+    )
+  }
+
+  onMounted(() => {
+    searchFunc()
+  })
+</script>
+
+<style scoped lang="scss">
+  #card_BlockchainTransaction {
+    .crm_search {
+      .search_action_btn {
+        .delete {
+          background-color: #a1a1a1;
+        }
+
+        .delete.active {
+          background-color: #368fec;
+        }
+      }
+    }
+  }
+</style>
+<style lang="scss">
+  #card_BlockchainTransaction {
+    .dialog_header_w {
+      .crm_search_down {
+        width: 400px;
+      }
+    }
+  }
+</style>