|
|
@@ -49,7 +49,7 @@
|
|
|
|
|
|
<!-- Hero -->
|
|
|
<view class="hero-section">
|
|
|
- <text class="hero-value">¥{{ formatAmount(todayRevenue) }}</text>
|
|
|
+ <text class="hero-value">¥{{ formatAmount(displayRevenue) }}</text>
|
|
|
<text class="hero-label">今日收入</text>
|
|
|
</view>
|
|
|
|
|
|
@@ -75,11 +75,11 @@
|
|
|
<!-- 主指标:订单 + 洗车人数 -->
|
|
|
<view class="metrics-primary">
|
|
|
<view class="metric-card-lg">
|
|
|
- <text class="metric-lg-value">{{ todayOrders }}</text>
|
|
|
+ <text class="metric-lg-value">{{ Math.round(displayOrders) }}</text>
|
|
|
<text class="metric-lg-label">今日订单</text>
|
|
|
</view>
|
|
|
<view class="metric-card-lg">
|
|
|
- <text class="metric-lg-value">{{ todayWashUsers }}</text>
|
|
|
+ <text class="metric-lg-value">{{ Math.round(displayWashUsers) }}</text>
|
|
|
<text class="metric-lg-label">洗车人数</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
@@ -87,11 +87,11 @@
|
|
|
<!-- 主指标:消费总额 + 今日退款 -->
|
|
|
<view class="metrics-primary">
|
|
|
<view class="metric-card-lg">
|
|
|
- <text class="metric-lg-value">¥{{ formatAmount(todayConsumption) }}</text>
|
|
|
+ <text class="metric-lg-value">¥{{ formatAmount(displayConsumption) }}</text>
|
|
|
<text class="metric-lg-label">消费总额</text>
|
|
|
</view>
|
|
|
<view class="metric-card-lg">
|
|
|
- <text class="metric-lg-value">¥{{ formatAmount(todayRefund) }}</text>
|
|
|
+ <text class="metric-lg-value">¥{{ formatAmount(displayRefund) }}</text>
|
|
|
<text class="metric-lg-label">今日退款</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
@@ -214,6 +214,7 @@ import { getDashboardData, getDeviceStatus } from '../../api/stat.js'
|
|
|
import { getStationList } from '../../api/station.js'
|
|
|
import { loadDicts } from '../../utils/dict.js'
|
|
|
import { storage, showToast, formatAmount } from '../../utils/index.js'
|
|
|
+import { animateNumber } from '../../utils/countup.js'
|
|
|
|
|
|
const userInfo = ref(storage.get('userInfo'))
|
|
|
const loading = ref(false)
|
|
|
@@ -224,11 +225,12 @@ const stationList = ref([])
|
|
|
const currentStation = ref(null)
|
|
|
const selectedStationIndex = ref(0)
|
|
|
|
|
|
-const todayRevenue = ref(0)
|
|
|
-const todayOrders = ref(0)
|
|
|
-const todayWashUsers = ref(0)
|
|
|
-const todayConsumption = ref(0)
|
|
|
-const todayRefund = ref(0)
|
|
|
+// 主指标展示值(数字滚动动画)
|
|
|
+const displayRevenue = ref(0)
|
|
|
+const displayOrders = ref(0)
|
|
|
+const displayWashUsers = ref(0)
|
|
|
+const displayConsumption = ref(0)
|
|
|
+const displayRefund = ref(0)
|
|
|
const avgOrderPrice = ref(0)
|
|
|
const avgDuration = ref(0)
|
|
|
const todayMembers = ref(0)
|
|
|
@@ -315,11 +317,11 @@ const loadData = async (stationId) => {
|
|
|
|
|
|
if (dashboardRes && dashboardRes.code === 200) {
|
|
|
const data = dashboardRes.data
|
|
|
- todayRevenue.value = data.todayIncome || 0
|
|
|
- todayOrders.value = data.todayWashOrders || 0
|
|
|
- todayWashUsers.value = data.todayWashUsers || 0
|
|
|
- todayConsumption.value = data.todayConsumptionAmount || 0
|
|
|
- todayRefund.value = data.todayRefundAmount || 0
|
|
|
+ animateNumber(displayRevenue, data.todayIncome || 0)
|
|
|
+ animateNumber(displayOrders, data.todayWashOrders || 0)
|
|
|
+ animateNumber(displayWashUsers, data.todayWashUsers || 0)
|
|
|
+ animateNumber(displayConsumption, data.todayConsumptionAmount || 0)
|
|
|
+ animateNumber(displayRefund, data.todayRefundAmount || 0)
|
|
|
avgOrderPrice.value = data.avgOrderPrice || 0
|
|
|
avgDuration.value = Math.round((data.avgOrderDuration || 0) / 60 * 10) / 10
|
|
|
todayMembers.value = data.todayRegisteredMembers || 0
|
|
|
@@ -651,7 +653,9 @@ onPullDownRefresh(async () => {
|
|
|
.skeleton-greeting {
|
|
|
width: 180rpx;
|
|
|
height: 30rpx;
|
|
|
- background: #E8E8E8;
|
|
|
+ background: linear-gradient(90deg, #ECEFF3 25%, #F7F9FB 37%, #ECEFF3 63%);
|
|
|
+ background-size: 800rpx 100%;
|
|
|
+ animation: app-shimmer 1.4s linear infinite;
|
|
|
border-radius: 8rpx;
|
|
|
margin: 32rpx auto;
|
|
|
}
|
|
|
@@ -662,7 +666,9 @@ onPullDownRefresh(async () => {
|
|
|
padding: 0 0 44rpx;
|
|
|
}
|
|
|
.skeleton-line {
|
|
|
- background: #E8E8E8;
|
|
|
+ background: linear-gradient(90deg, #ECEFF3 25%, #F7F9FB 37%, #ECEFF3 63%);
|
|
|
+ background-size: 800rpx 100%;
|
|
|
+ animation: app-shimmer 1.4s linear infinite;
|
|
|
border-radius: 8rpx;
|
|
|
}
|
|
|
.skeleton-line.hero-num {
|
|
|
@@ -693,7 +699,9 @@ onPullDownRefresh(async () => {
|
|
|
}
|
|
|
.skeleton-cell {
|
|
|
height: 120rpx;
|
|
|
- background: #E8E8E8;
|
|
|
+ background: linear-gradient(90deg, #ECEFF3 25%, #F7F9FB 37%, #ECEFF3 63%);
|
|
|
+ background-size: 800rpx 100%;
|
|
|
+ animation: app-shimmer 1.4s linear infinite;
|
|
|
border-radius: 24rpx;
|
|
|
}
|
|
|
.skeleton-cell.sm {
|
|
|
@@ -708,7 +716,9 @@ onPullDownRefresh(async () => {
|
|
|
.skeleton-action {
|
|
|
flex: 1;
|
|
|
height: 170rpx;
|
|
|
- background: #E8E8E8;
|
|
|
+ background: linear-gradient(90deg, #ECEFF3 25%, #F7F9FB 37%, #ECEFF3 63%);
|
|
|
+ background-size: 800rpx 100%;
|
|
|
+ animation: app-shimmer 1.4s linear infinite;
|
|
|
border-radius: 24rpx;
|
|
|
}
|
|
|
|