first commit
This commit is contained in:
@@ -0,0 +1,790 @@
|
||||
<template>
|
||||
<div class="dashboard">
|
||||
<!-- 欢迎区域 -->
|
||||
<div class="welcome-section">
|
||||
<div class="welcome-content">
|
||||
<h1 class="welcome-title">欢迎回来!</h1>
|
||||
<p class="welcome-subtitle">今天是 {{ currentDate }},祝您工作愉快</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 统计卡片 -->
|
||||
<div class="stats-grid">
|
||||
<div
|
||||
v-for="(stat, index) in stats"
|
||||
:key="index"
|
||||
class="stat-card"
|
||||
:class="stat.type"
|
||||
>
|
||||
<div class="stat-icon-wrapper">
|
||||
<el-icon :size="28">
|
||||
<component :is="stat.icon" />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value">{{ stat.value }}</div>
|
||||
<div class="stat-label">{{ stat.label }}</div>
|
||||
</div>
|
||||
<div
|
||||
class="stat-trend"
|
||||
:class="stat.change > 0 ? 'up' : stat.change < 0 ? 'down' : 'flat'"
|
||||
>
|
||||
<el-icon v-if="stat.change > 0" :size="14">
|
||||
<ArrowUp />
|
||||
</el-icon>
|
||||
<el-icon v-else-if="stat.change < 0" :size="14">
|
||||
<ArrowDown />
|
||||
</el-icon>
|
||||
<span>{{ stat.change > 0 ? "+" : "" }}{{ stat.change }}%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 图表区域 -->
|
||||
<!-- <div class="charts-section">
|
||||
<div class="chart-card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">月收入走势</h3>
|
||||
<el-dropdown trigger="click">
|
||||
<el-button type="primary" link>
|
||||
<el-icon>
|
||||
<MoreFilled />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item>查看详情</el-dropdown-item>
|
||||
<el-dropdown-item>导出数据</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
<div class="chart-container">
|
||||
<canvas id="lineChart" height="160"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="chart-card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">用户活跃分布</h3>
|
||||
<el-dropdown trigger="click">
|
||||
<el-button type="primary" link>
|
||||
<el-icon>
|
||||
<MoreFilled />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item>查看详情</el-dropdown-item>
|
||||
<el-dropdown-item>导出数据</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
<div class="chart-container">
|
||||
<canvas id="barChart" height="160"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<!-- 列表区域 -->
|
||||
<div class="lists-section">
|
||||
<div class="list-card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">待办任务</h3>
|
||||
<el-button type="primary" link size="small">
|
||||
<el-icon>
|
||||
<Plus />
|
||||
</el-icon>
|
||||
添加任务
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="list-content">
|
||||
<div
|
||||
v-for="(task, idx) in paginatedTasks"
|
||||
:key="idx"
|
||||
class="task-item"
|
||||
:class="{ done: task.completed }"
|
||||
>
|
||||
<!-- <el-checkbox v-model="task.completed" @change="handleTaskChange(task)" /> -->
|
||||
<div class="task-info">
|
||||
<div class="task-title">
|
||||
{{ task.title }}
|
||||
<el-tag
|
||||
:type="task.priorityTagType || getPriorityType(task.priority)"
|
||||
size="small"
|
||||
effect="plain"
|
||||
:class="'priority-' + task.priority"
|
||||
>
|
||||
{{ task.priorityLabel || task.priority }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div class="task-meta">
|
||||
<span class="task-date">
|
||||
<el-icon><Clock /></el-icon>
|
||||
{{ formatDate(task.date) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-empty
|
||||
description="暂无待办任务"
|
||||
:image-size="80"
|
||||
/>
|
||||
<div class="pagination-wrapper">
|
||||
<el-pagination
|
||||
v-model:current-page="taskCurrentPage"
|
||||
:page-size="taskPageSize"
|
||||
layout="prev, pager, next"
|
||||
size="small"
|
||||
@current-change="handleTaskPageChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="list-card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">最新动态</h3>
|
||||
<!-- <el-button type="primary" link size="small" @click="goToActivityLogs">
|
||||
查看全部
|
||||
</el-button> -->
|
||||
</div>
|
||||
<div class="list-content">
|
||||
<div
|
||||
v-for="(activity, idx) in paginatedActivityLogs"
|
||||
:key="idx"
|
||||
class="activity-item"
|
||||
>
|
||||
<div class="activity-icon" :class="activity.type">
|
||||
<el-icon>
|
||||
<component :is="getActivityIcon(activity.type)" />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="activity-info">
|
||||
<div class="activity-text">
|
||||
<span class="activity-module">{{ activity.operation }}</span>
|
||||
<span class="activity-action">{{ activity.description }}</span>
|
||||
</div>
|
||||
<div class="activity-time">
|
||||
{{ formatTime(activity.timestamp) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-empty
|
||||
description="暂无动态"
|
||||
:image-size="80"
|
||||
/>
|
||||
<div v-if="totalActivityLogs > pageSize" class="pagination-wrapper">
|
||||
<el-pagination
|
||||
v-model:current-page="currentPage"
|
||||
:page-size="pageSize"
|
||||
:total="totalActivityLogs"
|
||||
layout="prev, pager, next"
|
||||
size="small"
|
||||
@current-change="handlePageChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, markRaw } from "vue";
|
||||
import { Chart, registerables } from "chart.js";
|
||||
import {
|
||||
Money,
|
||||
User,
|
||||
ShoppingCart,
|
||||
TrendCharts,
|
||||
ArrowUp,
|
||||
ArrowDown,
|
||||
MoreFilled,
|
||||
Plus,
|
||||
Document,
|
||||
Edit,
|
||||
View,
|
||||
} from "@element-plus/icons-vue";
|
||||
import { getMenus } from "@/api/menu";
|
||||
|
||||
import { useAuthStore } from "@/stores/auth";
|
||||
import { useDictStore } from "@/stores/dict";
|
||||
|
||||
Chart.register(...registerables);
|
||||
|
||||
|
||||
// 当前日期
|
||||
const currentDate = computed(() => {
|
||||
const date = new Date();
|
||||
const weekdays = [
|
||||
"星期日",
|
||||
"星期一",
|
||||
"星期二",
|
||||
"星期三",
|
||||
"星期四",
|
||||
"星期五",
|
||||
"星期六",
|
||||
];
|
||||
const month = date.getMonth() + 1;
|
||||
const day = date.getDate();
|
||||
const weekday = weekdays[date.getDay()];
|
||||
return `${month}月${day}日 ${weekday}`;
|
||||
});
|
||||
|
||||
//格式化时间
|
||||
const formatDate = (date: string) => {
|
||||
const d = new Date(date);
|
||||
const month = d.getMonth() + 1;
|
||||
const day = d.getDate();
|
||||
return `${month}月${day}日`;
|
||||
};
|
||||
|
||||
// 统计数据(使用 markRaw 避免图标组件被响应式化)
|
||||
const stats = ref([
|
||||
{
|
||||
label: "知识库",
|
||||
value: "0",
|
||||
change: 0,
|
||||
icon: markRaw(Document),
|
||||
type: "knowledge",
|
||||
},
|
||||
{
|
||||
label: "新用户",
|
||||
value: "0",
|
||||
change: 0,
|
||||
icon: markRaw(User),
|
||||
type: "users",
|
||||
},
|
||||
{
|
||||
label: "员工数",
|
||||
value: "0",
|
||||
change: 0,
|
||||
icon: markRaw(ShoppingCart),
|
||||
type: "employees",
|
||||
},
|
||||
{
|
||||
label: "租户数",
|
||||
value: "0",
|
||||
change: 0,
|
||||
icon: markRaw(TrendCharts),
|
||||
type: "tenants",
|
||||
},
|
||||
]);
|
||||
|
||||
// 任务相关数据
|
||||
const tasks = ref([]);
|
||||
const taskCurrentPage = ref(1);
|
||||
const taskPageSize = ref(5);
|
||||
|
||||
// 活动日志相关数据
|
||||
const activityLogs = ref([]);
|
||||
const currentPage = ref(1);
|
||||
const pageSize = ref(5);
|
||||
const totalActivityLogs = ref(0);
|
||||
|
||||
// 计算属性
|
||||
const paginatedTasks = computed(() => {
|
||||
const start = (taskCurrentPage.value - 1) * taskPageSize.value;
|
||||
const end = start + taskPageSize.value;
|
||||
return tasks.value.slice(start, end);
|
||||
});
|
||||
|
||||
const paginatedActivityLogs = computed(() => {
|
||||
const start = (currentPage.value - 1) * pageSize.value;
|
||||
const end = start + pageSize.value;
|
||||
return activityLogs.value.slice(start, end);
|
||||
});
|
||||
|
||||
// 事件处理函数
|
||||
const handleTaskPageChange = (page) => {
|
||||
taskCurrentPage.value = page;
|
||||
};
|
||||
|
||||
const handlePageChange = (page) => {
|
||||
currentPage.value = page;
|
||||
};
|
||||
|
||||
const getPriorityType = (priority) => {
|
||||
const types = {
|
||||
high: 'danger',
|
||||
medium: 'warning',
|
||||
low: 'info'
|
||||
};
|
||||
return types[priority] || 'info';
|
||||
};
|
||||
|
||||
const getActivityIcon = (type) => {
|
||||
const icons = {
|
||||
operation: Edit,
|
||||
access: View
|
||||
};
|
||||
return icons[type] || Document;
|
||||
};
|
||||
|
||||
const authStore = useAuthStore();
|
||||
|
||||
// 格式化时间
|
||||
const formatTime = (timestamp: string | Date) => {
|
||||
if (!timestamp) return "-";
|
||||
const date = new Date(timestamp);
|
||||
if (isNaN(date.getTime())) return String(timestamp);
|
||||
|
||||
const now = new Date();
|
||||
const diff = now.getTime() - date.getTime();
|
||||
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
|
||||
|
||||
if (days < 1) {
|
||||
const hours = Math.floor(diff / (1000 * 60 * 60));
|
||||
if (hours < 1) {
|
||||
const minutes = Math.floor(diff / (1000 * 60));
|
||||
return `${minutes}分钟前`;
|
||||
}
|
||||
return `${hours}小时前`;
|
||||
}
|
||||
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||
const day = String(date.getDate()).padStart(2, "0");
|
||||
const hours = String(date.getHours()).padStart(2, "0");
|
||||
const minutes = String(date.getMinutes()).padStart(2, "0");
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}`;
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
// 从auth store获取用户信息
|
||||
const id = authStore.user.id;
|
||||
console.log('用户ID:', id);
|
||||
if (!id) {
|
||||
console.error('用户ID不存在');
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await getMenus(id);
|
||||
} catch (error) {
|
||||
console.error('获取菜单数据失败:', error);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.dashboard {
|
||||
min-height: 100%;
|
||||
background-color: var(--el-bg-color-page);
|
||||
}
|
||||
|
||||
// 欢迎区域
|
||||
.welcome-section {
|
||||
margin-bottom: 16px;
|
||||
padding: 32px;
|
||||
background: linear-gradient(135deg, #3973ff 0%, #4f84ff 100%);
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 12px rgba(6, 45, 163, 0.2);
|
||||
|
||||
.welcome-content {
|
||||
.welcome-title {
|
||||
margin: 0 0 8px;
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.welcome-subtitle {
|
||||
margin: 0;
|
||||
font-size: 15px;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 统计卡片
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
||||
gap: 16px;
|
||||
margin-bottom: 16px;
|
||||
|
||||
.stat-card {
|
||||
background: var(--el-bg-color);
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
border: 1px solid var(--el-border-color-lighter);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||
transition: all 0.3s;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||||
border-color: var(--el-color-primary-light-7);
|
||||
}
|
||||
|
||||
.stat-icon-wrapper {
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
|
||||
.el-icon {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&.income .stat-icon-wrapper {
|
||||
background: linear-gradient(135deg, #3973ff 0%, #4f84ff 100%);
|
||||
}
|
||||
|
||||
&.users .stat-icon-wrapper {
|
||||
background: linear-gradient(135deg, #10b981 0%, #34d399 100%);
|
||||
}
|
||||
|
||||
&.orders .stat-icon-wrapper {
|
||||
background: linear-gradient(135deg, #f59e0b 0%, #fbbf24 100%);
|
||||
}
|
||||
|
||||
&.active .stat-icon-wrapper {
|
||||
background: linear-gradient(135deg, #8b5cf6 0%, #a78bfa 100%);
|
||||
}
|
||||
|
||||
&.knowledge .stat-icon-wrapper {
|
||||
background: linear-gradient(135deg, #3973ff 0%, #4f84ff 100%);
|
||||
}
|
||||
|
||||
&.employees .stat-icon-wrapper {
|
||||
background: linear-gradient(135deg, #10b981 0%, #34d399 100%);
|
||||
}
|
||||
|
||||
&.tenants .stat-icon-wrapper {
|
||||
background: linear-gradient(135deg, #8b5cf6 0%, #a78bfa 100%);
|
||||
}
|
||||
|
||||
.stat-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
|
||||
.stat-value {
|
||||
font-size: 28px;
|
||||
font-weight: 700;
|
||||
color: var(--el-text-color-primary);
|
||||
line-height: 1;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 14px;
|
||||
color: var(--el-text-color-regular);
|
||||
}
|
||||
}
|
||||
|
||||
.stat-trend {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
padding: 4px 8px;
|
||||
border-radius: 6px;
|
||||
|
||||
&.up {
|
||||
color: #10b981;
|
||||
background: rgba(16, 185, 129, 0.1);
|
||||
}
|
||||
|
||||
&.down {
|
||||
color: #ef4444;
|
||||
background: rgba(239, 68, 68, 0.1);
|
||||
}
|
||||
|
||||
&.flat {
|
||||
color: var(--el-text-color-placeholder);
|
||||
background: var(--el-fill-color-lighter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 图表区域
|
||||
.charts-section {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
|
||||
gap: 20px;
|
||||
margin-bottom: 24px;
|
||||
|
||||
.chart-card {
|
||||
background: var(--el-bg-color);
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
border: 1px solid var(--el-border-color-lighter);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.card-title {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
height: 280px;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 列表区域
|
||||
.lists-section {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
|
||||
gap: 16px;
|
||||
|
||||
.list-card {
|
||||
background: var(--el-bg-color);
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
border: 1px solid var(--el-border-color-lighter);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.card-title {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.list-content {
|
||||
min-height: 400px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.task-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
padding: 12px 0;
|
||||
border-bottom: 1px solid var(--el-border-color-lighter);
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--el-fill-color-lighter);
|
||||
margin: 0 -24px;
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
&.done {
|
||||
.task-info {
|
||||
margin-left: 20px;
|
||||
.task-title {
|
||||
text-decoration: line-through;
|
||||
color: var(--el-text-color-placeholder);
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.task-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
|
||||
.task-title {
|
||||
font-size: 14px;
|
||||
color: var(--el-text-color-primary);
|
||||
margin-bottom: 4px;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.el-tag {
|
||||
margin-left: 8px !important;
|
||||
}
|
||||
|
||||
.task-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
.task-date {
|
||||
font-size: 12px;
|
||||
color: var(--el-text-color-placeholder);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pagination-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 16px;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid var(--el-border-color-lighter);
|
||||
}
|
||||
|
||||
.activity-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
padding: 12px 0;
|
||||
border-bottom: 1px solid var(--el-border-color-lighter);
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--el-fill-color-lighter);
|
||||
margin: 0 -24px;
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.activity-icon {
|
||||
flex-shrink: 0;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
|
||||
&.operation {
|
||||
background-color: rgba(79, 132, 255, 0.2);
|
||||
color: #4f84ff;
|
||||
}
|
||||
|
||||
&.access {
|
||||
background-color: rgba(85, 190, 130, 0.2);
|
||||
color: #55be82;
|
||||
}
|
||||
}
|
||||
|
||||
.activity-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
|
||||
.activity-text {
|
||||
font-size: 14px;
|
||||
color: var(--el-text-color-primary);
|
||||
margin-bottom: 4px;
|
||||
|
||||
.activity-module {
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
|
||||
.activity-action {
|
||||
color: var(--el-text-color-regular);
|
||||
}
|
||||
}
|
||||
|
||||
.activity-time {
|
||||
font-size: 12px;
|
||||
color: var(--el-text-color-placeholder);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 响应式
|
||||
@media (max-width: 1200px) {
|
||||
.charts-section,
|
||||
.lists-section {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.welcome-section {
|
||||
padding: 24px 16px;
|
||||
|
||||
.welcome-title {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
padding: 16px;
|
||||
|
||||
.stat-value {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.stats-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.priority-0 {
|
||||
color: #e6a23c;
|
||||
background-color: #fdf6ec;
|
||||
border-color: #f5dab1;
|
||||
}
|
||||
|
||||
.priority-1 {
|
||||
color: #67c23a;
|
||||
background-color: rgb(240, 249, 235);
|
||||
border-color: rgb(225, 243, 216);
|
||||
}
|
||||
|
||||
.priority-2 {
|
||||
color: #f56c6c;
|
||||
background-color: #fef0f0;
|
||||
border-color: #fbc4c4;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user