refactor(frontend): 重构首页仪表盘布局与功能

1. 更新收藏数量上限为12个,替换哔哩哔哩链接为Gitee
2. 调整统计卡片高度与列表项间距样式
3. 重构工作台页面布局,移除冗余统计卡片组件
4. 重构首页仪表盘布局,新增数据统计卡片与图表组件
5. 迁移热销产品表格功能到新用户模块,删除冗余的热销产品列表组件
6. 调整我的收藏列表样式与空状态尺寸
This commit is contained in:
zhangtao
2026-05-21 00:06:06 +08:00
parent b7304155ab
commit 173c2f1b08
9 changed files with 225 additions and 543 deletions
@@ -6,7 +6,7 @@
<p class="text-sm text-g-600">{{ subtitle }}</p>
</div>
<ElScrollbar :style="{ height: maxHeight }">
<div v-for="(item, index) in list" :key="index" class="flex-c py-3">
<div v-for="(item, index) in list" :key="index" class="flex-c py-2">
<div v-if="item.icon" class="flex-cc mr-3 size-10 rounded-lg" :class="item.class">
<FaSvgIcon :icon="item.icon" class="text-xl" />
</div>
@@ -57,7 +57,7 @@ interface Activity {
icon: string;
}
const ITEM_HEIGHT = 66;
const ITEM_HEIGHT = 70;
const DEFAULT_MAX_COUNT = 5;
const props = withDefaults(defineProps<Props>(), {
@@ -1,7 +1,7 @@
<!-- 统计卡片 -->
<template>
<div
class="fa-card h-32 flex-c px-5 transition-transform duration-200 hover:-translate-y-0.5"
class="fa-card h-30 flex-c px-5 transition-transform duration-200 hover:-translate-y-0.5"
:class="boxStyle"
>
<div v-if="icon" class="mr-4 size-11 flex-cc rounded-lg text-xl text-white" :class="iconStyle">
+2 -2
View File
@@ -525,8 +525,8 @@ export async function fetchAllPages<T>(options: FetchAllPagesOptions<T>): Promis
import { ElMessage } from "element-plus";
/** 收藏数量上限(工作台「我的收藏」为 3× 最多 5 排,共 15 个) */
export const QUICK_LINK_MAX = 15;
/** 收藏数量上限(工作台「我的收藏」为 2× 最多 6 排,共 12 个) */
export const QUICK_LINK_MAX = 12;
/**
* 快速链接数据类型
+120 -56
View File
@@ -5,20 +5,86 @@
<ElCol :xs="24" class="mb-5">
<Banner />
</ElCol>
<ElCol :xs="24" :sm="12" :md="12" class="mb-5">
<CardList />
<ElCol :xs="24" :md="18">
<ElRow :gutter="20">
<ElCol :xs="24" :sm="8" :md="24" class="mb-5">
<CardList />
</ElCol>
<ElCol :xs="24" :sm="8" :md="8" class="mb-5">
<FaStatsCard
:icon="'ri:money-cny-box-line'"
:iconStyle="'bg-theme'"
:boxStyle="'bg-theme/10!'"
:title="'总收入'"
:description="'月收入超过¥350,000+'"
:count="35000"
:textColor="'var(--theme-color)'"
:decimals="0"
:showArrow="false"
separator=","
customIconStyle="'text-theme! text-3xl!''"
/>
</ElCol>
<ElCol :xs="24" :sm="12" :md="8" class="mb-5">
<FaProgressCard :percentage="65" :title="'任务进度'" :color="'var(--theme-color)'" />
</ElCol>
<ElCol :xs="24" :sm="12" :md="8" class="mb-5">
<FaProgressCard
:percentage="80"
:title="'任务进度'"
:color="'var(--theme-color)'"
:icon="'ri:twitch-line'"
:iconStyle="'bg-theme/12 text-theme'"
/>
</ElCol>
<ElCol :xs="24" :sm="8" :md="8" class="mb-5">
<FaBarChartCard
:isMiniChart="true"
:value="15480"
label="浏览量"
date="过去14天"
:percentage="-4.15"
:height="9.5"
barWidth="45%"
:chartData="[120, 100, 150, 140, 90, 120, 130]"
/>
</ElCol>
<ElCol :xs="24" :sm="8" :md="8" class="mb-5">
<FaLineChartCard
:isMiniChart="true"
:value="2545"
label="粉丝数"
date="过去30天"
:percentage="1.2"
:height="9.5"
:showAreaColor="true"
:chartData="[150, 180, 160, 200, 180, 220, 240]"
/>
</ElCol>
<ElCol :xs="24" :sm="8" :md="8" class="mb-5">
<FaDonutChartCard
:value="36358"
title="粉丝量"
:percentage="18"
percentageLabel="较去年"
:data="[50, 40]"
:height="9.5"
currentValue="2022"
previousValue="2021"
:radius="['50%', '70%']"
/>
</ElCol>
</ElRow>
</ElCol>
<ElCol :xs="24" :sm="12" :md="12" class="mb-5">
<ElCard shadow="hover" class="flex flex-col h-full">
<ElCol :xs="24" :md="6">
<ElCard shadow="hover" class="flex flex-col h-108">
<template #header>
<div class="workplace-bookmarks-card__header">
<div>
<span class="workplace-panel-title workplace-bookmarks-card__title-line">
<ElIcon class="workplace-bookmarks-card__star" :size="18"><Star /></ElIcon>
我的收藏
<p class="workplace-section-sub workplace-section-sub--inline">
最多 {{ QUICK_LINK_MAX }} · 标签栏星标添加 · 仅本机
</p>
<ElTag
v-if="quickLinks.length > 0"
type="info"
@@ -50,50 +116,46 @@
:key="item.id || `${item.href}-${index}`"
:xs="24"
:sm="12"
:md="6"
:lg="6"
:xl="6"
class="mb-1"
:md="12"
class="mb-2.5"
>
<ElTooltip placement="top" :show-after="400" :content="item.title">
<div
class="workplace-quick-row workplace-quick-row--chip"
role="button"
tabindex="0"
@click="handleQuickLinkClick(item)"
@keydown.enter.prevent="handleQuickLinkClick(item)"
@keydown.space.prevent="handleQuickLinkClick(item)"
>
<span
class="workplace-quick-row__accent"
:style="{ backgroundColor: getQuickLinkColor(getQuickLinkStableIndex(item)) }"
/>
<div
class="workplace-quick-row workplace-quick-row--compact workplace-quick-row--chip"
role="button"
tabindex="0"
@click="handleQuickLinkClick(item)"
@keydown.enter.prevent="handleQuickLinkClick(item)"
@keydown.space.prevent="handleQuickLinkClick(item)"
class="workplace-quick-row__icon"
:style="{ color: getQuickLinkColor(getQuickLinkStableIndex(item)) }"
>
<span
class="workplace-quick-row__accent"
:style="{ backgroundColor: getQuickLinkColor(getQuickLinkStableIndex(item)) }"
/>
<div
class="workplace-quick-row__icon"
:style="{ color: getQuickLinkColor(getQuickLinkStableIndex(item)) }"
>
<FaMenuRouteIcon :icon="item.icon || 'menu'" />
</div>
<div class="workplace-quick-row__text">
<span class="workplace-quick-row__title">{{ item.title }}</span>
</div>
<div class="workplace-quick-row__actions">
<button
type="button"
class="workplace-quick-row__remove"
:disabled="!item.id && !item.href"
:title="item.id || item.href ? '移除收藏' : '无法移除(缺少路径)'"
:aria-label="`移除收藏 ${item.title}`"
@click.stop="handleDeleteLink(item)"
>
<ElIcon><Close /></ElIcon>
</button>
</div>
<FaMenuRouteIcon :icon="item.icon || 'menu'" />
</div>
</ElTooltip>
<div class="workplace-quick-row__text">
<span class="workplace-quick-row__title">{{ item.title }}</span>
</div>
<div class="workplace-quick-row__actions">
<button
type="button"
class="workplace-quick-row__remove"
:disabled="!item.id && !item.href"
:title="item.id || item.href ? '移除收藏' : '无法移除(缺少路径)'"
:aria-label="`移除收藏 ${item.title}`"
@click.stop="handleDeleteLink(item)"
>
<ElIcon><Close /></ElIcon>
</button>
</div>
</div>
</ElCol>
</ElRow>
<ElEmpty v-else :image-size="100">
<ElEmpty v-else :image-size="80">
<template #description>
<p class="workplace-quick-empty__title">暂无收藏</p>
<p class="workplace-quick-empty__hint">
@@ -127,9 +189,6 @@
<NewUser />
</ElCol>
<ElCol :xs="24" :sm="12" :md="6" class="mb-5">
<HotProductsList />
</ElCol>
<ElCol :xs="24" :sm="12" :md="6" class="mb-5">
<TodoList />
</ElCol>
@@ -176,7 +235,7 @@
@cancel="handleBannerDemoCancel"
/>
</ElCol>
<ElCol :xs="24" :sm="12" :md="12" class="mb-5">
<ElCol :xs="24" :sm="12" :md="18" class="mb-5">
<AboutProject />
</ElCol>
</ElRow>
@@ -198,7 +257,11 @@ import FaCardBanner from "@/components/banners/fa-card-banner/index.vue";
import FaImageCard from "@/components/cards/fa-image-card/index.vue";
import FaDataListCard from "@/components/cards/fa-data-list-card/index.vue";
import FaTimelineListCard from "@/components/cards/fa-timeline-list-card/index.vue";
import HotProductsList from "./modules/hot-products-list.vue";
import FaStatsCard from "@/components/cards/fa-stats-card/index.vue";
import FaLineChartCard from "@/components/cards/fa-line-chart-card/index.vue";
import FaBarChartCard from "@/components/cards/fa-bar-chart-card/index.vue";
import FaDonutChartCard from "@/components/cards/fa-donut-chart-card/index.vue";
import FaProgressCard from "@/components/cards/fa-progress-card/index.vue";
import Banner from "./modules/banner.vue";
import NewUser from "./modules/new-user.vue";
import TodoList from "./modules/todo-list.vue";
@@ -315,6 +378,13 @@ const dataList = [
class: "bg-success/12 text-success",
icon: "ri:message-3-line",
},
{
title: "筛选任务团队",
status: "进行中",
time: "20分钟",
class: "bg-error/12 text-error",
icon: "ri:account-circle-line",
},
];
const timelineData = [
{
@@ -520,12 +590,6 @@ onUnmounted(() => {
cursor: help;
}
.workplace-quick-row--compact {
gap: 12px;
min-height: 24px;
padding: 0 6px;
}
.workplace-quick-row {
position: relative;
display: flex;
@@ -31,7 +31,7 @@ const linkList = [
{ label: "项目官网", url: WEB_LINKS.DOCS },
{ label: "文档", url: WEB_LINKS.INTRODUCE },
{ label: "Github", url: WEB_LINKS.GITHUB_HOME },
{ label: "哔哩哔哩", url: WEB_LINKS.BILIBILI },
{ label: "Gitee", url: WEB_LINKS.GITEE },
];
/**
@@ -1,5 +1,5 @@
<template>
<ElRow :gutter="16" class="flex card-row">
<ElRow :gutter="16">
<ElCol v-for="(item, index) in dataList" :key="index" :sm="12" :md="8" :lg="8">
<div class="fa-card relative flex flex-col justify-center h-30 px-5">
<!-- 顶部标题行 -->
@@ -144,30 +144,12 @@ const dataList = ref<CardDataItem[]>([
icon: "ri:eye-line",
iconBg: "bg-primary/10",
iconColor: "text-primary",
num: 0,
num: 9999,
rich: true,
animatedCount: 0,
totalLabel: "总浏览量",
totalValue: 0,
},
{
des: "总访问次数",
icon: "ri:pie-chart-line",
num: 9120,
change: "+20%",
},
{
des: "点击量",
icon: "ri:fire-line",
num: 9520,
change: "-12%",
},
{
des: "新用户",
icon: "ri:progress-2-line",
num: 156,
change: "+30%",
},
]);
onMounted(() => {
@@ -1,200 +0,0 @@
<template>
<div class="fa-card p-5 h-[28.2rem] overflow-hidden">
<div class="fa-card-header">
<div class="title">
<h4>热销产品</h4>
<p>本月销售情况</p>
</div>
</div>
<ElScrollbar :style="{ height: '21.55rem' }" class="w-full">
<FaTable
:data="tableData"
:style="'margin-top: 0 !important'"
:border="false"
:stripe="false"
:header-cell-style="{ background: 'transparent' }"
>
<template #default>
<ElTableColumn type="index" label="序号" width="60" />
<ElTableColumn label="产品" prop="product" width="220px">
<template #default="scope">
<div class="flex-c">
<img
class="size-12.5 object-cover rounded-md"
:src="scope.row.image"
loading="eager"
/>
<div class="flex flex-col ml-3">
<div class="font-medium">{{ scope.row.name }}</div>
<div class="text-xs text-slate-500">{{ scope.row.category }}</div>
</div>
</div>
</template>
</ElTableColumn>
<ElTableColumn label="价格" prop="price">
<template #default="scope">
<span class="font-semibold">¥{{ scope.row.price.toLocaleString() }}</span>
</template>
</ElTableColumn>
<ElTableColumn label="库存" prop="stock">
<template #default="scope">
<div
class="inline-block px-2 py-1 text-xs font-medium rounded"
:class="getStockClass(scope.row.stock)"
>
{{ getStockStatus(scope.row.stock) }}
</div>
</template>
</ElTableColumn>
<ElTableColumn label="销量" prop="sales" />
<ElTableColumn label="销售趋势" width="240">
<template #default="scope">
<ElProgress :percentage="scope.row.pro" :color="scope.row.color" :stroke-width="4" />
</template>
</ElTableColumn>
</template>
</FaTable>
</ElScrollbar>
</div>
</template>
<script setup lang="ts">
import product1 from "@imgs/3d/icon1.webp";
import product2 from "@imgs/3d/icon2.webp";
import product3 from "@imgs/3d/icon3.webp";
import product4 from "@imgs/3d/icon4.webp";
import product5 from "@imgs/3d/icon5.webp";
import product6 from "@imgs/3d/icon6.webp";
interface ProductItem {
name: string;
category: string;
price: number;
stock: number;
sales: number;
percentage: number;
pro: number;
color: string;
image: string;
}
const ANIMATION_DELAY = 100;
const STOCK_THRESHOLD = {
LOW: 20,
MEDIUM: 50,
} as const;
/**
* 热销产品表格数据
* 包含产品信息、库存、销量和销售趋势
*/
const tableData = reactive<ProductItem[]>([
{
name: "智能手表 Pro",
category: "电子设备",
price: 1299,
stock: 156,
sales: 423,
percentage: 75,
pro: 0,
color: "var(--fa-primary)",
image: product1,
},
{
name: "无线蓝牙耳机",
category: "音频设备",
price: 499,
stock: 89,
sales: 652,
percentage: 85,
pro: 0,
color: "var(--fa-success)",
image: product2,
},
{
name: "机械键盘",
category: "电脑配件",
price: 399,
stock: 12,
sales: 238,
percentage: 45,
pro: 0,
color: "var(--fa-warning)",
image: product3,
},
{
name: "超薄笔记本电脑",
category: "电子设备",
price: 5999,
stock: 0,
sales: 126,
percentage: 30,
pro: 0,
color: "var(--fa-error)",
image: product4,
},
{
name: "智能音箱",
category: "智能家居",
price: 799,
stock: 45,
sales: 321,
percentage: 60,
pro: 0,
color: "var(--fa-info)",
image: product5,
},
{
name: "游戏手柄",
category: "游戏配件",
price: 299,
stock: 78,
sales: 489,
percentage: 70,
pro: 0,
color: "var(--fa-secondary)",
image: product6,
},
]);
/**
* 根据库存数量获取状态文本
* @param stock 库存数量
* @returns 库存状态文本
*/
const getStockStatus = (stock: number): string => {
if (stock === 0) return "缺货";
if (stock < STOCK_THRESHOLD.LOW) return "低库存";
if (stock < STOCK_THRESHOLD.MEDIUM) return "适中";
return "充足";
};
/**
* 根据库存数量获取状态样式类名
* @param stock 库存数量
* @returns CSS 类名
*/
const getStockClass = (stock: number): string => {
if (stock === 0) return "text-danger bg-danger/12";
if (stock < STOCK_THRESHOLD.LOW) return "text-warning bg-warning/12";
if (stock < STOCK_THRESHOLD.MEDIUM) return "text-info bg-info/12";
return "text-success bg-success/12";
};
/**
* 添加进度条动画效果
* 延迟后将进度值从 0 更新到目标百分比,触发动画
*/
const addAnimation = (): void => {
setTimeout(() => {
tableData.forEach((item) => {
item.pro = item.percentage;
});
}, ANIMATION_DELAY);
};
onMounted(() => {
addAnimation();
});
</script>
@@ -1,5 +1,5 @@
<template>
<div class="fa-card p-5 overflow-hidden flex flex-col h-full">
<div class="fa-card flex flex-col p-5 h-[34.2rem] overflow-hidden">
<div class="fa-card-header">
<div class="title">
<h4>新用户</h4>
@@ -24,15 +24,23 @@
>
<template #default>
<ElTableColumn type="index" label="序号" width="60" />
<ElTableColumn label="头像" prop="avatar" width="150px">
<ElTableColumn label="头像" prop="avatar" width="130px">
<template #default="scope">
<div class="flex items-center">
<img class="size-9 rounded-lg" :src="scope.row.avatar" alt="avatar" loading="eager" />
<span class="ml-2">{{ scope.row.username }}</span>
<div class="flex flex-col ml-3">
<div class="font-medium">{{ scope.row.username }}</div>
<div class="text-xs text-slate-500">{{ scope.row.province }}</div>
</div>
</div>
</template>
</ElTableColumn>
<ElTableColumn label="地区" prop="province" />
<ElTableColumn label="价格" prop="price">
<template #default="scope">
<span class="font-semibold">¥{{ scope.row.price.toLocaleString() }}</span>
</template>
</ElTableColumn>
<ElTableColumn label="性别" prop="avatar">
<template #default="scope">
<div class="flex items-center">
@@ -40,6 +48,17 @@
</div>
</template>
</ElTableColumn>
<ElTableColumn label="库存" prop="stock" width="100px">
<template #default="scope">
<div
class="inline-block px-2 py-1 text-xs font-medium rounded"
:class="getStockClass(scope.row.stock)"
>
{{ getStockStatus(scope.row.stock) }}
</div>
</template>
</ElTableColumn>
<ElTableColumn label="销量" prop="sales" />
<ElTableColumn label="进度" width="240">
<template #default="scope">
<ElProgress
@@ -67,6 +86,9 @@ interface UserTableItem {
username: string;
province: string;
sex: 0 | 1;
price: number;
stock: number;
sales: number;
age: number;
percentage: number;
pro: number;
@@ -87,6 +109,9 @@ const tableData = reactive<UserTableItem[]>([
username: "中小鱼",
province: "北京",
sex: 0,
price: 1299,
stock: 89,
sales: 652,
age: 22,
percentage: 60,
pro: 0,
@@ -97,6 +122,9 @@ const tableData = reactive<UserTableItem[]>([
username: "何小荷",
province: "深圳",
sex: 1,
price: 299,
stock: 12,
sales: 238,
age: 21,
percentage: 20,
pro: 0,
@@ -107,6 +135,9 @@ const tableData = reactive<UserTableItem[]>([
username: "誶誶淰",
province: "上海",
sex: 1,
price: 99,
stock: 0,
sales: 126,
age: 23,
percentage: 60,
pro: 0,
@@ -117,6 +148,9 @@ const tableData = reactive<UserTableItem[]>([
username: "发呆草",
province: "长沙",
sex: 0,
price: 399,
stock: 45,
sales: 321,
age: 28,
percentage: 50,
pro: 0,
@@ -127,6 +161,9 @@ const tableData = reactive<UserTableItem[]>([
username: "甜筒",
province: "浙江",
sex: 1,
price: 1599,
stock: 78,
sales: 489,
age: 26,
percentage: 70,
pro: 0,
@@ -137,6 +174,35 @@ const tableData = reactive<UserTableItem[]>([
username: "冷月呆呆",
province: "湖北",
sex: 1,
price: 1059,
stock: 0,
sales: 0,
age: 25,
percentage: 90,
pro: 0,
color: "var(--fa-success)",
avatar: avatar6,
},
{
username: "冷呆呆",
province: "湖北",
sex: 1,
price: 1059,
stock: 0,
sales: 0,
age: 25,
percentage: 90,
pro: 0,
color: "var(--fa-success)",
avatar: avatar6,
},
{
username: "冷月呆呆",
province: "湖北",
sex: 1,
price: 1059,
stock: 0,
sales: 0,
age: 25,
percentage: 90,
pro: 0,
@@ -145,6 +211,33 @@ const tableData = reactive<UserTableItem[]>([
},
]);
const STOCK_THRESHOLD = {
LOW: 20,
MEDIUM: 50,
} as const;
/**
* 根据库存数量获取状态文本
*/
const getStockStatus = (stock: number): string => {
if (stock === 0) return "缺货";
if (stock < STOCK_THRESHOLD.LOW) return "低库存";
if (stock < STOCK_THRESHOLD.MEDIUM) return "适中";
return "充足";
};
/**
* 根据库存数量获取状态样式类名
* @param stock 库存数量
* @returns CSS 类名
*/
const getStockClass = (stock: number): string => {
if (stock === 0) return "text-danger bg-danger/12";
if (stock < STOCK_THRESHOLD.LOW) return "text-warning bg-warning/12";
if (stock < STOCK_THRESHOLD.MEDIUM) return "text-info bg-info/12";
return "text-success bg-success/12";
};
/**
* 添加进度条动画效果
* 延迟后将进度值从 0 更新到目标百分比,触发动画
@@ -26,173 +26,6 @@
<ElRow :gutter="24">
<ElCol :sm="24" :md="12" :lg="12" class="mb-5"><ActiveUser /></ElCol>
<ElCol :sm="24" :md="12" :lg="12" class="mb-5"><SalesOverview /></ElCol>
<ElCol
v-for="card in statsCards"
:key="`t-${card.id}`"
:xs="24"
:sm="12"
:md="6"
class="mb-5"
>
<FaStatsCard
:icon="card.icon"
:iconStyle="card.iconStyle"
:title="card.title"
:description="card.description"
:showArrow="card.showArrow"
/>
</ElCol>
<ElCol
v-for="card in statsCards"
:key="`n-${card.id}`"
:xs="24"
:sm="12"
:md="6"
class="mb-5"
>
<FaStatsCard
:icon="card.icon"
:iconStyle="card.iconStyle"
:title="card.title"
:description="card.description"
:count="card.count"
:decimals="0"
:showArrow="card.showArrow"
separator=","
/>
</ElCol>
<ElCol
v-for="card in statsCards"
:key="`c-${card.id}`"
:xs="24"
:sm="12"
:md="6"
class="mb-5"
>
<FaStatsCard
:icon="card.icon"
:iconStyle="card.customIconStyle"
:boxStyle="card.boxStyle"
:title="card.title"
:description="card.description"
:textColor="card.textColor"
:showArrow="card.showArrow"
/>
</ElCol>
<ElCol
v-for="card in progressCards"
:key="`p-${card.id}`"
:xs="24"
:sm="12"
:md="6"
class="mb-5"
>
<FaProgressCard :percentage="card.percentage" :title="card.title" :color="card.color" />
</ElCol>
<ElCol
v-for="card in progressCards"
:key="`pi-${card.id}`"
:xs="24"
:sm="12"
:md="6"
class="mb-5"
>
<FaProgressCard
:percentage="card.percentage"
:title="card.title"
:color="card.color"
:icon="card.icon"
:iconStyle="card.iconStyle"
/>
</ElCol>
<ElCol :xs="24" :sm="12" :md="6" class="mb-5">
<FaLineChartCard
:isMiniChart="true"
:value="2545"
label="新用户"
date="过去7天"
:percentage="1.2"
:height="9.5"
:chartData="[120, 132, 101, 134, 90, 230, 210]"
/>
</ElCol>
<ElCol :xs="24" :sm="12" :md="6" class="mb-5">
<FaBarChartCard
:isMiniChart="true"
:value="15480"
label="浏览量"
date="过去14天"
:percentage="-4.15"
:height="9.5"
barWidth="45%"
:chartData="[120, 100, 150, 140, 90, 120, 130]"
/>
</ElCol>
<ElCol :xs="24" :sm="12" :md="6" class="mb-5">
<FaLineChartCard
:isMiniChart="true"
:value="2545"
label="粉丝数"
date="过去30天"
:percentage="1.2"
:height="9.5"
:showAreaColor="true"
:chartData="[150, 180, 160, 200, 180, 220, 240]"
/>
</ElCol>
<ElCol :xs="24" :sm="12" :md="6" class="mb-5">
<FaDonutChartCard
:value="36358"
title="粉丝量"
:percentage="18"
percentageLabel="较去年"
:data="[50, 40]"
:height="9.5"
currentValue="2022"
previousValue="2021"
:radius="['50%', '70%']"
/>
</ElCol>
<ElCol :xs="24" :sm="12" :md="6" class="mb-5">
<FaLineChartCard
:value="2545"
label="新用户"
:percentage="1.2"
:height="11"
:chartData="[120, 132, 101, 134, 90, 230, 210]"
/>
</ElCol>
<ElCol :xs="24" :sm="12" :md="6" class="mb-5">
<FaBarChartCard
:value="15480"
label="浏览量"
:percentage="-4.15"
:height="11"
:chartData="[120, 100, 150, 140, 90, 120, 130, 110]"
/>
</ElCol>
<ElCol :xs="24" :sm="12" :md="6" class="mb-5">
<FaLineChartCard
:value="2545"
label="粉丝数"
:percentage="1.2"
:height="11"
:showAreaColor="true"
:chartData="[150, 180, 160, 200, 180, 220, 240]"
/>
</ElCol>
<ElCol :xs="24" :sm="12" :md="6" class="mb-5">
<FaDonutChartCard
:value="36358"
title="粉丝量"
:percentage="-18"
percentageLabel="较2021年"
:data="[70, 30]"
:height="11"
currentValue="12月"
previousValue="11月"
/>
</ElCol>
</ElRow>
</div>
</div>
@@ -210,98 +43,8 @@ import AnnualSales from "./modules/annual-sales.vue";
import ProductSales from "./modules/product-sales.vue";
import SalesGrowth from "./modules/sales-growth.vue";
import CartConversionRate from "./modules/cart-conversion-rate.vue";
import FaLineChartCard from "@/components/cards/fa-line-chart-card/index.vue";
import FaStatsCard from "@/components/cards/fa-stats-card/index.vue";
import FaProgressCard from "@/components/cards/fa-progress-card/index.vue";
import FaBarChartCard from "@/components/cards/fa-bar-chart-card/index.vue";
import FaDonutChartCard from "@/components/cards/fa-donut-chart-card/index.vue";
defineOptions({ name: "DashboardWorkplace" });
const statsCards = [
{
id: 1,
title: "销售产品",
count: 1235,
description: "鞋子、牛仔裤、派对服装、手表",
icon: "ri:bar-chart-box-line",
boxStyle: "bg-theme/10!",
customIconStyle: "text-theme! text-3xl!",
iconStyle: "bg-info",
textColor: "var(--theme-color)",
showArrow: false,
},
{
id: 2,
title: "活跃用户",
count: 5000,
description: "日活跃用户超过5,000+",
icon: "ri:account-box-2-line",
boxStyle: "bg-warning/10!",
customIconStyle: "text-warning! text-3xl!",
iconStyle: "bg-warning",
textColor: "var(--fa-warning)",
showArrow: false,
},
{
id: 3,
title: "总收入",
count: 35000,
description: "月收入超过¥350,000+",
icon: "ri:money-cny-box-line",
boxStyle: "bg-secondary/10!",
customIconStyle: "text-secondary! text-3xl!",
iconStyle: "bg-secondary",
textColor: "var(--fa-secondary)",
showArrow: false,
},
{
id: 4,
title: "客户评价",
count: 4800,
description: "平均评分4.8/5",
icon: "ri:message-3-line",
boxStyle: "bg-error/10!",
customIconStyle: "text-error! text-3xl!",
iconStyle: "bg-error",
textColor: "var(--fa-error)",
showArrow: false,
},
];
const progressCards = [
{
id: 1,
title: "完成进度",
percentage: 75,
color: "var(--fa-success)",
icon: "ri:arrow-up-circle-line",
iconStyle: "bg-success/12 text-success",
},
{
id: 2,
title: "项目进度",
percentage: 65,
color: "var(--theme-color)",
icon: "ri:twitch-line",
iconStyle: "bg-theme/12 text-theme",
},
{
id: 3,
title: "学习进度",
percentage: 45,
color: "var(--fa-error)",
icon: "ri:game-line",
iconStyle: "bg-error/12! text-error",
},
{
id: 4,
title: "任务进度",
percentage: 90,
color: "var(--fa-secondary)",
icon: "ri:flag-2-line",
iconStyle: "bg-secondary/12 text-secondary",
},
];
</script>
<style scoped>