From ef52095f5e9f0a9fe2da779bb1573947d77d75b6 Mon Sep 17 00:00:00 2001
From: jhzh <1628036192@qq.com>
Date: Fri, 22 May 2026 10:53:01 +0800
Subject: [PATCH] 1

---
 src/views/my/assets.vue |  658 ++++++++++++++++++++++++++++++++++-------------------------
 1 files changed, 380 insertions(+), 278 deletions(-)

diff --git a/src/views/my/assets.vue b/src/views/my/assets.vue
index 46f71f2..e9887c1 100644
--- a/src/views/my/assets.vue
+++ b/src/views/my/assets.vue
@@ -1,79 +1,75 @@
 <template>
-    <div class="assets">
-        <div class="assets_title">{{ $t('总资产估值') }}</div>
-        <div class="assets_money font-bold mt-5 flex justify-start items-end">
-            {{ currency.currency_symbol }}{{ forexAssets?.money_contract ?
-                (forexAssets?.money_contract * (currency.rate ?? 0)).toFixed(2) : '0.00' }}
+    <div class="assets-page">
+        <assets-head :title="$t('My assets')" :show-left="true" :back-func="goBack">
+            <template #default>
+                <van-icon name="records-o" size="22" class="assets-head-menu"
+                    @click="toPage('/cryptos/accountChange')" />
+            </template>
+        </assets-head>
 
-            <div class="pricing_jj ml-5">
-                {{ pricing }}
-            </div>
-            <van-dropdown-menu>
-                <van-dropdown-item v-model="pricing" :options="pricingList" @change="changePricing">
-                    <div @click="toPage('/cryptos/exchangeRate')" class="text-center">{{ $t('更多') }}</div>
-                </van-dropdown-item>
-            </van-dropdown-menu>
-        </div>
-        <!-- <div class="assets_revenue mt-5">
-            <span>{{ $t('当日') }}</span>
-            {{ currency.currency_symbol }}
-            <span
-                :style="forexAssets?.money_contract_profit_today > 0 ? 'color:green' : forexAssets?.money_contract_profit_today < 0 ? 'color:red' : ''">
-                {{ forexAssets?.money_contract_profit_today ?
-                    (forexAssets?.money_contract_profit_today * (currency.rate ?? 0)).toFixed(2) :
-                    '--' }}
-            </span>
-        </div> -->
-
-        <div class="tabbers flex justify-between mt-20 pl-1 pr-1">
-            <div class="item" v-for="item in tabList" :key="item.key" @click="toPage(item.path)">
-                <img style="width: 100px;" :src="item.icon" alt="">
-                <div class="mt-3 text-center">{{ item.name }}</div>
-            </div>
-        </div>
-
-        <van-collapse v-model="activeNames" class="mt-10">
-            <van-collapse-item :title="$t('分布')" name="1">
-                <!-- <div class="divider"></div> -->
-                <div class="percentage flex just-between items-center">
-                    <div :style="`width:${assetObj.capital / (assetObj.capital + assetObj.contract) * 100}%`">
+        <div class="assets-body">
+            <!-- 总资产估值卡片:圆角浅灰 -->
+            <div class="assets-total-card">
+                <div class="assets-total-label">{{ $t('总资产估值') }}</div>
+                <div class="assets-total-value">
+                    {{ currency.currency_symbol }}{{ formatWithCommas(totalDisplay) }}
+                </div>
+                <div class="assets-futures-bonus-row">
+                    <div class="assets-futures-cell">
+                        <div class="assets-cell-label">{{ $t('永续') }}</div>
+                        <div class="assets-cell-value">{{ formatWithCommas(futuresDisplay) }}</div>
                     </div>
-                    <div class="flex-1">
+                    <div class="assets-bonus-cell" @click="toPage('/my/transfer')">
+                        <div>
+                            <div class="assets-cell-label">{{ $t('Bonus') }}</div>
+                            <div class="assets-cell-value">{{ formatWithCommas(bonusDisplay) }}</div>
+                        </div>
+                        <van-icon name="arrow" class="assets-cell-arrow" />
                     </div>
                 </div>
