|
|
@@ -1,202 +1,232 @@
|
|
|
<template>
|
|
|
<view class="page">
|
|
|
- <!-- 顶部导航 - 与内容融合 -->
|
|
|
- <view class="header">
|
|
|
- <view class="header-bg"></view>
|
|
|
- <view class="status-bar" :style="{ height: statusBarHeight + 'px' }"></view>
|
|
|
- <view class="header-content">
|
|
|
- <view class="greeting">
|
|
|
- <text class="greeting-time">{{ getTimeGreeting() }}</text>
|
|
|
- <text class="greeting-name">运营管理员</text>
|
|
|
- </view>
|
|
|
- <view class="avatar" @click="navigateTo('/pages/my/my')">
|
|
|
- <view class="avatar-icon"></view>
|
|
|
+ <!-- 顶部品牌栏 -->
|
|
|
+ <view class="header" :style="{ paddingTop: (statusBarHeight + 8) + 'px' }">
|
|
|
+ <view class="header-inner">
|
|
|
+ <view class="merchant">
|
|
|
+ <view class="avatar">富</view>
|
|
|
+ <text class="name-text">富玉餐饮</text>
|
|
|
</view>
|
|
|
+
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
- <!-- 统计卡片 -->
|
|
|
- <view class="stats-section">
|
|
|
- <view class="stats-card main">
|
|
|
- <view class="stats-item" @click="navigateTo('/pages/orders/list')">
|
|
|
- <text class="stats-value">{{ overview.todayOrders || 0 }}</text>
|
|
|
- <text class="stats-label">今日订单</text>
|
|
|
- </view>
|
|
|
- <view class="stats-divider"></view>
|
|
|
- <view class="stats-item">
|
|
|
- <text class="stats-value accent">¥{{ formatMoney(overview.todaySales || 0) }}</text>
|
|
|
- <text class="stats-label">今日销售额</text>
|
|
|
+ <!-- 悬浮主体区:上浮覆盖到头部 -->
|
|
|
+ <view class="content">
|
|
|
+ <!-- 通知栏 -->
|
|
|
+ <view class="notice-bar" v-if="noticeList.length > 0" @click="handleNoticeClick">
|
|
|
+ <view class="notice-tag">公告</view>
|
|
|
+ <view class="notice-content">
|
|
|
+ <swiper class="notice-swiper" vertical autoplay circular interval="3000" duration="500">
|
|
|
+ <swiper-item v-for="(notice, index) in noticeList" :key="index">
|
|
|
+ <text class="notice-text">{{ notice.content }}</text>
|
|
|
+ </swiper-item>
|
|
|
+ </swiper>
|
|
|
</view>
|
|
|
+ <text class="notice-arrow">›</text>
|
|
|
</view>
|
|
|
|
|
|
- <view class="stats-row">
|
|
|
- <view class="stats-card mini success" @click="navigateTo('/pages/device/list')">
|
|
|
- <view class="stats-dot green"></view>
|
|
|
- <view class="stats-info">
|
|
|
- <text class="stats-value">{{ overview.onlineDevices || 0 }}</text>
|
|
|
- <text class="stats-label">在线设备</text>
|
|
|
+ <!-- 核心销售卡片 -->
|
|
|
+ <view class="sales-card">
|
|
|
+ <view class="sales-main">
|
|
|
+ <view class="sales-primary">
|
|
|
+ <text class="label">今日销售额(元)</text>
|
|
|
+ <text class="primary-value">{{ formatMoney(overview.todaySales || 0) }}</text>
|
|
|
+ <view class="compare" v-if="overview.todayCompare !== undefined">
|
|
|
+ <text class="compare-text">较昨日</text>
|
|
|
+ <text class="compare-value">{{ overview.todayCompare >= 0 ? '+' : '' }}{{ overview.todayCompare || 0 }}%</text>
|
|
|
+ </view>
|
|
|
</view>
|
|
|
- </view>
|
|
|
- <view class="stats-card mini warning">
|
|
|
- <view class="stats-dot amber"></view>
|
|
|
- <view class="stats-info">
|
|
|
- <text class="stats-value">{{ overview.offlineDevices || 0 }}</text>
|
|
|
- <text class="stats-label">离线设备</text>
|
|
|
+ <view class="sales-secondary">
|
|
|
+ <text class="label">今日订单</text>
|
|
|
+ <text class="secondary-value">{{ overview.todayOrders || 0 }}</text>
|
|
|
+ <text class="unit">单</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 快捷功能 -->
|
|
|
- <view class="section">
|
|
|
- <view class="section-header">
|
|
|
- <text class="section-title">快捷功能</text>
|
|
|
- </view>
|
|
|
- <view class="quick-grid">
|
|
|
- <view class="quick-item" @click="navigateTo('/pages/orders/list')">
|
|
|
- <view class="quick-icon green">
|
|
|
- <view class="icon-order"></view>
|
|
|
+ <view class="sales-footer">
|
|
|
+ <view class="footer-item">
|
|
|
+ <text class="footer-label">本月销售额</text>
|
|
|
+ <text class="footer-value">¥{{ formatMoney(overview.monthSales || 0) }}</text>
|
|
|
</view>
|
|
|
- <text class="quick-name">订单管理</text>
|
|
|
- </view>
|
|
|
- <view class="quick-item" @click="navigateTo('/pages/device/list')">
|
|
|
- <view class="quick-icon cyan">
|
|
|
- <view class="icon-device"></view>
|
|
|
+ <view class="footer-divider"></view>
|
|
|
+ <view class="footer-item">
|
|
|
+ <text class="footer-label">本月订单</text>
|
|
|
+ <text class="footer-value">{{ overview.monthOrders || 0 }}</text>
|
|
|
</view>
|
|
|
- <text class="quick-name">设备管理</text>
|
|
|
</view>
|
|
|
- <view class="quick-item" @click="navigateTo('/pages/shop/list')">
|
|
|
- <view class="quick-icon amber">
|
|
|
- <view class="icon-shop"></view>
|
|
|
- </view>
|
|
|
- <text class="quick-name">门店管理</text>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 设备状态 + 数据入口 -->
|
|
|
+ <view class="device-card">
|
|
|
+ <view class="card-title">
|
|
|
+ <text>设备概况</text>
|
|
|
+ <text class="card-more" @click="navigateTo('/pages/device/list')">查看全部 ›</text>
|
|
|
</view>
|
|
|
- <view class="quick-item" @click="navigateTo('/pages/products/list')">
|
|
|
- <view class="quick-icon purple">
|
|
|
- <view class="icon-product"></view>
|
|
|
+ <view class="device-row">
|
|
|
+ <view class="device-box online">
|
|
|
+ <view class="device-top">
|
|
|
+ <view class="device-dot online-dot"></view>
|
|
|
+ <text class="device-label">在线设备</text>
|
|
|
+ </view>
|
|
|
+ <text class="device-num">{{ overview.onlineDevices || 0 }}</text>
|
|
|
</view>
|
|
|
- <text class="quick-name">商品管理</text>
|
|
|
- </view>
|
|
|
- <view class="quick-item" @click="navigateTo('/pages/inventory/query')">
|
|
|
- <view class="quick-icon blue">
|
|
|
- <view class="icon-chart"></view>
|
|
|
+ <view class="device-box offline">
|
|
|
+ <view class="device-top">
|
|
|
+ <view class="device-dot offline-dot"></view>
|
|
|
+ <text class="device-label">离线设备</text>
|
|
|
+ </view>
|
|
|
+ <text class="device-num">{{ overview.offlineDevices || 0 }}</text>
|
|
|
</view>
|
|
|
- <text class="quick-name">库存查询</text>
|
|
|
</view>
|
|
|
- <view class="quick-item" @click="navigateTo('/pages/customer/list')">
|
|
|
- <view class="quick-icon green">
|
|
|
- <view class="icon-user"></view>
|
|
|
+ <view class="data-entry-row">
|
|
|
+ <view class="data-entry" @click="navigateTo('/pages/statistics/overview')">
|
|
|
+ <view class="data-entry-icon chart">
|
|
|
+ <view class="icon-chart"></view>
|
|
|
+ </view>
|
|
|
+ <view class="data-entry-info">
|
|
|
+ <text class="data-entry-title">数据统计</text>
|
|
|
+ <text class="data-entry-sub">销售 · 订单分析</text>
|
|
|
+ </view>
|
|
|
+ <text class="data-entry-arrow">›</text>
|
|
|
</view>
|
|
|
- <text class="quick-name">客户管理</text>
|
|
|
- </view>
|
|
|
- <view class="quick-item" @click="navigateTo('/pages/statistics/overview')">
|
|
|
- <view class="quick-icon blue">
|
|
|
- <view class="icon-stats"></view>
|
|
|
+ <view class="data-entry" @click="navigateTo('/pages/statistics/overview')">
|
|
|
+ <view class="data-entry-icon analytics">
|
|
|
+ <view class="icon-analytics"></view>
|
|
|
+ </view>
|
|
|
+ <view class="data-entry-info">
|
|
|
+ <text class="data-entry-title">生意参谋</text>
|
|
|
+ <text class="data-entry-sub">经营决策助手</text>
|
|
|
+ </view>
|
|
|
+ <text class="data-entry-arrow">›</text>
|
|
|
</view>
|
|
|
- <text class="quick-name">数据统计</text>
|
|
|
</view>
|
|
|
- <view class="quick-item" @click="navigateTo('/pages/inventory/warning')">
|
|
|
- <view class="quick-icon rose">
|
|
|
- <view class="icon-warning"></view>
|
|
|
- </view>
|
|
|
- <text class="quick-name">库存预警</text>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 待办事项 -->
|
|
|
+ <view class="todo-card">
|
|
|
+ <view class="card-title">
|
|
|
+ <text>待办事项</text>
|
|
|
+ <text class="card-sub" v-if="totalTodo > 0">共 {{ totalTodo }} 项待处理</text>
|
|
|
+ <text class="card-sub" v-else>暂无待办</text>
|
|
|
</view>
|
|
|
- <view class="quick-item" @click="navigateTo('/pages/checkin/index')">
|
|
|
- <view class="quick-icon amber">
|
|
|
- <view class="icon-checkin"></view>
|
|
|
+ <view class="todo-grid">
|
|
|
+ <view class="todo-item" v-for="item in todoItems" :key="item.key" @click="navigateTo(item.url)">
|
|
|
+ <view :class="['todo-icon', item.color, { disabled: !item.count }]">
|
|
|
+ <view :class="item.iconClass"></view>
|
|
|
+ </view>
|
|
|
+ <view class="todo-info">
|
|
|
+ <text :class="['todo-value', { active: item.count > 0 }]">{{ item.count }}</text>
|
|
|
+ <text class="todo-label">{{ item.label }}</text>
|
|
|
+ </view>
|
|
|
</view>
|
|
|
- <text class="quick-name">签到打卡</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
- </view>
|
|
|
|
|
|
- <!-- 订单趋势 -->
|
|
|
- <view class="section">
|
|
|
- <view class="section-header">
|
|
|
- <text class="section-title">订单趋势</text>
|
|
|
- <text class="section-tag">近7天</text>
|
|
|
- </view>
|
|
|
- <view class="chart-card">
|
|
|
- <view class="chart-container">
|
|
|
- <view
|
|
|
- class="chart-bar-wrapper"
|
|
|
- v-for="(item, index) in orderTrend"
|
|
|
- :key="index"
|
|
|
- >
|
|
|
- <text class="chart-value">{{ item.count }}</text>
|
|
|
- <view class="chart-bar-bg">
|
|
|
- <view
|
|
|
- class="chart-bar"
|
|
|
- :style="{ height: getBarHeight(item.count) + '%' }"
|
|
|
- ></view>
|
|
|
+ <!-- 商户运营 -->
|
|
|
+ <view class="quick-card">
|
|
|
+ <view class="card-title">
|
|
|
+ <text>商户运营</text>
|
|
|
+ </view>
|
|
|
+ <view class="quick-grid">
|
|
|
+ <view class="quick-item" @click="navigateTo('/pages/products/apply')">
|
|
|
+ <view class="quick-icon primary">
|
|
|
+ <view class="icon-apply"></view>
|
|
|
+ </view>
|
|
|
+ <text class="quick-name">新品申请</text>
|
|
|
+ </view>
|
|
|
+ <view class="quick-item" @click="navigateTo('/pages/marketing/list')">
|
|
|
+ <view class="quick-icon orange">
|
|
|
+ <view class="icon-marketing"></view>
|
|
|
+ </view>
|
|
|
+ <text class="quick-name">营销管理</text>
|
|
|
+ </view>
|
|
|
+ <view class="quick-item" @click="navigateTo('/pages/staff/list')">
|
|
|
+ <view class="quick-icon green">
|
|
|
+ <view class="icon-staff"></view>
|
|
|
+ </view>
|
|
|
+ <text class="quick-name">人员管理</text>
|
|
|
+ </view>
|
|
|
+ <view class="quick-item" @click="navigateTo('/pages/shop/list')">
|
|
|
+ <view class="quick-icon blue">
|
|
|
+ <view class="icon-shop-quick"></view>
|
|
|
</view>
|
|
|
- <text class="chart-label">{{ item.date }}</text>
|
|
|
+ <text class="quick-name">门店管理</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<!-- 自定义TabBar -->
|
|
|
<CustomTabBar />
|
|
|
</view>
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
-import { ref, onMounted } from 'vue';
|
|
|
-import { getDashboardOverview, getDashboardStatistics } from '@/api/dashboard';
|
|
|
+import { ref, computed, onMounted } from 'vue';
|
|
|
+import { getDashboardOverview, getTodoList } from '@/api/dashboard';
|
|
|
import { formatMoney as formatMoneyUtil } from '@/utils/common';
|
|
|
import CustomTabBar from '@/components/CustomTabBar.vue';
|
|
|
|
|
|
-// 获取系统信息用于计算状态栏高度
|
|
|
-const systemInfo = uni.getSystemInfoSync();
|
|
|
-const statusBarHeight = ref(systemInfo.statusBarHeight || 20);
|
|
|
-
|
|
|
+const statusBarHeight = ref(20); // 状态栏高度,默认20px
|
|
|
const overview = ref<any>({});
|
|
|
-const statistics = ref<any>({});
|
|
|
-const orderTrend = ref<any[]>([]);
|
|
|
-const maxCount = ref(0);
|
|
|
+const todo = ref<any>({
|
|
|
+ pendingRefunds: 0,
|
|
|
+ pendingAlerts: 0,
|
|
|
+ unpaidOrders: 0,
|
|
|
+ lowStockItems: 0,
|
|
|
+ pendingInvoices: 0,
|
|
|
+ expiringProducts: 0
|
|
|
+});
|
|
|
+
|
|
|
+// 系统通知列表
|
|
|
+const noticeList = ref<any[]>([
|
|
|
+ { id: 1, content: '服务费账单功能升级通知', type: 'system' },
|
|
|
+ { id: 2, content: '应政府监管要求,请尽快完成资质备案信息填写', type: 'important' }
|
|
|
+]);
|
|
|
+
|
|
|
+// 待办项结构化配置
|
|
|
+const todoItems = computed(() => [
|
|
|
+ { key: 'pendingRefunds', label: '待处理退款', count: todo.value.pendingRefunds || 0, color: 'red', iconClass: 'icon-refund', url: '/pages/orders/list?tab=refund' },
|
|
|
+ { key: 'pendingAlerts', label: '待处理异常', count: todo.value.pendingAlerts || 0, color: 'orange', iconClass: 'icon-alert', url: '/pages/device/list?tab=alert' },
|
|
|
+ { key: 'unpaidOrders', label: '未支付订单', count: todo.value.unpaidOrders || 0, color: 'yellow', iconClass: 'icon-unpaid', url: '/pages/orders/list?tab=unpaid' },
|
|
|
+ { key: 'lowStockItems', label: '待补货', count: todo.value.lowStockItems || 0, color: 'blue', iconClass: 'icon-restock', url: '/pages/inventory/list' },
|
|
|
+ { key: 'pendingInvoices', label: '待开发票', count: todo.value.pendingInvoices || 0, color: 'purple', iconClass: 'icon-invoice', url: '/pages/invoice/list' },
|
|
|
+ { key: 'expiringProducts', label: '临期商品', count: todo.value.expiringProducts || 0, color: 'cyan', iconClass: 'icon-expire', url: '/pages/products/expire' }
|
|
|
+]);
|
|
|
+
|
|
|
+const totalTodo = computed(() =>
|
|
|
+ todoItems.value.reduce((sum, item) => sum + (item.count || 0), 0)
|
|
|
+);
|
|
|
|
|
|
const formatMoney = (amount: number | string) => {
|
|
|
const num = typeof amount === 'string' ? parseFloat(amount) : amount;
|
|
|
return formatMoneyUtil(num || 0);
|
|
|
};
|
|
|
|
|
|
-const getTimeGreeting = () => {
|
|
|
- const hour = new Date().getHours();
|
|
|
- if (hour < 6) return '凌晨好';
|
|
|
- if (hour < 12) return '上午好';
|
|
|
- if (hour < 18) return '下午好';
|
|
|
- return '晚上好';
|
|
|
-};
|
|
|
-
|
|
|
-const getBarHeight = (count: number) => {
|
|
|
- if (maxCount.value === 0) return 0;
|
|
|
- return Math.max(15, (count / maxCount.value) * 100);
|
|
|
-};
|
|
|
-
|
|
|
const navigateTo = (url: string) => {
|
|
|
uni.navigateTo({ url });
|
|
|
};
|
|
|
|
|
|
+const handleNoticeClick = () => {
|
|
|
+ uni.showToast({ title: '通知中心开发中', icon: 'none' });
|
|
|
+};
|
|
|
+
|
|
|
const loadData = async () => {
|
|
|
try {
|
|
|
- const [overviewRes, statisticsRes] = await Promise.all([
|
|
|
+ const [overviewRes, todoRes] = await Promise.all([
|
|
|
getDashboardOverview(),
|
|
|
- getDashboardStatistics('week')
|
|
|
+ getTodoList()
|
|
|
]);
|
|
|
overview.value = overviewRes || {};
|
|
|
- statistics.value = statisticsRes || {};
|
|
|
-
|
|
|
- // 构建订单趋势数据
|
|
|
- const dates = statisticsRes?.dates || [];
|
|
|
- const ordersData = statisticsRes?.ordersData || [];
|
|
|
- orderTrend.value = dates.map((date: string, index: number) => ({
|
|
|
- date: date.slice(5), // MM-dd
|
|
|
- count: ordersData[index] || 0
|
|
|
- }));
|
|
|
-
|
|
|
- if (orderTrend.value.length > 0) {
|
|
|
- maxCount.value = Math.max(...orderTrend.value.map((item: any) => item.count));
|
|
|
+ if (todoRes) {
|
|
|
+ todo.value = {
|
|
|
+ pendingRefunds: todoRes.pendingRefunds || 0,
|
|
|
+ pendingAlerts: todoRes.pendingAlerts || 0,
|
|
|
+ unpaidOrders: todoRes.unpaidOrders || 0,
|
|
|
+ lowStockItems: todoRes.lowStockItems || 0,
|
|
|
+ pendingInvoices: todoRes.pendingInvoices || 0,
|
|
|
+ expiringProducts: todoRes.expiringProducts || 0
|
|
|
+ };
|
|
|
}
|
|
|
} catch (error) {
|
|
|
console.error('获取仪表盘数据失败', error);
|
|
|
@@ -204,6 +234,12 @@ const loadData = async () => {
|
|
|
};
|
|
|
|
|
|
onMounted(() => {
|
|
|
+ try {
|
|
|
+ const systemInfo = uni.getSystemInfoSync();
|
|
|
+ statusBarHeight.value = systemInfo.statusBarHeight || 44;
|
|
|
+ } catch (e) {
|
|
|
+ statusBarHeight.value = 44;
|
|
|
+ }
|
|
|
loadData();
|
|
|
});
|
|
|
</script>
|
|
|
@@ -211,604 +247,766 @@ onMounted(() => {
|
|
|
<style lang="scss" scoped>
|
|
|
.page {
|
|
|
min-height: 100vh;
|
|
|
- background: #f8fafc;
|
|
|
- padding-bottom: 200rpx;
|
|
|
+ background: #f4f5f7;
|
|
|
+ padding-bottom: 180rpx;
|
|
|
}
|
|
|
|
|
|
-/* 顶部导航 */
|
|
|
+/* ========== 顶部品牌栏 ========== */
|
|
|
.header {
|
|
|
+ background: #fdd835;
|
|
|
+ padding: 0 32rpx 120rpx;
|
|
|
position: relative;
|
|
|
+}
|
|
|
+
|
|
|
+.header-inner {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+}
|
|
|
+
|
|
|
+.merchant {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ flex: 1;
|
|
|
+}
|
|
|
+
|
|
|
+.avatar {
|
|
|
+ width: 88rpx;
|
|
|
+ height: 88rpx;
|
|
|
+ border-radius: 20rpx;
|
|
|
background: #ffffff;
|
|
|
+ color: #333333;
|
|
|
+ font-size: 40rpx;
|
|
|
+ font-weight: 700;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ margin-right: 20rpx;
|
|
|
+ box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
|
|
|
}
|
|
|
|
|
|
-.header-bg {
|
|
|
- position: absolute;
|
|
|
- top: 0;
|
|
|
- left: 0;
|
|
|
- right: 0;
|
|
|
- height: 280rpx;
|
|
|
- background: #ecfdf5;
|
|
|
- border-radius: 0 0 40rpx 40rpx;
|
|
|
+.name-text {
|
|
|
+ font-size: 34rpx;
|
|
|
+ font-weight: 700;
|
|
|
+ color: #1a1a1a;
|
|
|
}
|
|
|
|
|
|
-.status-bar {
|
|
|
- width: 100%;
|
|
|
+/* ========== 内容区域(上浮) ========== */
|
|
|
+.content {
|
|
|
+ margin-top: -100rpx;
|
|
|
+ padding: 0 24rpx;
|
|
|
position: relative;
|
|
|
- z-index: 1;
|
|
|
+ z-index: 2;
|
|
|
}
|
|
|
|
|
|
-.header-content {
|
|
|
- position: relative;
|
|
|
+/* 通用卡片标题 */
|
|
|
+.card-title {
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
align-items: center;
|
|
|
- padding: 16rpx 24rpx 24rpx;
|
|
|
-}
|
|
|
+ margin-bottom: 24rpx;
|
|
|
|
|
|
-.greeting {
|
|
|
- .greeting-time {
|
|
|
- display: block;
|
|
|
- font-size: 26rpx;
|
|
|
- color: #64748b;
|
|
|
- margin-bottom: 4rpx;
|
|
|
- }
|
|
|
-
|
|
|
- .greeting-name {
|
|
|
- font-size: 40rpx;
|
|
|
- font-weight: 700;
|
|
|
- color: #1e293b;
|
|
|
+ > text:first-child {
|
|
|
+ font-size: 30rpx;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #1a1a1a;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-.avatar {
|
|
|
- width: 80rpx;
|
|
|
- height: 80rpx;
|
|
|
- border-radius: 50%;
|
|
|
- background: #ecfdf5;
|
|
|
+.card-more {
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #999999;
|
|
|
+
|
|
|
+ &:active { opacity: 0.6; }
|
|
|
+}
|
|
|
+
|
|
|
+.card-sub {
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #999999;
|
|
|
+}
|
|
|
+
|
|
|
+/* ========== 通知栏 ========== */
|
|
|
+.notice-bar {
|
|
|
+ background: #ffffff;
|
|
|
+ padding: 18rpx 20rpx;
|
|
|
+ border-radius: 16rpx;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
- justify-content: center;
|
|
|
- border: 2rpx solid #10b981;
|
|
|
- position: relative;
|
|
|
-
|
|
|
- .avatar-icon {
|
|
|
- width: 36rpx;
|
|
|
- height: 36rpx;
|
|
|
- background: #10b981;
|
|
|
- border-radius: 50%;
|
|
|
- position: relative;
|
|
|
-
|
|
|
- &::before {
|
|
|
- content: '';
|
|
|
- position: absolute;
|
|
|
- top: -16rpx;
|
|
|
- left: 50%;
|
|
|
- transform: translateX(-50%);
|
|
|
- width: 22rpx;
|
|
|
- height: 18rpx;
|
|
|
- background: #10b981;
|
|
|
- border-radius: 18rpx 18rpx 0 0;
|
|
|
- }
|
|
|
- }
|
|
|
+ margin-bottom: 20rpx;
|
|
|
+ box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.05);
|
|
|
+
|
|
|
+ &:active { opacity: 0.85; }
|
|
|
+}
|
|
|
+
|
|
|
+.notice-tag {
|
|
|
+ padding: 4rpx 14rpx;
|
|
|
+ background: #fff7ed;
|
|
|
+ color: #f97316;
|
|
|
+ font-size: 22rpx;
|
|
|
+ font-weight: 600;
|
|
|
+ border-radius: 8rpx;
|
|
|
+ margin-right: 16rpx;
|
|
|
+ flex-shrink: 0;
|
|
|
}
|
|
|
|
|
|
-/* 统计卡片 */
|
|
|
-.stats-section {
|
|
|
- padding: 16rpx 24rpx;
|
|
|
+.notice-content { flex: 1; overflow: hidden; }
|
|
|
+.notice-swiper { height: 40rpx; }
|
|
|
+.notice-text {
|
|
|
+ font-size: 26rpx;
|
|
|
+ color: #333333;
|
|
|
+ line-height: 40rpx;
|
|
|
+ display: block;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
}
|
|
|
|
|
|
-.stats-card {
|
|
|
+.notice-arrow {
|
|
|
+ font-size: 36rpx;
|
|
|
+ color: #cccccc;
|
|
|
+ margin-left: 12rpx;
|
|
|
+}
|
|
|
+
|
|
|
+/* ========== 核心销售卡片 ========== */
|
|
|
+.sales-card {
|
|
|
background: #ffffff;
|
|
|
- border: 1rpx solid #e2e8f0;
|
|
|
border-radius: 20rpx;
|
|
|
-
|
|
|
- &.main {
|
|
|
- display: flex;
|
|
|
- padding: 32rpx 0;
|
|
|
- margin-bottom: 16rpx;
|
|
|
-
|
|
|
- .stats-item {
|
|
|
- flex: 1;
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- }
|
|
|
-
|
|
|
- .stats-value {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- font-size: 48rpx;
|
|
|
- font-weight: 700;
|
|
|
- color: #1e293b;
|
|
|
- margin-bottom: 8rpx;
|
|
|
-
|
|
|
- &.accent {
|
|
|
- color: #f97316;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .stats-label {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- font-size: 24rpx;
|
|
|
- color: #64748b;
|
|
|
- }
|
|
|
-
|
|
|
- .stats-divider {
|
|
|
- width: 1rpx;
|
|
|
- background: #e2e8f0;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- &.mini {
|
|
|
- flex: 1;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- padding: 24rpx;
|
|
|
-
|
|
|
- &:not(:last-child) {
|
|
|
- margin-right: 12rpx;
|
|
|
- }
|
|
|
-
|
|
|
- .stats-dot {
|
|
|
- width: 12rpx;
|
|
|
- height: 12rpx;
|
|
|
- border-radius: 50%;
|
|
|
- margin-right: 16rpx;
|
|
|
- flex-shrink: 0;
|
|
|
-
|
|
|
- &.green { background: #10b981; }
|
|
|
- &.amber { background: #f97316; }
|
|
|
- }
|
|
|
-
|
|
|
- .stats-info {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
-
|
|
|
- .stats-value {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- font-size: 32rpx;
|
|
|
- font-weight: 700;
|
|
|
- color: #1e293b;
|
|
|
- }
|
|
|
-
|
|
|
- .stats-label {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- font-size: 22rpx;
|
|
|
- color: #64748b;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ padding: 32rpx;
|
|
|
+ margin-bottom: 20rpx;
|
|
|
+ box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.05);
|
|
|
}
|
|
|
|
|
|
-.stats-row {
|
|
|
+.sales-main {
|
|
|
display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: stretch;
|
|
|
+ padding-bottom: 24rpx;
|
|
|
+ border-bottom: 1rpx solid #f0f0f0;
|
|
|
}
|
|
|
|
|
|
-/* 区块 */
|
|
|
-.section {
|
|
|
- margin: 16rpx 24rpx;
|
|
|
+.sales-primary {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ flex: 1;
|
|
|
}
|
|
|
-
|
|
|
-.section-header {
|
|
|
+.sales-primary .label {
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #888888;
|
|
|
+ margin-bottom: 12rpx;
|
|
|
+}
|
|
|
+.primary-value {
|
|
|
+ font-size: 64rpx;
|
|
|
+ font-weight: 700;
|
|
|
+ color: #10b981;
|
|
|
+ line-height: 1;
|
|
|
+ margin-bottom: 10rpx;
|
|
|
+}
|
|
|
+.compare {
|
|
|
display: flex;
|
|
|
- justify-content: space-between;
|
|
|
align-items: center;
|
|
|
- margin-bottom: 16rpx;
|
|
|
+ font-size: 22rpx;
|
|
|
}
|
|
|
+.compare-text { color: #999999; margin-right: 8rpx; }
|
|
|
+.compare-value { color: #10b981; font-weight: 600; }
|
|
|
|
|
|
-.section-title {
|
|
|
- font-size: 32rpx;
|
|
|
- font-weight: 600;
|
|
|
- color: #1e293b;
|
|
|
+.sales-secondary {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: flex-start;
|
|
|
+ flex: 1;
|
|
|
}
|
|
|
|
|
|
-.section-tag {
|
|
|
+.sales-secondary .label {
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #888888;
|
|
|
+ margin-bottom: 12rpx;
|
|
|
+}
|
|
|
+.secondary-value {
|
|
|
+ font-size: 44rpx;
|
|
|
+ font-weight: 700;
|
|
|
+ color: #1a1a1a;
|
|
|
+ line-height: 1;
|
|
|
+}
|
|
|
+.unit {
|
|
|
font-size: 22rpx;
|
|
|
- color: #10b981;
|
|
|
- background: #ecfdf5;
|
|
|
- padding: 8rpx 16rpx;
|
|
|
- border-radius: 8rpx;
|
|
|
-
|
|
|
- &.hot {
|
|
|
- color: #f97316;
|
|
|
- background: #fff7ed;
|
|
|
- }
|
|
|
+ color: #999999;
|
|
|
+ margin-top: 6rpx;
|
|
|
}
|
|
|
|
|
|
-/* 快捷功能 */
|
|
|
-.quick-grid {
|
|
|
+.sales-footer {
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ margin-top: 24rpx;
|
|
|
+ gap: 0;
|
|
|
+}
|
|
|
+.footer-item {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ flex: 1;
|
|
|
+}
|
|
|
+.footer-label {
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #888888;
|
|
|
+ margin-bottom: 8rpx;
|
|
|
+}
|
|
|
+.footer-value {
|
|
|
+ font-size: 30rpx;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #1a1a1a;
|
|
|
+}
|
|
|
+.footer-divider {
|
|
|
+ width: 1rpx;
|
|
|
+ height: 40rpx;
|
|
|
+ background: #e5e7eb;
|
|
|
+}
|
|
|
+
|
|
|
+/* ========== 设备卡片 ========== */
|
|
|
+.device-card {
|
|
|
background: #ffffff;
|
|
|
- border: 1rpx solid #e2e8f0;
|
|
|
border-radius: 20rpx;
|
|
|
- padding: 24rpx 16rpx;
|
|
|
+ padding: 28rpx;
|
|
|
+ margin-bottom: 20rpx;
|
|
|
+ box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.05);
|
|
|
}
|
|
|
|
|
|
-.quick-item {
|
|
|
+.device-row {
|
|
|
+ display: flex;
|
|
|
+ gap: 20rpx;
|
|
|
+ margin-bottom: 24rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.device-box {
|
|
|
+ flex: 1;
|
|
|
+ padding: 24rpx;
|
|
|
+ border-radius: 16rpx;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
align-items: center;
|
|
|
-
|
|
|
- .quick-icon {
|
|
|
- width: 88rpx;
|
|
|
- height: 88rpx;
|
|
|
- border-radius: 20rpx;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- margin-bottom: 12rpx;
|
|
|
- transition: transform 0.15s;
|
|
|
-
|
|
|
- &:active {
|
|
|
- transform: scale(0.92);
|
|
|
- }
|
|
|
-
|
|
|
- &.green { background: #ecfdf5; }
|
|
|
- &.cyan { background: #ecfeff; }
|
|
|
- &.amber { background: #fff7ed; }
|
|
|
- &.purple { background: #faf5ff; }
|
|
|
- &.blue { background: #f0f9ff; }
|
|
|
- &.rose { background: #fff1f2; }
|
|
|
-
|
|
|
- /* 图标 - 纯CSS几何图形 */
|
|
|
- .icon-order {
|
|
|
- width: 32rpx;
|
|
|
- height: 40rpx;
|
|
|
- border: 3rpx solid #10b981;
|
|
|
- border-radius: 4rpx;
|
|
|
- position: relative;
|
|
|
-
|
|
|
- &::before, &::after {
|
|
|
- content: '';
|
|
|
- position: absolute;
|
|
|
- left: 6rpx;
|
|
|
- width: 14rpx;
|
|
|
- height: 3rpx;
|
|
|
- background: #10b981;
|
|
|
- border-radius: 2rpx;
|
|
|
- }
|
|
|
- &::before { top: 12rpx; }
|
|
|
- &::after { top: 20rpx; width: 10rpx; }
|
|
|
- }
|
|
|
-
|
|
|
- .icon-device {
|
|
|
- width: 24rpx;
|
|
|
- height: 40rpx;
|
|
|
- border: 3rpx solid #0ea5e9;
|
|
|
- border-radius: 6rpx;
|
|
|
- position: relative;
|
|
|
-
|
|
|
- &::after {
|
|
|
- content: '';
|
|
|
- position: absolute;
|
|
|
- bottom: 6rpx;
|
|
|
- left: 50%;
|
|
|
- transform: translateX(-50%);
|
|
|
- width: 8rpx;
|
|
|
- height: 4rpx;
|
|
|
- background: #0ea5e9;
|
|
|
- border-radius: 2rpx;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .icon-shop {
|
|
|
- position: relative;
|
|
|
- width: 36rpx;
|
|
|
- height: 36rpx;
|
|
|
-
|
|
|
- &::before {
|
|
|
- content: '';
|
|
|
- position: absolute;
|
|
|
- top: 0;
|
|
|
- left: 50%;
|
|
|
- transform: translateX(-50%);
|
|
|
- width: 0;
|
|
|
- height: 0;
|
|
|
- border-left: 20rpx solid transparent;
|
|
|
- border-right: 20rpx solid transparent;
|
|
|
- border-bottom: 14rpx solid #f97316;
|
|
|
- }
|
|
|
-
|
|
|
- &::after {
|
|
|
- content: '';
|
|
|
- position: absolute;
|
|
|
- bottom: 0;
|
|
|
- left: 50%;
|
|
|
- transform: translateX(-50%);
|
|
|
- width: 32rpx;
|
|
|
- height: 18rpx;
|
|
|
- background: #f97316;
|
|
|
- border-radius: 0 0 4rpx 4rpx;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .icon-product {
|
|
|
- width: 32rpx;
|
|
|
- height: 32rpx;
|
|
|
- position: relative;
|
|
|
-
|
|
|
- &::before {
|
|
|
- content: '';
|
|
|
- position: absolute;
|
|
|
- top: 0;
|
|
|
- left: 50%;
|
|
|
- transform: translateX(-50%);
|
|
|
- width: 0;
|
|
|
- height: 0;
|
|
|
- border-left: 10rpx solid transparent;
|
|
|
- border-right: 10rpx solid transparent;
|
|
|
- border-bottom: 12rpx solid #a855f7;
|
|
|
- }
|
|
|
-
|
|
|
- &::after {
|
|
|
- content: '';
|
|
|
- position: absolute;
|
|
|
- bottom: 0;
|
|
|
- left: 50%;
|
|
|
- transform: translateX(-50%);
|
|
|
- width: 28rpx;
|
|
|
- height: 16rpx;
|
|
|
- background: #a855f7;
|
|
|
- border-radius: 4rpx;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .icon-chart {
|
|
|
- display: flex;
|
|
|
- align-items: flex-end;
|
|
|
- justify-content: space-between;
|
|
|
- width: 32rpx;
|
|
|
- height: 28rpx;
|
|
|
-
|
|
|
- &::before, &::after, & {
|
|
|
- content: '';
|
|
|
- width: 8rpx;
|
|
|
- background: #0ea5e9;
|
|
|
- border-radius: 4rpx;
|
|
|
- }
|
|
|
- &::before { height: 12rpx; }
|
|
|
- & { height: 24rpx; }
|
|
|
- &::after { height: 16rpx; }
|
|
|
- }
|
|
|
-
|
|
|
- .icon-checkin {
|
|
|
- width: 28rpx;
|
|
|
- height: 28rpx;
|
|
|
- border: 3rpx solid #f97316;
|
|
|
- border-radius: 50%;
|
|
|
- position: relative;
|
|
|
-
|
|
|
- &::before {
|
|
|
- content: '';
|
|
|
- position: absolute;
|
|
|
- top: 50%;
|
|
|
- left: 50%;
|
|
|
- transform: translate(-50%, -50%);
|
|
|
- width: 8rpx;
|
|
|
- height: 8rpx;
|
|
|
- background: #f97316;
|
|
|
- border-radius: 50%;
|
|
|
- }
|
|
|
-
|
|
|
- &::after {
|
|
|
- content: '';
|
|
|
- position: absolute;
|
|
|
- top: -6rpx;
|
|
|
- right: -6rpx;
|
|
|
- width: 12rpx;
|
|
|
- height: 12rpx;
|
|
|
- background: #f97316;
|
|
|
- border-radius: 50%;
|
|
|
- }
|
|
|
- }
|
|
|
|
|
|
- .icon-user {
|
|
|
- width: 24rpx;
|
|
|
- height: 24rpx;
|
|
|
- border: 3rpx solid #10b981;
|
|
|
- border-radius: 50%;
|
|
|
- position: relative;
|
|
|
-
|
|
|
- &::before {
|
|
|
- content: '';
|
|
|
- position: absolute;
|
|
|
- top: -10rpx;
|
|
|
- left: 50%;
|
|
|
- transform: translateX(-50%);
|
|
|
- width: 12rpx;
|
|
|
- height: 12rpx;
|
|
|
- border: 3rpx solid #10b981;
|
|
|
- border-radius: 50%;
|
|
|
- }
|
|
|
- }
|
|
|
+ &.online { background: #ecfdf5; }
|
|
|
+ &.offline { background: #fff7ed; }
|
|
|
|
|
|
- .icon-stats {
|
|
|
- display: flex;
|
|
|
- align-items: flex-end;
|
|
|
- width: 28rpx;
|
|
|
- height: 24rpx;
|
|
|
-
|
|
|
- &::before, &::after, & {
|
|
|
- content: '';
|
|
|
- width: 8rpx;
|
|
|
- background: #0ea5e9;
|
|
|
- border-radius: 4rpx;
|
|
|
- }
|
|
|
-
|
|
|
- &::before { height: 10rpx; margin-right: 2rpx; }
|
|
|
- & { height: 22rpx; margin-right: 2rpx; }
|
|
|
- &::after { height: 16rpx; }
|
|
|
- }
|
|
|
+ &:active { opacity: 0.85; }
|
|
|
+}
|
|
|
|
|
|
- .icon-warning {
|
|
|
- width: 28rpx;
|
|
|
- height: 28rpx;
|
|
|
- border: 3rpx solid #f43f5e;
|
|
|
- border-radius: 50%;
|
|
|
- position: relative;
|
|
|
-
|
|
|
- &::before {
|
|
|
- content: '';
|
|
|
- position: absolute;
|
|
|
- top: 50%;
|
|
|
- left: 50%;
|
|
|
- transform: translate(-50%, -50%);
|
|
|
- width: 3rpx;
|
|
|
- height: 12rpx;
|
|
|
- background: #f43f5e;
|
|
|
- }
|
|
|
-
|
|
|
- &::after {
|
|
|
- content: '';
|
|
|
- position: absolute;
|
|
|
- bottom: 4rpx;
|
|
|
- left: 50%;
|
|
|
- transform: translateX(-50%);
|
|
|
- width: 3rpx;
|
|
|
- height: 3rpx;
|
|
|
- background: #f43f5e;
|
|
|
- border-radius: 50%;
|
|
|
- }
|
|
|
- }
|
|
|
+.device-top {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 12rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.device-dot {
|
|
|
+ width: 14rpx;
|
|
|
+ height: 14rpx;
|
|
|
+ border-radius: 50%;
|
|
|
+ margin-right: 10rpx;
|
|
|
+
|
|
|
+ &.online-dot { background: #10b981; }
|
|
|
+ &.offline-dot { background: #f97316; }
|
|
|
+}
|
|
|
+
|
|
|
+.device-label {
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #666666;
|
|
|
+}
|
|
|
+
|
|
|
+.device-num {
|
|
|
+ font-size: 48rpx;
|
|
|
+ font-weight: 700;
|
|
|
+ color: #1a1a1a;
|
|
|
+ line-height: 1;
|
|
|
+}
|
|
|
+
|
|
|
+.data-entry-row {
|
|
|
+ display: flex;
|
|
|
+ gap: 20rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.data-entry {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding: 20rpx;
|
|
|
+ background: #f9fafb;
|
|
|
+ border-radius: 16rpx;
|
|
|
+
|
|
|
+ &:active { opacity: 0.8; }
|
|
|
+}
|
|
|
+
|
|
|
+.data-entry-icon {
|
|
|
+ width: 60rpx;
|
|
|
+ height: 60rpx;
|
|
|
+ border-radius: 14rpx;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ margin-right: 14rpx;
|
|
|
+ flex-shrink: 0;
|
|
|
+
|
|
|
+ &.chart { background: #ecfdf5; }
|
|
|
+ &.analytics { background: #fff7ed; }
|
|
|
+}
|
|
|
+
|
|
|
+.data-entry-info {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ min-width: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.data-entry-title {
|
|
|
+ font-size: 26rpx;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #1a1a1a;
|
|
|
+ margin-bottom: 4rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.data-entry-sub {
|
|
|
+ font-size: 20rpx;
|
|
|
+ color: #999999;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
+}
|
|
|
+
|
|
|
+.data-entry-arrow {
|
|
|
+ font-size: 32rpx;
|
|
|
+ color: #cccccc;
|
|
|
+ margin-left: 8rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.icon-chart {
|
|
|
+ display: flex;
|
|
|
+ align-items: flex-end;
|
|
|
+ width: 30rpx;
|
|
|
+ height: 28rpx;
|
|
|
+
|
|
|
+ &::before, &::after {
|
|
|
+ content: '';
|
|
|
+ width: 7rpx;
|
|
|
+ background: #10b981;
|
|
|
+ border-radius: 2rpx;
|
|
|
+ margin-right: 3rpx;
|
|
|
}
|
|
|
+ &::before { height: 14rpx; }
|
|
|
+ &::after { height: 24rpx; margin-right: 0; }
|
|
|
+}
|
|
|
|
|
|
- .quick-name {
|
|
|
- font-size: 24rpx;
|
|
|
- color: #475569;
|
|
|
+.icon-analytics {
|
|
|
+ width: 28rpx;
|
|
|
+ height: 28rpx;
|
|
|
+ position: relative;
|
|
|
+
|
|
|
+ &::before {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ border: 3rpx solid #f97316;
|
|
|
+ border-radius: 50%;
|
|
|
+ }
|
|
|
+ &::after {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ top: 50%;
|
|
|
+ left: 50%;
|
|
|
+ width: 3rpx;
|
|
|
+ height: 14rpx;
|
|
|
+ background: #f97316;
|
|
|
+ transform-origin: bottom center;
|
|
|
+ transform: translate(-50%, -100%) rotate(35deg);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-/* 图表卡片 */
|
|
|
-.chart-card {
|
|
|
+/* ========== 待办事项 ========== */
|
|
|
+.todo-card {
|
|
|
background: #ffffff;
|
|
|
- border: 1rpx solid #e2e8f0;
|
|
|
border-radius: 20rpx;
|
|
|
- padding: 24rpx;
|
|
|
+ padding: 28rpx;
|
|
|
+ margin-bottom: 20rpx;
|
|
|
+ box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.05);
|
|
|
}
|
|
|
|
|
|
-.chart-container {
|
|
|
+.todo-grid {
|
|
|
display: flex;
|
|
|
- justify-content: space-between;
|
|
|
- align-items: flex-end;
|
|
|
- height: 240rpx;
|
|
|
- padding-top: 32rpx;
|
|
|
+ flex-wrap: wrap;
|
|
|
}
|
|
|
|
|
|
-.chart-bar-wrapper {
|
|
|
- flex: 1;
|
|
|
+.todo-item {
|
|
|
+ width: 33.333%;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding: 14rpx 6rpx;
|
|
|
+ box-sizing: border-box;
|
|
|
+
|
|
|
+ &:active { opacity: 0.7; }
|
|
|
+}
|
|
|
+
|
|
|
+.todo-icon {
|
|
|
+ width: 64rpx;
|
|
|
+ height: 64rpx;
|
|
|
+ border-radius: 16rpx;
|
|
|
display: flex;
|
|
|
- flex-direction: column;
|
|
|
align-items: center;
|
|
|
- height: 100%;
|
|
|
-
|
|
|
- .chart-value {
|
|
|
+ justify-content: center;
|
|
|
+ margin-right: 14rpx;
|
|
|
+ flex-shrink: 0;
|
|
|
+
|
|
|
+ &.red { background: #fef2f2; }
|
|
|
+ &.orange { background: #fff7ed; }
|
|
|
+ &.yellow { background: #fefce8; }
|
|
|
+ &.blue { background: #eff6ff; }
|
|
|
+ &.purple { background: #f5f3ff; }
|
|
|
+ &.cyan { background: #ecfeff; }
|
|
|
+
|
|
|
+ &.disabled { opacity: 0.6; }
|
|
|
+}
|
|
|
+
|
|
|
+.todo-info {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ min-width: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.todo-value {
|
|
|
+ font-size: 32rpx;
|
|
|
+ font-weight: 700;
|
|
|
+ color: #cccccc;
|
|
|
+ line-height: 1.2;
|
|
|
+
|
|
|
+ &.active { color: #1a1a1a; }
|
|
|
+}
|
|
|
+
|
|
|
+.todo-label {
|
|
|
+ font-size: 22rpx;
|
|
|
+ color: #666666;
|
|
|
+ margin-top: 2rpx;
|
|
|
+ white-space: nowrap;
|
|
|
+}
|
|
|
+
|
|
|
+/* 待办图标 */
|
|
|
+.icon-refund {
|
|
|
+ width: 30rpx;
|
|
|
+ height: 30rpx;
|
|
|
+ border: 3rpx solid #ef4444;
|
|
|
+ border-radius: 50%;
|
|
|
+ position: relative;
|
|
|
+
|
|
|
+ &::before {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ top: 50%;
|
|
|
+ left: 50%;
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
+ width: 14rpx;
|
|
|
+ height: 3rpx;
|
|
|
+ background: #ef4444;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.icon-alert {
|
|
|
+ width: 0;
|
|
|
+ height: 0;
|
|
|
+ border-left: 16rpx solid transparent;
|
|
|
+ border-right: 16rpx solid transparent;
|
|
|
+ border-bottom: 28rpx solid #f97316;
|
|
|
+ position: relative;
|
|
|
+
|
|
|
+ &::before {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ bottom: -20rpx;
|
|
|
+ left: 50%;
|
|
|
+ transform: translateX(-50%);
|
|
|
+ width: 3rpx;
|
|
|
+ height: 10rpx;
|
|
|
+ background: #ffffff;
|
|
|
+ }
|
|
|
+ &::after {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ bottom: -26rpx;
|
|
|
+ left: 50%;
|
|
|
+ transform: translateX(-50%);
|
|
|
+ width: 3rpx;
|
|
|
+ height: 3rpx;
|
|
|
+ background: #ffffff;
|
|
|
+ border-radius: 50%;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.icon-unpaid {
|
|
|
+ width: 30rpx;
|
|
|
+ height: 30rpx;
|
|
|
+ border: 3rpx solid #eab308;
|
|
|
+ border-radius: 50%;
|
|
|
+ position: relative;
|
|
|
+
|
|
|
+ &::before {
|
|
|
+ content: '¥';
|
|
|
+ position: absolute;
|
|
|
+ top: 50%;
|
|
|
+ left: 50%;
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
font-size: 22rpx;
|
|
|
- font-weight: 600;
|
|
|
- color: #475569;
|
|
|
- margin-bottom: 8rpx;
|
|
|
+ font-weight: 700;
|
|
|
+ color: #eab308;
|
|
|
+ line-height: 1;
|
|
|
}
|
|
|
-
|
|
|
- .chart-bar-bg {
|
|
|
- flex: 1;
|
|
|
- width: 28rpx;
|
|
|
- display: flex;
|
|
|
- align-items: flex-end;
|
|
|
- background: #f1f5f9;
|
|
|
- border-radius: 6rpx;
|
|
|
-
|
|
|
- .chart-bar {
|
|
|
- width: 100%;
|
|
|
- background: #10b981;
|
|
|
- border-radius: 6rpx;
|
|
|
- min-height: 20rpx;
|
|
|
- }
|
|
|
+}
|
|
|
+
|
|
|
+.icon-restock {
|
|
|
+ width: 30rpx;
|
|
|
+ height: 28rpx;
|
|
|
+ background: #3b82f6;
|
|
|
+ border-radius: 3rpx;
|
|
|
+ position: relative;
|
|
|
+
|
|
|
+ &::before {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 50%;
|
|
|
+ transform: translateX(-50%);
|
|
|
+ width: 14rpx;
|
|
|
+ height: 6rpx;
|
|
|
+ background: #3b82f6;
|
|
|
+ border-radius: 3rpx 3rpx 0 0;
|
|
|
+ top: -4rpx;
|
|
|
}
|
|
|
-
|
|
|
- .chart-label {
|
|
|
- font-size: 20rpx;
|
|
|
- color: #94a3b8;
|
|
|
- margin-top: 10rpx;
|
|
|
+ &::after {
|
|
|
+ content: '+';
|
|
|
+ position: absolute;
|
|
|
+ top: 50%;
|
|
|
+ left: 50%;
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #ffffff;
|
|
|
+ font-weight: 700;
|
|
|
+ line-height: 1;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-/* 热销列表 */
|
|
|
-.hot-list {
|
|
|
+.icon-invoice {
|
|
|
+ width: 28rpx;
|
|
|
+ height: 32rpx;
|
|
|
+ background: #8b5cf6;
|
|
|
+ border-radius: 3rpx;
|
|
|
+ position: relative;
|
|
|
+
|
|
|
+ &::before {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ top: 10rpx;
|
|
|
+ left: 50%;
|
|
|
+ transform: translateX(-50%);
|
|
|
+ width: 16rpx;
|
|
|
+ height: 2rpx;
|
|
|
+ background: #ffffff;
|
|
|
+ box-shadow: 0 5rpx 0 #ffffff, 0 10rpx 0 #ffffff;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.icon-expire {
|
|
|
+ width: 30rpx;
|
|
|
+ height: 30rpx;
|
|
|
+ border: 3rpx solid #06b6d4;
|
|
|
+ border-radius: 50%;
|
|
|
+ position: relative;
|
|
|
+
|
|
|
+ &::before {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ top: 50%;
|
|
|
+ left: 50%;
|
|
|
+ width: 3rpx;
|
|
|
+ height: 10rpx;
|
|
|
+ background: #06b6d4;
|
|
|
+ transform-origin: bottom center;
|
|
|
+ transform: translate(-50%, -100%);
|
|
|
+ }
|
|
|
+ &::after {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ top: 50%;
|
|
|
+ left: 50%;
|
|
|
+ width: 3rpx;
|
|
|
+ height: 7rpx;
|
|
|
+ background: #06b6d4;
|
|
|
+ transform-origin: bottom center;
|
|
|
+ transform: translate(-50%, -100%) rotate(90deg);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* ========== 商户运营 ========== */
|
|
|
+.quick-card {
|
|
|
background: #ffffff;
|
|
|
- border: 1rpx solid #e2e8f0;
|
|
|
border-radius: 20rpx;
|
|
|
- padding: 8rpx 20rpx;
|
|
|
+ padding: 28rpx 20rpx 20rpx;
|
|
|
+ margin-bottom: 20rpx;
|
|
|
+ box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.05);
|
|
|
+
|
|
|
+ .card-title {
|
|
|
+ padding: 0 8rpx;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.quick-grid {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+}
|
|
|
+
|
|
|
+.quick-item {
|
|
|
+ width: 25%;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ padding: 8rpx 0;
|
|
|
+
|
|
|
+ &:active .quick-icon { transform: scale(0.92); }
|
|
|
}
|
|
|
|
|
|
-.hot-item {
|
|
|
+.quick-icon {
|
|
|
+ width: 92rpx;
|
|
|
+ height: 92rpx;
|
|
|
+ border-radius: 22rpx;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
- padding: 20rpx 8rpx;
|
|
|
- border-bottom: 1rpx solid #f1f5f9;
|
|
|
-
|
|
|
- &:last-child {
|
|
|
- border-bottom: none;
|
|
|
+ justify-content: center;
|
|
|
+ margin-bottom: 12rpx;
|
|
|
+ transition: transform 0.15s;
|
|
|
+
|
|
|
+ &.primary { background: #ecfdf5; }
|
|
|
+ &.orange { background: #fff7ed; }
|
|
|
+ &.green { background: #f0fdf4; }
|
|
|
+ &.blue { background: #eff6ff; }
|
|
|
+}
|
|
|
+
|
|
|
+.quick-name {
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #333333;
|
|
|
+}
|
|
|
+
|
|
|
+.icon-apply {
|
|
|
+ width: 36rpx;
|
|
|
+ height: 36rpx;
|
|
|
+ position: relative;
|
|
|
+
|
|
|
+ &::before {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ border: 3rpx solid #10b981;
|
|
|
+ border-radius: 6rpx;
|
|
|
}
|
|
|
-
|
|
|
- .hot-rank {
|
|
|
- width: 44rpx;
|
|
|
- height: 44rpx;
|
|
|
- border-radius: 12rpx;
|
|
|
- background: #f1f5f9;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- margin-right: 16rpx;
|
|
|
- font-size: 24rpx;
|
|
|
- font-weight: 600;
|
|
|
- color: #94a3b8;
|
|
|
-
|
|
|
- &.top {
|
|
|
- background: #10b981;
|
|
|
- color: #fff;
|
|
|
- }
|
|
|
+ &::after {
|
|
|
+ content: '+';
|
|
|
+ position: absolute;
|
|
|
+ top: 50%;
|
|
|
+ left: 50%;
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #10b981;
|
|
|
+ font-weight: 700;
|
|
|
+ line-height: 1;
|
|
|
}
|
|
|
-
|
|
|
- .hot-info {
|
|
|
- flex: 1;
|
|
|
-
|
|
|
- .hot-name {
|
|
|
- display: block;
|
|
|
- font-size: 28rpx;
|
|
|
- color: #1e293b;
|
|
|
- margin-bottom: 4rpx;
|
|
|
- font-weight: 500;
|
|
|
- }
|
|
|
-
|
|
|
- .hot-sales {
|
|
|
- font-size: 24rpx;
|
|
|
- color: #94a3b8;
|
|
|
- }
|
|
|
+}
|
|
|
+
|
|
|
+.icon-marketing {
|
|
|
+ width: 36rpx;
|
|
|
+ height: 36rpx;
|
|
|
+ position: relative;
|
|
|
+
|
|
|
+ &::before {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ top: 50%;
|
|
|
+ left: 0;
|
|
|
+ transform: translateY(-50%);
|
|
|
+ width: 26rpx;
|
|
|
+ height: 16rpx;
|
|
|
+ background: #f97316;
|
|
|
+ border-radius: 2rpx 0 0 2rpx;
|
|
|
}
|
|
|
-
|
|
|
- .hot-progress {
|
|
|
- width: 80rpx;
|
|
|
- height: 8rpx;
|
|
|
- background: #f1f5f9;
|
|
|
- border-radius: 4rpx;
|
|
|
- overflow: hidden;
|
|
|
-
|
|
|
- .hot-progress-bar {
|
|
|
- height: 100%;
|
|
|
- background: #f97316;
|
|
|
- border-radius: 4rpx;
|
|
|
- }
|
|
|
+ &::after {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ top: 50%;
|
|
|
+ right: 0;
|
|
|
+ transform: translateY(-50%);
|
|
|
+ width: 0;
|
|
|
+ height: 0;
|
|
|
+ border-top: 14rpx solid transparent;
|
|
|
+ border-bottom: 14rpx solid transparent;
|
|
|
+ border-left: 14rpx solid #f97316;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.icon-staff {
|
|
|
+ width: 32rpx;
|
|
|
+ height: 36rpx;
|
|
|
+ position: relative;
|
|
|
+
|
|
|
+ &::before {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 50%;
|
|
|
+ transform: translateX(-50%);
|
|
|
+ width: 18rpx;
|
|
|
+ height: 18rpx;
|
|
|
+ background: #22c55e;
|
|
|
+ border-radius: 50%;
|
|
|
+ }
|
|
|
+ &::after {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ bottom: 0;
|
|
|
+ left: 50%;
|
|
|
+ transform: translateX(-50%);
|
|
|
+ width: 30rpx;
|
|
|
+ height: 14rpx;
|
|
|
+ background: #22c55e;
|
|
|
+ border-radius: 14rpx 14rpx 0 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.icon-shop-quick {
|
|
|
+ width: 36rpx;
|
|
|
+ height: 36rpx;
|
|
|
+ position: relative;
|
|
|
+
|
|
|
+ &::before {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 50%;
|
|
|
+ transform: translateX(-50%);
|
|
|
+ width: 0;
|
|
|
+ height: 0;
|
|
|
+ border-left: 20rpx solid transparent;
|
|
|
+ border-right: 20rpx solid transparent;
|
|
|
+ border-bottom: 14rpx solid #3b82f6;
|
|
|
+ }
|
|
|
+ &::after {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ bottom: 0;
|
|
|
+ left: 50%;
|
|
|
+ transform: translateX(-50%);
|
|
|
+ width: 30rpx;
|
|
|
+ height: 20rpx;
|
|
|
+ background: #3b82f6;
|
|
|
+ border-radius: 2rpx;
|
|
|
}
|
|
|
}
|
|
|
</style>
|