Commit 2404ddaf by wusiyi

feat: 概览页更新

parent fc2f3c04
......@@ -16,6 +16,7 @@ declare module 'vue' {
ElCarousel: typeof import('element-plus/es')['ElCarousel']
ElCarouselItem: typeof import('element-plus/es')['ElCarouselItem']
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
ElCheckboxButton: typeof import('element-plus/es')['ElCheckboxButton']
ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
ElCol: typeof import('element-plus/es')['ElCol']
ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
......@@ -54,7 +55,6 @@ declare module 'vue' {
ElTag: typeof import('element-plus/es')['ElTag']
ElTimeline: typeof import('element-plus/es')['ElTimeline']
ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
ElTimePicker: typeof import('element-plus/es')['ElTimePicker']
ElTooltip: typeof import('element-plus/es')['ElTooltip']
ElTree: typeof import('element-plus/es')['ElTree']
ElUpload: typeof import('element-plus/es')['ElUpload']
......
......@@ -14,6 +14,7 @@
"axios": "^1.6.7",
"bignumber.js": "^9.3.0",
"dayjs": "^1.11.13",
"echarts": "^6.0.0",
"element-plus": "^2.6.0",
"lodash-es": "^4.17.21",
"luxon": "^3.7.1",
......@@ -3635,6 +3636,16 @@
"node": ">= 0.4"
}
},
"node_modules/echarts": {
"version": "6.0.0",
"resolved": "https://registry.npmmirror.com/echarts/-/echarts-6.0.0.tgz",
"integrity": "sha512-Tte/grDQRiETQP4xz3iZWSvoHrkCQtwqd6hs+mifXcjrCuo2iKWbajFObuLJVBlDIJlOzgQPd1hsaKt/3+OMkQ==",
"license": "Apache-2.0",
"dependencies": {
"tslib": "2.3.0",
"zrender": "6.0.0"
}
},
"node_modules/electron-to-chromium": {
"version": "1.5.157",
"resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.157.tgz",
......@@ -6009,6 +6020,12 @@
"typescript": ">=4.2.0"
}
},
"node_modules/tslib": {
"version": "2.3.0",
"resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
"license": "0BSD"
},
"node_modules/type": {
"version": "2.7.3",
"resolved": "https://registry.npmmirror.com/type/-/type-2.7.3.tgz",
......@@ -6848,6 +6865,15 @@
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/zrender": {
"version": "6.0.0",
"resolved": "https://registry.npmmirror.com/zrender/-/zrender-6.0.0.tgz",
"integrity": "sha512-41dFXEEXuJpNecuUQq6JlbybmnHaqqpGlbH1yxnA5V9MMP4SbohSVZsJIwz+zdjQXSSlR1Vc34EgH1zxyTDvhg==",
"license": "BSD-3-Clause",
"dependencies": {
"tslib": "2.3.0"
}
}
}
}
......@@ -16,6 +16,7 @@
"axios": "^1.6.7",
"bignumber.js": "^9.3.0",
"dayjs": "^1.11.13",
"echarts": "^6.0.0",
"element-plus": "^2.6.0",
"lodash-es": "^4.17.21",
"luxon": "^3.7.1",
......
import axios from './axios'
import { BaseRespData } from '@/types/api'
import { statisticData } from '@/types/api/statistic'
export function getStatisticData() {
return axios.get<never, BaseRespData<statisticData>>('factory/overview/statistic')
}
\ No newline at end of file
export interface statisticData {
todayNewOrderNum: number,
todayNewProductNum: number,
todayConfirmOrderNum: number,
todayConfirmProductNum: number,
notShipmentOrderNum: number,
overTimeNotShipmentOrderNum: number,
yesterdayShipmentOrderNum: number,
beforeYesterdayShipmentOrderNum: number,
compareYesterdayShipmentOrderNum: number,
shipmentRateOf24Hour: number,
compareLastDayShipmentRateOf24Hour: number,
shipmentRateOf48Hour: number,
compareLastDayShipmentRateOf48Hour: number,
overTimeShipmentRate: number,
compareLastDayOverTimeShipmentRate: number,
waitCreateLogisticOrderNum: number,
waitArrangeOrderNum: number,
producingOrderNum: number,
waitShipmentNum: number,
blockApplyOrderNum: number,
exceptionOrderNum: number,
outOfStockOrderNum: number,
outOfStock24HourOrderNum: number,
outOfStock48HourOrderNum: number,
outOfStockOver48HourOrderNum: number,
outOfStockSkuNum: number,
outOfStockProductNum: number,
yesterdayOverTimeShipmentOrderNum: number,
}
\ No newline at end of file
<template>
<div class="card h-100 dashboard">
<div
v-if="userInfo"
class="factory-info flex h-100 flex-center"
>
<span class="title">{{ userInfo.factory.title }}</span>
<span>欢迎您!</span>
<div class="dashboard-wrapper">
<div class="dashboard-title">核心数据看板</div>
<div class="card-container">
<div class="card-item">
<div class="card-item-header">
<div class="card-title">今日新单(件/单)</div>
<el-tooltip
class="item"
effect="light"
content="今日新增订单的订单数量"
placement="bottom"
>
<div class="card-icon"></div>
</el-tooltip>
</div>
<div class="card-item-content-box">
<div class="card-item-content text-blue">
{{
(statisticData?.todayNewProductNum ?? '-') +
'/' +
(statisticData?.todayNewOrderNum ?? '-')
}}
</div>
</div>
</div>
<div class="card-item">
<div class="card-item-header">
<div class="card-title">今日接单(件/单)</div>
<el-tooltip
class="item"
effect="light"
content="今日新增确认生产的订单数量"
placement="bottom"
>
<div class="card-icon"></div>
</el-tooltip>
</div>
<div class="card-item-content-box">
<div class="card-item-content text-blue">
{{
(statisticData?.todayNewProductNum ?? '-') +
'/' +
(statisticData?.todayNewOrderNum ?? '-')
}}
</div>
</div>
</div>
<div class="card-item">
<div class="card-item-header">
<div class="card-title">未发货订单(单)</div>
<el-tooltip
class="item"
effect="light"
content="目前确认生产后还未转为已发货状态的总订单数"
placement="bottom"
>
<div class="card-icon"></div>
</el-tooltip>
</div>
<div class="card-item-content-box">
<div class="card-item-content text-blue">
{{ statisticData?.notShipmentOrderNum ?? '-' }}
</div>
</div>
</div>
<div class="card-item">
<div class="card-item-header">
<div class="card-title">超时未发订单(单)</div>
<el-tooltip
class="item"
effect="light"
content="目前确认生产后超过48H还未转为已发货状态的总订单数"
placement="bottom"
>
<div class="card-icon"></div>
</el-tooltip>
</div>
<div class="card-item-content-box">
<div class="card-item-content text-red">
{{ statisticData?.overTimeNotShipmentOrderNum ?? '-' }}
</div>
</div>
</div>
</div>
<div class="card-container">
<div class="card-item">
<div class="card-item-header">
<div class="card-title">昨日发货数(单)</div>
<el-tooltip
class="item"
effect="light"
content="昨日转为已发货状态的总订单数(昨日北京时间0-24点数据)"
placement="bottom"
>
<div class="card-icon"></div>
</el-tooltip>
</div>
<div class="card-item-content-box">
<div class="card-item-content text-blue">
{{ statisticData?.yesterdayShipmentOrderNum ?? '-' }}
</div>
<div class="card-item-content-text">较前天</div>
<div
v-if="
statisticData &&
statisticData.compareYesterdayShipmentOrderNum >= 0
"
style="display: flex; align-items: flex-end; gap: 5px"
>
<div class="text-red" style="margin-bottom: -2px">
{{ statisticData?.compareYesterdayShipmentOrderNum }}
</div>
<div class="up-icon"></div>
</div>
<div v-else style="display: flex; align-items: flex-end; gap: 5px">
<div class="text-green" style="margin-bottom: -2px">
{{
Math.abs(statisticData?.compareYesterdayShipmentOrderNum || 0)
}}
</div>
<div class="down-icon"></div>
</div>
</div>
</div>
<div class="card-item">
<div class="card-item-header">
<div class="card-title">24h发货率</div>
<el-tooltip
class="item"
effect="light"
content="昨日已发货订单中从接单转为已发货状态在24小时内的比例(昨日北京时间0-24点数据)"
placement="bottom"
>
<div class="card-icon"></div>
</el-tooltip>
</div>
<div class="card-item-content-box">
<div class="card-item-content text-blue">
{{ (statisticData?.shipmentRateOf24Hour ?? '-') + '%' }}
</div>
<div class="card-item-content-text">较前天</div>
<div
v-if="
statisticData &&
statisticData.compareLastDayShipmentRateOf24Hour >= 0
"
style="display: flex; align-items: flex-end; gap: 5px"
>
<div class="text-red" style="margin-bottom: -2px">
{{
(statisticData?.compareLastDayShipmentRateOf24Hour ?? '-') + '%'
}}
</div>
<div class="up-icon"></div>
</div>
<div v-else style="display: flex; align-items: flex-end; gap: 5px">
<div class="text-green" style="margin-bottom: -2px">
{{
Math.abs(
statisticData?.compareLastDayShipmentRateOf24Hour || 0,
) + '%'
}}
</div>
<div class="down-icon"></div>
</div>
</div>
</div>
<div class="card-item">
<div class="card-item-header">
<div class="card-title">48h发货率</div>
<el-tooltip
class="item"
effect="light"
content="昨日已发货订单中从接单转为已发货状态在48小时内的比例(昨日北京时间0-24点数据)"
placement="bottom"
>
<div class="card-icon"></div>
</el-tooltip>
</div>
<div class="card-item-content-box">
<div class="card-item-content text-blue">
{{ (statisticData?.shipmentRateOf48Hour ?? '-') + '%' }}
</div>
<div class="card-item-content-text">较前天</div>
<div
v-if="
statisticData &&
statisticData.compareLastDayShipmentRateOf48Hour >= 0
"
style="display: flex; align-items: flex-end; gap: 5px"
>
<div class="text-red" style="margin-bottom: -2px">
{{
(statisticData?.compareLastDayShipmentRateOf48Hour ?? '-') + '%'
}}
</div>
<div class="up-icon"></div>
</div>
<div v-else style="display: flex; align-items: flex-end; gap: 5px">
<div class="text-green" style="margin-bottom: -2px">
{{
Math.abs(
statisticData?.compareLastDayShipmentRateOf48Hour || 0,
) + '%'
}}
</div>
<div class="down-icon"></div>
</div>
</div>
</div>
<div class="card-item">
<div class="card-item-header">
<div class="card-title">发货超时率</div>
<el-tooltip
class="item"
effect="light"
content="昨日已发货订单中从接单转为已发货状态大于48小时的比例(昨日北京时间0-24点数据)"
placement="bottom"
>
<div class="card-icon"></div>
</el-tooltip>
</div>
<div class="card-item-content-box">
<div class="card-item-content text-red">
{{
(statisticData?.overTimeShipmentRate ?? '-') +
'%(' +
(statisticData?.yesterdayOverTimeShipmentOrderNum ?? '-') +
')'
}}
</div>
<div class="card-item-content-text">较前天</div>
<div
v-if="
statisticData &&
statisticData.compareLastDayOverTimeShipmentRate >= 0
"
style="display: flex; align-items: flex-end; gap: 5px"
>
<div class="text-red" style="margin-bottom: -2px">
{{
(statisticData?.compareLastDayOverTimeShipmentRate ?? '-') + '%'
}}
</div>
<div class="up-icon"></div>
</div>
<div v-else style="display: flex; align-items: flex-end; gap: 5px">
<div class="text-green" style="margin-bottom: -2px">
{{
Math.abs(
statisticData?.compareLastDayOverTimeShipmentRate || 0,
) + '%'
}}
</div>
<div class="down-icon"></div>
</div>
</div>
</div>
</div>
<div class="card-container">
<div class="card-item">
<div class="card-item-header">
<div class="card-title">待创建物流(单)</div>
<el-tooltip
class="item"
effect="light"
content="目前订单中待创建物流的总订单数"
placement="bottom"
>
<div class="card-icon"></div>
</el-tooltip>
</div>
<div class="card-item-content-box">
<div class="card-item-content text-blue">
{{ statisticData?.waitCreateLogisticOrderNum ?? '-' }}
</div>
</div>
</div>
<div class="card-item">
<div class="card-item-header">
<div class="card-title">待排单(单)</div>
<el-tooltip
class="item"
effect="light"
content="目前订单中待排单的总订单数"
placement="bottom"
>
<div class="card-icon"></div>
</el-tooltip>
</div>
<div class="card-item-content-box">
<div class="card-item-content text-blue">
{{ statisticData?.waitArrangeOrderNum ?? '-' }}
</div>
</div>
</div>
<div class="card-item">
<div class="card-item-header">
<div class="card-title">生产中(单)</div>
<el-tooltip
class="item"
effect="light"
content="目前订单中排单完成后到发货前的总订单数"
placement="bottom"
>
<div class="card-icon"></div>
</el-tooltip>
</div>
<div class="card-item-content-box">
<div class="card-item-content text-blue">
{{ statisticData?.producingOrderNum ?? '-' }}
</div>
</div>
</div>
<div class="card-item">
<div class="card-item-header">
<div class="card-title">待发货(单)</div>
<el-tooltip
class="item"
effect="light"
content="目前订单中待发货状态的总订单数"
placement="bottom"
>
<div class="card-icon"></div>
</el-tooltip>
</div>
<div class="card-item-content-box">
<div class="card-item-content text-blue">
{{ statisticData?.waitShipmentNum ?? '-' }}
</div>
</div>
</div>
<div class="card-item">
<div class="card-item-header">
<div class="card-title">拦截申请(单)</div>
<el-tooltip
class="item"
effect="light"
content="目前在生产拦截和发货拦截中的总订单数"
placement="bottom"
>
<div class="card-icon"></div>
</el-tooltip>
</div>
<div class="card-item-content-box">
<div class="card-item-content text-yellow">
{{ statisticData?.blockApplyOrderNum ?? '-' }}
</div>
</div>
</div>
<div class="card-item">
<div class="card-item-header">
<div class="card-title">异常单(单)</div>
<el-tooltip
class="item"
effect="light"
content="所有订单中的异常单总单数"
placement="bottom"
>
<div class="card-icon"></div>
</el-tooltip>
</div>
<div class="card-item-content-box">
<div class="card-item-content text-red">
{{ statisticData?.exceptionOrderNum ?? '-' }}
</div>
</div>
</div>
</div>
<div class="card-container">
<div class="card-item">
<div class="card-item-header">
<div class="card-title">缺货中订单(单)</div>
<el-tooltip
class="item"
effect="light"
content="缺货统计中的商品总订单数"
placement="bottom"
>
<div class="card-icon"></div>
</el-tooltip>
</div>
<div class="card-item-content-box">
<div class="card-item-content text-yellow">
{{ statisticData?.outOfStockOrderNum ?? '-' }}
</div>
</div>
</div>
<div class="card-item">
<div class="card-item-header">
<div class="card-title">缺货&lt;24h单(单)</div>
<el-tooltip
class="item"
effect="light"
content="缺货总订单中的缺货时长在24h内的订单数"
placement="bottom"
>
<div class="card-icon"></div>
</el-tooltip>
</div>
<div class="card-item-content-box">
<div class="card-item-content text-yellow">
{{ statisticData?.outOfStock24HourOrderNum ?? '-' }}
</div>
</div>
</div>
<div class="card-item">
<div class="card-item-header">
<div class="card-title">缺货&lt;48h单(单)</div>
<el-tooltip
class="item"
effect="light"
content="缺货总订单中的缺货时长在48h内的订单数"
placement="bottom"
>
<div class="card-icon"></div>
</el-tooltip>
</div>
<div class="card-item-content-box">
<div class="card-item-content text-yellow">
{{ statisticData?.outOfStock48HourOrderNum ?? '-' }}
</div>
</div>
</div>
<div class="card-item">
<div class="card-item-header">
<div class="card-title">缺货≥48h单(单)</div>
<el-tooltip
class="item"
effect="light"
content="缺货总订单中的缺货时长大于48h内的订单数"
placement="bottom"
>
<div class="card-icon"></div>
</el-tooltip>
</div>
<div class="card-item-content-box">
<div class="card-item-content text-red">
{{ statisticData?.outOfStockOver48HourOrderNum ?? '-' }}
</div>
</div>
</div>
<div class="card-item">
<div class="card-item-header">
<div class="card-title">缺货库存SKU数</div>
<el-tooltip
class="item"
effect="light"
content="缺货的库存SKU的总数目"
placement="bottom"
>
<div class="card-icon"></div>
</el-tooltip>
</div>
<div class="card-item-content-box">
<div class="card-item-content text-red">
{{ statisticData?.outOfStockSkuNum ?? '-' }}
</div>
</div>
</div>
<div class="card-item">
<div class="card-item-header">
<div class="card-title">缺货总件数</div>
<el-tooltip
class="item"
effect="light"
content="缺货的货物总件数"
placement="bottom"
>
<div class="card-icon"></div>
</el-tooltip>
</div>
<div class="card-item-content-box">
<div class="card-item-content text-yellow">
{{ statisticData?.outOfStockProductNum ?? '-' }}
</div>
</div>
</div>
</div>
<div class="chart-wrapper" style="width: 100%">
<el-radio-group v-model="chartTimes1" size="small" class="chart-controls">
<el-radio-button
v-for="time in timeOptions"
:key="time.type"
:value="time.type"
:label="time.name"
>
</el-radio-button>
</el-radio-group>
<div ref="orderChart1" class="chart-container" style="width: 100%" />
</div>
<div class="charts-row">
<div class="chart-wrapper chart-half">
<el-radio-group
v-model="chartTimes2"
size="small"
class="chart-controls"
>
<el-radio-button
v-for="time in timeOptions"
:key="time.type"
:value="time.type"
:label="time.name"
>
</el-radio-button>
</el-radio-group>
<div ref="orderChart2" class="chart-container" style="width: 100%" />
</div>
<div class="chart-wrapper chart-half">
<el-radio-group
v-model="chartTimes3"
size="small"
class="chart-controls"
>
<el-radio-button
v-for="time in timeOptions"
:key="time.type"
:value="time.type"
:label="time.name"
>
</el-radio-button>
</el-radio-group>
<div ref="orderChart3" class="chart-container" style="width: 100%" />
</div>
</div>
</div>
</template>
<script setup lang="ts">
import useUserStore from '@/store/user'
const userInfo = useUserStore().user
import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue'
import * as echarts from 'echarts/core'
import {
TitleComponent,
GridComponent,
LegendComponent,
} from 'echarts/components'
import { LineChart } from 'echarts/charts'
import { UniversalTransition } from 'echarts/features'
import { CanvasRenderer } from 'echarts/renderers'
import { getStatisticData } from '@/api/statistic'
import type { statisticData as StatisticData } from '@/types/api/statistic'
echarts.use([
TitleComponent,
GridComponent,
LegendComponent,
LineChart,
CanvasRenderer,
UniversalTransition,
])
// 获取统计数据
const statisticData = ref<StatisticData | null>(null)
const getStatisticDataApi = async () => {
const res = await getStatisticData()
if (res.code === 200) {
statisticData.value = res.data
}
}
const timeOptions = ref<{ type: string; name: string }[]>([
{ type: 'day', name: '日数据' },
{ type: 'moon', name: '月数据' },
{ type: 'year', name: '年数据' },
])
const chartTimes1 = ref<string>('day')
const chartTimes2 = ref<string>('day')
const chartTimes3 = ref<string>('day')
// 图表容器引用
const orderChart1 = ref<HTMLDivElement | null>(null)
const orderChart2 = ref<HTMLDivElement | null>(null)
const orderChart3 = ref<HTMLDivElement | null>(null)
// 图表实例数组
const chartInstances: (echarts.ECharts | null)[] = [null, null, null]
// 图表配置
const chartConfig1 = {
title: '订单趋势统计(单)',
legend: ['接单数', '生产数', '发货数'],
xAxisData: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
series: [
{
name: '接单数',
data: [220, 182, 191, 234, 290, 330, 310],
color: '#6495ED',
},
{
name: '生产数',
data: [120, 132, 101, 134, 90, 230, 210],
color: '#9370DB',
},
{
name: '发货数',
data: [150, 232, 201, 154, 190, 330, 410],
color: '#48D1CC',
},
],
}
const chartConfig2 = {
title: '订单发货效率',
legend: ['生产数', '发货数'],
xAxisData: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
series: [
{
name: '生产数',
data: [85, 88, 90, 87, 92, 89, 91],
color: '#4ECDC4',
},
{
name: '发货数',
data: [95, 96, 98, 97, 99, 98, 99],
color: '#95E1D3',
},
],
}
const chartConfig3 = {
title: '订单生产效率',
legend: ['发货超时率'],
xAxisData: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
series: [
{
name: '发货超时率',
data: [100, 100, 100, 100, 100, 100, 100],
color: '#AA96DA',
},
],
}
// 创建图表配置的函数
const createChartOption = (config: typeof chartConfig1) => {
return {
title: {
text: config.title,
left: 'left',
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
crossStyle: {
type: 'dashed',
},
label: {
backgroundColor: '#6a7985',
},
},
},
legend: {
data: config.legend,
top: 'top',
left: 'center',
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true,
},
xAxis: {
type: 'category',
boundaryGap: false,
data: config.xAxisData,
},
yAxis: {
type: 'value',
},
series: config.series.map((item) => ({
name: item.name,
type: 'line',
stack: 'Total',
data: item.data,
smooth: true,
lineStyle: {
color: item.color,
width: 3,
},
itemStyle: {
color: item.color,
},
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: item.color,
},
{
offset: 1,
color: item.color + '00', // 添加透明度,00 表示完全透明
},
],
globalCoord: false,
},
},
})),
}
}
onMounted(async () => {
await nextTick()
await getStatisticDataApi()
// 初始化第一个图表:订单趋势统计
if (orderChart1.value) {
chartInstances[0] = echarts.init(orderChart1.value)
chartInstances[0]?.setOption(createChartOption(chartConfig1))
}
// 初始化第二个图表:订单发货效率
if (orderChart2.value) {
chartInstances[1] = echarts.init(orderChart2.value)
chartInstances[1]?.setOption(createChartOption(chartConfig2))
}
// 初始化第三个图表:订单生产效率
if (orderChart3.value) {
chartInstances[2] = echarts.init(orderChart3.value)
chartInstances[2]?.setOption(createChartOption(chartConfig3))
}
// 监听窗口大小变化,自动调整图表大小
window.addEventListener('resize', handleResize)
})
const handleResize = () => {
chartInstances.forEach((instance) => {
instance?.resize()
})
}
onBeforeUnmount(() => {
window.removeEventListener('resize', handleResize)
chartInstances.forEach((instance, index) => {
instance?.dispose()
chartInstances[index] = null
})
})
</script>
<style lang="scss" scoped>
.dashboard-title {
font-size: 18px;
font-weight: 600;
color: #333;
margin-bottom: 10px;
}
.factory-info {
font-size: 24px;
.title {
margin-right: 10px;
......@@ -23,4 +758,142 @@ const userInfo = useUserStore().user
color: green;
}
}
.card-container {
padding: 12px 10px;
width: 100%;
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
margin-bottom: 15px;
row-gap: 15px;
column-gap: 70px;
background-color: #fff;
border-radius: 5px;
box-sizing: border-box;
.card-item {
width: 300px;
height: 90px;
background-color: #f7f7f7;
border-radius: 5px;
padding: 8px 15px;
.card-item-header {
display: flex;
align-items: center;
.card-title {
font-size: 14px;
font-weight: 600;
color: #333;
}
.card-icon {
width: 20px;
height: 20px;
cursor: pointer;
background-size: 100% 100%;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='256' height='256' viewBox='0 0 256 256'%3E%3Cpath fill='%238e8d8d' d='M140 180a12 12 0 1 1-12-12a12 12 0 0 1 12 12M128 72c-22.06 0-40 16.15-40 36v4a8 8 0 0 0 16 0v-4c0-11 10.77-20 24-20s24 9 24 20s-10.77 20-24 20a8 8 0 0 0-8 8v8a8 8 0 0 0 16 0v-.72c18.24-3.35 32-17.9 32-35.28c0-19.85-17.94-36-40-36m104 56A104 104 0 1 1 128 24a104.11 104.11 0 0 1 104 104m-16 0a88 88 0 1 0-88 88a88.1 88.1 0 0 0 88-88'/%3E%3C/svg%3E");
}
}
.card-item-content-box {
display: flex;
align-items: flex-end;
gap: 10px;
.card-item-content {
font-size: 38px;
font-weight: 500;
margin-bottom: -5px;
}
.card-item-content-text {
font-size: 14px;
color: #666;
}
.up-icon {
width: 18px;
height: 18px;
background-size: 100% 100%;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='256' height='256' viewBox='0 0 24 24'%3E%3Cpath fill='%23f56c6c' d='M12.725 2.451a.75.75 0 0 0-1.007-.013L3.504 9.69A.75.75 0 0 0 4 11.003h4.382c.138 1.255.057 2.576-.252 3.969c-.318 1.434-1.722 3.25-4.515 5.438a.75.75 0 0 0 .535 1.337c3.311-.322 6.112-1.537 8.365-3.662c2.08-1.963 3.228-4.334 3.422-7.082H20a.75.75 0 0 0 .511-1.299z'/%3E%3C/svg%3E");
}
.down-icon {
width: 18px;
height: 18px;
background-size: 100% 100%;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='256' height='256' viewBox='0 0 24 24'%3E%3Cpath fill='%2367C23A' d='M4.15 2.253a.75.75 0 0 0-.535 1.337C6.408 5.778 7.812 7.594 8.13 9.028c.309 1.393.39 2.714.252 3.969H4a.75.75 0 0 0-.496 1.312l8.214 7.253a.75.75 0 0 0 1.007-.013l7.786-7.253a.75.75 0 0 0-.511-1.3h-4.063c-.194-2.747-1.342-5.118-3.422-7.08C10.262 3.79 7.46 2.574 4.15 2.252'/%3E%3C/svg%3E");
}
}
}
}
.text-blue {
color: #409eff;
}
.text-green {
color: #67c23a;
}
.text-red {
color: #f56c6c;
}
.text-yellow {
color: #e6a23c;
}
.dashboard-wrapper {
padding: 0 10px;
height: 100%;
width: 85%;
margin: 0 auto;
overflow-x: hidden;
background-color: #fafafa;
padding: 10px 40px;
border-radius: 5px;
}
.chart-wrapper {
position: relative;
margin-top: 20px;
}
.chart-container {
min-height: 500px;
height: 500px;
background-color: #fff;
border-radius: 5px;
padding: 20px;
box-sizing: border-box;
}
.chart-controls {
position: absolute;
top: 30px;
right: 30px;
z-index: 10;
}
.charts-row {
display: flex;
gap: 10px;
}
.chart-half {
width: 50%;
}
@media (max-width: 1000px) {
.charts-row {
flex-direction: column;
}
.chart-half {
width: 100%;
}
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment