feat: 添加 SubscribeRwa 组件,优化 RWA 申购功能并更新相关类型定义
This commit is contained in:
2
auto-imports.d.ts
vendored
2
auto-imports.d.ts
vendored
@@ -270,6 +270,7 @@ declare global {
|
||||
const useStorage: typeof import('@vueuse/core').useStorage
|
||||
const useStorageAsync: typeof import('@vueuse/core').useStorageAsync
|
||||
const useStyleTag: typeof import('@vueuse/core').useStyleTag
|
||||
const useSubscribeModal: typeof import('./src/composables/useSubscribeModal').useSubscribeModal
|
||||
const useSupported: typeof import('@vueuse/core').useSupported
|
||||
const useSwipe: typeof import('@vueuse/core').useSwipe
|
||||
const useTemplateRef: typeof import('vue').useTemplateRef
|
||||
@@ -611,6 +612,7 @@ declare module 'vue' {
|
||||
readonly useStorage: UnwrapRef<typeof import('@vueuse/core')['useStorage']>
|
||||
readonly useStorageAsync: UnwrapRef<typeof import('@vueuse/core')['useStorageAsync']>
|
||||
readonly useStyleTag: UnwrapRef<typeof import('@vueuse/core')['useStyleTag']>
|
||||
readonly useSubscribeModal: UnwrapRef<typeof import('./src/composables/useSubscribeModal')['useSubscribeModal']>
|
||||
readonly useSupported: UnwrapRef<typeof import('@vueuse/core')['useSupported']>
|
||||
readonly useSwipe: UnwrapRef<typeof import('@vueuse/core')['useSwipe']>
|
||||
readonly useTemplateRef: UnwrapRef<typeof import('vue')['useTemplateRef']>
|
||||
|
||||
4
components.d.ts
vendored
4
components.d.ts
vendored
@@ -35,6 +35,7 @@ declare module 'vue' {
|
||||
IonIcon: typeof import('@ionic/vue')['IonIcon']
|
||||
IonInfiniteScroll: typeof import('@ionic/vue')['IonInfiniteScroll']
|
||||
IonInfiniteScrollContent: typeof import('@ionic/vue')['IonInfiniteScrollContent']
|
||||
IonInput: typeof import('@ionic/vue')['IonInput']
|
||||
IonInputOtp: typeof import('@ionic/vue')['IonInputOtp']
|
||||
IonItem: typeof import('@ionic/vue')['IonItem']
|
||||
IonLabel: typeof import('@ionic/vue')['IonLabel']
|
||||
@@ -61,6 +62,7 @@ declare module 'vue' {
|
||||
QrScanner: typeof import('./src/components/qr-scanner/index.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
SubscribeRwa: typeof import('./src/components/subscribe-rwa/index.vue')['default']
|
||||
UiAvatar: typeof import('./src/components/ui/avatar/index.vue')['default']
|
||||
UiCollapse: typeof import('./src/components/ui/collapse/index.vue')['default']
|
||||
UiDatetime: typeof import('./src/components/ui/datetime/index.vue')['default']
|
||||
@@ -99,6 +101,7 @@ declare global {
|
||||
const IonIcon: typeof import('@ionic/vue')['IonIcon']
|
||||
const IonInfiniteScroll: typeof import('@ionic/vue')['IonInfiniteScroll']
|
||||
const IonInfiniteScrollContent: typeof import('@ionic/vue')['IonInfiniteScrollContent']
|
||||
const IonInput: typeof import('@ionic/vue')['IonInput']
|
||||
const IonInputOtp: typeof import('@ionic/vue')['IonInputOtp']
|
||||
const IonItem: typeof import('@ionic/vue')['IonItem']
|
||||
const IonLabel: typeof import('@ionic/vue')['IonLabel']
|
||||
@@ -125,6 +128,7 @@ declare global {
|
||||
const QrScanner: typeof import('./src/components/qr-scanner/index.vue')['default']
|
||||
const RouterLink: typeof import('vue-router')['RouterLink']
|
||||
const RouterView: typeof import('vue-router')['RouterView']
|
||||
const SubscribeRwa: typeof import('./src/components/subscribe-rwa/index.vue')['default']
|
||||
const UiAvatar: typeof import('./src/components/ui/avatar/index.vue')['default']
|
||||
const UiCollapse: typeof import('./src/components/ui/collapse/index.vue')['default']
|
||||
const UiDatetime: typeof import('./src/components/ui/datetime/index.vue')['default']
|
||||
|
||||
45
src/components/subscribe-rwa/index.vue
Normal file
45
src/components/subscribe-rwa/index.vue
Normal file
@@ -0,0 +1,45 @@
|
||||
<script lang='ts' setup>
|
||||
const props = defineProps<{
|
||||
unitPrice: number;
|
||||
}>();
|
||||
|
||||
const walletStore = useWalletStore();
|
||||
const { balances } = storeToRefs(walletStore);
|
||||
const currentUSDTBalance = computed(() => balances.value[0].available);
|
||||
const maxSubscribeNumber = computed(() => {
|
||||
return Math.floor(Number(currentUSDTBalance.value) / props.unitPrice);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ion-content class="ion-padding" :scroll-y="false">
|
||||
<div class="space-y-5 mt-3">
|
||||
<div>申购RWA</div>
|
||||
|
||||
<ion-input :placeholder="`最大可申购数量: ${maxSubscribeNumber}`" type="number" :max="maxSubscribeNumber" />
|
||||
|
||||
<div class="mt-4 text-sm color-(--ion-text-color-secondary)">
|
||||
单价: ${{ unitPrice }}
|
||||
</div>
|
||||
|
||||
<div class="mt-4 text-sm color-(--ion-text-color-secondary)">
|
||||
可用余额: ${{ Number(currentUSDTBalance) }}
|
||||
</div>
|
||||
|
||||
<ion-button expand="block" class="mt-6 ui-button" color="primary">
|
||||
确认申购
|
||||
</ion-button>
|
||||
</div>
|
||||
</ion-content>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
@reference "tailwindcss";
|
||||
|
||||
ion-input {
|
||||
@apply rounded-lg;
|
||||
--padding-start: 16px;
|
||||
--padding-end: 16px;
|
||||
border: 1px solid var(--ion-color-light-shade);
|
||||
}
|
||||
</style>
|
||||
@@ -47,26 +47,34 @@ const { data } = safeClient(client.api.rwa.subscription.available_editions({ edi
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
<ion-row>
|
||||
<ion-col>
|
||||
<div class="label">
|
||||
单价
|
||||
</div>
|
||||
<div>${{ formatAmount(data?.unitPrice) }}</div>
|
||||
</ion-col>
|
||||
<ion-col>
|
||||
<div class="label">
|
||||
总发行量
|
||||
</div>
|
||||
<div>{{ Number(data?.totalSupply) }}份</div>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
<ion-row>
|
||||
<ion-col>
|
||||
<div class="label">
|
||||
每人限量
|
||||
</div>
|
||||
<div>{{ Number(data?.perUserLimit) }}份</div>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
<ion-row>
|
||||
<ion-col>
|
||||
<div class="label">
|
||||
发行时间
|
||||
</div>
|
||||
<div>{{ useDateFormat(data?.launchDate || '', 'YYYY/MM/DD') }}</div>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
<ion-row>
|
||||
<ion-col>
|
||||
<div class="label">
|
||||
认购截止时间
|
||||
@@ -90,12 +98,13 @@ const { data } = safeClient(client.api.rwa.subscription.available_editions({ edi
|
||||
<ion-footer>
|
||||
<ion-toolbar class="ion-padding-horizontal ui-toolbar">
|
||||
<div class="flex justify-center my-2 gap-5">
|
||||
<ion-button shape="round" expand="block" color="success">
|
||||
<ion-button id="open-modal" shape="round" expand="block" color="success">
|
||||
申购
|
||||
</ion-button>
|
||||
<ion-button shape="round" expand="block" color="danger">
|
||||
赎回
|
||||
</ion-button>
|
||||
|
||||
<ion-modal trigger="open-modal" :initial-breakpoint="0.4" :breakpoints="[0, 0.4]">
|
||||
<subscribe-rwa :unit-price="Number(data?.unitPrice || 0)" />
|
||||
</ion-modal>
|
||||
</div>
|
||||
</ion-toolbar>
|
||||
</ion-footer>
|
||||
|
||||
@@ -1,11 +1,36 @@
|
||||
<script lang='ts' setup>
|
||||
import type { Animation } from "@ionic/vue";
|
||||
import { createAnimation } from "@ionic/vue";
|
||||
import { cartOutline } from "ionicons/icons";
|
||||
|
||||
const model = defineModel<"sale" | "buy" | null>();
|
||||
|
||||
const operationInst = useTemplateRef<HTMLDivElement>("operationInst");
|
||||
const targetIsVisible = useElementVisibility(operationInst);
|
||||
const animation = ref<Animation | null>(null);
|
||||
|
||||
watch(targetIsVisible, (visible) => {
|
||||
if (visible) {
|
||||
animation.value?.easing("ease-in")
|
||||
.fromTo("opacity", "0", "1")
|
||||
.play();
|
||||
}
|
||||
else {
|
||||
animation.value?.easing("ease-out")
|
||||
.fromTo("opacity", "1", "0")
|
||||
.play();
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
animation.value = createAnimation()
|
||||
.addElement(operationInst.value!)
|
||||
.duration(500);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="model === null" class="operation-container">
|
||||
<div v-if="model === null" ref="operationInst" class="operation-container">
|
||||
<div class="wrapper" />
|
||||
|
||||
<div class="box">
|
||||
|
||||
@@ -3,18 +3,17 @@ import { cartOutline } from "ionicons/icons";
|
||||
import OperationWrapper from "./components/operation-wrapper.vue";
|
||||
|
||||
const { t } = useI18n();
|
||||
const current = ref<"sale" | "buy" | null>(null);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonHeader class="ion-no-border">
|
||||
<ion-toolbar class="ui-toolbar">
|
||||
<IonTitle>{{ t('tabs.trade') }}</IonTitle>
|
||||
</IonToolbar>
|
||||
</ion-toolbar>
|
||||
</IonHeader>
|
||||
<IonContent :fullscreen="true">
|
||||
<OperationWrapper v-model="current" />
|
||||
<!-- <OperationWrapper v-model="current" /> -->
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user