|
@@ -1,73 +1,94 @@
|
|
|
<template>
|
|
<template>
|
|
|
<view class="order-statistics">
|
|
<view class="order-statistics">
|
|
|
|
|
+ <u-skeleton :loading="loading" :rows="4" title></u-skeleton>
|
|
|
<!-- 顶部统计卡片 -->
|
|
<!-- 顶部统计卡片 -->
|
|
|
- <view class="overview-card">
|
|
|
|
|
- <view class="overview-grid">
|
|
|
|
|
- <view class="grid-item">
|
|
|
|
|
- <text class="item-label">今日订单</text>
|
|
|
|
|
- <text class="item-value">{{
|
|
|
|
|
- orderStatData.todayOrderNum || 0
|
|
|
|
|
- }}</text>
|
|
|
|
|
- </view>
|
|
|
|
|
- <view class="grid-item">
|
|
|
|
|
- <text class="item-label">昨日订单</text>
|
|
|
|
|
- <text class="item-value">{{
|
|
|
|
|
- orderStatData.yesterdayOrderNum || 0
|
|
|
|
|
- }}</text>
|
|
|
|
|
- </view>
|
|
|
|
|
- <view class="grid-item">
|
|
|
|
|
- <text class="item-label">本月订单</text>
|
|
|
|
|
- <text class="item-value"
|
|
|
|
|
- >{{ formatOrderNum(orderStatData.monthOrderNum) || 0
|
|
|
|
|
- }}<text
|
|
|
|
|
- class="unit"
|
|
|
|
|
- v-if="orderStatData.monthOrderNum > 10000"
|
|
|
|
|
- >万</text
|
|
|
|
|
- ></text
|
|
|
|
|
- >
|
|
|
|
|
|
|
+ <view v-if="!loading">
|
|
|
|
|
+ <view class="overview-card">
|
|
|
|
|
+ <view class="overview-grid">
|
|
|
|
|
+ <view class="grid-item">
|
|
|
|
|
+ <text class="item-label">今日订单</text>
|
|
|
|
|
+ <text class="item-value">{{ orderStatData.todayOrderNum || 0 }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="grid-item">
|
|
|
|
|
+ <text class="item-label">昨日订单</text>
|
|
|
|
|
+ <text class="item-value">{{ orderStatData.yesterdayOrderNum || 0 }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="grid-item">
|
|
|
|
|
+ <text class="item-label">本月订单</text>
|
|
|
|
|
+ <text class="item-value">{{ formatOrderNum(orderStatData.monthOrderNum) || 0 }}<text
|
|
|
|
|
+ class="unit" v-if="orderStatData.monthOrderNum > 10000">万</text></text>
|
|
|
|
|
+ </view>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
- </view>
|
|
|
|
|
|
|
|
|
|
- <!-- 订单状态网格 -->
|
|
|
|
|
- <view class="status-grid">
|
|
|
|
|
- <view
|
|
|
|
|
- v-for="(item, index) in statusList"
|
|
|
|
|
- :key="index"
|
|
|
|
|
- class="status-item"
|
|
|
|
|
- @tap="navigateToDetail(item.path)"
|
|
|
|
|
- >
|
|
|
|
|
- <view class="status-content">
|
|
|
|
|
- <text class="status-label">{{ item.label }}</text>
|
|
|
|
|
- <view class="status-value-wrap">
|
|
|
|
|
- <text class="status-value">{{
|
|
|
|
|
- orderStatData[item.key] || 0
|
|
|
|
|
- }}</text>
|
|
|
|
|
- <u-icon
|
|
|
|
|
- name="arrow-right"
|
|
|
|
|
- color="#999"
|
|
|
|
|
- size="14"
|
|
|
|
|
- ></u-icon>
|
|
|
|
|
|
|
+ <!-- 订单状态网格 -->
|
|
|
|
|
+ <view class="status-grid">
|
|
|
|
|
+ <view v-for="(item, index) in statusList" :key="index" class="status-item"
|
|
|
|
|
+ @tap="navigateToDetail(item.path)">
|
|
|
|
|
+ <view class="status-content">
|
|
|
|
|
+ <text class="status-label">{{ item.label }}</text>
|
|
|
|
|
+ <view class="status-value-wrap">
|
|
|
|
|
+ <text class="status-value">{{
|
|
|
|
|
+ orderStatData[item.key] || 0
|
|
|
|
|
+ }}</text>
|
|
|
|
|
+ <u-icon name="arrow-right" color="#999" size="14"></u-icon>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="workorder-section">
|
|
|
|
|
+ <view class="workorder-card">
|
|
|
|
|
+ <view class="workorder-header">
|
|
|
|
|
+ <view class="header-left">
|
|
|
|
|
+ <view class="dot"></view><text>回收工单</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="workorder-body">
|
|
|
|
|
+ <view @tap="navigateToDetail('/pages/order/recycle/pending')">
|
|
|
|
|
+ <text class="workorder-label">待我完成</text>
|
|
|
|
|
+ <text class="workorder-value">{{
|
|
|
|
|
+ workOrderStat.recycle.myPending || 0
|
|
|
|
|
+ }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view @tap="navigateToDetail('/pages/order/recycle/created')">
|
|
|
|
|
+ <text class="workorder-label">我创建的</text>
|
|
|
|
|
+ <text class="workorder-value">{{
|
|
|
|
|
+ workOrderStat.recycle.myCreated || 0
|
|
|
|
|
+ }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="workorder-card">
|
|
|
|
|
+ <view class="workorder-header">
|
|
|
|
|
+ <view class="header-left">
|
|
|
|
|
+ <view class="dot"></view><text>商城工单</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="workorder-body">
|
|
|
|
|
+ <view @tap="navigateToDetail('/pages/order/mall/pending')">
|
|
|
|
|
+ <text class="workorder-label">待我完成</text>
|
|
|
|
|
+ <text class="workorder-value">{{
|
|
|
|
|
+ workOrderStat.mall.myPending || 0
|
|
|
|
|
+ }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view @tap="navigateToDetail('/pages/order/mall/created')">
|
|
|
|
|
+ <text class="workorder-label">我创建的</text>
|
|
|
|
|
+ <text class="workorder-value">{{
|
|
|
|
|
+ workOrderStat.mall.myCreated || 0
|
|
|
|
|
+ }}</text>
|
|
|
|
|
+ </view>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
- </view>
|
|
|
|
|
|
|
|
|
|
- <!-- 底部操作项 -->
|
|
|
|
|
- <view class="bottom-actions">
|
|
|
|
|
- <u-cell-group :border="false">
|
|
|
|
|
- <u-cell
|
|
|
|
|
- title="收货统计"
|
|
|
|
|
- isLink
|
|
|
|
|
- @click="navigateToDetail('/pages/order/stat/receive-stat')"
|
|
|
|
|
- ></u-cell>
|
|
|
|
|
- <u-cell
|
|
|
|
|
- title="全部订单"
|
|
|
|
|
- isLink
|
|
|
|
|
- @click="navigateToDetail('/pages/order/stat/all')"
|
|
|
|
|
- :border="false"
|
|
|
|
|
- ></u-cell>
|
|
|
|
|
- </u-cell-group>
|
|
|
|
|
|
|
+ <!-- 底部操作项 -->
|
|
|
|
|
+ <view class="bottom-actions">
|
|
|
|
|
+ <u-cell-group :border="false">
|
|
|
|
|
+ <u-cell title="收货统计" isLink @click="navigateToDetail('/pages/order/stat/receive-stat')"></u-cell>
|
|
|
|
|
+ <u-cell title="全部订单" isLink @click="navigateToDetail('/pages/order/stat/all')"
|
|
|
|
|
+ :border="false"></u-cell>
|
|
|
|
|
+ </u-cell-group>
|
|
|
|
|
+ </view>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
</template>
|
|
</template>
|
|
@@ -77,6 +98,7 @@ import { ref, onMounted, computed } from "vue";
|
|
|
|
|
|
|
|
// 订单统计数据
|
|
// 订单统计数据
|
|
|
const orderStatData = ref({});
|
|
const orderStatData = ref({});
|
|
|
|
|
+const loading = ref(true);
|
|
|
|
|
|
|
|
// 订单状态数据
|
|
// 订单状态数据
|
|
|
const statusList = computed(() => [
|
|
const statusList = computed(() => [
|
|
@@ -118,6 +140,11 @@ const statusList = computed(() => [
|
|
|
},
|
|
},
|
|
|
]);
|
|
]);
|
|
|
|
|
|
|
|
|
|
+const workOrderStat = ref({
|
|
|
|
|
+ recycle: { myPending: 0, myCreated: 0 },
|
|
|
|
|
+ mall: { myPending: 0, myCreated: 0 },
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
// 格式化订单数量(超过万的显示为X.XX万)
|
|
// 格式化订单数量(超过万的显示为X.XX万)
|
|
|
const formatOrderNum = (num) => {
|
|
const formatOrderNum = (num) => {
|
|
|
if (!num) return 0;
|
|
if (!num) return 0;
|
|
@@ -129,35 +156,43 @@ const formatOrderNum = (num) => {
|
|
|
|
|
|
|
|
// 获取订单统计数据
|
|
// 获取订单统计数据
|
|
|
const getOrderStatData = async () => {
|
|
const getOrderStatData = async () => {
|
|
|
- uni.showLoading({
|
|
|
|
|
- title: "加载中...",
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res = await uni.$u.http.get("/app/ordersignstat/getPdaOrderStat");
|
|
|
|
|
+ if (res.code === 200) {
|
|
|
|
|
+ orderStatData.value = res.data || {};
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (e) { }
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
- uni.$u.http
|
|
|
|
|
- .get("/app/ordersignstat/getPdaOrderStat")
|
|
|
|
|
- .then((res) => {
|
|
|
|
|
- if (res.code === 200) {
|
|
|
|
|
- orderStatData.value = res.data;
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- .finally(() => {
|
|
|
|
|
- uni.hideLoading();
|
|
|
|
|
- });
|
|
|
|
|
|
|
+const getWorkOrderStat = async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const [recycleRes, mallRes] = await Promise.all([
|
|
|
|
|
+ uni.$u.http.get("/app/workorder/stat", { params: { type: "recycle" } }),
|
|
|
|
|
+ uni.$u.http.get("/app/workorder/stat", { params: { type: "mall" } }),
|
|
|
|
|
+ ]);
|
|
|
|
|
+ if (recycleRes.code === 200 && recycleRes.data) {
|
|
|
|
|
+ workOrderStat.value.recycle.myPending = recycleRes.data.myPending || 0;
|
|
|
|
|
+ workOrderStat.value.recycle.myCreated = recycleRes.data.myCreated || 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (mallRes.code === 200 && mallRes.data) {
|
|
|
|
|
+ workOrderStat.value.mall.myPending = mallRes.data.myPending || 0;
|
|
|
|
|
+ workOrderStat.value.mall.myCreated = mallRes.data.myCreated || 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (e) { }
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
// 页面跳转
|
|
// 页面跳转
|
|
|
const navigateToDetail = (path) => {
|
|
const navigateToDetail = (path) => {
|
|
|
- if(path!='/pages/order/stat/receive-stat'){
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
uni.navigateTo({
|
|
uni.navigateTo({
|
|
|
url: path,
|
|
url: path,
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
// 页面加载时获取数据
|
|
// 页面加载时获取数据
|
|
|
-onMounted(() => {
|
|
|
|
|
- getOrderStatData();
|
|
|
|
|
|
|
+onMounted(async () => {
|
|
|
|
|
+ loading.value = true;
|
|
|
|
|
+ await Promise.all([getOrderStatData(), getWorkOrderStat()]);
|
|
|
|
|
+ loading.value = false;
|
|
|
});
|
|
});
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
@@ -168,13 +203,14 @@ page {
|
|
|
</style>
|
|
</style>
|
|
|
<style lang="scss" scoped>
|
|
<style lang="scss" scoped>
|
|
|
.order-statistics {
|
|
.order-statistics {
|
|
|
- padding: 20rpx;
|
|
|
|
|
|
|
+ padding: 26rpx;
|
|
|
|
|
|
|
|
.overview-card {
|
|
.overview-card {
|
|
|
- background: #ffffff;
|
|
|
|
|
|
|
+ background: linear-gradient(135deg, #22ac38 0%, #41c957 100%);
|
|
|
border-radius: 16rpx;
|
|
border-radius: 16rpx;
|
|
|
- padding: 30rpx 20rpx;
|
|
|
|
|
|
|
+ padding: 32rpx 24rpx;
|
|
|
margin-bottom: 20rpx;
|
|
margin-bottom: 20rpx;
|
|
|
|
|
+ box-shadow: 0 12rpx 24rpx rgba(34, 172, 56, 0.15);
|
|
|
|
|
|
|
|
.overview-grid {
|
|
.overview-grid {
|
|
|
display: flex;
|
|
display: flex;
|
|
@@ -193,24 +229,25 @@ page {
|
|
|
transform: translateY(-50%);
|
|
transform: translateY(-50%);
|
|
|
height: 60%;
|
|
height: 60%;
|
|
|
width: 2rpx;
|
|
width: 2rpx;
|
|
|
- background: #eeeeee;
|
|
|
|
|
|
|
+ background: rgba(255, 255, 255, 0.35);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.item-label {
|
|
.item-label {
|
|
|
- font-size: 32rpx;
|
|
|
|
|
- color: #666666;
|
|
|
|
|
|
|
+ font-size: 30rpx;
|
|
|
|
|
+ color: #ffffffcc;
|
|
|
margin-bottom: 12rpx;
|
|
margin-bottom: 12rpx;
|
|
|
display: block;
|
|
display: block;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.item-value {
|
|
.item-value {
|
|
|
- font-size: 44rpx;
|
|
|
|
|
- color: #333333;
|
|
|
|
|
|
|
+ font-size: 48rpx;
|
|
|
|
|
+ color: #ffffff;
|
|
|
font-weight: 500;
|
|
font-weight: 500;
|
|
|
|
|
|
|
|
.unit {
|
|
.unit {
|
|
|
- font-size: 24rpx;
|
|
|
|
|
|
|
+ font-size: 26rpx;
|
|
|
margin-left: 4rpx;
|
|
margin-left: 4rpx;
|
|
|
|
|
+ color: #ffffffcc;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -232,12 +269,14 @@ page {
|
|
|
.status-item {
|
|
.status-item {
|
|
|
background: #ffffff;
|
|
background: #ffffff;
|
|
|
border-radius: 16rpx;
|
|
border-radius: 16rpx;
|
|
|
- padding: 24rpx 12rpx;
|
|
|
|
|
|
|
+ padding: 26rpx 14rpx;
|
|
|
|
|
+ box-shadow: 0 8rpx 20rpx rgba(0, 0, 0, 0.04);
|
|
|
|
|
+ border: 1rpx solid #f0f2f5;
|
|
|
|
|
|
|
|
.status-content {
|
|
.status-content {
|
|
|
.status-label {
|
|
.status-label {
|
|
|
- font-size: 32rpx;
|
|
|
|
|
- color: #666666;
|
|
|
|
|
|
|
+ font-size: 30rpx;
|
|
|
|
|
+ color: #333333;
|
|
|
margin-bottom: 16rpx;
|
|
margin-bottom: 16rpx;
|
|
|
display: block;
|
|
display: block;
|
|
|
}
|
|
}
|
|
@@ -248,7 +287,7 @@ page {
|
|
|
justify-content: space-between;
|
|
justify-content: space-between;
|
|
|
|
|
|
|
|
.status-value {
|
|
.status-value {
|
|
|
- font-size: 44rpx;
|
|
|
|
|
|
|
+ font-size: 46rpx;
|
|
|
color: #333333;
|
|
color: #333333;
|
|
|
font-weight: 500;
|
|
font-weight: 500;
|
|
|
}
|
|
}
|
|
@@ -265,6 +304,63 @@ page {
|
|
|
background: #ffffff;
|
|
background: #ffffff;
|
|
|
border-radius: 16rpx;
|
|
border-radius: 16rpx;
|
|
|
overflow: hidden;
|
|
overflow: hidden;
|
|
|
|
|
+ box-shadow: 0 8rpx 20rpx rgba(0, 0, 0, 0.04);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .workorder-section {
|
|
|
|
|
+ display: grid;
|
|
|
|
|
+ grid-template-columns: 1fr;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .workorder-card {
|
|
|
|
|
+ background: #ffffff;
|
|
|
|
|
+ border-radius: 16rpx;
|
|
|
|
|
+ padding: 26rpx;
|
|
|
|
|
+ margin-bottom: 20rpx;
|
|
|
|
|
+ box-shadow: 0 8rpx 20rpx rgba(0, 0, 0, 0.04);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .workorder-header {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ font-size: 32rpx;
|
|
|
|
|
+ color: #22ac38;
|
|
|
|
|
+ margin-bottom: 16rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .header-left {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .dot {
|
|
|
|
|
+ width: 16rpx;
|
|
|
|
|
+ height: 16rpx;
|
|
|
|
|
+ border-radius: 50%;
|
|
|
|
|
+ background: #22ac38;
|
|
|
|
|
+ margin-right: 12rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .workorder-body {
|
|
|
|
|
+ display: grid;
|
|
|
|
|
+ grid-template-columns: 1fr 1fr;
|
|
|
|
|
+ gap: 12rpx;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .workorder-label {
|
|
|
|
|
+ font-size: 28rpx;
|
|
|
|
|
+ color: #666666;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .workorder-value {
|
|
|
|
|
+ font-size: 44rpx;
|
|
|
|
|
+ color: #333333;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ margin-left: 20rpx;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
</style>
|
|
</style>
|