feat: 添加收益模块,包含总收益概览、收益趋势和收益来源,更新相关组件和路由

This commit is contained in:
2025-12-27 19:55:45 +07:00
parent 0ffd8566c8
commit 4a3de581d8
23 changed files with 458 additions and 72 deletions

5
auto-imports.d.ts vendored
View File

@@ -41,7 +41,7 @@ declare global {
const effectScope: typeof import('vue').effectScope
const emailPattern: typeof import('./src/utils/pattern').emailPattern
const extendRef: typeof import('@vueuse/core').extendRef
const formatAmount: typeof import('./src/utils/helper').formatAmount
const formatAmountWithSplit: typeof import('./src/utils/helper').formatAmountWithSplit
const formatAmountWithUnit: typeof import('./src/utils/helper').formatAmountWithUnit
const formatBalance: typeof import('./src/utils/helper').formatBalance
const getActivePinia: typeof import('pinia').getActivePinia
@@ -405,7 +405,8 @@ declare module 'vue' {
readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
readonly emailPattern: UnwrapRef<typeof import('./src/utils/pattern')['emailPattern']>
readonly extendRef: UnwrapRef<typeof import('@vueuse/core')['extendRef']>
readonly formatAmount: UnwrapRef<typeof import('./src/utils/helper')['formatAmount']>
readonly formatAmountWithSplit: UnwrapRef<typeof import('./src/utils/helper')['formatAmountWithSplit']>
readonly formatAmountWithUnit: UnwrapRef<typeof import('./src/utils/helper')['formatAmountWithUnit']>
readonly formatBalance: UnwrapRef<typeof import('./src/utils/helper')['formatBalance']>
readonly getActivePinia: UnwrapRef<typeof import('pinia')['getActivePinia']>
readonly getCacheRemainingTime: UnwrapRef<typeof import('./src/composables/useStorageCache')['getCacheRemainingTime']>

6
components.d.ts vendored
View File

@@ -39,6 +39,9 @@ declare module 'vue' {
IonLabel: typeof import('@ionic/vue')['IonLabel']
IonList: typeof import('@ionic/vue')['IonList']
IonListHeader: typeof import('@ionic/vue')['IonListHeader']
IonMenu: typeof import('@ionic/vue')['IonMenu']
IonMenuButton: typeof import('@ionic/vue')['IonMenuButton']
IonMenuToggle: typeof import('@ionic/vue')['IonMenuToggle']
IonModal: typeof import('@ionic/vue')['IonModal']
IonNote: typeof import('@ionic/vue')['IonNote']
IonPage: typeof import('@ionic/vue')['IonPage']
@@ -97,6 +100,9 @@ declare global {
const IonLabel: typeof import('@ionic/vue')['IonLabel']
const IonList: typeof import('@ionic/vue')['IonList']
const IonListHeader: typeof import('@ionic/vue')['IonListHeader']
const IonMenu: typeof import('@ionic/vue')['IonMenu']
const IonMenuButton: typeof import('@ionic/vue')['IonMenuButton']
const IonMenuToggle: typeof import('@ionic/vue')['IonMenuToggle']
const IonModal: typeof import('@ionic/vue')['IonModal']
const IonNote: typeof import('@ionic/vue')['IonNote']
const IonPage: typeof import('@ionic/vue')['IonPage']

View File

@@ -33,7 +33,7 @@
"@elysiajs/eden": "^1.4.5",
"@ionic/vue": "^8.7.11",
"@ionic/vue-router": "^8.7.11",
"@riwa/api-types": "http://192.168.1.27:9527/api/riwa-api-types-0.0.64.tgz",
"@riwa/api-types": "http://192.168.1.27:9527/api/riwa-api-types-0.0.67.tgz",
"@tailwindcss/vite": "^4.1.18",
"@vee-validate/yup": "^4.15.1",
"@vueuse/core": "^14.1.0",

12
pnpm-lock.yaml generated
View File

@@ -57,8 +57,8 @@ importers:
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))
'@riwa/api-types':
specifier: http://192.168.1.27:9527/api/riwa-api-types-0.0.64.tgz
version: http://192.168.1.27:9527/api/riwa-api-types-0.0.64.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)))
specifier: http://192.168.1.27:9527/api/riwa-api-types-0.0.67.tgz
version: http://192.168.1.27:9527/api/riwa-api-types-0.0.67.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':
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))
@@ -1401,9 +1401,9 @@ packages:
resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==}
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
'@riwa/api-types@http://192.168.1.27:9527/api/riwa-api-types-0.0.64.tgz':
resolution: {tarball: http://192.168.1.27:9527/api/riwa-api-types-0.0.64.tgz}
version: 0.0.64
'@riwa/api-types@http://192.168.1.27:9527/api/riwa-api-types-0.0.67.tgz':
resolution: {tarball: http://192.168.1.27:9527/api/riwa-api-types-0.0.67.tgz}
version: 0.0.67
peerDependencies:
'@elysiajs/eden': ^1.4.5
@@ -6644,7 +6644,7 @@ snapshots:
'@pkgr/core@0.2.9': {}
'@riwa/api-types@http://192.168.1.27:9527/api/riwa-api-types-0.0.64.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/api-types@http://192.168.1.27:9527/api/riwa-api-types-0.0.67.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:
'@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))

View File

@@ -1,12 +1,12 @@
import type { Awaitable } from "@vueuse/core";
import type { ChartOptions, DeepPartial, IChartApi, ISeriesApi, LayoutOptions, OhlcData, SeriesType } from "lightweight-charts";
import type { ChartOptions, DeepPartial, IChartApi, ISeriesApi, LayoutOptions, OhlcData, SeriesDataItemTypeMap, SeriesType } from "lightweight-charts";
import type { ThemeMode } from "./useTheme";
import { AreaSeries, BarSeries, BaselineSeries, CandlestickSeries, ColorType, createChart, HistogramSeries, LineSeries } from "lightweight-charts";
import { mergeWith } from "lodash-es";
export type Series = "Area" | "Bar" | "Baseline" | "Candlestick" | "Histogram" | "Line";
export type TData = OhlcData;
export type TData = SeriesDataItemTypeMap[SeriesType];
export type WeightChartOptions = DeepPartial<ChartOptions>;

View File

@@ -241,6 +241,44 @@
"revenueDetails": "Revenue Details"
}
},
"income": {
"title": "Total Revenue",
"overview": {
"totalRevenue": "Total Revenue",
"yesterdayRevenue": "Yesterday's Revenue",
"monthRevenue": "This Month",
"pendingRevenue": "Pending Revenue"
},
"trend": {
"title": "Revenue Trend",
"last7Days": "Last 7 Days",
"last30Days": "Last 30 Days",
"last90Days": "Last 90 Days"
},
"sources": {
"title": "Revenue Sources",
"dividend": "Dividend",
"appreciation": "Appreciation",
"trade": "Trading"
},
"records": {
"title": "Revenue Records",
"all": "All",
"recent": "Recent Records",
"viewAll": "View All",
"assetName": "Asset Name",
"type": "Type",
"amount": "Amount",
"date": "Date",
"status": "Status",
"noData": "No revenue records"
},
"status": {
"completed": "Completed",
"pending": "Pending",
"processing": "Processing"
}
},
"myIssues": {
"title": "My Issuance Applications",
"search": "Search",
@@ -317,7 +355,10 @@
"common": {
"failedSendCode": "Failed to send verification code",
"uploadFile": "Upload File",
"files": "files"
"files": "files",
"today": "Today",
"yesterday": "Yesterday",
"items": "items"
},
"auth": {
"login": {

View File

@@ -247,6 +247,44 @@
"revenueDetails": "收益明细"
}
},
"income": {
"title": "总收益",
"overview": {
"totalRevenue": "累计总收益",
"yesterdayRevenue": "昨日收益",
"monthRevenue": "本月收益",
"pendingRevenue": "待确认收益"
},
"trend": {
"title": "收益趋势",
"last7Days": "最近7天",
"last30Days": "最近30天",
"last90Days": "最近90天"
},
"sources": {
"title": "收益来源",
"dividend": "分红收益",
"appreciation": "资产增值",
"trade": "交易收益"
},
"records": {
"title": "收益明细",
"all": "全部",
"recent": "最近记录",
"viewAll": "查看全部",
"assetName": "资产名称",
"type": "类型",
"amount": "金额",
"date": "日期",
"status": "状态",
"noData": "暂无收益记录"
},
"status": {
"completed": "已完成",
"pending": "待确认",
"processing": "处理中"
}
},
"myIssues": {
"title": "我的发行申请",
"search": "搜索",
@@ -323,7 +361,10 @@
"common": {
"failedSendCode": "发送验证码失败",
"uploadFile": "上传文件",
"files": "个文件"
"files": "个文件",
"today": "今天",
"yesterday": "昨天",
"items": "项"
},
"auth": {
"login": {

129
src/mocks/data/income.ts Normal file
View File

@@ -0,0 +1,129 @@
import { useMocks } from "../index";
const mocks = useMocks();
// 总收益 Mock 数据
mocks.register("income/total", () => {
return {
// 总收益概览
overview: {
totalRevenue: 125680.50, // 累计总收益
yesterdayRevenue: 1256.80, // 昨日收益
monthRevenue: 38450.20, // 本月收益
pendingRevenue: 5420.30, // 待确认收益
currency: "USD",
},
// 收益趋势数据最近7天
trend: [
{ date: "2025-12-21", revenue: 1100.50 },
{ date: "2025-12-22", revenue: 1300.80 },
{ date: "2025-12-23", revenue: 1450.20 },
{ date: "2025-12-24", revenue: 1200.60 },
{ date: "2025-12-25", revenue: 1350.90 },
{ date: "2025-12-26", revenue: 1380.40 },
{ date: "2025-12-27", revenue: 1256.80 },
],
// 收益来源分布
sources: [
{
type: "dividend", // 分红收益
name: "分红收益",
amount: 85420.30,
percentage: 67.96,
count: 125,
},
{
type: "appreciation", // 资产增值
name: "资产增值",
amount: 32150.20,
percentage: 25.59,
count: 45,
},
{
type: "trade", // 交易收益
name: "交易收益",
amount: 8110.00,
percentage: 6.45,
count: 89,
},
],
// 最近收益明细
recentRecords: [
{
id: "1",
type: "dividend",
typeName: "分红收益",
assetName: "纽约曼哈顿中心公寓",
assetCode: "NYC-001",
amount: 520.50,
currency: "USD",
date: "2025-12-27 10:30:00",
status: "completed", // completed, pending, processing
},
{
id: "2",
type: "appreciation",
typeName: "资产增值",
assetName: "旧金山商业地产",
assetCode: "SF-002",
amount: 320.80,
currency: "USD",
date: "2025-12-27 09:15:00",
status: "completed",
},
{
id: "3",
type: "trade",
typeName: "交易收益",
assetName: "洛杉矶住宅楼",
assetCode: "LA-003",
amount: 215.50,
currency: "USD",
date: "2025-12-26 16:45:00",
status: "completed",
},
{
id: "4",
type: "dividend",
typeName: "分红收益",
assetName: "迈阿密海景别墅",
assetCode: "MIA-004",
amount: 680.20,
currency: "USD",
date: "2025-12-26 14:20:00",
status: "pending",
},
{
id: "5",
type: "appreciation",
typeName: "资产增值",
assetName: "芝加哥写字楼",
assetCode: "CHI-005",
amount: 450.60,
currency: "USD",
date: "2025-12-25 11:30:00",
status: "completed",
},
],
};
});
// 收益明细列表(支持筛选)
mocks.register("income/records", () => {
return {
list: Array.from({ length: 20 }, (_, index) => ({
id: String(index + 1),
type: ["dividend", "appreciation", "trade"][index % 3],
typeName: ["分红收益", "资产增值", "交易收益"][index % 3],
assetName: `资产名称 ${index + 1}`,
assetCode: `ASSET-${String(index + 1).padStart(3, "0")}`,
amount: (Math.random() * 1000 + 100).toFixed(2),
currency: "USD",
date: new Date(Date.now() - index * 86400000).toISOString(),
status: ["completed", "pending", "processing"][index % 3],
})),
total: 100,
page: 1,
pageSize: 20,
};
});

View File

@@ -1 +1,2 @@
import "./notify";
import "./income";

View File

@@ -59,6 +59,11 @@ const routes: Array<RouteRecordRaw> = [
component: () => import("@/views/withdraw/index.vue"),
meta: { requiresAuth: true },
},
{
path: "/income/total",
component: () => import("@/views/income/total/index.vue"),
meta: { requiresAuth: true },
},
{
path: "/wallet/bill",
component: () => import("@/views/wallet/bill.vue"),
@@ -135,12 +140,12 @@ const routes: Array<RouteRecordRaw> = [
component: () => import("@/views/trade-settings/my-subscribe/index.vue"),
meta: { requiresAuth: true },
},
// {
// path: ":id",
// props: true,
// component: () => import("@/views/trade-settings/my-subscribe/detail.vue"),
// meta: { requiresAuth: true },
// },
{
path: ":id",
props: true,
component: () => import("@/views/trade-settings/my-subscribe/detail.vue"),
meta: { requiresAuth: true },
},
],
},
{

View File

@@ -23,9 +23,9 @@ html.ion-palette-light {
--ion-color-tertiary-tint: #757575;
--ion-color-success: #2c810e;
--ion-color-success-rgb: 44,129,14;
--ion-color-success-rgb: 44, 129, 14;
--ion-color-success-contrast: #ffffff;
--ion-color-success-contrast-rgb: 255,255,255;
--ion-color-success-contrast-rgb: 255, 255, 255;
--ion-color-success-shade: #27720c;
--ion-color-success-tint: #418e26;
@@ -143,9 +143,9 @@ html.ion-palette-dark {
--ion-color-tertiary-tint: #dadada;
--ion-color-success: #2c810e;
--ion-color-success-rgb: 44,129,14;
--ion-color-success-rgb: 44, 129, 14;
--ion-color-success-contrast: #ffffff;
--ion-color-success-contrast-rgb: 255,255,255;
--ion-color-success-contrast-rgb: 255, 255, 255;
--ion-color-success-shade: #27720c;
--ion-color-success-tint: #418e26;

View File

@@ -15,7 +15,7 @@ export function timeToLocal(originalTime: number) {
return Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds()) / 1000;
}
export function formatAmount(amount: MaybeRefOrGetter<number | string | null | undefined>): string {
export function formatAmountWithUnit(amount: MaybeRefOrGetter<number | string | null | undefined>): string {
const value = toValue(amount);
if (Number.isNaN(Number(value))) {
return "0";
@@ -24,21 +24,37 @@ export function formatAmount(amount: MaybeRefOrGetter<number | string | null | u
const num = Number(value);
// 不超过1万原样显示
if (num < 10000) {
if (num < 1e4) {
return String(num);
}
// 1亿以上显示为xx亿
if (num >= 100000000) {
const yi = (num / 100000000).toFixed(1);
if (num >= 1e8) {
const yi = (num / 1e8).toFixed(1);
return yi.endsWith(".0") ? `${Number.parseInt(yi)}亿` : `${yi}亿`;
}
// 1万到1亿显示为xx万
if (num >= 10000) {
const wan = (num / 10000).toFixed(1);
if (num >= 1e4) {
const wan = (num / 1e4).toFixed(1);
return wan.endsWith(".0") ? `${Number.parseInt(wan)}` : `${wan}`;
}
return String(num);
}
export function formatAmountWithSplit(amount: MaybeRefOrGetter<number | string | null | undefined>): string {
const value = toValue(amount);
if (Number.isNaN(Number(value))) {
return "0";
}
const num = Number(value);
return Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}).format(num);
}

View File

@@ -0,0 +1,41 @@
<script lang='ts' setup>
</script>
<template>
<div class="bg-text-900 rounded-xl p-7">
<div>
<div class="text-sm mb-2">
累计总收益
</div>
<div class="text-4xl font-bold">
{{ formatAmountWithSplit(190421321) }}
</div>
<div class="flex items-center gap-2 text-xs mt-1">
<div>昨日收益</div>
<div>+{{ formatAmountWithSplit(864314) }}</div>
</div>
</div>
<div class="h-px bg-text-800 my-5" />
<div class="flex justify-around">
<div class="flex-col-center">
<div class="text-base font-bold">
{{ formatAmountWithSplit(42523) }}
</div>
<div class="text-xs">
本月收益
</div>
</div>
<div class="h-auto w-px bg-text-800" />
<div class="flex-col-center">
<div class="text-base font-bold">
{{ formatAmountWithSplit(12345) }}
</div>
<div class="text-xs">
待确认收益
</div>
</div>
</div>
</div>
</template>
<style lang='css' scoped></style>

View File

@@ -0,0 +1,59 @@
<script lang='ts' setup>
const tradingViewInst = useTemplateRef<HTMLDivElement>("tradingViewInst");
useTradingView(tradingViewInst, {
type: "Area",
data: [
{
time: "2023-01-01",
value: 1000,
},
{
time: "2023-02-01",
value: 1200,
},
{
time: "2023-03-01",
value: 900,
},
{
time: "2023-04-01",
value: 1400,
},
{
time: "2023-05-01",
value: 1300,
},
{
time: "2023-06-01",
value: 1500,
},
{
time: "2023-07-01",
value: 1700,
},
{
time: "2023-08-01",
value: 1600,
},
],
weightChartOptions: {
height: 150,
rightPriceScale: {
visible: false,
},
leftPriceScale: {
visible: false,
},
},
});
</script>
<template>
<div>
<h4>收益趋势</h4>
<div ref="tradingViewInst" />
</div>
</template>
<style lang='css' scoped></style>

View File

@@ -0,0 +1,53 @@
<script lang='ts' setup>
import type { RefresherCustomEvent } from "@ionic/vue";
import { mockClient } from "@/api";
import Overview from "./components/overview.vue";
import Trend from "./components/trend.vue";
const { t } = useI18n();
const { vibrate } = useHaptics();
// 收益数据
const loading = ref(true);
const { data } = await mockClient("income/total");
async function loadIncomeData() {
loading.value = true;
useTimeoutFn(() => {
loading.value = false;
}, 800);
}
async function handleRefresh(event: RefresherCustomEvent) {
vibrate();
useTimeoutFn(() => {
event.target.complete();
}, 800);
}
onMounted(() => {
loadIncomeData();
});
</script>
<template>
<ion-page>
<ion-header class="ion-no-border">
<ion-toolbar class="ui-toolbar">
<ion-back-button slot="start" />
<ion-title>{{ t("income.title") }}</ion-title>
</ion-toolbar>
</ion-header>
<ion-content :fullscreen="true" class="ion-padding">
<ion-refresher slot="fixed" @ion-refresh="handleRefresh($event)">
<ion-refresher-content />
</ion-refresher>
<div>
<Overview />
<Trend />
</div>
</ion-content>
</ion-page>
</template>

View File

@@ -33,7 +33,7 @@ const { t } = useI18n();
<div class="label">
{{ t('market.tradeRwa.fields.valuation') }}
</div>
<div>${{ formatAmount(data?.product.estimatedValue) }}</div>
<div>${{ formatAmountWithUnit(data?.product.estimatedValue) }}</div>
</ion-col>
</ion-row>
<ion-row>
@@ -41,7 +41,7 @@ const { t } = useI18n();
<div class="label">
{{ t('market.tradeRwa.fields.unitPrice') }}
</div>
<div>${{ formatAmount(data?.unitPrice) }}</div>
<div>${{ formatAmountWithUnit(data?.unitPrice) }}</div>
</ion-col>
<ion-col>
<div class="label">

View File

@@ -126,7 +126,7 @@ onUpdated(() => {
</p>
<ion-button
expand="block"
color="success"
fill="outline"
@click="handleAddCard"
>
<ion-icon slot="start" :icon="addOutline" />

View File

@@ -33,7 +33,7 @@ const { t } = useI18n();
<div class="label">
{{ t('market.tradeRwa.fields.valuation') }}
</div>
<div>${{ formatAmount(data?.estimatedValue) }}</div>
<div>${{ formatAmountWithUnit(data?.estimatedValue) }}</div>
</ion-col>
</ion-row>
</ion-grid>

View File

@@ -28,16 +28,13 @@ async function handleSubscribe(val: number) {
await toast.present();
model.value?.$el.dismiss();
}
function gotoEdit() {
router.push({ name: "trade-rwa-edit" });
}
</script>
<template>
<ion-page>
<ion-header>
<ion-toolbar class="ui-toolbar">
<ion-back-button slot="start" text="" />
<ion-back-button slot="start" />
<ion-title>
{{ data?.edition.product.code }}
</ion-title>
@@ -53,7 +50,7 @@ function gotoEdit() {
{{ data?.edition.product.name }}
</div>
<div class="text-xs text-gray-500 font-semibold">
{{ data?.edition.product.categoryId }}
{{ data?.edition.product.code }}
</div>
</div>
</div>

View File

@@ -3,13 +3,7 @@
<template>
<ion-page>
<ion-header>
<ion-toolbar class="ui-toolbar">
<ion-back-button slot="start" />
<ion-title>我的申购</ion-title>
</ion-toolbar>
</ion-header>
<router-view />
<ion-router-outlet />
</ion-page>
</template>

View File

@@ -2,6 +2,13 @@
import { calendarOutline, listOutline, timeOutline, walletOutline } from "ionicons/icons";
const { t } = useI18n();
const router = useRouter();
const { vibrate } = useHaptics();
function navigateToTotal() {
vibrate();
router.push("/income/total");
}
</script>
<template>
@@ -10,26 +17,29 @@ const { t } = useI18n();
{{ t("asset.revenue.myRevenue") }}
</ion-label>
<div class="grid grid-cols-4 mt-5">
<div class="col-span-1 flex-col-center gap-2">
<ion-icon :icon="walletOutline" />
<div
class="col-span-1 flex flex-col items-center gap-2 cursor-pointer transition-opacity active:opacity-70"
@click="navigateToTotal"
>
<ion-icon :icon="walletOutline" class="text-2xl text-primary" />
<div class="text-xs">
{{ t("asset.revenue.totalRevenue") }}
</div>
</div>
<div class="col-span-1 flex-col-center gap-2">
<ion-icon :icon="calendarOutline" />
<div class="col-span-1 flex flex-col items-center gap-2 cursor-pointer transition-opacity active:opacity-70">
<ion-icon :icon="calendarOutline" class="text-2xl text-primary" />
<div class="text-xs">
{{ t("asset.revenue.monthlyRevenue") }}
</div>
</div>
<div class="col-span-1 flex-col-center gap-2">
<ion-icon :icon="timeOutline" />
<div class="col-span-1 flex flex-col items-center gap-2 cursor-pointer transition-opacity active:opacity-70">
<ion-icon :icon="timeOutline" class="text-2xl text-primary" />
<div class="text-xs">
{{ t("asset.revenue.pendingRevenue") }}
</div>
</div>
<div class="col-span-1 flex-col-center gap-2">
<ion-icon :icon="listOutline" />
<div class="col-span-1 flex flex-col items-center gap-2 cursor-pointer transition-opacity active:opacity-70">
<ion-icon :icon="listOutline" class="text-2xl text-primary" />
<div class="text-xs">
{{ t("asset.revenue.revenueDetails") }}
</div>
@@ -37,10 +47,3 @@ const { t } = useI18n();
</div>
</div>
</template>
<style lang='css' scoped>
ion-icon {
font-size: 1.5rem;
color: var(--ion-color-primary);
}
</style>

View File

@@ -39,7 +39,7 @@ async function handleScan() {
</script>
<template>
<IonPage>
<ion-page>
<ion-header class="ion-no-border">
<ion-toolbar class="ui-toolbar">
<div slot="end">
@@ -55,7 +55,7 @@ async function handleScan() {
</div>
</ion-toolbar>
</ion-header>
<IonContent :fullscreen="true" class="ion-padding">
<ion-content :fullscreen="true" class="ion-padding">
<ion-refresher slot="fixed" @ion-refresh="handleRefresh($event)">
<ion-refresher-content />
</ion-refresher>
@@ -68,8 +68,8 @@ async function handleScan() {
<MyRevenue />
<TradeSettings />
</div>
</IonContent>
</IonPage>
</ion-content>
</ion-page>
</template>
<style scoped></style>

View File

@@ -4,7 +4,6 @@ low float Y 最低价
close float Y 收盘价
settle float Y 结算价 每一个纬度(某一个时间段之内的金额总和 / 交易量)
接口
代币化分类接口
代币化列表接口