-                <div class="assets_item flex justify-start items-center mt-14 font-bold">
-                    <div class="icon" style="background-color: #8A90FE;"></div>
-                    <span class="ml-5 flex-1">{{ $t('资金账户') }}</span>
-                    <span class="mr-5">{{ assetObj.capital }}</span>
-                    <van-icon name="arrow" />
+
+                <!-- 展开后:BTC Price + ETH Price K 线图 -->
+                <div v-if="expanded" class="assets-chart-section">
+                    <div class="assets-chart-title">{{ $t('BTC Price') }}</div>
+                    <div class="assets-kline-wrap">
+                        <fx-kline chart-id="kline-btc" :height="260" symbol="btcusdt" :show-bottom="false"
+                            chart-type="candle_stroke" />
+                    </div>
                 </div>
-                <!-- <div class="assets_item flex justify-start items-center mt-14 font-bold">
-                    <div class="icon" style="background-color: #f7b600;"></div>
-                    <span class="ml-5 flex-1">{{ $t('交易账户') }}</span>
-                    <span class="mr-5">{{ assetObj.contract }}</span>
-                    <van-icon name="arrow" />
-                </div> -->
-            </van-collapse-item>
-        </van-collapse>
-
-        <div class="assets_item flex font-bold justify-between items-center mt-14 mb-10">
-            <span>{{ $t('资产') }}</span>
-            <van-icon name="exchange" size="3rem" />
-        </div>
-
-        <div class="assets_item flex justify-start items-center mb-10 font-bold" v-for="item in assetList"
-            :key="item.id">
-            <img :src="`${HOST_URL}/symbol/${item.symbol_data}.png`" />
-
-            <span class="ml-5 flex-1">{{ arrGk((item.name || '').toUpperCase())[0] }}</span>
-
-            <div class="mr-3">
-                <div class="text-right">
-                    {{ item.volume ? formatWithCommas(Number(item.volume).toFixed(2)) : '0.0' }}
+                <div v-if="expanded" class="assets-chart-section">
+                    <div class="assets-chart-title">{{ $t('ETH Price') }}</div>
+                    <div class="assets-kline-wrap">
+                        <fx-kline chart-id="kline-eth" :height="260" symbol="ethusdt" :show-bottom="false"
+                            chart-type="candle_stroke" />
+                    </div>
                 </div>
-                <div class="assets_item_light text-right">
-                    ≈{{ currency.currency_symbol }}
-                    {{ item.usdt ? formatWithCommas(Number(item.usdt).toFixed(2)) : '0.0' }}
+
+                <div class="assets-expand-btn" @click="expanded = !expanded">
+                    <van-icon :name="expanded ? 'arrow-up' : 'arrow-down'" class="assets-chevron" />
+                </div>
+            </div>
+
+
+            <!-- 资产列表 -->
+            <div class="assets-list-head">{{ $t('Asset list') }}</div>
+            <div class="assets-list">
+                <div v-for="item in assetList" :key="item.id || item.symbol_data" class="assets-list-card">
+                    <div class="assets-list-top">
+                        <img :src="`${HOST_URL}/symbol/${item.symbol_data || item.symbol}.png`" alt=""
+                            class="assets-list-icon" onerror="this.style.display='none'" />
+                        <span class="assets-list-symbol">{{ (item.name || item.symbol_data || item.symbol ||
+                            '').toUpperCase().split('/')[0] }}</span>
+                    </div>
+                    <div class="assets-list-bottom">
+                        <div class="assets-list-cell">
+                            <span class="assets-list-label">{{ $t('Usable') }}</span>
+                            <span class="assets-list-num">{{ item.volume != null ? item.volume : 0 }}</span>
+                        </div>
+                        <div class="assets-list-cell">
+                            <span class="assets-list-label">{{ $t('Locked') }}</span>
+                            <span class="assets-list-num">{{ item.locked != null ? item.locked : 0 }}</span>
+                        </div>
+                    </div>
                 </div>
             </div>
         </div>
@@ -81,241 +77,347 @@
 </template>
 
 <script setup>
-import { ref } from "vue";
-import { useI18n } from "vue-i18n";
+import { ref, computed } from "vue";
 import { useRouter } from 'vue-router';
 import { _getExchangeRate } from '@/service/cryptos.api'
 import { _exchangerateuserconfig } from "@/service/trade.api";
 import store from '@/store/store'
 import { useStore } from "vuex"
