feat: 更新依赖版本,优化路由组件,重构文件预览和订单面板,添加市场组件
This commit is contained in:
@@ -34,7 +34,7 @@
|
|||||||
"@elysiajs/eden": "^1.4.5",
|
"@elysiajs/eden": "^1.4.5",
|
||||||
"@ionic/vue": "^8.7.11",
|
"@ionic/vue": "^8.7.11",
|
||||||
"@ionic/vue-router": "^8.7.11",
|
"@ionic/vue-router": "^8.7.11",
|
||||||
"@riwa/api-types": "http://192.168.1.7:9527/api/riwa-eden-0.0.123.tgz",
|
"@riwa/api-types": "http://192.168.1.7:9527/api/riwa-eden-0.0.125.tgz",
|
||||||
"@tailwindcss/vite": "^4.1.18",
|
"@tailwindcss/vite": "^4.1.18",
|
||||||
"@vee-validate/zod": "^4.15.1",
|
"@vee-validate/zod": "^4.15.1",
|
||||||
"@vueuse/core": "^14.1.0",
|
"@vueuse/core": "^14.1.0",
|
||||||
|
|||||||
12
pnpm-lock.yaml
generated
12
pnpm-lock.yaml
generated
@@ -57,8 +57,8 @@ importers:
|
|||||||
specifier: ^8.7.11
|
specifier: ^8.7.11
|
||||||
version: 8.7.11(@stencil/core@4.39.0)(vue-router@4.6.3(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3))
|
version: 8.7.11(@stencil/core@4.39.0)(vue-router@4.6.3(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3))
|
||||||
'@riwa/api-types':
|
'@riwa/api-types':
|
||||||
specifier: http://192.168.1.7:9527/api/riwa-eden-0.0.123.tgz
|
specifier: http://192.168.1.7:9527/api/riwa-eden-0.0.125.tgz
|
||||||
version: '@riwa/eden@http://192.168.1.7:9527/api/riwa-eden-0.0.123.tgz(@elysiajs/eden@1.4.5(elysia@1.4.18(@sinclair/typebox@0.34.41)(exact-mirror@0.2.5(@sinclair/typebox@0.34.41))(file-type@21.1.1)(openapi-types@12.1.3)(typescript@5.9.3)))'
|
version: '@riwa/eden@http://192.168.1.7:9527/api/riwa-eden-0.0.125.tgz(@elysiajs/eden@1.4.5(elysia@1.4.18(@sinclair/typebox@0.34.41)(exact-mirror@0.2.5(@sinclair/typebox@0.34.41))(file-type@21.1.1)(openapi-types@12.1.3)(typescript@5.9.3)))'
|
||||||
'@tailwindcss/vite':
|
'@tailwindcss/vite':
|
||||||
specifier: ^4.1.18
|
specifier: ^4.1.18
|
||||||
version: 4.1.18(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))
|
version: 4.1.18(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))
|
||||||
@@ -2832,9 +2832,9 @@ packages:
|
|||||||
'@remirror/core-constants@3.0.0':
|
'@remirror/core-constants@3.0.0':
|
||||||
resolution: {integrity: sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==}
|
resolution: {integrity: sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==}
|
||||||
|
|
||||||
'@riwa/eden@http://192.168.1.7:9527/api/riwa-eden-0.0.123.tgz':
|
'@riwa/eden@http://192.168.1.7:9527/api/riwa-eden-0.0.125.tgz':
|
||||||
resolution: {tarball: http://192.168.1.7:9527/api/riwa-eden-0.0.123.tgz}
|
resolution: {tarball: http://192.168.1.7:9527/api/riwa-eden-0.0.125.tgz}
|
||||||
version: 0.0.123
|
version: 0.0.125
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@elysiajs/eden': ^1.4.5
|
'@elysiajs/eden': ^1.4.5
|
||||||
|
|
||||||
@@ -12199,7 +12199,7 @@ snapshots:
|
|||||||
|
|
||||||
'@remirror/core-constants@3.0.0': {}
|
'@remirror/core-constants@3.0.0': {}
|
||||||
|
|
||||||
'@riwa/eden@http://192.168.1.7:9527/api/riwa-eden-0.0.123.tgz(@elysiajs/eden@1.4.5(elysia@1.4.18(@sinclair/typebox@0.34.41)(exact-mirror@0.2.5(@sinclair/typebox@0.34.41))(file-type@21.1.1)(openapi-types@12.1.3)(typescript@5.9.3)))':
|
'@riwa/eden@http://192.168.1.7:9527/api/riwa-eden-0.0.125.tgz(@elysiajs/eden@1.4.5(elysia@1.4.18(@sinclair/typebox@0.34.41)(exact-mirror@0.2.5(@sinclair/typebox@0.34.41))(file-type@21.1.1)(openapi-types@12.1.3)(typescript@5.9.3)))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@elysiajs/eden': 1.4.5(elysia@1.4.18(@sinclair/typebox@0.34.41)(exact-mirror@0.2.5(@sinclair/typebox@0.34.41))(file-type@21.1.1)(openapi-types@12.1.3)(typescript@5.9.3))
|
'@elysiajs/eden': 1.4.5(elysia@1.4.18(@sinclair/typebox@0.34.41)(exact-mirror@0.2.5(@sinclair/typebox@0.34.41))(file-type@21.1.1)(openapi-types@12.1.3)(typescript@5.9.3))
|
||||||
|
|
||||||
|
|||||||
@@ -185,41 +185,29 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
{
|
{
|
||||||
path: "/trade-rwa/:id",
|
path: "/trade-rwa/:id",
|
||||||
props: true,
|
props: true,
|
||||||
component: () => import("@/views/trade-rwa/outlet.vue"),
|
|
||||||
meta: { requiresAuth: true },
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: "",
|
|
||||||
component: () => import("@/views/trade-rwa/index.vue"),
|
component: () => import("@/views/trade-rwa/index.vue"),
|
||||||
meta: { requiresAuth: true },
|
meta: { requiresAuth: true },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "edit",
|
path: "/trade-rwa/:id/edit",
|
||||||
name: "trade-rwa-edit",
|
name: "trade-rwa-edit",
|
||||||
|
props: true,
|
||||||
component: () => import("@/views/trade-rwa/edit.vue"),
|
component: () => import("@/views/trade-rwa/edit.vue"),
|
||||||
meta: { requiresAuth: true },
|
meta: { requiresAuth: true },
|
||||||
},
|
},
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: "/trade-tokenized/:id",
|
path: "/trade-tokenized/:id",
|
||||||
props: true,
|
props: true,
|
||||||
component: () => import("@/views/trade-tokenized/outlet.vue"),
|
|
||||||
meta: { requiresAuth: true },
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: "",
|
|
||||||
component: () => import("@/views/trade-tokenized/index.vue"),
|
component: () => import("@/views/trade-tokenized/index.vue"),
|
||||||
meta: { requiresAuth: true },
|
meta: { requiresAuth: true },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "edit",
|
path: "/trade-tokenized/:id/edit",
|
||||||
name: "trade-tokenized-edit",
|
name: "trade-tokenized-edit",
|
||||||
|
props: true,
|
||||||
component: () => import("@/views/trade-tokenized/edit.vue"),
|
component: () => import("@/views/trade-tokenized/edit.vue"),
|
||||||
meta: { requiresAuth: true },
|
meta: { requiresAuth: true },
|
||||||
},
|
},
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: "/market/orders",
|
path: "/market/orders",
|
||||||
component: () => import("@/views/market/orders.vue"),
|
component: () => import("@/views/market/orders.vue"),
|
||||||
|
|||||||
22
src/ui/file-preview/index.vue
Normal file
22
src/ui/file-preview/index.vue
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<script lang='ts' setup>
|
||||||
|
import IcRoundDownload from "~icons/ic/round-download";
|
||||||
|
import { client, safeClient } from "@/api";
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
id: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const { data } = await safeClient(client.api.file_storage({ id: props.id }).get());
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div>{{ data?.fileName }}</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<IcRoundDownload />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang='css' scoped></style>
|
||||||
@@ -125,7 +125,7 @@ function handleSubmit(values: GenericObject) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Field v-slot="{ field }" name="proofDocuments">
|
<Field v-slot="{ field }" name="proofDocumentIds">
|
||||||
<ui-file-upload
|
<ui-file-upload
|
||||||
v-bind="field"
|
v-bind="field"
|
||||||
:fetch-options="{
|
:fetch-options="{
|
||||||
@@ -136,10 +136,9 @@ function handleSubmit(values: GenericObject) {
|
|||||||
:max-files="5"
|
:max-files="5"
|
||||||
:max-size="10"
|
:max-size="10"
|
||||||
accept="application/pdf,image/*,.doc,.docx"
|
accept="application/pdf,image/*,.doc,.docx"
|
||||||
@update:model-value="field.onChange($event.join(','))"
|
|
||||||
/>
|
/>
|
||||||
</Field>
|
</Field>
|
||||||
<ErrorMessage name="proofDocuments" />
|
<ErrorMessage name="proofDocumentIds" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ion-button type="submit" expand="block" shape="round" color="success">
|
<ion-button type="submit" expand="block" shape="round" color="success">
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
<script lang='ts' setup>
|
<script lang='ts' setup>
|
||||||
import type { RwaData } from "@/api/types";
|
import type { RwaData } from "@/api/types";
|
||||||
|
import { client, safeClient } from "@/api";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
data: RwaData | null;
|
data: RwaData | null;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const { data: file } = safeClient(client.api.file_storage({ id: props.data?.product.proofDocumentIds || "" }).get());
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -13,9 +16,7 @@ const props = defineProps<{
|
|||||||
<div class="font-semibold">
|
<div class="font-semibold">
|
||||||
相关文档
|
相关文档
|
||||||
</div>
|
</div>
|
||||||
<div class="text-xs mt-2">
|
<a class="link" :href="file?.publicUrl || ''" target="_blank" rel="noopener noreferrer">{{ file?.fileName }}</a>
|
||||||
{{ data?.product.proofDocuments }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
<script lang='ts' setup>
|
<script lang='ts' setup>
|
||||||
import type { RwaData } from "@/api/types";
|
|
||||||
import { toastController } from "@ionic/vue";
|
import { toastController } from "@ionic/vue";
|
||||||
import CryptocurrencyColorNuls from "~icons/cryptocurrency-color/nuls";
|
import CryptocurrencyColorNuls from "~icons/cryptocurrency-color/nuls";
|
||||||
import IcSharpEditNote from "~icons/ic/sharp-edit-note";
|
import IcSharpEditNote from "~icons/ic/sharp-edit-note";
|
||||||
@@ -8,9 +7,11 @@ import RwaAbout from "./components/about.vue";
|
|||||||
import RwaBase from "./components/base.vue";
|
import RwaBase from "./components/base.vue";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
data: RwaData;
|
id: string;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const { data } = safeClient(client.api.rwa.subscription.available_editions({ editionId: props.id }).get());
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
@@ -18,7 +19,7 @@ const model = useTemplateRef<ModalInstance>("model");
|
|||||||
|
|
||||||
async function handleSubscribe(val: number) {
|
async function handleSubscribe(val: number) {
|
||||||
await safeClient(client.api.rwa.subscription.apply.post({
|
await safeClient(client.api.rwa.subscription.apply.post({
|
||||||
editionId: props.data.id,
|
editionId: data.value!.id,
|
||||||
quantity: String(val),
|
quantity: String(val),
|
||||||
}));
|
}));
|
||||||
const toast = await toastController.create({
|
const toast = await toastController.create({
|
||||||
@@ -72,7 +73,7 @@ function gotoEdit() {
|
|||||||
<ui-tab-pane name="overview" :title="t('market.tradeRwa.tabs.overview')">
|
<ui-tab-pane name="overview" :title="t('market.tradeRwa.tabs.overview')">
|
||||||
<RwaBase :data="data" />
|
<RwaBase :data="data" />
|
||||||
</ui-tab-pane>
|
</ui-tab-pane>
|
||||||
<ui-tab-pane name="about" title="相关文档">
|
<ui-tab-pane name="about" title="相关文档" lazy>
|
||||||
<RwaAbout :data="data" />
|
<RwaAbout :data="data" />
|
||||||
</ui-tab-pane>
|
</ui-tab-pane>
|
||||||
</ui-tabs>
|
</ui-tabs>
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
<script lang='ts' setup>
|
|
||||||
import { client, safeClient } from "@/api";
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
id: string;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const { data } = safeClient(client.api.rwa.subscription.available_editions({ editionId: props.id }).get());
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<ion-page>
|
|
||||||
<ion-header>
|
|
||||||
<ion-toolbar class="ion-toolbar">
|
|
||||||
<ui-back-button slot="start" />
|
|
||||||
<ion-title>
|
|
||||||
{{ data?.product.code }}
|
|
||||||
</ion-title>
|
|
||||||
</ion-toolbar>
|
|
||||||
</ion-header>
|
|
||||||
<ion-content :fullscreen="true" class="ion-padding">
|
|
||||||
<RouterView :data="data" />
|
|
||||||
</ion-content>
|
|
||||||
</ion-page>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
||||||
@@ -14,7 +14,7 @@ const props = defineProps<{
|
|||||||
相关文档
|
相关文档
|
||||||
</div>
|
</div>
|
||||||
<div class="text-xs mt-2">
|
<div class="text-xs mt-2">
|
||||||
{{ data?.proofDocuments }}
|
{{ data?.proofDocumentIds }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const props = defineProps<{
|
|||||||
相关文档
|
相关文档
|
||||||
</div>
|
</div>
|
||||||
<div class="text-xs mt-2">
|
<div class="text-xs mt-2">
|
||||||
{{ data?.product?.proofDocuments }}
|
{{ data?.product?.proofDocumentIds }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,10 +10,9 @@ const { t } = useI18n();
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
<!-- Rwa about -->
|
|
||||||
<div>
|
<div>
|
||||||
<div class="font-semibold">
|
<div class="font-semibold">
|
||||||
{{ t('market.tradeRwa.about') }}
|
关于
|
||||||
</div>
|
</div>
|
||||||
<div class="text-xs mt-2">
|
<div class="text-xs mt-2">
|
||||||
{{ data?.product?.description || t('market.tradeRwa.noDescription') }}
|
{{ data?.product?.description || t('market.tradeRwa.noDescription') }}
|
||||||
@@ -31,7 +30,7 @@ const { t } = useI18n();
|
|||||||
</ion-col>
|
</ion-col>
|
||||||
<ion-col>
|
<ion-col>
|
||||||
<div class="label">
|
<div class="label">
|
||||||
{{ t('market.tradeRwa.fields.valuation') }}
|
市值
|
||||||
</div>
|
</div>
|
||||||
<div>${{ formatAmountWithUnit(data?.product?.estimatedValue) }}</div>
|
<div>${{ formatAmountWithUnit(data?.product?.estimatedValue) }}</div>
|
||||||
</ion-col>
|
</ion-col>
|
||||||
@@ -64,4 +63,10 @@ const { t } = useI18n();
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang='css' scoped></style>
|
<style lang='css' scoped>
|
||||||
|
@reference "tailwindcss";
|
||||||
|
|
||||||
|
.label {
|
||||||
|
@apply text-(--ion-text-color-step-300) mb-1 text-sm;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
35
src/views/trade-tokenized/components/market.vue
Normal file
35
src/views/trade-tokenized/components/market.vue
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<script lang='ts' setup>
|
||||||
|
import type { ChartingLibraryWidgetOptions } from "#/charting_library";
|
||||||
|
import type { TradableData } from "@/api/types";
|
||||||
|
import type { TradingViewInst } from "@/tradingview";
|
||||||
|
import { client, safeClient } from "@/api";
|
||||||
|
import { TradingViewChart } from "@/tradingview";
|
||||||
|
import OrderBook from "./order-book.vue";
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
data: TradableData | null;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const tradingviewOptions: Partial<ChartingLibraryWidgetOptions> = {
|
||||||
|
disabled_features: [
|
||||||
|
"create_volume_indicator_by_default",
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const tradingViewInst = useTemplateRef<TradingViewInst>("tradingViewInst");
|
||||||
|
const symbol = computed(() => props.data?.asset?.tradingPairsAsBase[0].symbol || "");
|
||||||
|
|
||||||
|
const { data } = await safeClient(client.api.trading_pairs.orderbook.get({ query: { symbol: symbol.value, depth: 30 } }));
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<TradingViewChart v-if="symbol" ref="tradingViewInst" class="mb-5" height="300px" :symbol="symbol" :options="tradingviewOptions" />
|
||||||
|
|
||||||
|
<ui-tabs size="small" class="my-3">
|
||||||
|
<ui-tab-pane name="order_book" title="订单表">
|
||||||
|
<OrderBook :symbol="symbol" />
|
||||||
|
</ui-tab-pane>
|
||||||
|
</ui-tabs>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang='css' scoped></style>
|
||||||
125
src/views/trade-tokenized/components/order-book.vue
Normal file
125
src/views/trade-tokenized/components/order-book.vue
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
<script lang='ts' setup>
|
||||||
|
import { client, safeClient } from "@/api";
|
||||||
|
|
||||||
|
const props = defineProps<{ symbol: string }>();
|
||||||
|
|
||||||
|
const { data } = await safeClient(client.api.trading_pairs.orderbook.get({ query: { symbol: props.symbol, depth: 30 } }));
|
||||||
|
|
||||||
|
// 计算买单和卖单的最大数量,用于计算占比
|
||||||
|
const maxBidAmount = computed(() => {
|
||||||
|
if (!data.value?.bids)
|
||||||
|
return 0;
|
||||||
|
return Math.max(...data.value.bids.map(item => Number(item[1])));
|
||||||
|
});
|
||||||
|
|
||||||
|
const maxAskAmount = computed(() => {
|
||||||
|
if (!data.value?.asks)
|
||||||
|
return 0;
|
||||||
|
return Math.max(...data.value.asks.map(item => Number(item[1])));
|
||||||
|
});
|
||||||
|
|
||||||
|
// 计算每个订单的占比百分比
|
||||||
|
function getBidPercentage(amount: string) {
|
||||||
|
const num = Number(amount);
|
||||||
|
return maxBidAmount.value > 0 ? (num / maxBidAmount.value) * 100 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAskPercentage(amount: string) {
|
||||||
|
const num = Number(amount);
|
||||||
|
return maxAskAmount.value > 0 ? (num / maxAskAmount.value) * 100 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化价格
|
||||||
|
function formatPrice(price: string) {
|
||||||
|
return Number(price).toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化数量
|
||||||
|
function formatAmount(amount: string) {
|
||||||
|
return Number(amount).toFixed(4);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="h-full w-full overflow-hidden bg-(--ion-background-color)">
|
||||||
|
<div class="grid h-full grid-cols-2 gap-0.5">
|
||||||
|
<!-- 买单区域 (Bids) -->
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<!-- 标题 -->
|
||||||
|
<div class="grid grid-cols-2 gap-2 border-b border-(--ion-border-color) px-3 py-2 text-xs text-(--ion-color-medium)">
|
||||||
|
<div class="text-left">
|
||||||
|
价格
|
||||||
|
</div>
|
||||||
|
<div class="text-right">
|
||||||
|
数量
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 买单列表 -->
|
||||||
|
<div class="flex-1 overflow-y-auto">
|
||||||
|
<div
|
||||||
|
v-for="(bid, index) in data?.bids"
|
||||||
|
:key="index"
|
||||||
|
class="relative grid grid-cols-2 gap-2 px-3 py-1 text-xs"
|
||||||
|
>
|
||||||
|
<!-- 背景色显示占比 -->
|
||||||
|
<div
|
||||||
|
class="absolute inset-y-0 right-0 bg-(--ion-color-success)/10"
|
||||||
|
:style="{ width: `${getBidPercentage(bid[1])}%` }"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 价格 -->
|
||||||
|
<div class="relative z-1 text-left text-(--ion-color-success)">
|
||||||
|
{{ formatPrice(bid[0]) }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 数量 -->
|
||||||
|
<div class="relative z-1 text-right text-(--ion-color-step-600)">
|
||||||
|
{{ formatAmount(bid[1]) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 卖单区域 (Asks) -->
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<!-- 标题 -->
|
||||||
|
<div class="grid grid-cols-2 gap-2 border-b border-(--ion-border-color) px-3 py-2 text-xs text-(--ion-color-medium)">
|
||||||
|
<div class="text-left">
|
||||||
|
价格
|
||||||
|
</div>
|
||||||
|
<div class="text-right">
|
||||||
|
数量
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 卖单列表 -->
|
||||||
|
<div class="flex-1 overflow-y-auto">
|
||||||
|
<div
|
||||||
|
v-for="(ask, index) in data?.asks"
|
||||||
|
:key="index"
|
||||||
|
class="relative grid grid-cols-2 gap-2 px-3 py-1 text-xs"
|
||||||
|
>
|
||||||
|
<!-- 背景色显示占比 -->
|
||||||
|
<div
|
||||||
|
class="absolute inset-y-0 right-0 bg-(--ion-color-danger)/10"
|
||||||
|
:style="{ width: `${getAskPercentage(ask[1])}%` }"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 价格 -->
|
||||||
|
<div class="relative z-1 text-left text-(--ion-color-danger)">
|
||||||
|
{{ formatPrice(ask[0]) }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 数量 -->
|
||||||
|
<div class="relative z-1 text-right text-(--ion-color-step-600)">
|
||||||
|
{{ formatAmount(ask[1]) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang='css' scoped></style>
|
||||||
@@ -1,19 +1,22 @@
|
|||||||
<script lang='ts' setup>
|
<script lang='ts' setup>
|
||||||
import type { TradableData } from "@/api/types";
|
|
||||||
import CryptocurrencyColorNuls from "~icons/cryptocurrency-color/nuls";
|
import CryptocurrencyColorNuls from "~icons/cryptocurrency-color/nuls";
|
||||||
|
import { client, safeClient } from "@/api";
|
||||||
import { TradeTypeEnum } from "@/api/enum";
|
import { TradeTypeEnum } from "@/api/enum";
|
||||||
import About from "./components/about.vue";
|
import About from "./components/about.vue";
|
||||||
import Base from "./components/base.vue";
|
import Base from "./components/base.vue";
|
||||||
|
import Market from "./components/market.vue";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
data: TradableData;
|
id: string;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const { data } = safeClient(client.api.rwa.tokenization.tradable_products({ id: props.id }).get());
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
function gotoTrade(mode: TradeTypeEnum) {
|
function gotoTrade(mode: TradeTypeEnum) {
|
||||||
router.push(`/layout/trade?mode=${mode}&symbol=${props.data.asset?.tradingPairsAsBase[0].symbol}`);
|
router.push(`/layout/trade?mode=${mode}&symbol=${data.value?.asset?.tradingPairsAsBase[0].symbol}`);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -50,6 +53,9 @@ function gotoTrade(mode: TradeTypeEnum) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ui-tabs size="small" class="my-3">
|
<ui-tabs size="small" class="my-3">
|
||||||
|
<ui-tab-pane name="market" title="行情">
|
||||||
|
<Market :data="data" />
|
||||||
|
</ui-tab-pane>
|
||||||
<ui-tab-pane name="overview" :title="t('market.tradeRwa.tabs.overview')">
|
<ui-tab-pane name="overview" :title="t('market.tradeRwa.tabs.overview')">
|
||||||
<Base :data="data" />
|
<Base :data="data" />
|
||||||
</ui-tab-pane>
|
</ui-tab-pane>
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
<script lang='ts' setup>
|
|
||||||
import { client, safeClient } from "@/api";
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
id: string;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const { data } = safeClient(client.api.rwa.tokenization.tradable_products({ id: props.id }).get());
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<ion-page>
|
|
||||||
<ion-header>
|
|
||||||
<ion-toolbar class="ion-toolbar">
|
|
||||||
<ui-back-button slot="start" />
|
|
||||||
<ion-title>
|
|
||||||
{{ data?.product?.code }}
|
|
||||||
</ion-title>
|
|
||||||
</ion-toolbar>
|
|
||||||
</ion-header>
|
|
||||||
<ion-content :fullscreen="true" class="ion-padding">
|
|
||||||
<RouterView :data="data" />
|
|
||||||
</ion-content>
|
|
||||||
</ion-page>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
||||||
@@ -7,10 +7,12 @@ import { orderStatusMap } from "../config";
|
|||||||
type Item = Treaty.Data<typeof client.api.spot_order.list.get>["orders"][number];
|
type Item = Treaty.Data<typeof client.api.spot_order.list.get>["orders"][number];
|
||||||
type TabType = "current" | "history";
|
type TabType = "current" | "history";
|
||||||
|
|
||||||
|
const props = defineProps<{ symbol: string }>();
|
||||||
|
|
||||||
const activeTab = ref<TabType>("current");
|
const activeTab = ref<TabType>("current");
|
||||||
const [DefineTemplate, ReuseTemplate] = createReusableTemplate<{ item: Item }>();
|
const [DefineTemplate, ReuseTemplate] = createReusableTemplate<{ item: Item }>();
|
||||||
|
|
||||||
const { data } = await safeClient(client.api.spot_order.list.get());
|
const { data } = await safeClient(client.api.spot_order.list.get({ query: { symbol: props.symbol } }));
|
||||||
const currentOrders = computed(() =>
|
const currentOrders = computed(() =>
|
||||||
data.value?.orders.filter(order => order.status !== "filled" && order.status !== "cancelled") || [],
|
data.value?.orders.filter(order => order.status !== "filled" && order.status !== "cancelled") || [],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ async function handleSubmit() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-6 px-4 pb-4">
|
<div class="mt-6 px-4 pb-4">
|
||||||
<OrdersPanel />
|
<OrdersPanel :symbol="form.symbol" />
|
||||||
</div>
|
</div>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
</ion-page>
|
</ion-page>
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ async function handleScan() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
console.log("扫描结果:", result.text);
|
console.log("扫描结果:", result);
|
||||||
// TODO: 根据扫描结果进行相应处理
|
// TODO: 根据扫描结果进行相应处理
|
||||||
// 例如:跳转到对应页面、显示信息等
|
// 例如:跳转到对应页面、显示信息等
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user