bm-bmt/pages/index/index.vue

1189 lines
29 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="asset-page asset-theme home-page">
<view class="home-topbar">
<view class="home-topbar__side"></view>
<text class="home-topbar__title">{{ overview.title || "数字资产" }}</text>
<view class="home-wallet-btn" @click="openWallet">
<view class="home-wallet-btn__icon">
<image src="https://imgs.agrimedia.cn/bm-bmt/qianbao.png" mode="widthFix"></image>
</view>
<text class="home-wallet-btn__text" style="margin-top: 4rpx;">钱包</text>
</view>
</view>
<view class="asset-scroll home-scroll">
<view v-if="isHomeLoading" class="home-skeleton">
<view class="home-skeleton__hero">
<view class="home-skeleton__banner skeleton-block"></view>
<view class="home-skeleton__stat-panel">
<view v-for="index in 2" :key="'home-skeleton-stat-' + index"
class="home-skeleton__stat-card skeleton-card">
<view class="home-skeleton__line home-skeleton__line--label skeleton-block"></view>
<view class="home-skeleton__line home-skeleton__line--value skeleton-block"></view>
</view>
</view>
</view>
<view class="home-skeleton__section">
<view class="home-skeleton__title skeleton-block"></view>
<view class="home-skeleton__asset-grid">
<view v-for="index in 5" :key="'home-skeleton-asset-' + index"
class="home-skeleton__asset-card skeleton-card">
<view class="home-skeleton__line home-skeleton__line--asset-label skeleton-block"></view>
<view class="home-skeleton__line home-skeleton__line--asset-value skeleton-block"></view>
</view>
</view>
</view>
<view class="home-skeleton__section">
<view class="home-skeleton__title skeleton-block"></view>
<view class="home-skeleton__feature-list">
<view v-for="index in 6" :key="'home-skeleton-feature-' + index"
class="home-skeleton__feature-item skeleton-card">
<view class="home-skeleton__feature-main">
<view class="home-skeleton__feature-icon skeleton-block"></view>
<view class="home-skeleton__line home-skeleton__line--feature skeleton-block"></view>
</view>
<view class="home-skeleton__feature-arrow skeleton-block"></view>
</view>
</view>
</view>
<view class="home-skeleton__notice">
<view class="home-skeleton__notice-icon skeleton-block"></view>
<view class="home-skeleton__notice-lines">
<view class="home-skeleton__line home-skeleton__line--notice skeleton-block"></view>
<view class="home-skeleton__line home-skeleton__line--notice-short skeleton-block"></view>
</view>
</view>
</view>
<view v-show="!isHomeLoading">
<view class="home-hero">
<view class="brand-banner"></view>
<view class="stat-panel">
<view v-for="item in overview.topStats" :key="item.key" class="stat-card"
:class="'stat-card--' + item.accent" @click="openTopStat(item)">
<view class="stat-card__body">
<text class="stat-card__label">{{ item.title }}</text>
<view class="stat-card__value-row">
<text class="stat-card__value asset-number-font">{{ item.value }}</text>
<text class="stat-card__unit">{{ item.unit }}</text>
</view>
</view>
</view>
</view>
</view>
<view class="home-section">
<view class="home-section__head">
<text class="home-section__title">我的资产</text>
</view>
<view class="asset-grid">
<view v-for="item in overview.quickAssets" :key="item.key" class="asset-mini-card" :class="[
'asset-mini-card--' + item.accent,
item.key === 'balance' ? 'asset-mini-card--full' : '',
]" @click="openQuickAsset(item)">
<image class="asset-mini-card__bg" :src="quickAssetBg(item.key)" mode="aspectFill"></image>
<view class="asset-mini-card__head">
<text class="asset-mini-card__label">{{ item.title }}</text>
</view>
<text class="asset-mini-card__value asset-number-font">{{
item.key === "bmtr"
? formatBmtrValue(item.value)
: formatAssetValue(item.value)
}}</text>
</view>
</view>
</view>
<view class="home-section">
<view class="home-section__head">
<text class="home-section__title">功能中心</text>
</view>
<view class="feature-list">
<view v-for="feature in overview.features" :key="feature.key" class="feature-list__item"
@click="openFeature(feature.key)">
<view class="feature-list__main">
<view class="feature-list__icon">
<image class="feature-list__icon-image" :src="featureIcon(feature.key)" mode="aspectFit"></image>
</view>
<text class="feature-list__title">{{ feature.title }}</text>
</view>
<image class="feature-list__arrow" src="https://imgs.agrimedia.cn/bm-bmt/more.png"></image>
</view>
</view>
</view>
<view class="notice-bar">
<image class="notice-bar__icon" src="https://imgs.agrimedia.cn/bm-bmt/tips.png" mode="widthFix"></image>
<text class="notice-bar__text">{{ overview.notice }}</text>
</view>
<image src="https://imgs.agrimedia.cn/bm-bmt/bottom.png" mode="widthFix" style="width: 100%; margin-top: 20rpx">
</image>
</view>
</view>
<asset-confirm-popup :visible="signPopupVisible" :title="signPopupTitle" :message="signPopupMessage"
:confirm-text="signPopupConfirmText" cancel-text="取消" @cancel="handleSignPopupCancel"
@confirm="handleSignPopupConfirm" />
</view>
</template>
<script>
import {
fetchAssetHome,
fetchCouponRedeemLinkData,
} from "../../api/assets";
import {
fetchBmtContractStatus,
checkBmtSignCondition,
startBmtSigning,
} from "../../api/bmt";
import AssetConfirmPopup from "../../components/asset-confirm-popup.vue";
import serviceConfig from "../../config/service";
import { truncateToTwo } from "../../utils/index.js";
// H5 下点击弹框「取消」后固定跳转的推广页
const BMT_CANCEL_REDIRECT_URL =
`${window.location.origin}/JXH5/pages/users/user_spread_user/index`;
/** personal_auth_status 可能是对象或标量,统一取出 status 值(1 表示需要先走协议签约) */
function resolvePersonalAuthStatus(source) {
const raw = source && source.personal_auth_status;
if (raw && typeof raw === "object") {
return Number(raw.status) === 1 ? 1 : 0;
}
return Number(raw) === 1 ? 1 : 0;
}
export default {
components: {
AssetConfirmPopup,
},
data() {
return {
isHomeLoading: true,
hasLoadedOnce: false,
isFetchingHome: false,
isOpeningCouponRedeem: false,
signPopupVisible: false,
signPopupMode: "",
signPopupTitle: "BMT签约",
signPopupMessage: "",
signPopupConfirmText: "确认",
signContractType: 0,
signContractId: "",
signRecordId: "",
signPersonalAuthStatus: 0,
signInfoData: {},
isSigning: false,
overview: {
title: "数字资产",
heroTitle: "BM数字资产管理",
topStats: [],
quickAssets: [],
features: [],
notice: "",
},
};
},
onLoad() {
this.loadPage({
showSkeleton: true,
});
},
onShow() {
// 首次进入首页校验 BMT 签约状态,命中条件时弹框引导,不自动跳页
this.checkBmtContract();
this.loadPage({
showSkeleton: !this.hasLoadedOnce,
});
},
methods: {
async checkBmtContract() {
try {
const status = (await fetchBmtContractStatus()) || {};
// status === 2:无需签约提示,不再做后续判断与接口请求
if (Number(status.status) === 2) {
return;
}
const rawComplete = status.sign_info_complete;
const signInfoComplete =
rawComplete === undefined || rawComplete === null || rawComplete === ""
? 1
: Number(rawComplete);
const contractStatus = Number(status.contract_status || 0);
// 签约信息未完善:弹框引导,用户点击后再进认证页
if (signInfoComplete !== 1) {
this.openSignInfoPopup(status);
return;
}
// 未签约:弹框引导,点击后直接发起签约
if (contractStatus === 0) {
await this.openSigningPopup(status);
}
} catch (error) {
// 签约状态查询失败不阻断首页加载
}
},
openSignInfoPopup(status) {
this.signPopupMode = "info";
this.signPopupTitle = "BMT签约";
this.signPopupMessage =
"您的签约信息尚未完善,请先补充签约信息后再进行签约。";
this.signPopupConfirmText = "去补充信息";
this.signInfoData = status || {};
this.signPopupVisible = true;
},
async openSigningPopup(status) {
let tips = String((status && status.tips) || "");
let contractType = Number((status && status.contract_type) || 0);
let checkData = {};
// 提示签约时先请求前置校验接口,取 tips / contract_type / c_id
try {
checkData =
(await checkBmtSignCondition(
{},
{
showLoading: true,
loadingText: "校验中",
},
)) || {};
} catch (error) {
checkData = {};
}
const checkTips = String(checkData.tips || "");
const checkType = checkData.contract_type;
if (checkTips) {
tips = checkTips;
}
if (checkType !== undefined && checkType !== null && checkType !== "") {
contractType = Number(checkType) === 1 ? 1 : 0;
}
// c_id / id 来自前置校验接口,点击「去签约」时随请求一并带上
this.signContractId = String(checkData.c_id || "");
this.signRecordId = String(checkData.id || (status && status.id) || "");
this.signPersonalAuthStatus = resolvePersonalAuthStatus(checkData);
this.signPopupMode = "sign";
this.signPopupTitle = "BMT签约";
this.signPopupMessage =
tips || "您尚未签署 BMT 相关协议,请完成签约后继续使用。";
this.signPopupConfirmText = contractType === 1 ? "更新协议" : "签约新协议";
this.signContractType = contractType;
this.signPopupVisible = true;
},
handleSignPopupConfirm() {
if (this.signPopupMode === "info") {
const data = encodeURIComponent(
JSON.stringify(this.signInfoData || {}),
);
this.signPopupVisible = false;
uni.navigateTo({
url: "/pages/assets/bmt-sign-info?data=" + data,
});
return;
}
this.handleGoSigning();
},
handleSignPopupCancel() {
this.signPopupVisible = false;
this.exitToHostPage();
},
/** 退出当前页:H5 固定跳转推广页;其它端返回上一页 / 关闭 webview */
exitToHostPage() {
const ua = navigator.userAgent.toLowerCase();
const isAppWebview = ua.indexOf('html5plus') > -1 || window.plus;
// App内嵌webview:跳约定的uniwebview协议,外层拦截
if (isAppWebview) {
window.location.href = "uniwebview://redirectTo?url=/pages/users/user_spread_user/index";
return;
}
// 普通浏览器H5,跳转推广页
if (typeof window !== "undefined") {
window.location.href = BMT_CANCEL_REDIRECT_URL;
return;
}
// uni-app原生App页面(非webview)
if (typeof getCurrentPages === "function" && getCurrentPages().length > 1) {
uni.navigateBack();
return;
}
if (typeof plus !== "undefined") {
const currentWebview = plus.webview.currentWebview();
currentWebview?.close?.();
}
},
async handleGoSigning() {
if (this.isSigning) {
return;
}
// personal_auth_status.status === 1:先到协议页阅读并签约(协议页用 id 签约)
if (this.signPersonalAuthStatus === 1) {
this.isSigning = true;
try {
this.signPopupVisible = false;
uni.navigateTo({
url: "/pages/assets/bmt-sign-agreement",
});
} finally {
this.isSigning = false;
}
return;
}
if (!this.signContractId) {
uni.showToast({
title: "签约信息获取失败,请稍后重试",
icon: "none",
});
return;
}
this.isSigning = true;
try {
const result = await startBmtSigning(
{
contract_type: this.signContractType,
c_id: this.signContractId,
id: this.signRecordId,
},
{
showLoading: true,
loadingText: "发起签约",
},
);
// 输出原始返回,便于确认字段实际层级(排查完可删)
console.log("[BMT签约] start_signing_bmt_v2 返回:", result.raw);
// status 为 0:直接跳转 saasShortLink 去认证
if (Number(result.status) === 0 && result.saasShortLink) {
this.signPopupVisible = false;
this.navigateToExternalUrl(result.saasShortLink);
return;
}
uni.showToast({
title: result.message || "发起签约失败,请稍后重试",
icon: "none",
});
} catch (error) {
uni.showToast({
title: error.message || "发起签约失败",
icon: "none",
});
} finally {
this.isSigning = false;
}
},
formatAssetValue(value) {
return truncateToTwo(value);
},
formatBmtrValue(value) {
const number = Number(value || 0);
return Number.isFinite(number) ? number.toFixed(2) : "0.00";
},
async loadPage(options = {}) {
if (this.isFetchingHome) {
return;
}
const shouldShowSkeleton =
Boolean(options.showSkeleton) || !this.hasLoadedOnce;
if (shouldShowSkeleton) {
this.isHomeLoading = true;
}
this.isFetchingHome = true;
try {
const nextOverview = await fetchAssetHome();
this.overview = nextOverview;
this.hasLoadedOnce = true;
} catch (error) {
uni.showToast({
title: error.message || "首页加载失败",
icon: "none",
});
} finally {
if (shouldShowSkeleton || !this.hasLoadedOnce) {
this.isHomeLoading = false;
}
this.isFetchingHome = false;
}
},
quickAssetIcon(key) {
const iconMap = {
points: "https://imgs.agrimedia.cn/bm-bmt/jifen-icon.png",
voucher: "https://imgs.agrimedia.cn/bm-bmt/quan-icon.png",
coupon: "https://imgs.agrimedia.cn/bm-bmt/xiaofei-icon.png",
power: "https://imgs.agrimedia.cn/bm-bmt/suanli-icon.png",
bmtr: "https://imgs.agrimedia.cn/webimg/202607171808386371853.svg",
};
return iconMap[key] || "";
},
quickAssetBg(key) {
const bgMap = {
balance: "https://imgs.agrimedia.cn/bm-bmt/brokerage-icon.png",
points: "https://imgs.agrimedia.cn/bm-bmt/jifen-bg.png",
voucher: "https://imgs.agrimedia.cn/bm-bmt/quan-bg.png",
coupon: "https://imgs.agrimedia.cn/bm-bmt/xiaofei-bg.png",
power: "https://imgs.agrimedia.cn/bm-bmt/suanli-bg.png",
bmtr: "https://imgs.agrimedia.cn/webimg/202607201122331061368.svg",
};
return bgMap[key] || "";
},
featureIcon(key) {
const iconMap = {
"bmt-exchange": "https://imgs.agrimedia.cn/bm-bmt/b.png",
"bmt-flash": "https://imgs.agrimedia.cn/bm-bmt/shandui.png",
"power-exchange": "https://imgs.agrimedia.cn/bm-bmt/s.png",
transfer: "https://imgs.agrimedia.cn/bm-bmt/z.png",
withdraw: "https://imgs.agrimedia.cn/bm-bmt/t.png",
"points-convert": "https://imgs.agrimedia.cn/bm-bmt/j.png",
};
return iconMap[key] || "";
},
openFeature(key) {
const urlMap = {
transfer: "/pages/assets/transfer",
"power-exchange": "/pages/assets/power-exchange",
"bmt-exchange": "/pages/assets/bmt-exchange",
"bmt-flash": "/pages/assets/bmt-flash",
withdraw: "/pages/assets/withdraw",
"points-convert": "/pages/assets/points-convert",
};
const targetUrl = urlMap[key];
if (!targetUrl) {
uni.showToast({
title: "功能开发中",
icon: "none",
});
return;
}
uni.navigateTo({
url: targetUrl,
});
},
openTopStat(item) {
const key = item && item.key ? item.key : "";
const urlMap = {
"wallet-bmt": "/pages/assets/ledger?type=withdraw",
};
const targetUrl = urlMap[key];
if (!targetUrl) {
return;
}
uni.navigateTo({
url: targetUrl,
});
},
openQuickAsset(item) {
if (item && item.key === "balance") {
this.openBalanceSpread();
return;
}
if (item && item.key === "voucher") {
this.openVoucherBroker();
return;
}
if (item && item.key === "coupon") {
this.openCouponRedeem();
return;
}
const urlMap = {
points: "/pages/assets/ledger?type=points",
power: "/pages/assets/ledger?type=power-flow",
bmtr: "/pages/assets/bmtr",
};
const targetUrl = urlMap[item.key];
if (!targetUrl) {
return;
}
uni.navigateTo({
url: targetUrl,
});
},
navigateToExternalUrl(targetUrl) {
if (!targetUrl) {
return;
}
if (typeof window !== "undefined" && window.location) {
window.location.href = targetUrl;
return;
}
if (
typeof plus !== "undefined" &&
plus.webview &&
plus.webview.currentWebview
) {
const currentWebview = plus.webview.currentWebview();
if (currentWebview && typeof currentWebview.loadURL === "function") {
currentWebview.loadURL(targetUrl);
return;
}
}
uni.navigateTo({
url: targetUrl,
});
},
async openVoucherBroker() {
uni.navigateTo({
url: "/pages/assets/voucher-center",
});
},
async openCouponRedeem() {
if (this.isOpeningCouponRedeem) {
return;
}
this.isOpeningCouponRedeem = true;
try {
const result = await fetchCouponRedeemLinkData({
showLoading: true,
loadingText: "加载中",
});
this.navigateToExternalUrl(result.targetUrl);
} catch (error) {
uni.showToast({
title: error.message || "跳转失败",
icon: "none",
});
} finally {
this.isOpeningCouponRedeem = false;
}
},
openBalanceSpread() {
uni.navigateTo({
url: "/pages/assets/balance-center",
});
},
openWallet() {
uni.navigateTo({
url: "/pages/assets/wallet",
});
},
},
};
</script>
<style lang="scss" scoped>
@import "../../styles/tokens.scss";
@import "../../styles/common.scss";
.home-page {
background: #191e32;
}
.home-topbar {
display: grid;
grid-template-columns: 136rpx 1fr 136rpx;
align-items: center;
padding: calc(env(safe-area-inset-top) + 20rpx) 16rpx 8rpx;
}
.home-topbar__side {
width: 136rpx;
height: 1rpx;
}
.home-topbar__title {
text-align: center;
font-size: 36rpx;
font-weight: 700;
color: #ffffff;
letter-spacing: 1rpx;
}
.home-wallet-btn {
justify-self: end;
display: flex;
align-items: center;
height: 52rpx;
color: rgba(229, 235, 255, 0.82);
padding-right: 10rpx;
}
.home-wallet-btn__icon {
width: 30rpx;
height: 32rpx;
margin-right: 8rpx;
image {
width: 30rpx;
height: 32rpx;
}
}
.home-wallet-btn__text {
font-size: 28rpx;
line-height: 1;
color: rgba(229, 235, 255, 0.82);
}
.home-scroll {
padding: 12rpx 20rpx 24rpx;
}
.home-skeleton {
padding-bottom: 6rpx;
}
.skeleton-block {
position: relative;
overflow: hidden;
background: rgba(86, 98, 135, 0.32);
}
.skeleton-block::after {
content: "";
position: absolute;
top: 0;
bottom: 0;
left: -140rpx;
width: 140rpx;
background: linear-gradient(90deg,
rgba(255, 255, 255, 0) 0%,
rgba(255, 255, 255, 0.24) 50%,
rgba(255, 255, 255, 0) 100%);
animation: home-skeleton-shimmer 1.35s linear infinite;
}
.skeleton-card {
border-radius: 12rpx;
background: rgba(36, 41, 68, 0.92);
border: 1px solid rgba(129, 141, 183, 0.16);
}
.home-skeleton__hero {
position: relative;
margin-bottom: 26rpx;
}
.home-skeleton__banner {
height: 380rpx;
border-radius: 28rpx;
}
.home-skeleton__stat-panel {
position: absolute;
left: 20rpx;
right: 20rpx;
bottom: 24rpx;
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 20rpx;
}
.home-skeleton__stat-card {
padding: 22rpx 22rpx 20rpx;
min-height: 126rpx;
}
.home-skeleton__section {
margin-top: 28rpx;
}
.home-skeleton__title {
width: 154rpx;
height: 34rpx;
border-radius: 8rpx;
margin-bottom: 16rpx;
}
.home-skeleton__asset-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 16rpx;
}
.home-skeleton__asset-card {
height: 80rpx;
padding: 14rpx 20rpx;
display: flex;
justify-content: space-between;
align-items: center;
}
.home-skeleton__feature-list {
display: grid;
gap: 16rpx;
}
.home-skeleton__feature-item {
min-height: 100rpx;
padding: 0 22rpx;
display: flex;
align-items: center;
justify-content: space-between;
}
.home-skeleton__feature-main {
display: flex;
align-items: center;
min-width: 0;
flex: 1;
}
.home-skeleton__feature-icon {
width: 36rpx;
height: 36rpx;
border-radius: 8rpx;
flex-shrink: 0;
}
.home-skeleton__feature-arrow {
width: 24rpx;
height: 24rpx;
border-radius: 999rpx;
margin-left: 20rpx;
}
.home-skeleton__notice {
display: flex;
align-items: flex-start;
margin-top: 20rpx;
padding: 0 2rpx;
}
.home-skeleton__notice-icon {
width: 28rpx;
height: 28rpx;
border-radius: 50%;
margin-right: 8rpx;
margin-top: 4rpx;
flex-shrink: 0;
}
.home-skeleton__notice-lines {
flex: 1;
}
.home-skeleton__line {
border-radius: 8rpx;
}
.home-skeleton__line--label {
width: 150rpx;
height: 24rpx;
}
.home-skeleton__line--value {
width: 200rpx;
height: 34rpx;
margin-top: 16rpx;
}
.home-skeleton__line--asset-label {
width: 86rpx;
height: 24rpx;
}
.home-skeleton__line--asset-value {
width: 118rpx;
height: 30rpx;
}
.home-skeleton__line--feature {
width: 200rpx;
height: 28rpx;
margin-left: 20rpx;
}
.home-skeleton__line--notice {
width: 100%;
height: 24rpx;
}
.home-skeleton__line--notice-short {
width: 72%;
height: 24rpx;
margin-top: 10rpx;
}
@keyframes home-skeleton-shimmer {
0% {
transform: translateX(0);
}
100% {
transform: translateX(900rpx);
}
}
.home-hero {
position: relative;
margin-bottom: 26rpx;
}
.brand-banner {
position: relative;
overflow: hidden;
height: 380rpx;
border-radius: 28rpx;
background:
linear-gradient(180deg,
rgba(5, 12, 28, 0.06) 0%,
rgba(5, 12, 28, 0.16) 100%),
url("https://imgs.agrimedia.cn/bm-bmt/home2-bg.png") no-repeat;
border: 1px solid rgba(112, 135, 196, 0.18);
background-size: cover;
box-shadow: 0 24rpx 48rpx rgba(7, 12, 32, 0.28);
}
.brand-banner::before {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.02), transparent 26%);
pointer-events: none;
}
.brand-banner::after {
content: "";
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: 120rpx;
background: linear-gradient(180deg, rgba(4, 10, 24, 0), rgba(4, 10, 24, 0.18));
pointer-events: none;
}
.stat-panel {
position: absolute;
z-index: 2;
left: 20rpx;
right: 20rpx;
bottom: 24rpx;
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 20rpx;
padding: 0;
background: transparent;
}
.stat-card {
position: relative;
overflow: hidden;
min-height: 126rpx;
padding: 22rpx 22rpx 20rpx;
border-radius: 8rpx;
background: linear-gradient(180deg,
rgba(42, 55, 82, 0.98) 0%,
rgba(39, 51, 76, 0.98) 100%);
border: 1px solid rgba(121, 139, 190, 0.16);
box-shadow: 0 14rpx 24rpx rgba(5, 11, 29, 0.2);
}
.stat-card::before {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.05), transparent 34%);
pointer-events: none;
}
.stat-card__icon-box {
position: absolute;
right: 16rpx;
top: 16rpx;
display: flex;
align-items: center;
justify-content: center;
width: 56rpx;
height: 56rpx;
border-radius: 8rpx;
border: 1px solid rgba(255, 255, 255, 0.08);
flex-shrink: 0;
}
.stat-card__icon-box--gold {
background: linear-gradient(135deg,
rgba(20, 182, 255, 0.22) 0%,
rgba(20, 182, 255, 0.08) 100%);
}
.stat-card__icon-box--green {
background: linear-gradient(135deg,
rgba(46, 233, 167, 0.22) 0%,
rgba(46, 233, 167, 0.08) 100%);
}
.stat-card__body {
position: relative;
z-index: 1;
display: flex;
flex-direction: column;
justify-content: flex-end;
flex: 1;
min-width: 0;
min-height: 84rpx;
margin-left: 0;
padding-right: 56rpx;
}
.stat-card__label {
display: block;
font-size: 26rpx;
font-weight: 500;
line-height: 1.25;
white-space: nowrap;
}
.stat-card--gold .stat-card__label {
color: #19b9ff;
}
.stat-card--green .stat-card__label {
color: #28e0a6;
}
.stat-card__value-row {
display: flex;
align-items: baseline;
flex-wrap: wrap;
margin-top: 16rpx;
min-width: 0;
}
.stat-card__value {
font-size: 32rpx;
font-weight: 800;
color: #ffffff;
line-height: 1;
}
.stat-card__unit {
margin-left: 8rpx;
font-size: 22rpx;
line-height: 1.2;
color: rgba(170, 181, 208, 0.92);
white-space: nowrap;
}
.home-section {
margin-top: 28rpx;
}
.home-section__head {
margin-bottom: 16rpx;
}
.home-section__title {
font-size: 28rpx;
font-weight: 500;
color: #ffffff;
}
.asset-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 16rpx;
}
.asset-mini-card {
position: relative;
overflow: hidden;
display: flex;
align-items: center;
justify-content: space-between;
min-width: 0;
height: 80rpx;
line-height: 80rpx;
padding: 0rpx 20rpx;
border-radius: 12rpx;
box-shadow: 0 12rpx 24rpx rgba(10, 16, 37, 0.16);
background: rgba(35, 45, 79, 0.9);
}
// .asset-mini-card--full {
// grid-column: 1 / -1;
// }
.asset-mini-card__bg {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
}
.asset-mini-card--blue {
background: linear-gradient(135deg, #10acee 0%, #1aa4ff 100%);
}
.asset-mini-card--green {
background: linear-gradient(135deg, #25d8a4 0%, #36e08f 100%);
}
.asset-mini-card--orange {
background: linear-gradient(135deg, #ff8d58 0%, #ff7d7d 100%);
}
.asset-mini-card--violet {
background: linear-gradient(135deg, #a667f3 0%, #b27cff 100%);
}
.asset-mini-card__head,
.asset-mini-card__value {
position: relative;
z-index: 1;
}
.asset-mini-card__head {
display: flex;
font-size: 26rpx;
align-items: center;
}
.asset-mini-card__icon {
display: flex;
align-items: center;
justify-content: center;
width: 38rpx;
height: 38rpx;
flex-shrink: 0;
}
.asset-mini-card__icon-image {
width: 32rpx;
height: 32rpx;
}
.asset-mini-card__label {
margin-left: 14rpx;
font-size: 26rpx;
font-weight: 500;
color: rgba(255, 255, 255, 0.94);
white-space: nowrap;
}
.asset-mini-card__value {
display: block;
font-size: 32rpx;
font-weight: 800;
text-align: right;
color: #ffffff;
}
.feature-list {
display: grid;
gap: 16rpx;
}
.feature-list__item {
display: flex;
align-items: center;
justify-content: space-between;
min-height: 100rpx;
padding: 0 22rpx;
border-radius: 12rpx;
background: #242944;
box-shadow: 0 12rpx 22rpx rgba(8, 13, 30, 0.14);
}
.feature-list__main {
display: flex;
align-items: center;
min-width: 0;
}
.feature-list__icon {
display: flex;
align-items: center;
justify-content: center;
width: 36rpx;
height: 36rpx;
flex-shrink: 0;
}
.feature-list__icon-image {
width: 32rpx;
height: 32rpx;
}
.feature-list__title {
margin-left: 20rpx;
font-size: 28rpx;
font-weight: 400;
color: #f3f6ff;
}
.feature-list__arrow {
margin-left: 16rpx;
width: 26rpx;
height: 26rpx;
line-height: 1;
}
.notice-bar {
display: flex;
align-items: flex-start;
margin-top: 20rpx;
padding: 0 2rpx;
}
.notice-bar__icon {
display: flex;
align-items: center;
justify-content: center;
width: 28rpx;
height: 28rpx;
margin-right: 8rpx;
margin-top: 4rpx;
background: linear-gradient(180deg, #ffd764 0%, #ffbb2e 100%);
font-size: 16rpx;
font-weight: 700;
color: #ffffff;
flex-shrink: 0;
}
.notice-bar__text {
font-size: 24rpx;
line-height: 1.65;
color: rgba(200, 207, 227, 0.82);
}
</style>