848 lines
23 KiB
Vue
848 lines
23 KiB
Vue
<template>
|
|
<page-container>
|
|
<div class="dashboard">
|
|
<a-row :gutter="{ xs: 8, sm: 16, md: 24 }" class="data-overview">
|
|
<!-- 用户数据卡片 -->
|
|
<a-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" class="data-card-col">
|
|
<a-card class="data-card user-card">
|
|
<template #title>
|
|
<span class="card-title">
|
|
<span class="icon-wrapper user-icon">
|
|
<svg class="icon" viewBox="0 0 1024 1024" width="20" height="20">
|
|
<path d="M858.5 763.6c-18.9-44.8-46.1-85-80.6-119.5-34.5-34.5-74.7-61.6-119.5-80.6-0.4-0.2-0.8-0.3-1.2-0.5C719.5 518 760 444.7 760 362c0-137-111-248-248-248S264 225 264 362c0 82.7 40.5 156 102.8 201.1-0.4 0.2-0.8 0.3-1.2 0.5-44.8 18.9-85 46-119.5 80.6-34.5 34.5-61.6 74.7-80.6 119.5C146.9 807.5 137 854 136 901.8c-0.1 4.5 3.5 8.2 8 8.2h60c4.4 0 7.9-3.5 8-7.8 2-77.2 33-149.5 87.8-204.3 56.7-56.7 132-87.9 212.2-87.9s155.5 31.2 212.2 87.9C779 752.7 810 825 812 902.2c0.1 4.4 3.6 7.8 8 7.8h60c4.5 0 8.1-3.7 8-8.2-1-47.8-10.9-94.3-29.5-138.2zM512 534c-45.9 0-89.1-17.9-121.6-50.4S340 407.9 340 362c0-45.9 17.9-89.1 50.4-121.6S466.1 190 512 190s89.1 17.9 121.6 50.4S684 316.1 684 362c0 45.9-17.9 89.1-50.4 121.6S557.9 534 512 534z" fill="currentColor"></path>
|
|
</svg>
|
|
</span>
|
|
总用户
|
|
</span>
|
|
</template>
|
|
<div class="main-stat-row">
|
|
<a-statistic
|
|
title="总用户数"
|
|
:value="dashboardData.total_user_count || 0"
|
|
class="main-stat"
|
|
:value-style="{ color: '#722ed1' }"
|
|
/>
|
|
<a-statistic
|
|
title="下单用户数"
|
|
:value="dashboardData.has_order_user_count || 0"
|
|
class="main-stat"
|
|
:value-style="{ color: '#722ed1' }"
|
|
/>
|
|
</div>
|
|
<div class="sub-stats">
|
|
<a-statistic
|
|
title="完成配送用户数"
|
|
:value="dashboardData.has_order_completed_user_count || 0"
|
|
:value-style="{ color: '#722ed1' }"
|
|
/>
|
|
<a-statistic
|
|
title="复购用户数"
|
|
:value="dashboardData.repeat_user_count || 0"
|
|
:value-style="{ color: '#722ed1' }"
|
|
/>
|
|
<a-statistic
|
|
title="今日增加用户"
|
|
:value="dashboardData.today_user_count || 0"
|
|
:value-style="{ color: '#722ed1' }"
|
|
/>
|
|
</div>
|
|
</a-card>
|
|
</a-col>
|
|
|
|
<!-- 配送订单数据卡片 -->
|
|
<a-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" class="data-card-col">
|
|
<a-card class="data-card order-card">
|
|
<template #title>
|
|
<span class="card-title">
|
|
<span class="icon-wrapper order-icon">
|
|
<svg class="icon" viewBox="0 0 1024 1024" width="20" height="20">
|
|
<path d="M832 312H696v-16c0-101.6-82.4-184-184-184s-184 82.4-184 184v16H192c-17.7 0-32 14.3-32 32v536c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V344c0-17.7-14.3-32-32-32z m-432-16c0-61.9 50.1-112 112-112s112 50.1 112 112v16H400v-16z m392 544H232V384h96v88c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-88h224v88c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-88h96v456z" fill="currentColor"></path>
|
|
</svg>
|
|
</span>
|
|
配送订单
|
|
</span>
|
|
</template>
|
|
<div class="main-stat-row">
|
|
<a-statistic
|
|
title="配送订单数"
|
|
:value="dashboardData.order_count || 0"
|
|
class="main-stat"
|
|
:value-style="{ color: '#fa8c16' }"
|
|
/>
|
|
<a-statistic
|
|
title="完成订单数"
|
|
:value="dashboardData.order_completed_count || 0"
|
|
class="main-stat"
|
|
:value-style="{ color: '#fa8c16' }"
|
|
/>
|
|
</div>
|
|
<div class="sub-stats">
|
|
<a-statistic
|
|
title="今日订单数"
|
|
:value="dashboardData.today_order_count || 0"
|
|
:value-style="{ color: '#fa8c16' }"
|
|
/>
|
|
<a-statistic
|
|
title="昨日订单数"
|
|
:value="dashboardData.yesterday_order_count || 0"
|
|
:value-style="{ color: '#fa8c16' }"
|
|
/>
|
|
</div>
|
|
</a-card>
|
|
</a-col>
|
|
|
|
<!-- 订单金额数据卡片 -->
|
|
<a-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" class="data-card-col">
|
|
<a-card class="data-card amount-card">
|
|
<template #title>
|
|
<span class="card-title">
|
|
<span class="icon-wrapper amount-icon">
|
|
<svg class="icon" viewBox="0 0 1024 1024" width="20" height="20">
|
|
<path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64z m0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z" fill="currentColor"></path>
|
|
<path d="M426.6 599.7V521H344c-4.4 0-8-3.6-8-8v-48c0-4.4 3.6-8 8-8h82.6v-78.7c0-4.4 3.6-8 8-8h52c4.4 0 8 3.6 8 8V457H592c4.4 0 8 3.6 8 8v48c0 4.4-3.6 8-8 8h-97.4v78.7c0 4.4-3.6 8-8 8h-52c-4.4 0-8-3.6-8-8z" fill="currentColor"></path>
|
|
</svg>
|
|
</span>
|
|
配送订单金额
|
|
</span>
|
|
</template>
|
|
<div class="main-stat-row">
|
|
<a-statistic
|
|
title="总配送金额"
|
|
:value="dashboardData.order_amount || 0"
|
|
:precision="1"
|
|
prefix="¥"
|
|
class="main-stat"
|
|
:value-style="{ color: '#52c41a' }"
|
|
/>
|
|
<a-statistic
|
|
title="完成配送金额"
|
|
:value="dashboardData.completed_order_amount || 0"
|
|
:precision="1"
|
|
prefix="¥"
|
|
class="main-stat"
|
|
:value-style="{ color: '#52c41a' }"
|
|
/>
|
|
</div>
|
|
<div class="sub-stats">
|
|
<a-statistic
|
|
title="今日订单金额"
|
|
:value="dashboardData.today_order_amount || 0"
|
|
:precision="1"
|
|
prefix="¥"
|
|
:value-style="{ color: '#52c41a' }"
|
|
/>
|
|
<a-statistic
|
|
title="昨日订单金额"
|
|
:value="dashboardData.yesterday_order_amount || 0"
|
|
:precision="1"
|
|
prefix="¥"
|
|
:value-style="{ color: '#52c41a' }"
|
|
/>
|
|
</div>
|
|
</a-card>
|
|
</a-col>
|
|
</a-row>
|
|
|
|
<!-- 每日统计列表 -->
|
|
<div class="daily-stats-section">
|
|
<div class="section-header">
|
|
<h2 class="section-title">
|
|
<span class="icon-wrapper stats-icon">
|
|
<svg class="icon" viewBox="0 0 1024 1024" width="26" height="26">
|
|
<path d="M888 792H200V168c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v688c0 4.4 3.6 8 8 8h752c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8z" fill="currentColor"></path>
|
|
<path d="M288 712h56c4.4 0 8-3.6 8-8V550c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v154c0 4.4 3.6 8 8 8zM440 712h56c4.4 0 8-3.6 8-8V426c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v278c0 4.4 3.6 8 8 8zM592 712h56c4.4 0 8-3.6 8-8V302c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v402c0 4.4 3.6 8 8 8zM744 712h56c4.4 0 8-3.6 8-8V178c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v526c0 4.4 3.6 8 8 8z" fill="currentColor"></path>
|
|
</svg>
|
|
</span>
|
|
每日统计列表
|
|
</h2>
|
|
</div>
|
|
<a-table
|
|
:columns="dailyStatsColumns"
|
|
:data-source="dailyStatsList"
|
|
:pagination="dailyStatsPagination"
|
|
:loading="dailyStatsLoading"
|
|
row-key="stats_date"
|
|
class="daily-stats-table"
|
|
@change="handleDailyStatsTableChange"
|
|
>
|
|
<template #bodyCell="{ column, record }">
|
|
<template v-if="column.key === 'total_original_amount' || column.key === 'total_final_amount'">
|
|
¥{{ record[column.key].toFixed(2) }}
|
|
</template>
|
|
</template>
|
|
</a-table>
|
|
</div>
|
|
|
|
<!-- 配送员列表 -->
|
|
<div class="deliveryman-list-section">
|
|
<div class="section-header">
|
|
<h2 class="section-title">
|
|
<span class="icon-wrapper deliveryman-icon">
|
|
<svg class="icon" viewBox="0 0 1024 1024" width="26" height="26">
|
|
<path d="M959 413.4L935.3 372.2c-2.2-3.8-7.1-5.1-10.9-2.9l-50.7 29.6-78.3-216.2c-8.5-26.5-33.1-44.4-60.9-44.4H301.2c-34.7 0-65.5 22.4-76.2 55.5l-74.6 205.2-50.8-29.6c-3.8-2.2-8.7-0.9-10.9 2.9L65 413.4c-2.2 3.8-0.9 8.6 2.9 10.8l60.4 35.2-14.5 40c-1.2 3.2-1.8 6.6-1.8 10v348.2c0 15.7 11.8 28.4 26.3 28.4h67.6c12.3 0 23-9.3 25.6-22.3l7.7-37.7h545.6l7.7 37.7c2.7 13 13.3 22.3 25.6 22.3h67.6c14.5 0 26.3-12.7 26.3-28.4V509.4c0-3.4-0.6-6.8-1.8-10l-14.5-40 60.3-35.2c3.8-2.2 5.1-7 3-10.8zM264 621c-22.1 0-40-17.9-40-40s17.9-40 40-40 40 17.9 40 40-17.9 40-40 40z m388 75c0 4.4-3.6 8-8 8H380c-4.4 0-8-3.6-8-8v-84c0-4.4 3.6-8 8-8h40c4.4 0 8 3.6 8 8v36h168v-36c0-4.4 3.6-8 8-8h40c4.4 0 8 3.6 8 8v84z m108-75c-22.1 0-40-17.9-40-40s17.9-40 40-40 40 17.9 40 40-17.9 40-40 40zM220 418l72.7-199.9c1.4-3.8 4.9-6.1 8.9-6.1h420.8c4 0 7.5 2.3 8.9 6.1l72.7 199.9H220z" fill="currentColor"></path>
|
|
</svg>
|
|
</span>
|
|
配送员列表
|
|
</h2>
|
|
<div class="filter-container">
|
|
<a-select
|
|
v-model:value="selectedCommunity"
|
|
placeholder="选择小区筛选"
|
|
style="width: 240px"
|
|
:loading="communityLoading"
|
|
@change="handleCommunityChange"
|
|
allowClear
|
|
>
|
|
<a-select-option :value="0">全部小区</a-select-option>
|
|
<a-select-option v-for="item in communityList" :key="item.id" :value="item.id">
|
|
{{ item.name }}
|
|
</a-select-option>
|
|
</a-select>
|
|
</div>
|
|
</div>
|
|
<a-table
|
|
:columns="deliverymanColumns"
|
|
:data-source="deliverymanList"
|
|
:pagination="false"
|
|
:loading="loading"
|
|
row-key="deliveryman_id"
|
|
class="deliveryman-table"
|
|
>
|
|
<template #bodyCell="{ column, record }">
|
|
<template v-if="column.key === 'today_order_amount' || column.key === 'order_amount'">
|
|
¥{{ record[column.key].toFixed(2) }}
|
|
</template>
|
|
</template>
|
|
</a-table>
|
|
</div>
|
|
</div>
|
|
</page-container>
|
|
</template>
|
|
|
|
<script>
|
|
import { defineComponent, computed, ref, onMounted } from 'vue'
|
|
import { Card, Row, Col, Statistic, Table, Select } from 'ant-design-vue'
|
|
import PageContainer from '@/components/PageContainer.vue'
|
|
import request from '@/utils/request'
|
|
|
|
export default defineComponent({
|
|
name: 'Dashboard',
|
|
components: {
|
|
PageContainer,
|
|
ACard: Card,
|
|
ARow: Row,
|
|
ACol: Col,
|
|
AStatistic: Statistic,
|
|
AStatisticGroup: Statistic.Group,
|
|
ATable: Table,
|
|
ASelect: Select,
|
|
ASelectOption: Select.Option
|
|
},
|
|
setup() {
|
|
const loading = ref(false)
|
|
const communityLoading = ref(false)
|
|
const selectedCommunity = ref(0)
|
|
const communityList = ref([])
|
|
|
|
const dashboardData = ref({
|
|
total_community_count: 0,
|
|
total_user_count: 0,
|
|
has_order_user_count: 0,
|
|
has_paid_user_count: 0,
|
|
has_order_completed_user_count: 0,
|
|
repeat_user_count: 0,
|
|
order_count: 0,
|
|
order_pay_count: 0,
|
|
order_unpaid_count: 0,
|
|
order_completed_count: 0,
|
|
pay_rate: 0,
|
|
order_amount: 0,
|
|
pay_amount: 0,
|
|
completed_order_amount: 0,
|
|
unpaid_amount: 0,
|
|
today_user_count: 0,
|
|
yesterday_user_count: 0,
|
|
today_order_count: 0,
|
|
yesterday_order_count: 0,
|
|
today_order_amount: 0,
|
|
yesterday_order_amount: 0
|
|
})
|
|
|
|
const deliverymanList = ref([])
|
|
|
|
const deliverymanColumns = [
|
|
{
|
|
title: '配送员ID',
|
|
dataIndex: 'deliveryman_id',
|
|
key: 'deliveryman_id',
|
|
width: 80,
|
|
align: 'center'
|
|
},
|
|
{
|
|
title: '所属小区',
|
|
dataIndex: 'deliveryman_community_name',
|
|
key: 'deliveryman_community_name',
|
|
width: 150
|
|
},
|
|
{
|
|
title: '配送员名字',
|
|
dataIndex: 'deliveryman_auth_name',
|
|
key: 'deliveryman_auth_name',
|
|
width: 120
|
|
},
|
|
{
|
|
title: '今日订单数',
|
|
dataIndex: 'today_order_count',
|
|
key: 'today_order_count',
|
|
width: 100,
|
|
align: 'center'
|
|
},
|
|
{
|
|
title: '今日订单金额',
|
|
dataIndex: 'today_order_amount',
|
|
key: 'today_order_amount',
|
|
width: 120,
|
|
align: 'right'
|
|
},
|
|
{
|
|
title: '总订单数',
|
|
dataIndex: 'order_count',
|
|
key: 'order_count',
|
|
width: 100,
|
|
align: 'center'
|
|
},
|
|
{
|
|
title: '总订单金额',
|
|
dataIndex: 'order_amount',
|
|
key: 'order_amount',
|
|
width: 120,
|
|
align: 'right'
|
|
}
|
|
]
|
|
|
|
const dailyStatsList = ref([])
|
|
const dailyStatsLoading = ref(false)
|
|
const dailyStatsPagination = ref({
|
|
current: 1,
|
|
pageSize: 10,
|
|
total: 0,
|
|
showSizeChanger: true,
|
|
showTotal: (total) => `共 ${total} 条记录`
|
|
})
|
|
|
|
const dailyStatsColumns = [
|
|
{
|
|
title: '日期',
|
|
dataIndex: 'stats_date',
|
|
key: 'stats_date',
|
|
width: 120,
|
|
align: 'center'
|
|
},
|
|
{
|
|
title: '订单数',
|
|
dataIndex: 'total_order_count',
|
|
key: 'total_order_count',
|
|
width: 100,
|
|
align: 'center'
|
|
},
|
|
{
|
|
title: '订单金额',
|
|
dataIndex: 'total_original_amount',
|
|
key: 'total_original_amount',
|
|
width: 120,
|
|
align: 'right'
|
|
},
|
|
{
|
|
title: '支付金额',
|
|
dataIndex: 'total_final_amount',
|
|
key: 'total_final_amount',
|
|
width: 120,
|
|
align: 'right'
|
|
},
|
|
{
|
|
title: '小区数',
|
|
dataIndex: 'total_communities',
|
|
key: 'total_communities',
|
|
width: 100,
|
|
align: 'center'
|
|
}
|
|
]
|
|
|
|
const greeting = computed(() => {
|
|
const hour = new Date().getHours()
|
|
if (hour < 6) return '夜深了,请注意休息'
|
|
if (hour < 9) return '早上好'
|
|
if (hour < 12) return '上午好'
|
|
if (hour < 14) return '中午好'
|
|
if (hour < 17) return '下午好'
|
|
if (hour < 19) return '傍晚好'
|
|
return '晚上好'
|
|
})
|
|
|
|
const paymentRate = computed(() => {
|
|
if (!dashboardData.value.order_count || dashboardData.value.order_count === 0) {
|
|
return 0;
|
|
}
|
|
return dashboardData.value.pay_rate * 100;
|
|
});
|
|
|
|
const fetchDashboardData = async () => {
|
|
loading.value = true
|
|
try {
|
|
const res = await request.get('/api/dashboard')
|
|
if (res.code === 200) {
|
|
dashboardData.value = res.data
|
|
}
|
|
} catch (error) {
|
|
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
const fetchDeliverymanList = async (communityId = null) => {
|
|
loading.value = true
|
|
try {
|
|
const url = '/api/dashboard/deliveryman'
|
|
const params = communityId ? { community_id: communityId } : {}
|
|
const res = await request.get(url, { params })
|
|
if (res.code === 200) {
|
|
deliverymanList.value = res.data
|
|
}
|
|
} catch (error) {
|
|
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
const fetchCommunityList = async () => {
|
|
communityLoading.value = true
|
|
try {
|
|
const res = await request.get('/api/community?limit=1000', {
|
|
params: {
|
|
limit: 1000,
|
|
skip: 0,
|
|
status: "OPENING"
|
|
}
|
|
})
|
|
if (res.code === 200) {
|
|
communityList.value = res.data.items || []
|
|
}
|
|
} catch (error) {
|
|
|
|
} finally {
|
|
communityLoading.value = false
|
|
}
|
|
}
|
|
|
|
const fetchDailyStats = async () => {
|
|
dailyStatsLoading.value = true
|
|
try {
|
|
const params = {
|
|
skip: (dailyStatsPagination.value.current - 1) * dailyStatsPagination.value.pageSize,
|
|
limit: dailyStatsPagination.value.pageSize
|
|
}
|
|
|
|
const res = await request.get('/api/dashboard/order_stats', { params })
|
|
if (res.code === 200) {
|
|
dailyStatsList.value = res.data.items || []
|
|
dailyStatsPagination.value.total = res.data.total || 0
|
|
}
|
|
} catch (error) {
|
|
|
|
} finally {
|
|
dailyStatsLoading.value = false
|
|
}
|
|
}
|
|
|
|
const handleCommunityChange = (value) => {
|
|
if (value === 0) {
|
|
fetchDeliverymanList()
|
|
} else {
|
|
fetchDeliverymanList(value)
|
|
}
|
|
}
|
|
|
|
const handleDailyStatsTableChange = (pagination) => {
|
|
dailyStatsPagination.value.current = pagination.current
|
|
dailyStatsPagination.value.pageSize = pagination.pageSize
|
|
fetchDailyStats()
|
|
}
|
|
|
|
onMounted(() => {
|
|
fetchDashboardData()
|
|
fetchDeliverymanList()
|
|
fetchCommunityList()
|
|
fetchDailyStats()
|
|
})
|
|
|
|
return {
|
|
greeting,
|
|
dashboardData,
|
|
deliverymanList,
|
|
deliverymanColumns,
|
|
loading,
|
|
communityLoading,
|
|
communityList,
|
|
selectedCommunity,
|
|
handleCommunityChange,
|
|
paymentRate,
|
|
dailyStatsList,
|
|
dailyStatsColumns,
|
|
dailyStatsPagination,
|
|
dailyStatsLoading,
|
|
handleDailyStatsTableChange
|
|
}
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<style scoped>
|
|
.dashboard {
|
|
background: #fff;
|
|
}
|
|
|
|
.data-overview {
|
|
margin-bottom: 24px;
|
|
}
|
|
|
|
.data-card {
|
|
height: 100%;
|
|
border-radius: 8px;
|
|
overflow: hidden;
|
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
|
|
transition: all 0.3s ease;
|
|
position: relative;
|
|
|
|
&:hover {
|
|
transform: translateY(-5px);
|
|
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
:deep(.ant-card-head) {
|
|
min-height: 42px;
|
|
padding: 0 12px;
|
|
border-bottom: none;
|
|
|
|
.ant-card-head-title {
|
|
padding: 12px 0;
|
|
font-weight: 600;
|
|
font-size: 15px;
|
|
}
|
|
}
|
|
|
|
:deep(.ant-card-body) {
|
|
padding: 0 15px 15px;
|
|
}
|
|
|
|
&::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
height: 6px;
|
|
z-index: 1;
|
|
}
|
|
}
|
|
|
|
.community-card {
|
|
:deep(.ant-card-head) {
|
|
background: linear-gradient(135deg, #1890ff 0%, #36cfc9 100%);
|
|
|
|
.ant-card-head-title {
|
|
color: white;
|
|
}
|
|
}
|
|
|
|
&::before {
|
|
background-color: #1890ff;
|
|
}
|
|
}
|
|
|
|
.user-card {
|
|
:deep(.ant-card-head) {
|
|
background: linear-gradient(135deg, #722ed1 0%, #eb2f96 100%);
|
|
|
|
.ant-card-head-title {
|
|
color: white;
|
|
}
|
|
}
|
|
|
|
&::before {
|
|
background-color: #722ed1;
|
|
}
|
|
}
|
|
|
|
.order-card {
|
|
:deep(.ant-card-head) {
|
|
background: linear-gradient(135deg, #fa8c16 0%, #faad14 100%);
|
|
|
|
.ant-card-head-title {
|
|
color: white;
|
|
}
|
|
}
|
|
|
|
&::before {
|
|
background-color: #fa8c16;
|
|
}
|
|
}
|
|
|
|
.amount-card {
|
|
:deep(.ant-card-head) {
|
|
background: linear-gradient(135deg, #52c41a 0%, #73d13d 100%);
|
|
|
|
.ant-card-head-title {
|
|
color: white;
|
|
}
|
|
}
|
|
|
|
&::before {
|
|
background-color: #52c41a;
|
|
}
|
|
}
|
|
|
|
.card-title {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
font-size: 16px;
|
|
}
|
|
|
|
.icon-wrapper {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
width: 34px;
|
|
height: 34px;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
.community-icon {
|
|
background-color: rgba(24, 144, 255, 0.2);
|
|
color: #1890ff;
|
|
}
|
|
|
|
.user-icon {
|
|
background-color: rgba(114, 46, 209, 0.2);
|
|
color: #722ed1;
|
|
}
|
|
|
|
.order-icon {
|
|
background-color: rgba(250, 140, 22, 0.2);
|
|
color: #fa8c16;
|
|
}
|
|
|
|
.amount-icon {
|
|
background-color: rgba(82, 196, 26, 0.2);
|
|
color: #52c41a;
|
|
}
|
|
|
|
.deliveryman-icon {
|
|
background-color: rgba(24, 144, 255, 0.2);
|
|
color: #1890ff;
|
|
}
|
|
|
|
.icon {
|
|
font-size: 20px;
|
|
}
|
|
|
|
.main-stat-row {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
margin-bottom: 12px;
|
|
|
|
.main-stat {
|
|
margin-bottom: 0;
|
|
|
|
:deep(.ant-statistic-content) {
|
|
font-size: 22px;
|
|
}
|
|
}
|
|
}
|
|
|
|
.main-stat-row .main-stat:last-child :deep(.ant-statistic-content) {
|
|
text-align: right;
|
|
}
|
|
|
|
.sub-stats {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
border-top: 1px solid #f0f0f0;
|
|
padding-top: 12px;
|
|
margin-top: 6px;
|
|
flex-wrap: wrap;
|
|
|
|
:deep(.ant-statistic) {
|
|
padding: 0 8px;
|
|
min-width: 30%;
|
|
margin-bottom: 6px;
|
|
|
|
&:first-child {
|
|
padding-left: 0;
|
|
}
|
|
|
|
&:last-child {
|
|
padding-right: 0;
|
|
}
|
|
|
|
.ant-statistic-title {
|
|
font-size: 13px;
|
|
margin-bottom: 3px;
|
|
color: rgba(0, 0, 0, 0.65);
|
|
}
|
|
|
|
.ant-statistic-content {
|
|
font-size: 18px;
|
|
font-weight: 500;
|
|
}
|
|
}
|
|
}
|
|
|
|
.sub-stats :deep(.ant-statistic:last-child) .ant-statistic-content {
|
|
text-align: right;
|
|
}
|
|
|
|
.sub-stats :deep(.ant-statistic:last-child) .ant-statistic-title {
|
|
text-align: right;
|
|
}
|
|
|
|
.daily-stats-section {
|
|
background: white;
|
|
border-radius: 8px;
|
|
padding: 20px;
|
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
|
|
position: relative;
|
|
margin-bottom: 24px;
|
|
|
|
&::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
height: 6px;
|
|
background-color: #722ed1;
|
|
border-top-left-radius: 8px;
|
|
border-top-right-radius: 8px;
|
|
}
|
|
}
|
|
|
|
.stats-icon {
|
|
background-color: rgba(114, 46, 209, 0.2);
|
|
color: #722ed1;
|
|
}
|
|
|
|
.daily-stats-table {
|
|
:deep(.ant-table-thead > tr > th) {
|
|
background-color: #f5f5f5;
|
|
font-weight: 500;
|
|
}
|
|
|
|
:deep(.ant-table-tbody > tr:hover > td) {
|
|
background-color: #f0e6fa;
|
|
}
|
|
|
|
:deep(.ant-table-tbody > tr > td) {
|
|
transition: background 0.3s;
|
|
}
|
|
}
|
|
|
|
.deliveryman-list-section {
|
|
background: white;
|
|
border-radius: 8px;
|
|
padding: 20px;
|
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
|
|
position: relative;
|
|
|
|
&::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
height: 6px;
|
|
background-color: #1890ff;
|
|
border-top-left-radius: 8px;
|
|
border-top-right-radius: 8px;
|
|
}
|
|
}
|
|
|
|
.section-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 20px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.section-title {
|
|
font-size: 18px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
font-weight: 600;
|
|
margin: 0;
|
|
}
|
|
|
|
.filter-container {
|
|
display: flex;
|
|
gap: 16px;
|
|
}
|
|
|
|
.deliveryman-table {
|
|
:deep(.ant-table-wrapper) {
|
|
}
|
|
|
|
:deep(.ant-table-container) {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
:deep(.ant-table) {
|
|
}
|
|
|
|
:deep(.ant-table-content) {
|
|
}
|
|
|
|
:deep(.ant-table-thead > tr > th) {
|
|
background-color: #f5f5f5;
|
|
font-weight: 500;
|
|
}
|
|
|
|
:deep(.ant-table-tbody > tr:hover > td) {
|
|
background-color: #e6f7ff;
|
|
}
|
|
|
|
:deep(.ant-table-tbody > tr > td) {
|
|
transition: background 0.3s;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.data-overview {
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.data-card {
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.main-stat-row {
|
|
.main-stat {
|
|
:deep(.ant-statistic-content) {
|
|
font-size: 20px;
|
|
}
|
|
}
|
|
}
|
|
|
|
.sub-stats {
|
|
:deep(.ant-statistic) {
|
|
.ant-statistic-content {
|
|
font-size: 16px;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style> |