-import {
-    _getContractBySymbolType
-} from "@/service/etf.api";
+import { _getContractBySymbolType } from "@/service/etf.api";
 import { SET_CURRENCY } from "@/store/const.store";
 import { _getassets } from "@/service/user.api.js";
 import { _getAllWallet } from '@/service/fund.api';
 import { HOST_URL } from '@/config';
 import { formatWithCommas } from '@/utils';
+import AssetsHead from '@/components/Transform/assets-head/index.vue';
+import fxKline from '@/components/fx-kline/index.vue';
 
-const router = useRouter()
-const { t } = useI18n()
-const activeNames = ref(['1'])
+const router = useRouter();
 const { dispatch } = useStore();
 
-const tabList = [
-    { key: 1, name: t('充值'), icon: new URL('@/assets/imgs/assets/chonbi.png', import.meta.url), path: '/cryptos/recharge/rechargeList?isForeign=true' },
-    { key: 2, name: t('提现'), icon: new URL('@/assets/imgs/assets/tibi.png', import.meta.url), path: '/cryptos/Withdraw/withdrawPage' },
-    // { key: 3, name: t('划转'), icon: new URL('@/assets/imgs/assets/huazhuan.png', import.meta.url), path: '/my/transfer' },
-    { key: 5, name: t('闪兑'), icon: new URL('@/assets/imgs/assets/sd.png', import.meta.url), path: '/cryptos/exchangePage' },
-    { key: 4, name: t('账单'), icon: new URL('@/assets/imgs/assets/zd.png', import.meta.url), path: '/cryptos/accountChange' },
-]
+const expanded = ref(false);
 
-// 处理分隔符
-const arrGk = (str) => {
-    if (!str) return ['--'];
-    let arr = str.split('/');
-    return arr;
-}
+const goBack = () => router.go(-1);
+const toPage = (path) => {
+    if (!path) return;
+    router.push(path);
+};
+
+// 计价与资产
+const currency = ref({});
+const forexAssets = ref({});
+const assetObj = ref({});
+const symbolType = ref('cryptos');
+
+const totalDisplay = computed(() => {
+    const v = forexAssets.value?.money_contract;
+    const rate = currency.value?.rate ?? 0;
+    if (v == null) return '0.00';
+    return (v * rate).toFixed(2);
+});
+
+const futuresDisplay = computed(() => {
+    const v = forexAssets.value?.money_wallet ?? assetObj.value?.contract;
+    if (v == null) return '0';
+    return Number(v).toFixed(2);
+});
+
+const bonusDisplay = computed(() => {
+    const v = assetObj.value?.capitalUSDT ?? 0;
+    return Number(v).toFixed(2);
+});
+
+const getCurrency = async () => {
+    try {
+        const res = await _getExchangeRate({ token: store.state.user.userInfo?.token });
+        currency.value = res;
+    } catch (e) { }
+};
+
+const getContractBySymbolType = () => {
+    _getContractBySymbolType(symbolType.value).then(res => {
+        forexAssets.value = res;
+    });
+};
+
+const getassets = () => {
+    _getassets().then(res => {
+        assetObj.value = res;
+    });
+};
+
+// 资产列表
+const assetList = ref([]);
+const getList = () => {
+    _getAllWallet({ symbolType: 'cryptos' }).then((res) => {
+        assetList.value = res.extends || [];
+    });
+};
 
 // 计价切换
-const pricing = ref('')
+const pricing = ref('');
 const pricingList = [
     { text: 'USD', value: 'USD', key: 'USD_in' },
     { text: 'EUR', value: 'EUR', key: 'EUR_in' },
     { text: 'JPY', value: 'JPY', key: 'JPY_in' },
-]
+];
 const changePricing = (e) => {
-    let item = pricingList.find((item) => item.value == e)
+    const item = pricingList.find((i) => i.value === e);
+    if (item) {
+        _exchangerateuserconfig({ rateId: item.key }).then(() => {
+            dispatch(`home/${SET_CURRENCY}`);
+            getCurrency();
+            getContractBySymbolType();
+        });
+    }
+};
 
