P1: - 收益曲线 Y 轴刻度(5档刻度线+标签) P2: - 交易记录时间格式合并为一行 - 组合名称长度限制(max-width + ellipsis) - 去掉无意义标签("账本追踪中"、"NV") P3: - 我的页面会员等级改为运行天数 改进: - 信息密度提升 - 图表可读性增强 - 去除冗余信息
757 lines
17 KiB
Vue
Executable File
757 lines
17 KiB
Vue
Executable File
<template>
|
||
<view class="page-container">
|
||
|
||
<!-- 骨架屏:资产卡片区域 -->
|
||
<view class="header-section" v-if="loading">
|
||
<view class="skeleton-asset-card">
|
||
<view class="skeleton-row">
|
||
<view class="skeleton-text skeleton-label"></view>
|
||
</view>
|
||
<view class="skeleton-row">
|
||
<view class="skeleton-text skeleton-big"></view>
|
||
</view>
|
||
<view class="skeleton-row skeleton-bottom">
|
||
<view class="skeleton-text skeleton-stat"></view>
|
||
<view class="skeleton-text skeleton-stat"></view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 真实内容:资产卡片 -->
|
||
<view class="header-section" v-else>
|
||
<view class="asset-card">
|
||
|
||
|
||
<view class="card-row top-row">
|
||
<view class="row-left">
|
||
<text class="label-text">账本总额 (CNY)</text>
|
||
<view class="eye-btn">
|
||
<uni-icons type="eye-filled" size="18" color="rgba(255,255,255,0.7)"></uni-icons>
|
||
</view>
|
||
</view>
|
||
|
||
|
||
</view>
|
||
|
||
<view class="card-row main-row">
|
||
<text class="currency-symbol">¥</text>
|
||
<text class="big-number">{{ (assetData.totalValue || 0).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) }}</text>
|
||
</view>
|
||
|
||
<view class="card-row bottom-row">
|
||
<view class="stat-col">
|
||
<text class="stat-label">今日账面变动</text>
|
||
<text class="stat-value">{{ (assetData.todayProfit || 0) >= 0 ? '+' : '' }}{{ getCurrencySymbol(assetData.todayProfitCurrency || 'CNY') }}{{ (assetData.todayProfit || 0).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) }}</text>
|
||
</view>
|
||
<view class="stat-col align-right">
|
||
<text class="stat-label">历史总变动</text>
|
||
<text class="stat-value">{{ (assetData.totalReturnRate || 0) >= 0 ? '+' : '' }}{{ assetData.totalReturnRate || 0 }}%</text>
|
||
</view>
|
||
</view>
|
||
|
||
</view>
|
||
</view>
|
||
|
||
<view class="part-add-portfolio">
|
||
<view class="dashed-btn" @click="goConfig">
|
||
<uni-icons type="plus" size="20" color="#9CA3AF"></uni-icons>
|
||
<text class="btn-text">新建组合</text>
|
||
</view>
|
||
</view>
|
||
|
||
|
||
<view class="part-holdings-list">
|
||
|
||
<view class="section-header">
|
||
<text class="section-title">当前记录组合</text>
|
||
</view>
|
||
|
||
<!-- 骨架屏:持仓卡片 -->
|
||
<view v-if="loading" class="holding-card" v-for="i in 2" :key="'skeleton-' + i">
|
||
<view class="card-top">
|
||
<view class="flex-row items-center gap-2">
|
||
<view class="skeleton-icon"></view>
|
||
<view class="flex-col">
|
||
<view class="skeleton-text skeleton-name"></view>
|
||
<view class="skeleton-text skeleton-tags"></view>
|
||
</view>
|
||
</view>
|
||
<view class="skeleton-text skeleton-status"></view>
|
||
</view>
|
||
<view class="card-divider"></view>
|
||
<view class="card-bottom">
|
||
<view class="skeleton-text skeleton-data"></view>
|
||
<view class="skeleton-text skeleton-data"></view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 空状态 -->
|
||
<view v-else-if="holdings.length === 0" class="empty-state">
|
||
<view class="empty-icon">
|
||
<uni-icons type="folder" size="64" color="#D1D5DB"></uni-icons>
|
||
</view>
|
||
<text class="empty-title">暂无组合记录</text>
|
||
<text class="empty-desc">点击上方"新建组合"开始记账</text>
|
||
<view class="empty-btn" @click="goConfig">
|
||
<uni-icons type="plus" size="16" color="#064E3B"></uni-icons>
|
||
<text class="empty-btn-text">新建第一个组合</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 真实内容:持仓卡片 -->
|
||
<view
|
||
v-else
|
||
v-for="holding in holdings"
|
||
:key="holding.id"
|
||
class="holding-card"
|
||
@click="goDetail(holding.id)"
|
||
>
|
||
<view class="card-top">
|
||
<view class="flex-row items-center gap-2">
|
||
<view class="strategy-icon" :class="holding.iconBgClass">
|
||
<text class="icon-text" :class="holding.iconTextClass">{{ holding.iconChar }}</text>
|
||
</view>
|
||
<view class="flex-col">
|
||
<text class="card-name">{{ holding.name }}</text>
|
||
<text class="card-tags">{{ holding.tags }}</text>
|
||
</view>
|
||
</view>
|
||
<view class="status-badge" :class="getStatusBgClass(holding.statusType)">
|
||
<text class="status-text" :class="getStatusTextClass(holding.statusType)">● {{ holding.status }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="card-divider"></view>
|
||
|
||
<view class="card-bottom">
|
||
<view class="data-col">
|
||
<text class="data-label">当前估值</text>
|
||
<text class="data-val">{{ getCurrencySymbol(holding.currency) }}{{ (holding.value || 0).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) }}</text>
|
||
</view>
|
||
<view class="data-col align-right">
|
||
<text class="data-label">收益率</text>
|
||
<text class="data-val" :class="holding.returnType === 'positive' ? 'text-red' : 'text-green'">{{ (holding.returnRate || 0) >= 0 ? '+' : '' }}{{ holding.returnRate || 0 }}%</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="card-extra" v-if="holding.todayProfit">
|
||
<text class="extra-label">今日变动</text>
|
||
<text class="extra-val" :class="(holding.todayProfit || 0) >= 0 ? 'text-red' : 'text-green'">
|
||
{{ (holding.todayProfit || 0) >= 0 ? '+' : '' }}{{ getCurrencySymbol(holding.todayProfitCurrency || holding.currency) }}{{ Math.abs(holding.todayProfit || 0).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) }}
|
||
</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view style="height: 100rpx;"></view>
|
||
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref } from 'vue';
|
||
import { onShow, onPullDownRefresh } from '@dcloudio/uni-app';
|
||
import { api } from '@/utils/api';
|
||
import { getCurrencySymbol } from '@/utils/currency';
|
||
import type { PortfolioListItem, TotalAssetsResponse } from '@/types';
|
||
|
||
const loading = ref<boolean>(true);
|
||
const refreshing = ref<boolean>(false);
|
||
|
||
const assetData = ref<TotalAssetsResponse>({
|
||
totalValue: 0,
|
||
todayProfit: 0,
|
||
todayProfitCurrency: 'CNY',
|
||
totalReturnRate: 0
|
||
});
|
||
|
||
const holdings = ref<PortfolioListItem[]>([]);
|
||
|
||
const getStatusBgClass = (statusType?: string): string => {
|
||
const classes: Record<string, string> = {
|
||
'green': 'bg-green-50',
|
||
'yellow': 'bg-yellow-50',
|
||
'red': 'bg-red-50',
|
||
'gray': 'bg-gray-100'
|
||
};
|
||
return classes[statusType || 'gray'] || 'bg-gray-100';
|
||
};
|
||
|
||
const getStatusTextClass = (statusType?: string): string => {
|
||
const classes: Record<string, string> = {
|
||
'green': 'text-green-600',
|
||
'yellow': 'text-yellow-600',
|
||
'red': 'text-red-600',
|
||
'gray': 'text-gray-500'
|
||
};
|
||
return classes[statusType || 'gray'] || 'text-gray-500';
|
||
};
|
||
|
||
let isFetching = false;
|
||
|
||
const fetchAssetData = async (): Promise<void> => {
|
||
try {
|
||
const response = await api.assets.getAssetData();
|
||
if (response.code === 200) {
|
||
const data = response.data;
|
||
assetData.value = {
|
||
totalValue: data.totalValue,
|
||
todayProfit: data.todayProfit,
|
||
todayProfitCurrency: data.todayProfitCurrency || 'CNY',
|
||
totalReturnRate: data.totalReturnRate
|
||
};
|
||
}
|
||
} catch (error) {
|
||
console.error('获取资产数据失败:', error);
|
||
}
|
||
};
|
||
|
||
const fetchHoldingsData = async (): Promise<void> => {
|
||
try {
|
||
const response = await api.assets.getHoldings();
|
||
if (response.code === 200) {
|
||
const items = response.data.items || [];
|
||
holdings.value = items.map((item: any) => ({
|
||
id: item.id,
|
||
name: item.name,
|
||
tags: item.tags,
|
||
status: item.status,
|
||
statusType: item.statusType,
|
||
iconChar: item.iconChar,
|
||
iconBgClass: item.iconBgClass,
|
||
iconTextClass: item.iconTextClass,
|
||
value: item.value,
|
||
currency: item.currency,
|
||
returnRate: item.returnRate,
|
||
returnType: item.returnType,
|
||
todayProfit: item.todayProfit,
|
||
todayProfitCurrency: item.todayProfitCurrency
|
||
}));
|
||
}
|
||
} catch (error) {
|
||
console.error('获取持仓数据失败:', error);
|
||
}
|
||
};
|
||
|
||
const goConfig = (): void => {
|
||
uni.navigateTo({ url: '/pages/config/config' });
|
||
};
|
||
|
||
const goDetail = (holdingId?: string): void => {
|
||
if (holdingId) {
|
||
uni.navigateTo({ url: `/pages/detail/detail?id=${holdingId}` });
|
||
}
|
||
};
|
||
|
||
onShow(async () => {
|
||
isFetching = true;
|
||
loading.value = true;
|
||
await Promise.all([fetchAssetData(), fetchHoldingsData()]);
|
||
loading.value = false;
|
||
isFetching = false;
|
||
});
|
||
|
||
// 下拉刷新
|
||
onPullDownRefresh(async () => {
|
||
refreshing.value = true;
|
||
await Promise.all([fetchAssetData(), fetchHoldingsData()]);
|
||
refreshing.value = false;
|
||
uni.stopPullDownRefresh();
|
||
});
|
||
|
||
// 刷新按钮点击
|
||
const handleRefresh = async (): Promise<void> => {
|
||
loading.value = true;
|
||
await Promise.all([fetchAssetData(), fetchHoldingsData()]);
|
||
loading.value = false;
|
||
uni.showToast({ title: '刷新成功', icon: 'success', duration: 1500 });
|
||
};
|
||
</script>
|
||
|
||
<style scoped>
|
||
/* 通用布局 */
|
||
.page-container {
|
||
min-height: 100vh;
|
||
background-color: #F9FAFB;
|
||
/* 浅灰色背景,与添加按钮背景一致 */
|
||
}
|
||
|
||
.flex-row {
|
||
display: flex;
|
||
flex-direction: row;
|
||
}
|
||
|
||
.flex-col {
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.items-center {
|
||
align-items: center;
|
||
}
|
||
|
||
.gap-2 {
|
||
gap: 16rpx;
|
||
}
|
||
|
||
/* 字体颜色工具类 */
|
||
.text-gray-500 {
|
||
color: #6B7280;
|
||
}
|
||
|
||
.text-green-600 {
|
||
color: #059669;
|
||
}
|
||
|
||
.text-yellow-600 {
|
||
color: #D97706;
|
||
}
|
||
|
||
.text-red-600 {
|
||
color: #DC2626;
|
||
}
|
||
|
||
.text-red {
|
||
color: #EF4444;
|
||
}
|
||
|
||
/* 涨 */
|
||
.text-green {
|
||
color: #10B981;
|
||
}
|
||
|
||
/* 跌 */
|
||
|
||
/* ============================ */
|
||
/* 骨架屏样式 */
|
||
/* ============================ */
|
||
.skeleton-asset-card {
|
||
background-color: #064E3B;
|
||
border-radius: 40rpx;
|
||
padding: 40rpx 48rpx;
|
||
min-height: 320rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
}
|
||
|
||
.skeleton-row {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.skeleton-bottom {
|
||
justify-content: space-between;
|
||
}
|
||
|
||
.skeleton-text {
|
||
background: linear-gradient(90deg, rgba(255,255,255,0.1) 25%, rgba(255,255,255,0.2) 37%, rgba(255,255,255,0.1) 50%);
|
||
background-size: 400% 100%;
|
||
animation: skeleton-loading 1.8s ease infinite;
|
||
border-radius: 8rpx;
|
||
}
|
||
|
||
.skeleton-label {
|
||
width: 200rpx;
|
||
height: 28rpx;
|
||
}
|
||
|
||
.skeleton-big {
|
||
width: 400rpx;
|
||
height: 68rpx;
|
||
margin-top: 20rpx;
|
||
}
|
||
|
||
.skeleton-stat {
|
||
width: 180rpx;
|
||
height: 36rpx;
|
||
}
|
||
|
||
.skeleton-icon {
|
||
width: 80rpx;
|
||
height: 80rpx;
|
||
border-radius: 20rpx;
|
||
background: linear-gradient(90deg, #F1F2F4 25%, #e6e6e6 37%, #F1F2F4 50%);
|
||
background-size: 400% 100%;
|
||
animation: skeleton-loading 1.8s ease infinite;
|
||
}
|
||
|
||
.skeleton-name {
|
||
width: 160rpx;
|
||
height: 30rpx;
|
||
margin-bottom: 8rpx;
|
||
background: linear-gradient(90deg, #F1F2F4 25%, #e6e6e6 37%, #F1F2F4 50%);
|
||
background-size: 400% 100%;
|
||
animation: skeleton-loading 1.8s ease infinite;
|
||
}
|
||
|
||
.skeleton-tags {
|
||
width: 100rpx;
|
||
height: 22rpx;
|
||
background: linear-gradient(90deg, #F1F2F4 25%, #e6e6e6 37%, #F1F2F4 50%);
|
||
background-size: 400% 100%;
|
||
animation: skeleton-loading 1.8s ease infinite;
|
||
}
|
||
|
||
.skeleton-status {
|
||
width: 100rpx;
|
||
height: 32rpx;
|
||
border-radius: 100rpx;
|
||
background: linear-gradient(90deg, #F1F2F4 25%, #e6e6e6 37%, #F1F2F4 50%);
|
||
background-size: 400% 100%;
|
||
animation: skeleton-loading 1.8s ease infinite;
|
||
}
|
||
|
||
.skeleton-data {
|
||
width: 140rpx;
|
||
height: 32rpx;
|
||
background: linear-gradient(90deg, #F1F2F4 25%, #e6e6e6 37%, #F1F2F4 50%);
|
||
background-size: 400% 100%;
|
||
animation: skeleton-loading 1.8s ease infinite;
|
||
}
|
||
|
||
@keyframes skeleton-loading {
|
||
0% {
|
||
background-position: 100% 50%
|
||
}
|
||
100% {
|
||
background-position: 0 50%
|
||
}
|
||
}
|
||
|
||
/* ============================ */
|
||
/* Part 1: 资产卡片样式 (精修版) */
|
||
/* ============================ */
|
||
.header-section {
|
||
padding: 20rpx 32rpx;
|
||
background-color: #F9FAFB;
|
||
/* 浅灰色背景,与页面背景一致 */
|
||
}
|
||
|
||
.asset-card {
|
||
background-color: #064E3B;
|
||
/* 深墨绿色 */
|
||
border-radius: 40rpx;
|
||
padding: 40rpx 48rpx;
|
||
position: relative;
|
||
overflow: hidden;
|
||
box-shadow: 0 10rpx 30rpx rgba(6, 78, 59, 0.25);
|
||
min-height: 320rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
}
|
||
|
||
|
||
/* 内容行通用设置 */
|
||
.card-row {
|
||
position: relative;
|
||
z-index: 1;
|
||
}
|
||
|
||
/* 第一行:顶部布局 (关键修复:两端对齐) */
|
||
.top-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
/* 让铃铛靠右 */
|
||
align-items: center;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.row-left {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.label-text {
|
||
font-size: 26rpx;
|
||
color: rgba(255, 255, 255, 0.7);
|
||
font-weight: 400;
|
||
}
|
||
|
||
.eye-btn {
|
||
margin-left: 12rpx;
|
||
opacity: 0.8;
|
||
}
|
||
|
||
|
||
/* 第二行:大数字 */
|
||
.main-row {
|
||
display: flex;
|
||
align-items: baseline;
|
||
margin-bottom: 30rpx;
|
||
}
|
||
|
||
.currency-symbol {
|
||
font-size: 40rpx;
|
||
color: #FFFFFF;
|
||
font-weight: bold;
|
||
margin-right: 8rpx;
|
||
font-family: 'DIN Alternate', sans-serif;
|
||
}
|
||
|
||
.big-number {
|
||
font-size: 68rpx;
|
||
color: #FFFFFF;
|
||
font-weight: 800;
|
||
letter-spacing: 1rpx;
|
||
font-family: 'DIN Alternate', sans-serif;
|
||
}
|
||
|
||
/* 第三行:底部数据 */
|
||
.bottom-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: flex-end;
|
||
}
|
||
|
||
.stat-col {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8rpx;
|
||
}
|
||
|
||
.align-right {
|
||
align-items: flex-end;
|
||
}
|
||
|
||
.stat-label {
|
||
font-size: 24rpx;
|
||
color: rgba(255, 255, 255, 0.6);
|
||
}
|
||
|
||
.stat-value {
|
||
font-size: 36rpx;
|
||
color: #FFFFFF;
|
||
font-weight: 700;
|
||
font-family: 'DIN Alternate', sans-serif;
|
||
}
|
||
|
||
/* ============================ */
|
||
/* Part 2: 添加组合按钮样式 */
|
||
/* ============================ */
|
||
.part-add-portfolio {
|
||
padding: 10rpx 32rpx 30rpx 32rpx;
|
||
}
|
||
|
||
.dashed-btn {
|
||
width: 100%;
|
||
height: 96rpx;
|
||
background-color: #F9FAFB;
|
||
border: 2rpx dashed #D1D5DB;
|
||
border-radius: 24rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 12rpx;
|
||
transition: all 0.2s;
|
||
}
|
||
|
||
.dashed-btn:active {
|
||
background-color: #F3F4F6;
|
||
border-color: #9CA3AF;
|
||
}
|
||
|
||
.btn-text {
|
||
font-size: 28rpx;
|
||
color: #6B7280;
|
||
font-weight: 500;
|
||
}
|
||
|
||
/* ============================ */
|
||
/* Part 3: 持仓列表样式 */
|
||
/* ============================ */
|
||
.part-holdings-list {
|
||
padding: 0 32rpx;
|
||
}
|
||
|
||
.section-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 24rpx;
|
||
padding-left: 8rpx;
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 32rpx;
|
||
font-weight: 800;
|
||
color: #1F2937;
|
||
}
|
||
|
||
/* 卡片样式 */
|
||
.holding-card {
|
||
background-color: #FFFFFF;
|
||
border: 1rpx solid #E5E7EB;
|
||
border-radius: 32rpx;
|
||
padding: 32rpx;
|
||
margin-bottom: 24rpx;
|
||
box-shadow: 0 12rpx 32rpx rgba(0, 0, 0, 0.06);
|
||
transition: all 0.2s ease;
|
||
}
|
||
|
||
.holding-card:active {
|
||
transform: translateY(2rpx);
|
||
box-shadow: 0 6rpx 16rpx rgba(0, 0, 0, 0.04);
|
||
}
|
||
|
||
.card-top {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: flex-start;
|
||
}
|
||
|
||
.strategy-icon {
|
||
width: 80rpx;
|
||
height: 80rpx;
|
||
border-radius: 20rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.bg-green-50 {
|
||
background-color: #ECFDF5;
|
||
}
|
||
|
||
.bg-yellow-50 {
|
||
background-color: #FFFBEB;
|
||
}
|
||
|
||
.bg-red-50 {
|
||
background-color: #FEF2F2;
|
||
}
|
||
|
||
.bg-gray-100 {
|
||
background-color: #F3F4F6;
|
||
}
|
||
|
||
.icon-text {
|
||
font-size: 36rpx;
|
||
font-weight: 800;
|
||
}
|
||
|
||
.card-name {
|
||
font-size: 30rpx;
|
||
font-weight: 700;
|
||
color: #1F2937;
|
||
margin-bottom: 6rpx;
|
||
max-width: 320rpx;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.card-tags {
|
||
font-size: 22rpx;
|
||
color: #9CA3AF;
|
||
}
|
||
|
||
.status-badge {
|
||
padding: 6rpx 16rpx;
|
||
border-radius: 100rpx;
|
||
}
|
||
|
||
.status-text {
|
||
font-size: 20rpx;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.card-divider {
|
||
height: 1rpx;
|
||
background-color: #F3F4F6;
|
||
margin: 24rpx 0;
|
||
}
|
||
|
||
.card-bottom {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
}
|
||
|
||
.data-col {
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.data-label {
|
||
font-size: 22rpx;
|
||
color: #9CA3AF;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.data-val {
|
||
font-size: 32rpx;
|
||
font-weight: 700;
|
||
font-family: 'DIN Alternate', sans-serif;
|
||
color: #1F2937;
|
||
}
|
||
|
||
.card-extra {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-top: 16rpx;
|
||
padding-top: 16rpx;
|
||
border-top: 1rpx solid #F3F4F6;
|
||
}
|
||
|
||
.extra-label {
|
||
font-size: 22rpx;
|
||
color: #9CA3AF;
|
||
}
|
||
|
||
.extra-val {
|
||
font-size: 28rpx;
|
||
font-weight: 600;
|
||
font-family: 'DIN Alternate', sans-serif;
|
||
}
|
||
|
||
/* 空状态 */
|
||
.empty-state {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 80rpx 40rpx;
|
||
background-color: #FFFFFF;
|
||
border-radius: 32rpx;
|
||
margin: 20rpx 0;
|
||
}
|
||
|
||
.empty-icon {
|
||
margin-bottom: 32rpx;
|
||
}
|
||
|
||
.empty-title {
|
||
font-size: 32rpx;
|
||
font-weight: 700;
|
||
color: #374151;
|
||
margin-bottom: 16rpx;
|
||
}
|
||
|
||
.empty-desc {
|
||
font-size: 26rpx;
|
||
color: #9CA3AF;
|
||
margin-bottom: 40rpx;
|
||
}
|
||
|
||
.empty-btn {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
background-color: #ECFDF5;
|
||
padding: 20rpx 40rpx;
|
||
border-radius: 100rpx;
|
||
border: 2rpx solid #10B981;
|
||
}
|
||
|
||
.empty-btn:active {
|
||
background-color: #D1FAE5;
|
||
}
|
||
|
||
.empty-btn-text {
|
||
font-size: 28rpx;
|
||
font-weight: 600;
|
||
color: #064E3B;
|
||
}
|
||
</style> |