feat: 更新钱包管理功能,添加银行账户和余额的初始化逻辑,优化API请求和响应处理
This commit is contained in:
12
auto-imports.d.ts
vendored
12
auto-imports.d.ts
vendored
@@ -364,6 +364,7 @@ declare module 'vue' {
|
|||||||
interface GlobalComponents {}
|
interface GlobalComponents {}
|
||||||
interface ComponentCustomProperties {
|
interface ComponentCustomProperties {
|
||||||
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
|
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
|
||||||
|
readonly acceptHMRUpdate: UnwrapRef<typeof import('pinia')['acceptHMRUpdate']>
|
||||||
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
|
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
|
||||||
readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']>
|
readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']>
|
||||||
readonly computed: UnwrapRef<typeof import('vue')['computed']>
|
readonly computed: UnwrapRef<typeof import('vue')['computed']>
|
||||||
@@ -377,6 +378,7 @@ declare module 'vue' {
|
|||||||
readonly createEventHook: UnwrapRef<typeof import('@vueuse/core')['createEventHook']>
|
readonly createEventHook: UnwrapRef<typeof import('@vueuse/core')['createEventHook']>
|
||||||
readonly createGlobalState: UnwrapRef<typeof import('@vueuse/core')['createGlobalState']>
|
readonly createGlobalState: UnwrapRef<typeof import('@vueuse/core')['createGlobalState']>
|
||||||
readonly createInjectionState: UnwrapRef<typeof import('@vueuse/core')['createInjectionState']>
|
readonly createInjectionState: UnwrapRef<typeof import('@vueuse/core')['createInjectionState']>
|
||||||
|
readonly createPinia: UnwrapRef<typeof import('pinia')['createPinia']>
|
||||||
readonly createReactiveFn: UnwrapRef<typeof import('@vueuse/core')['createReactiveFn']>
|
readonly createReactiveFn: UnwrapRef<typeof import('@vueuse/core')['createReactiveFn']>
|
||||||
readonly createRef: UnwrapRef<typeof import('@vueuse/core')['createRef']>
|
readonly createRef: UnwrapRef<typeof import('@vueuse/core')['createRef']>
|
||||||
readonly createReusableTemplate: UnwrapRef<typeof import('@vueuse/core')['createReusableTemplate']>
|
readonly createReusableTemplate: UnwrapRef<typeof import('@vueuse/core')['createReusableTemplate']>
|
||||||
@@ -388,11 +390,13 @@ declare module 'vue' {
|
|||||||
readonly debouncedWatch: UnwrapRef<typeof import('@vueuse/core')['debouncedWatch']>
|
readonly debouncedWatch: UnwrapRef<typeof import('@vueuse/core')['debouncedWatch']>
|
||||||
readonly defineAsyncComponent: UnwrapRef<typeof import('vue')['defineAsyncComponent']>
|
readonly defineAsyncComponent: UnwrapRef<typeof import('vue')['defineAsyncComponent']>
|
||||||
readonly defineComponent: UnwrapRef<typeof import('vue')['defineComponent']>
|
readonly defineComponent: UnwrapRef<typeof import('vue')['defineComponent']>
|
||||||
|
readonly defineStore: UnwrapRef<typeof import('pinia')['defineStore']>
|
||||||
readonly eagerComputed: UnwrapRef<typeof import('@vueuse/core')['eagerComputed']>
|
readonly eagerComputed: UnwrapRef<typeof import('@vueuse/core')['eagerComputed']>
|
||||||
readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
|
readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
|
||||||
readonly emailPattern: UnwrapRef<typeof import('./src/utils/pattern')['emailPattern']>
|
readonly emailPattern: UnwrapRef<typeof import('./src/utils/pattern')['emailPattern']>
|
||||||
readonly extendRef: UnwrapRef<typeof import('@vueuse/core')['extendRef']>
|
readonly extendRef: UnwrapRef<typeof import('@vueuse/core')['extendRef']>
|
||||||
readonly formatBalance: UnwrapRef<typeof import('./src/utils/helper')['formatBalance']>
|
readonly formatBalance: UnwrapRef<typeof import('./src/utils/helper')['formatBalance']>
|
||||||
|
readonly getActivePinia: UnwrapRef<typeof import('pinia')['getActivePinia']>
|
||||||
readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
|
readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
|
||||||
readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
|
readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
|
||||||
readonly getCurrentWatcher: UnwrapRef<typeof import('vue')['getCurrentWatcher']>
|
readonly getCurrentWatcher: UnwrapRef<typeof import('vue')['getCurrentWatcher']>
|
||||||
@@ -407,6 +411,11 @@ declare module 'vue' {
|
|||||||
readonly isRef: UnwrapRef<typeof import('vue')['isRef']>
|
readonly isRef: UnwrapRef<typeof import('vue')['isRef']>
|
||||||
readonly isShallow: UnwrapRef<typeof import('vue')['isShallow']>
|
readonly isShallow: UnwrapRef<typeof import('vue')['isShallow']>
|
||||||
readonly makeDestructurable: UnwrapRef<typeof import('@vueuse/core')['makeDestructurable']>
|
readonly makeDestructurable: UnwrapRef<typeof import('@vueuse/core')['makeDestructurable']>
|
||||||
|
readonly mapActions: UnwrapRef<typeof import('pinia')['mapActions']>
|
||||||
|
readonly mapGetters: UnwrapRef<typeof import('pinia')['mapGetters']>
|
||||||
|
readonly mapState: UnwrapRef<typeof import('pinia')['mapState']>
|
||||||
|
readonly mapStores: UnwrapRef<typeof import('pinia')['mapStores']>
|
||||||
|
readonly mapWritableState: UnwrapRef<typeof import('pinia')['mapWritableState']>
|
||||||
readonly markRaw: UnwrapRef<typeof import('vue')['markRaw']>
|
readonly markRaw: UnwrapRef<typeof import('vue')['markRaw']>
|
||||||
readonly nextTick: UnwrapRef<typeof import('vue')['nextTick']>
|
readonly nextTick: UnwrapRef<typeof import('vue')['nextTick']>
|
||||||
readonly numberPattern: UnwrapRef<typeof import('./src/utils/pattern')['numberPattern']>
|
readonly numberPattern: UnwrapRef<typeof import('./src/utils/pattern')['numberPattern']>
|
||||||
@@ -450,9 +459,12 @@ declare module 'vue' {
|
|||||||
readonly refWithControl: UnwrapRef<typeof import('@vueuse/core')['refWithControl']>
|
readonly refWithControl: UnwrapRef<typeof import('@vueuse/core')['refWithControl']>
|
||||||
readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']>
|
readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']>
|
||||||
readonly resolveRef: UnwrapRef<typeof import('@vueuse/core')['resolveRef']>
|
readonly resolveRef: UnwrapRef<typeof import('@vueuse/core')['resolveRef']>
|
||||||
|
readonly setActivePinia: UnwrapRef<typeof import('pinia')['setActivePinia']>
|
||||||
|
readonly setMapStoreSuffix: UnwrapRef<typeof import('pinia')['setMapStoreSuffix']>
|
||||||
readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
|
readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
|
||||||
readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
|
readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
|
||||||
readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
|
readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
|
||||||
|
readonly storeToRefs: UnwrapRef<typeof import('pinia')['storeToRefs']>
|
||||||
readonly syncRef: UnwrapRef<typeof import('@vueuse/core')['syncRef']>
|
readonly syncRef: UnwrapRef<typeof import('@vueuse/core')['syncRef']>
|
||||||
readonly syncRefs: UnwrapRef<typeof import('@vueuse/core')['syncRefs']>
|
readonly syncRefs: UnwrapRef<typeof import('@vueuse/core')['syncRefs']>
|
||||||
readonly templateRef: UnwrapRef<typeof import('@vueuse/core')['templateRef']>
|
readonly templateRef: UnwrapRef<typeof import('@vueuse/core')['templateRef']>
|
||||||
|
|||||||
10
src/App.vue
10
src/App.vue
@@ -1,12 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { client, safeClient } from "./api";
|
const { initializeWallet } = useWalletStore();
|
||||||
|
|
||||||
const walletStore = useWalletStore();
|
onMounted(() => {
|
||||||
|
initializeWallet();
|
||||||
onMounted(async () => {
|
|
||||||
const { data } = await safeClient(() => client.api.asset.balances.get(), { silent: true });
|
|
||||||
walletStore.state.balances = data.value;
|
|
||||||
client.api.rwa.issuance.products.get();
|
|
||||||
console.log("App mounted successfully");
|
console.log("App mounted successfully");
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -8,15 +8,21 @@ const client = treaty<App>(window.location.origin, {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export interface SafeClientOptions {
|
||||||
|
silent?: boolean;
|
||||||
|
immediate?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export async function safeClient<T, E>(
|
export async function safeClient<T, E>(
|
||||||
requestPromise: () => Promise<{ data: T; error: E }>,
|
requestPromise: () => Promise<{ data: T; error: E }>,
|
||||||
options: { silent?: boolean; immediate?: boolean } = {},
|
options: SafeClientOptions = {},
|
||||||
) {
|
) {
|
||||||
const { immediate = true } = options;
|
const { immediate = true } = options;
|
||||||
const data = ref<T | null>(null);
|
const data = ref<T | null>(null);
|
||||||
const error = ref<E | null>(null);
|
const error = ref<E | null>(null);
|
||||||
|
let responseCallback: ((data: T, error: E) => void) | null = null;
|
||||||
|
|
||||||
const executeRequest = async () => {
|
const execute = async () => {
|
||||||
const res = await requestPromise();
|
const res = await requestPromise();
|
||||||
|
|
||||||
if (res.error) {
|
if (res.error) {
|
||||||
@@ -34,13 +40,22 @@ export async function safeClient<T, E>(
|
|||||||
}
|
}
|
||||||
data.value = res.data;
|
data.value = res.data;
|
||||||
error.value = res.error;
|
error.value = res.error;
|
||||||
|
|
||||||
|
// 调用注册的回调函数
|
||||||
|
if (responseCallback) {
|
||||||
|
responseCallback(res.data, res.error);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (immediate) {
|
function onFetchResponse(callback: (data: T, error: E) => void) {
|
||||||
await executeRequest();
|
responseCallback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
return { data, error, refresh: executeRequest };
|
if (immediate) {
|
||||||
|
await execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
return { data, error, refresh: execute, onFetchResponse };
|
||||||
}
|
}
|
||||||
|
|
||||||
export { client };
|
export { client };
|
||||||
|
|||||||
@@ -1,16 +1,50 @@
|
|||||||
import type { BalancesData } from "@/api/types";
|
import type { BalancesData, BankAccountsData } from "@/api/types";
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
|
import { client, safeClient } from "@/api";
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
balances: BalancesData | null;
|
balances: BalancesData;
|
||||||
|
bankAccounts: BankAccountsData["data"];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useWalletStore = defineStore("wallet", () => {
|
export const useWalletStore = defineStore("wallet", () => {
|
||||||
const state = reactive<State>({
|
const state = reactive<State>({
|
||||||
balances: null,
|
balances: [],
|
||||||
|
bankAccounts: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const balances = computed(() => state.balances);
|
||||||
|
const bankAccounts = computed(() => state.bankAccounts);
|
||||||
|
|
||||||
|
async function initializeWallet() {
|
||||||
|
updateBalances();
|
||||||
|
updateBankAccounts();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateBalances(data?: BalancesData) {
|
||||||
|
if (data) {
|
||||||
|
state.balances = data;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { data: balances } = await safeClient(() => client.api.asset.balances.get(), { silent: true });
|
||||||
|
state.balances = balances.value || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateBankAccounts(data?: BankAccountsData["data"]) {
|
||||||
|
if (data) {
|
||||||
|
state.bankAccounts = data;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { data: bankAccounts } = await safeClient(() => client.api.bank_account.get(), { silent: true });
|
||||||
|
state.bankAccounts = bankAccounts.value?.data || [];
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
state,
|
state,
|
||||||
|
balances,
|
||||||
|
bankAccounts,
|
||||||
|
initializeWallet,
|
||||||
|
updateBalances,
|
||||||
|
updateBankAccounts,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,10 +11,15 @@ import { client, safeClient } from "@/api";
|
|||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const { updateBankAccounts } = useWalletStore();
|
||||||
|
|
||||||
const { data, refresh } = await safeClient(() => client.api.bank_account.get());
|
const { data, refresh, onFetchResponse } = await safeClient(() => client.api.bank_account.get());
|
||||||
const bankCards = computed(() => data.value?.data || []);
|
const bankCards = computed(() => data.value?.data || []);
|
||||||
|
|
||||||
|
onFetchResponse((data) => {
|
||||||
|
data?.data && updateBankAccounts(data.data);
|
||||||
|
});
|
||||||
|
|
||||||
function handleAddCard() {
|
function handleAddCard() {
|
||||||
router.push("/trade-settings/bank-management/add");
|
router.push("/trade-settings/bank-management/add");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ import RechargeChannel from "./recharge-channel.vue";
|
|||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { state } = useWalletStore();
|
const walletStore = useWalletStore();
|
||||||
|
const { balances } = storeToRefs(walletStore);
|
||||||
const rechargeInstance = ref<ModalInstance>();
|
const rechargeInstance = ref<ModalInstance>();
|
||||||
|
|
||||||
function onCloseModal() {
|
function onCloseModal() {
|
||||||
@@ -12,12 +13,16 @@ function onCloseModal() {
|
|||||||
function handleWithdraw() {
|
function handleWithdraw() {
|
||||||
router.push("/withdraw/index");
|
router.push("/withdraw/index");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onUpdated(() => {
|
||||||
|
walletStore.updateBalances();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="mt-5 shadow-md rounded-lg overflow-hidden">
|
<div class="mt-5 shadow-md rounded-lg overflow-hidden">
|
||||||
<div class="grid grid-cols-1 gap-5 p-5 bg-(--ion-card-background)">
|
<div class="grid grid-cols-1 gap-5 p-5 bg-(--ion-card-background)">
|
||||||
<div v-for="item in state.balances" :key="item.assetCode" class="flex flex-col gap-1">
|
<div v-for="item in balances" :key="item.assetCode" class="flex flex-col gap-1">
|
||||||
<div class="uppercase text-xs text-text-400 font-medium tracking-[0.4px]">
|
<div class="uppercase text-xs text-text-400 font-medium tracking-[0.4px]">
|
||||||
{{ item.assetCode }}
|
{{ item.assetCode }}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<script lang='ts' setup>
|
<script lang='ts' setup>
|
||||||
import type { WithdrawBody } from "@/api/types";
|
import type { WithdrawBody } from "@/api/types";
|
||||||
import { toastController } from "@ionic/vue";
|
|
||||||
import { client, safeClient } from "@/api";
|
import { client, safeClient } from "@/api";
|
||||||
import { AssetCodeEnum, ChainEnum, WithdrawMethodEnum } from "@/api/enum";
|
import { AssetCodeEnum, ChainEnum, WithdrawMethodEnum } from "@/api/enum";
|
||||||
|
|
||||||
@@ -15,9 +14,10 @@ const [form, resetForm] = useResetRef<WithdrawBody>({
|
|||||||
bankAccountId: "",
|
bankAccountId: "",
|
||||||
chain: "BEP20",
|
chain: "BEP20",
|
||||||
});
|
});
|
||||||
const { state } = useWalletStore();
|
const walletStore = useWalletStore();
|
||||||
|
const { balances } = storeToRefs(walletStore);
|
||||||
const maxAmount = computed(() => {
|
const maxAmount = computed(() => {
|
||||||
const balance = state.balances?.find(item => item.assetCode === form.value.assetCode);
|
const balance = balances.value?.find(item => item.assetCode === form.value.assetCode);
|
||||||
return balance ? balance.available : "0";
|
return balance ? balance.available : "0";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export default defineConfig({
|
|||||||
tailwindcss(),
|
tailwindcss(),
|
||||||
autoImport({
|
autoImport({
|
||||||
dirs: ["src/composables", "src/utils", "src/store"],
|
dirs: ["src/composables", "src/utils", "src/store"],
|
||||||
imports: ["vue", "vue-router", "@vueuse/core", "vue-i18n"],
|
imports: ["vue", "vue-router", "@vueuse/core", "vue-i18n", "pinia"],
|
||||||
resolvers: [IonicResolver()],
|
resolvers: [IonicResolver()],
|
||||||
vueTemplate: true,
|
vueTemplate: true,
|
||||||
}),
|
}),
|
||||||
|
|||||||
Reference in New Issue
Block a user