From 0bccd85744a581e92b4a00a288da4a791694bd94 Mon Sep 17 00:00:00 2001 From: Seven Date: Fri, 19 Dec 2025 18:01:21 +0700 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0=E7=8E=AF=E5=A2=83?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=EF=BC=8C=E4=BF=AE=E6=94=B9=20API=20=E5=9C=B0?= =?UTF-8?q?=E5=9D=80=EF=BC=8C=E6=B7=BB=E5=8A=A0=E6=A0=BC=E5=BC=8F=E5=8C=96?= =?UTF-8?q?=E9=87=91=E9=A2=9D=E5=8A=9F=E8=83=BD=EF=BC=8C=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20RWA=20=E4=BA=A4=E6=98=93=E8=A7=86=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.development | 2 +- .env.production | 2 +- auto-imports.d.ts | 3 + components.d.ts | 10 +++ package.json | 3 +- pnpm-lock.yaml | 86 ++++++++++++++++++++-- src/api/index.ts | 21 ++---- src/main.ts | 4 +- src/utils/helper.ts | 28 ++++++++ src/views/market/components/rwa-list.vue | 2 +- src/views/trade-rwa/index.vue | 90 +++++++++++++++++++++--- 11 files changed, 215 insertions(+), 36 deletions(-) diff --git a/.env.development b/.env.development index 72038a4..5df7f72 100644 --- a/.env.development +++ b/.env.development @@ -1 +1 @@ -VITE_API_URL=http://192.168.1.33:9528 \ No newline at end of file +VITE_API_URL=http://192.168.1.22:9528 \ No newline at end of file diff --git a/.env.production b/.env.production index 240ca57..652f4c5 100644 --- a/.env.production +++ b/.env.production @@ -1 +1 @@ -VITE_API_URL=http://192.168.1.33:9527 \ No newline at end of file +VITE_API_URL=http://192.168.1.22:9527 \ No newline at end of file diff --git a/auto-imports.d.ts b/auto-imports.d.ts index e54fa92..7091ad3 100644 --- a/auto-imports.d.ts +++ b/auto-imports.d.ts @@ -38,6 +38,8 @@ 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 formatAmountWithUnit: typeof import('./src/utils/helper').formatAmountWithUnit const formatBalance: typeof import('./src/utils/helper').formatBalance const getActivePinia: typeof import('pinia').getActivePinia const getCurrentInstance: typeof import('vue').getCurrentInstance @@ -378,6 +380,7 @@ declare module 'vue' { readonly effectScope: UnwrapRef readonly emailPattern: UnwrapRef readonly extendRef: UnwrapRef + readonly formatAmount: UnwrapRef readonly formatBalance: UnwrapRef readonly getActivePinia: UnwrapRef readonly getCurrentInstance: UnwrapRef diff --git a/components.d.ts b/components.d.ts index e242fd9..7ab223f 100644 --- a/components.d.ts +++ b/components.d.ts @@ -20,6 +20,11 @@ declare module 'vue' { IonBackButton: typeof import('@ionic/vue')['IonBackButton'] IonButton: typeof import('@ionic/vue')['IonButton'] IonButtons: typeof import('@ionic/vue')['IonButtons'] + IonCard: typeof import('@ionic/vue')['IonCard'] + IonCardContent: typeof import('@ionic/vue')['IonCardContent'] + IonCardHeader: typeof import('@ionic/vue')['IonCardHeader'] + IonCardSubtitle: typeof import('@ionic/vue')['IonCardSubtitle'] + IonCardTitle: typeof import('@ionic/vue')['IonCardTitle'] IonCol: typeof import('@ionic/vue')['IonCol'] IonContent: typeof import('@ionic/vue')['IonContent'] IonDatetime: typeof import('@ionic/vue')['IonDatetime'] @@ -78,6 +83,11 @@ declare global { const IonBackButton: typeof import('@ionic/vue')['IonBackButton'] const IonButton: typeof import('@ionic/vue')['IonButton'] const IonButtons: typeof import('@ionic/vue')['IonButtons'] + const IonCard: typeof import('@ionic/vue')['IonCard'] + const IonCardContent: typeof import('@ionic/vue')['IonCardContent'] + const IonCardHeader: typeof import('@ionic/vue')['IonCardHeader'] + const IonCardSubtitle: typeof import('@ionic/vue')['IonCardSubtitle'] + const IonCardTitle: typeof import('@ionic/vue')['IonCardTitle'] const IonCol: typeof import('@ionic/vue')['IonCol'] const IonContent: typeof import('@ionic/vue')['IonContent'] const IonDatetime: typeof import('@ionic/vue')['IonDatetime'] diff --git a/package.json b/package.json index 5160cf3..45982ad 100644 --- a/package.json +++ b/package.json @@ -29,12 +29,13 @@ "@elysiajs/eden": "^1.4.5", "@ionic/vue": "^8.7.11", "@ionic/vue-router": "^8.7.11", - "@riwa/api-types": "http://192.168.1.33:9527/api/riwa-api-types-0.0.30.tgz", + "@riwa/api-types": "http://192.168.1.33:9527/api/riwa-api-types-0.0.35.tgz", "@tailwindcss/vite": "^4.1.18", "@vee-validate/yup": "^4.15.1", "@vueuse/core": "^14.1.0", "@vueuse/router": "^14.1.0", "better-auth": "^1.4.6", + "ethers": "^6.16.0", "ionicons": "^8.0.13", "lightweight-charts": "^5.1.0", "lodash-es": "^4.17.21", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1ce2856..881bd6c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -45,8 +45,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.33:9527/api/riwa-api-types-0.0.30.tgz - version: http://192.168.1.33:9527/api/riwa-api-types-0.0.30.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.33:9527/api/riwa-api-types-0.0.35.tgz + version: http://192.168.1.33:9527/api/riwa-api-types-0.0.35.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)) @@ -62,6 +62,9 @@ importers: better-auth: specifier: ^1.4.6 version: 1.4.6(vue@3.5.25(typescript@5.9.3)) + ethers: + specifier: ^6.16.0 + version: 6.16.0 ionicons: specifier: ^8.0.13 version: 8.0.13 @@ -189,6 +192,9 @@ packages: '@acemir/cssom@0.9.28': resolution: {integrity: sha512-LuS6IVEivI75vKN8S04qRD+YySP0RmU/cV8UNukhQZvprxF+76Z43TNo/a08eCodaGhT1Us8etqS1ZRY9/Or0A==} + '@adraffy/ens-normalize@1.10.1': + resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==} + '@antfu/eslint-config@6.6.1': resolution: {integrity: sha512-ZOdoVhZHu1FMOYJcqPNyFvkoRlfI1qnaMUxQuB3C0MbamgkpOsuKtWQlcqDTeVDEUiXnfcE/XpFP+ZOQDS6I3A==} hasBin: true @@ -1264,6 +1270,13 @@ packages: resolution: {integrity: sha512-bysYuiVfhxNJuldNXlFEitTVdNnYUc+XNJZd7Qm2a5j1vZHgY+fazadNFWFaMK/2vye0JVlxV3gHmC0WDfAOQw==} engines: {node: '>= 20.19.0'} + '@noble/curves@1.2.0': + resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==} + + '@noble/hashes@1.3.2': + resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} + engines: {node: '>= 16'} + '@noble/hashes@1.8.0': resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} engines: {node: ^14.21.3 || >=16} @@ -1302,9 +1315,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.33:9527/api/riwa-api-types-0.0.30.tgz': - resolution: {tarball: http://192.168.1.33:9527/api/riwa-api-types-0.0.30.tgz} - version: 0.0.30 + '@riwa/api-types@http://192.168.1.33:9527/api/riwa-api-types-0.0.35.tgz': + resolution: {tarball: http://192.168.1.33:9527/api/riwa-api-types-0.0.35.tgz} + version: 0.0.35 peerDependencies: '@elysiajs/eden': ^1.4.5 @@ -1629,6 +1642,9 @@ packages: '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + '@types/node@22.7.5': + resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==} + '@types/node@24.10.2': resolution: {integrity: sha512-WOhQTZ4G8xZ1tjJTvKOpyEVSGgOTvJAfDK3FNFgELyaTpzhdgHVHeqW8V+UJvzF5BT+/B54T/1S2K6gd9c7bbA==} @@ -1917,6 +1933,9 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + aes-js@4.0.0-beta.5: + resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==} + agent-base@7.1.4: resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} engines: {node: '>= 14'} @@ -2790,6 +2809,10 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} + ethers@6.16.0: + resolution: {integrity: sha512-U1wulmetNymijEhpSEQ7Ct/P/Jw9/e7R1j5XIbPRydgV2DjLVMsULDlNksq3RQnFgKoLlZf88ijYtWEXcPa07A==} + engines: {node: '>=14.0.0'} + eventemitter2@6.4.7: resolution: {integrity: sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==} @@ -4538,6 +4561,9 @@ packages: tslib@1.14.1: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + tslib@2.7.0: + resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -4592,6 +4618,9 @@ packages: unctx@2.4.1: resolution: {integrity: sha512-AbaYw0Nm4mK4qjhns67C+kgxR2YWiwlDBPzxrN8h8C6VtAdCgditAY5Dezu3IJy4XVqAnbrXt9oQJvsn3fyozg==} + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} @@ -4894,6 +4923,18 @@ packages: write-file-atomic@3.0.3: resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} + ws@8.17.1: + resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + ws@8.18.3: resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} engines: {node: '>=10.0.0'} @@ -4964,6 +5005,8 @@ snapshots: '@acemir/cssom@0.9.28': {} + '@adraffy/ens-normalize@1.10.1': {} + '@antfu/eslint-config@6.6.1(@vue/compiler-sfc@3.5.25)(eslint-plugin-format@1.1.0(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)(vitest@4.0.15(@types/node@24.10.2)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))': dependencies: '@antfu/install-pkg': 1.1.0 @@ -6288,6 +6331,12 @@ snapshots: '@noble/ciphers@2.1.1': {} + '@noble/curves@1.2.0': + dependencies: + '@noble/hashes': 1.3.2 + + '@noble/hashes@1.3.2': {} + '@noble/hashes@1.8.0': {} '@noble/hashes@2.0.1': {} @@ -6341,7 +6390,7 @@ snapshots: '@pkgr/core@0.2.9': {} - '@riwa/api-types@http://192.168.1.33:9527/api/riwa-api-types-0.0.30.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.33:9527/api/riwa-api-types-0.0.35.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)) @@ -6592,6 +6641,10 @@ snapshots: '@types/ms@2.1.0': {} + '@types/node@22.7.5': + dependencies: + undici-types: 6.19.8 + '@types/node@24.10.2': dependencies: undici-types: 7.16.0 @@ -6988,6 +7041,8 @@ snapshots: acorn@8.15.0: {} + aes-js@4.0.0-beta.5: {} + agent-base@7.1.4: {} aggregate-error@3.1.0: @@ -7915,6 +7970,19 @@ snapshots: esutils@2.0.3: {} + ethers@6.16.0: + dependencies: + '@adraffy/ens-normalize': 1.10.1 + '@noble/curves': 1.2.0 + '@noble/hashes': 1.3.2 + '@types/node': 22.7.5 + aes-js: 4.0.0-beta.5 + tslib: 2.7.0 + ws: 8.17.1 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + eventemitter2@6.4.7: {} eventemitter3@5.0.1: {} @@ -9840,6 +9908,8 @@ snapshots: tslib@1.14.1: {} + tslib@2.7.0: {} + tslib@2.8.1: {} tunnel-agent@0.6.0: @@ -9889,6 +9959,8 @@ snapshots: unplugin: 2.3.11 optional: true + undici-types@6.19.8: {} + undici-types@7.16.0: {} unicode-canonical-property-names-ecmascript@2.0.1: {} @@ -10195,6 +10267,8 @@ snapshots: signal-exit: 3.0.7 typedarray-to-buffer: 3.1.5 + ws@8.17.1: {} + ws@8.18.3: {} xml-name-validator@4.0.0: {} diff --git a/src/api/index.ts b/src/api/index.ts index a10bdeb..f9f8eae 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -24,8 +24,10 @@ export interface SafeClientReturn { stopWatching?: () => void; } +export type RequestPromise = Promise<{ data: T; error: E; status?: number; response?: Response }>; + export function safeClient( - requestPromise: (() => Promise<{ data: T; error: E }>) | Promise<{ data: T; error: E }>, + requestPromise: (() => RequestPromise) | RequestPromise, options: SafeClientOptions = {}, ): SafeClientReturn & Promise> { const { immediate = true, watchSource } = options; @@ -37,7 +39,7 @@ export function safeClient( const execute = async () => { isPending.value = true; - let request: () => Promise<{ data: T; error: E }>; + let request: () => RequestPromise; if (typeof requestPromise !== "function") { request = () => Promise.resolve(requestPromise); } @@ -49,21 +51,10 @@ export function safeClient( isPending.value = false; }); - if (res.error) { - let errMsg = ""; - if (!res.error) { - errMsg = "Request failed. Please try again."; - } - else if (typeof res.error === "string") { - errMsg = res.error; - } - else if (res.error && "value" in (res.error as unknown as object)) { - errMsg = String((res.error as unknown as { value: string }).value); - } - // if(res.error && typeof res.error === 'object' && 'err' in res.error) { + if (res.error && res.status === 418) { if (!options.silent) { const toast = await toastController.create({ - message: errMsg, + message: (res.error as any).value.message, duration: 3000, position: "bottom", color: "danger", diff --git a/src/main.ts b/src/main.ts index fd83f0d..bded661 100644 --- a/src/main.ts +++ b/src/main.ts @@ -28,8 +28,8 @@ import "@ionic/vue/css/display.css"; * https://ionicframework.com/docs/theming/dark-mode */ -/* @import '@ionic/vue/css/palettes/dark.always.css'; */ -/* @import '@ionic/vue/css/palettes/dark.class.css'; */ +// import "@ionic/vue/css/palettes/dark.always.css"; +// import "@ionic/vue/css/palettes/dark.class.css"; import "@ionic/vue/css/palettes/dark.system.css"; /* Theme variables */ diff --git a/src/utils/helper.ts b/src/utils/helper.ts index 02b0314..383361f 100644 --- a/src/utils/helper.ts +++ b/src/utils/helper.ts @@ -14,3 +14,31 @@ export function timeToLocal(originalTime: number) { const d = new Date(originalTime * 1000); return Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds()) / 1000; } + +export function formatAmount(amount: MaybeRefOrGetter): string { + const value = toValue(amount); + if (Number.isNaN(Number(value))) { + return "0"; + } + + const num = Number(value); + + // 不超过1万,原样显示 + if (num < 10000) { + return String(num); + } + + // 1亿以上,显示为xx亿 + if (num >= 100000000) { + const yi = (num / 100000000).toFixed(1); + return yi.endsWith(".0") ? `${Number.parseInt(yi)}亿` : `${yi}亿`; + } + + // 1万到1亿,显示为xx万 + if (num >= 10000) { + const wan = (num / 10000).toFixed(1); + return wan.endsWith(".0") ? `${Number.parseInt(wan)}万` : `${wan}万`; + } + + return String(num); +} diff --git a/src/views/market/components/rwa-list.vue b/src/views/market/components/rwa-list.vue index 5922d58..656b3b0 100644 --- a/src/views/market/components/rwa-list.vue +++ b/src/views/market/components/rwa-list.vue @@ -55,7 +55,7 @@ function gotoTradeRwa(id: string) { {{ item.product?.code }}
- {{ item.product?.code }} + {{ item.product.category?.name }}
diff --git a/src/views/trade-rwa/index.vue b/src/views/trade-rwa/index.vue index e76e4a7..0d25e3c 100644 --- a/src/views/trade-rwa/index.vue +++ b/src/views/trade-rwa/index.vue @@ -1,26 +1,98 @@ - +