-    _exchangerateuserconfig({ rateId: item.key }).then((res) => {
-        dispatch(`home/${SET_CURRENCY}`)
-        getCurrency()
-        getContractBySymbolType()
-    })
-}
-
-// 跳转页面
-const toPage = (path) => {
-    if (!path) return
-    router.push(path)
-}
-
-// 资产信息获取
-const currency = ref({})
-const forexAssets = ref({})
-const symbolType = ref('cryptos') //默认etf
-const getCurrency = async () => {
-    _getExchangeRate({
-        token: store.state.user.userInfo.token
-    }).then(res => {
-        currency.value = res
-        pricing.value = res.currency
-    }).catch(err => Promise.reject(err))
-}
-const getContractBySymbolType = () => {
-    _getContractBySymbolType(symbolType.value)
-        .then(res => {
-            forexAssets.value = res
-        })
-}
-const assetObj = ref({})
-const getassets = () => { // 获取资产
-    _getassets().then(res => {
-        assetObj.value = res
-    })
-}
-
-// 获取资产列表
-const assetList = ref([])
-const getList = () => {
-    _getAllWallet({
-        symbolType: 'cryptos'
-    }).then((res) => {
-        assetList.value = res.extends
-        console.log("资产列表", assetList.value);
-
-    });
-}
-
-getList()
-getassets()
-getCurrency()
-getContractBySymbolType()
+getList();
+getassets();
+getCurrency();
+getContractBySymbolType();
 </script>
 
-
 <style lang="scss" scoped>
