diff --git a/pages/config/config.vue b/pages/config/config.vue index 9c62f96..043138c 100755 --- a/pages/config/config.vue +++ b/pages/config/config.vue @@ -2,8 +2,27 @@ - - + + + + + + + + + + + + + + + + + + + + + @@ -164,6 +183,9 @@ import { api } from '../../utils/api'; const { proxy } = getCurrentInstance(); const uToastRef = ref(); +// 加载状态 +const loading = ref(true); + const strategies = ref([]); const strategyIndex = ref(-1); // 币种选择 @@ -401,7 +423,9 @@ const submitForm = async () => { onShow(async () => { isFetching = true; + loading.value = true; await fetchStrategies(); + loading.value = false; isFetching = false; }); @@ -412,7 +436,60 @@ onShow(async () => { min-height: 100vh; background-color: #F3F4F6; padding-bottom: 200rpx; - /* 给底部按钮留空 */ +} + +/* 骨架屏样式 */ +.skeleton-form-item { + margin-bottom: 32rpx; +} + +.skeleton-label { + width: 120rpx; + height: 26rpx; + background: linear-gradient(90deg, #E5E7EB 25%, #F3F4F6 37%, #E5E7EB 50%); + background-size: 400% 100%; + animation: skeleton-loading 1.8s ease infinite; + border-radius: 8rpx; + margin-bottom: 16rpx; +} + +.skeleton-label-sm { + width: 80rpx; + height: 22rpx; + background: linear-gradient(90deg, #E5E7EB 25%, #F3F4F6 37%, #E5E7EB 50%); + background-size: 400% 100%; + animation: skeleton-loading 1.8s ease infinite; + border-radius: 6rpx; + margin-bottom: 12rpx; +} + +.skeleton-input { + width: 100%; + height: 96rpx; + background: linear-gradient(90deg, #F9FAFB 25%, #F3F4F6 37%, #F9FAFB 50%); + background-size: 400% 100%; + animation: skeleton-loading 1.8s ease infinite; + border-radius: 20rpx; +} + +.skeleton-input-sm { + flex: 1; + height: 72rpx; + background: linear-gradient(90deg, #F9FAFB 25%, #F3F4F6 37%, #F9FAFB 50%); + background-size: 400% 100%; + animation: skeleton-loading 1.8s ease infinite; + border-radius: 16rpx; +} + +.skeleton-row { + display: flex; + gap: 24rpx; + flex-direction: column; +} + +@keyframes skeleton-loading { + 0% { background-position: 100% 50% } + 100% { background-position: 0 50% } } .flex-row { diff --git a/pages/detail/detail.vue b/pages/detail/detail.vue index db7259d..9c11091 100755 --- a/pages/detail/detail.vue +++ b/pages/detail/detail.vue @@ -3,8 +3,25 @@ - - + + + + + + + + + + + + + + + + + + + @@ -367,6 +384,9 @@ import { api } from '../../utils/api'; const { proxy } = getCurrentInstance(); const uToastRef = ref(); +// 加载状态 +const loading = ref(true); + // 获取货币符号 const getCurrencySymbol = (currency) => { const symbols = { @@ -541,8 +561,10 @@ const fetchTransactions = async () => { }; onMounted(async () => { + loading.value = true; await fetchPortfolioData(); await fetchTransactions(); + loading.value = false; }); const goStrategyConfig = () => { @@ -712,9 +734,62 @@ const deletePortfolio = async () => { .page-container { min-height: 100vh; background-color: #F9FAFB; - /* 关键:底部留出空间,防止内容被固定按钮遮挡 */ padding-bottom: 180rpx; } + +/* 骨架屏样式 */ +.skeleton-card { + background-color: #064E3B; + border-radius: 40rpx; + padding: 40rpx 48rpx; + min-height: 320rpx; +} + +.skeleton-row { + display: flex; + align-items: center; + margin-bottom: 20rpx; +} + +.skeleton-bottom { + justify-content: space-between; + margin-bottom: 0; +} + +.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: 160rpx; + height: 28rpx; +} + +.skeleton-badge { + width: 120rpx; + height: 40rpx; + border-radius: 20rpx; +} + +.skeleton-big { + width: 350rpx; + height: 68rpx; +} + +.skeleton-stat { + width: 150rpx; + height: 36rpx; +} + +@keyframes skeleton-loading { + 0% { background-position: 100% 50% } + 100% { background-position: 0 50% } +} + +/* 工具类 */ .flex-row { display: flex; flex-direction: row; } .flex-col { display: flex; flex-direction: column; } .items-center { align-items: center; } diff --git a/pages/me/me.vue b/pages/me/me.vue index 028fdca..4acf8af 100755 --- a/pages/me/me.vue +++ b/pages/me/me.vue @@ -1,6 +1,20 @@