-.assets {
+@import '@/assets/theme/index.scss';
+
+.assets-page {
     min-height: 100vh;
-    background: $mainbgWhiteColor;
-    padding: 2.8rem 2rem 10rem 2rem;
-    $assets_title_color: #9a9a9a;
-    color: $assets_title_color;
+    padding-bottom: 4rem;
 
-    :deep(.van-cell) {
-        padding-left: 0;
-        padding-right: 0;
-    }
-
-    :deep(.van-cell:after) {
-        display: none;
-    }
-
-    :deep(.van-collapse-item__content) {
-        padding-left: 0;
-        padding-right: 0;
-    }
-
-    :deep(.van-cell__title) {
-        font-size: 2.1rem;
-        font-weight: 600;
-    }
-
-    .assets_title {
-        font-size: 2.1rem;
-    }
-
-    .assets_money {
-        color: $text_color4;
-        font-size: 3.4rem;
-
-        .pricing_jj {
-            font-size: 1.6rem;
-            margin-right: -8px;
-        }
-
-        :deep(.van-dropdown-menu__bar) {
-            height: auto;
-            box-shadow: none;
-        }
-
-        :deep(.van-dropdown-menu__title--down:after) {
-            margin-top: -14px !important;
-        }
-
-        :deep(.van-dropdown-menu__title:after) {
-            margin-top: -16px;
-        }
-
-        :deep(.van-ellipsis) {
-            display: none;
-        }
-
-        :deep(.van-popup--top) {
-            padding: 10px 20px;
-            font-size: 2rem;
-        }
-    }
-
-    .assets_revenue {
-        font-size: 2rem;
-        color: #646464;
-        font-weight: 600;
-
-        span {
-            color: #6e6e6e;
-            text-decoration: underline dotted;
-            font-weight: 400;
-        }
-    }
-
-    .tabbers {
-        .item {
-            $item_width: 8.3rem;
-            width: $item_width;
-            font-size: 1.8rem;
-            color: $text_color4;
-
-            img {
-                height: $item_width;
-                border-radius: 50%;
-            }
-        }
-    }
-
-    // .divider {
-    //     height: 1rem;
-    //     border-radius: 0.5rem;
-    //     background: $bg_yellow;
-    // }
-
-    .percentage {
-        div {
-            height: 1rem;
-            border-radius: 0.5rem;
-        }
-
-        &>div:last-child {
-            background: $bg_yellow;
-        }
-
-        &>div:first-child {
-            background: #8A90FE;
-            margin-right: 0.2rem;
-        }
-    }
-
-    .assets_item {
-        color: $text_color4;
-        font-size: 2.1rem;
-
-        .icon {
-            width: 1.8rem;
-            height: 1.8rem;
-            border-radius: 50%;
-            background: $icon-bg;
-        }
-
-        img {
-            width: 2.8rem;
-            height: 2.8rem;
-            border-radius: 50%;
-        }
-
-        .assets_item_light {
-            color: #9b9b9b;
-            font-weight: 300;
-        }
+    @include themify() {
+        background-color: #f6f5fa;
+        color: themed("text_color2");
     }
 }
-</style>
\ No newline at end of file
+
+.assets-head-menu {
+    padding: 0 8px;
+
+    @include themify() {
+        color: themed("text_color2");
+    }
+}
+
+.assets-body {
+    padding: 0;
+}
+
+.assets-total-card {
+    background: #fff;
+    border-radius: 16px;
+    padding: 20px 20px 12px;
+    margin-top: 10px;
+
+    @include themify() {
+        background: themed("card_bg");
+    }
+}
+
+.assets-total-label {
+    font-size: 1.6rem;
+
+    @include themify() {
+        color: themed("text_color2");
+    }
+}
+
+.assets-total-value {
+    font-size: 2.6rem;
+    font-weight: 700;
+    margin-top: 8px;
+
+    @include themify() {
+        color: themed("text_color");
+    }
+}
+
+.assets-futures-bonus-row {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-top: 16px;
+    padding-top: 12px;
+    border-top: 1px solid rgba(0, 0, 0, 0.06);
+
+    @include themify() {
+        border-top-color: themed("border_color");
+    }
+}
+
+.assets-futures-cell,
+.assets-bonus-cell {
+    display: flex;
+    flex-direction: column;
+    align-items: flex-start;
+}
+
+.assets-bonus-cell {
+    width: 50%;
+    flex-direction: row;
+    align-items: center;
+    gap: 6px;
+    cursor: pointer;
+}
+
+.assets-cell-label {
+    font-size: 1.8rem;
+
+    @include themify() {
+        color: themed("text_color2");
+    }
+}
+
+.assets-cell-value {
+    font-size: 2.2rem;
+    font-weight: 600;
+    margin-top: 4px;
+
+    @include themify() {
+        color: themed("text_color");
+    }
+}
+
+.assets-cell-arrow {
+    font-size: 16px;
+    margin-top: 2px;
+
+    @include themify() {
+        color: themed("text_color2");
+    }
+}
+
+.assets-expand-btn {
+    display: flex;
+    justify-content: center;
+    padding: 8px 0 4px;
+}
+
+.assets-chevron {
+    font-size: 20px;
+
+    @include themify() {
+        color: themed("text_color2");
+    }
+}
+
+.assets-chart-section {
+    margin-top: 16px;
+    border-radius: 16px;
+
+    @include themify() {
+        background: themed("card_bg");
+    }
+}
+
+.assets-chart-title {
+    font-size: 1.8rem;
+    margin-bottom: 12px;
+
+    @include themify() {
+        color: themed("text_color2");
+    }
+}
+
+.assets-kline-wrap {
+    border-radius: 8px;
+    overflow: hidden;
+    min-height: 260px;
+}
+
+.assets-list-head {
+    font-size: 2.4rem;
+    font-weight: 700;
+    margin-top: 24px;
+    margin-bottom: 12px;
+    padding-left: 20px;
+
+    @include themify() {
+        color: themed("text_color");
+    }
+}
+
+.assets-list {
+    display: flex;
+    flex-direction: column;
+    padding: 0 20px;
+
+}
+
+.assets-list-card {
+    display: flex;
+    flex-direction: column;
+    margin: 10px 0 0;
+    background-color: #fff;
+    border-radius: 16px;
+    padding: 20px 18px;
+    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
+
+    @include themify() {
+        background: themed("card_bg");
+        color: themed("text_color2");
+        box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
+    }
+}
+
+.assets-list-top {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+}
+
+.assets-list-icon {
+    width: 22px;
+    height: 22px;
+    border-radius: 50%;
+    object-fit: cover;
+    flex-shrink: 0;
+}
+
+.assets-list-symbol {
+    font-size: 2rem;
+    font-weight: 500;
+
+    @include themify() {
+        color: themed("text_color");
+    }
+}
+
+.assets-list-bottom {
+    display: flex;
+    justify-content: space-around;
+    align-items: flex-start;
+    padding-top: 12px;
+
+    @include themify() {
+        border-top-color: themed("border_color");
+    }
+}
+
+.assets-list-cell {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    gap: 4px;
+}
+
+.assets-list-label {
+    font-size: 1.4rem;
+    font-weight: 400;
+    text-align: center;
+
+    @include themify() {
+        color: themed("text_color2");
+    }
+}
+
+.assets-list-num {
+    font-size: 2.2rem;
+    font-weight: 700;
+    text-align: center;
+
+    @include themify() {
+        color: themed("text_color");
+    }
+}
+</style>

--
Gitblit v1.9.3