✨ feat: 数据分析-基础骨架
This commit is contained in:
parent
68ebd4b72f
commit
8ca95304c1
2
.env
2
.env
|
@ -14,7 +14,7 @@ VITE_APP_URL=http://localhost:8801
|
||||||
VITE_STRICT_PORT=false
|
VITE_STRICT_PORT=false
|
||||||
|
|
||||||
# 是否启用屏幕转vw适配,可以选择 postcss-px-to-viewport-8-plugin || autofit
|
# 是否启用屏幕转vw适配,可以选择 postcss-px-to-viewport-8-plugin || autofit
|
||||||
VITE_POST_CSS_PX_TO_VIEWPORT8_PLUGIN="autofit"
|
; VITE_POST_CSS_PX_TO_VIEWPORT8_PLUGIN="postcss-px-to-viewport-8-plugin"
|
||||||
|
|
||||||
# 是否在打包时使用cdn替换本地库 替换 true 不替换 false
|
# 是否在打包时使用cdn替换本地库 替换 true 不替换 false
|
||||||
VITE_CDN=false
|
VITE_CDN=false
|
||||||
|
|
|
@ -20,8 +20,8 @@ VITE_MOCK_DEV_SERVER=true
|
||||||
VITE_STRICT_PORT=false
|
VITE_STRICT_PORT=false
|
||||||
|
|
||||||
# 是否启用屏幕转vw适配,可以选择 postcss-px-to-viewport-8-plugin || autofit
|
# 是否启用屏幕转vw适配,可以选择 postcss-px-to-viewport-8-plugin || autofit
|
||||||
VITE_POST_CSS_PX_TO_VIEWPORT8_PLUGIN="autofit"
|
# VITE_POST_CSS_PX_TO_VIEWPORT8_PLUGIN="autofit"
|
||||||
#VITE_POST_CSS_PX_TO_VIEWPORT8_PLUGIN="postcss-px-to-viewport-8-plugin"
|
VITE_POST_CSS_PX_TO_VIEWPORT8_PLUGIN="postcss-px-to-viewport-8-plugin"
|
||||||
|
|
||||||
# 是否在打包时使用cdn替换本地库 替换 true 不替换 false
|
# 是否在打包时使用cdn替换本地库 替换 true 不替换 false
|
||||||
VITE_CDN=false
|
VITE_CDN=false
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
/**
|
||||||
|
* 复制到剪切板
|
||||||
|
* @param text 文本内容
|
||||||
|
*/
|
||||||
|
export const copy = (text: string) => {
|
||||||
|
const textarea = document.createElement('textarea');
|
||||||
|
textarea.value = text;
|
||||||
|
textarea.style.position = 'fixed';
|
||||||
|
document.body.appendChild(textarea);
|
||||||
|
textarea.select();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const success = document.execCommand('copy');
|
||||||
|
if (success) {
|
||||||
|
(window as any as any).$message.success('复制成功!');
|
||||||
|
} else {
|
||||||
|
(window as any).$message.success('复制失败!');
|
||||||
|
}
|
||||||
|
} catch (err: any) {
|
||||||
|
(window as any).$message.success('复制失败!请手动复制');
|
||||||
|
} finally {
|
||||||
|
document.body.removeChild(textarea);
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,45 @@
|
||||||
|
export function downloadTextAsFile(text: string, filename: string) {
|
||||||
|
// 直接创建 File 对象(比 Blob 更高级)
|
||||||
|
const file = new File([text], filename, { type: 'text/plain' });
|
||||||
|
|
||||||
|
// 创建下载链接
|
||||||
|
const url = URL.createObjectURL(file);
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
a.download = filename;
|
||||||
|
|
||||||
|
// 触发下载
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
|
||||||
|
// 清理
|
||||||
|
requestIdleCallback(() => {
|
||||||
|
document.body.removeChild(a);
|
||||||
|
URL.revokeObjectURL(a.href);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const downloadBlob = (response: any) => {
|
||||||
|
try {
|
||||||
|
// 从响应头获取文件名
|
||||||
|
const contentDisposition = response.headers['content-disposition'];
|
||||||
|
let fileName = 'download.zip';
|
||||||
|
if (contentDisposition) {
|
||||||
|
const fileNameMatch = contentDisposition.match(/filename="?(.+)"/);
|
||||||
|
if (fileNameMatch && fileNameMatch[1]) {
|
||||||
|
fileName = fileNameMatch[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = window.URL.createObjectURL(new Blob([response.data]));
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = url;
|
||||||
|
link.setAttribute('download', fileName);
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
link.remove();
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,11 +1,12 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, onUnmounted, ref } from 'vue';
|
import { useIntervalFn } from '@vueuse/core';
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
|
||||||
import { renderEcharts, updateChart } from '@/views/big-data/charts/left-bottom';
|
import { renderEcharts, updateChart } from '@/views/big-data/charts/left-bottom';
|
||||||
|
|
||||||
const chart = ref<HTMLDivElement>();
|
const chart = ref<HTMLDivElement>();
|
||||||
const timer = ref(null);
|
|
||||||
|
|
||||||
|
/* 随机数据 */
|
||||||
const randomData = () => {
|
const randomData = () => {
|
||||||
function random() {
|
function random() {
|
||||||
return Array(12)
|
return Array(12)
|
||||||
|
@ -21,18 +22,18 @@ const randomData = () => {
|
||||||
updateChart(data);
|
updateChart(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* 模拟数据 */
|
||||||
|
const mockRandomData = () => {
|
||||||
|
useIntervalFn(() => {
|
||||||
|
randomData();
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
renderEcharts(chart);
|
renderEcharts(chart);
|
||||||
randomData();
|
randomData();
|
||||||
|
|
||||||
timer.value = setInterval(() => {
|
mockRandomData();
|
||||||
randomData();
|
|
||||||
}, 6000);
|
|
||||||
});
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
clearInterval(timer.value);
|
|
||||||
timer.value = null;
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<script lang="tsx" setup>
|
<script lang="tsx" setup>
|
||||||
import { onMounted, onUnmounted, ref } from 'vue';
|
import { useIntervalFn } from '@vueuse/core';
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
|
||||||
import { formatter } from '@/utils/chart';
|
import { formatter } from '@/utils/chart';
|
||||||
import { ChartProgress } from '@/views/big-data/charts/left-middle';
|
import { ChartProgress } from '@/views/big-data/charts/left-middle';
|
||||||
|
|
||||||
const timer = ref(null);
|
|
||||||
const randomNumber = (range: number = 100) => {
|
const randomNumber = (range: number = 100) => {
|
||||||
return parseInt((Math.random() * range).toFixed(0));
|
return parseInt((Math.random() * range).toFixed(0));
|
||||||
};
|
};
|
||||||
|
@ -34,8 +34,8 @@ const renderItem = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
const mockList = () => {
|
||||||
timer.value = setInterval(() => {
|
useIntervalFn(() => {
|
||||||
list.value = [
|
list.value = [
|
||||||
{ title: '经营总收入', amount: randomNumber(9999999), percent: randomNumber() },
|
{ title: '经营总收入', amount: randomNumber(9999999), percent: randomNumber() },
|
||||||
{ title: '经营总收入', amount: randomNumber(9999999), percent: randomNumber() },
|
{ title: '经营总收入', amount: randomNumber(9999999), percent: randomNumber() },
|
||||||
|
@ -43,11 +43,10 @@ onMounted(() => {
|
||||||
{ title: '经营总收入', amount: randomNumber(9999999), percent: randomNumber() },
|
{ title: '经营总收入', amount: randomNumber(9999999), percent: randomNumber() },
|
||||||
];
|
];
|
||||||
}, 1000);
|
}, 1000);
|
||||||
});
|
};
|
||||||
|
|
||||||
onUnmounted(() => {
|
onMounted(() => {
|
||||||
clearInterval(timer.value);
|
mockList();
|
||||||
timer.value = null;
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -11,5 +11,3 @@ import RightTop from '@/views/big-data/components/big-data-right/components/righ
|
||||||
<right-bottom />
|
<right-bottom />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
import 'echarts/lib/component/dataZoom';
|
||||||
|
|
||||||
|
import type { Ref } from 'vue';
|
||||||
|
|
||||||
|
import echarts from '@/plugins/echarts';
|
||||||
|
import { debounceChart } from '@/utils/chart';
|
||||||
|
|
||||||
|
let myChart = null;
|
||||||
|
|
||||||
|
const option = {
|
||||||
|
tooltip: { trigger: 'item' },
|
||||||
|
legend: {
|
||||||
|
top: 'bottom',
|
||||||
|
data: ['品牌A', '品牌B', '品牌C', '品牌D', '品牌E', '品牌F'],
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '品牌占比',
|
||||||
|
type: 'pie',
|
||||||
|
radius: [25, 100],
|
||||||
|
center: ['50%', '45%'],
|
||||||
|
roseType: 'area',
|
||||||
|
emphasis: {
|
||||||
|
itemStyle: {
|
||||||
|
shadowBlur: 10,
|
||||||
|
shadowOffsetX: 0,
|
||||||
|
shadowColor: 'rgba(0, 0, 0, 0.5)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
formatter: '{b}: {c}%',
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{ value: 10.89, name: '品牌A' },
|
||||||
|
{ value: 30.89, name: '品牌B' },
|
||||||
|
{ value: 38.38, name: '品牌C' },
|
||||||
|
{ value: 27.47, name: '品牌D' },
|
||||||
|
{ value: 29.79, name: '品牌E' },
|
||||||
|
{ value: 50, name: '品牌F' },
|
||||||
|
{ value: 50, name: '品牌G' },
|
||||||
|
{ value: 39.72, name: '品牌H' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 渲染图表 */
|
||||||
|
export const renderEcharts = (element: Ref<HTMLDivElement>) => {
|
||||||
|
myChart = echarts.init(element.value, null, {
|
||||||
|
renderer: 'canvas',
|
||||||
|
devicePixelRatio: window.devicePixelRatio,
|
||||||
|
});
|
||||||
|
|
||||||
|
debounceChart(myChart);
|
||||||
|
|
||||||
|
myChart.setOption(option);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 更新图表数据 */
|
||||||
|
export const updateChart = (option: Array<Array<number>>) => {
|
||||||
|
const series = myChart.getOption().series;
|
||||||
|
// series[0].data = option[0];
|
||||||
|
// series[1].data = option[1];
|
||||||
|
myChart.setOption({ series });
|
||||||
|
};
|
|
@ -0,0 +1,97 @@
|
||||||
|
import type { Ref } from 'vue';
|
||||||
|
|
||||||
|
import echarts from '@/plugins/echarts';
|
||||||
|
import { debounceChart } from '@/utils/chart';
|
||||||
|
|
||||||
|
let myChart = null;
|
||||||
|
const myData = [
|
||||||
|
{
|
||||||
|
value: 137,
|
||||||
|
name: '数学',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 103,
|
||||||
|
name: '语文',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 124,
|
||||||
|
name: '英语',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 180,
|
||||||
|
name: '理综',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const option = {
|
||||||
|
color: ['#1aa3ff', '#04f9fa', '#16bd87', '#c961ff', '#7cfc12'],
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
formatter: '{b}:{c} ({d}%)',
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
bottom: '20%',
|
||||||
|
itemWidth: 10,
|
||||||
|
itemHeight: 10,
|
||||||
|
textStyle: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: '14',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
// 内圈
|
||||||
|
{
|
||||||
|
type: 'pie',
|
||||||
|
center: ['50%', '40%'],
|
||||||
|
radius: ['33.5%', '35.5%'],
|
||||||
|
silent: true, //取消高亮
|
||||||
|
label: { show: false, position: 'center' },
|
||||||
|
data: myData,
|
||||||
|
},
|
||||||
|
// 外圈
|
||||||
|
{
|
||||||
|
type: 'pie',
|
||||||
|
center: ['50%', '40%'],
|
||||||
|
radius: ['40%', '50%'],
|
||||||
|
label: { show: false, position: 'center' },
|
||||||
|
emphasis: {
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
fontSize: 33,
|
||||||
|
lineHeight: 45,
|
||||||
|
formatter: (params) => {
|
||||||
|
return '{name|' + params.name + '}\n{value|' + params.value + '}';
|
||||||
|
},
|
||||||
|
rich: {
|
||||||
|
name: {
|
||||||
|
color: '#fff',
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
color: '#04F9FA',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data: myData,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
/** 渲染图表 */
|
||||||
|
export const renderEcharts = (element: Ref<HTMLDivElement>) => {
|
||||||
|
myChart = echarts.init(element.value, null, {
|
||||||
|
renderer: 'canvas',
|
||||||
|
devicePixelRatio: window.devicePixelRatio,
|
||||||
|
});
|
||||||
|
|
||||||
|
debounceChart(myChart);
|
||||||
|
|
||||||
|
myChart.setOption(option);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 更新图表数据 */
|
||||||
|
export const updateChart = (option: Array<Array<number>>) => {
|
||||||
|
const series = myChart.getOption().series;
|
||||||
|
// series[0].data = option[0];
|
||||||
|
// series[1].data = option[1];
|
||||||
|
myChart.setOption({ series });
|
||||||
|
};
|
|
@ -1,7 +1,21 @@
|
||||||
<script lang="ts" setup></script>
|
<script lang="ts" setup>
|
||||||
|
const titleList = [170582, 586220, 168902];
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="data-analyse-content">data-analyse-content</div>
|
<div class="data-analyse-content">
|
||||||
|
<ul class="data-analyse-content__header">
|
||||||
|
<li v-for="(item, index) in titleList" :key="index">
|
||||||
|
<h3>数据展示</h3>
|
||||||
|
<strong>{{ item }}</strong>
|
||||||
|
<span>台</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<main class="data-analyse-content__body">body</main>
|
||||||
|
|
||||||
|
<footer class="data-analyse-content__footer">footer</footer>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -10,6 +24,38 @@
|
||||||
width: 803px;
|
width: 803px;
|
||||||
height: 970px;
|
height: 970px;
|
||||||
|
|
||||||
background: darkgrey;
|
&__header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin: 15px 0 0 0;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
color: #94ddff;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
strong {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
margin: 0 0 0 8px;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__body {
|
||||||
|
margin: 14px 0 0 0;
|
||||||
|
width: 803px;
|
||||||
|
height: 567px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__footer {
|
||||||
|
margin: 6px 0 0 0;
|
||||||
|
width: 860px;
|
||||||
|
height: 284px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
<script lang="ts" setup>
|
|
||||||
import PanelTitle1 from '@/components/PanelItem/PanelTitle/PanelTitle1.vue';
|
|
||||||
import Progress1 from '@/components/PanelItem/Progress/Progress1.vue';
|
|
||||||
|
|
||||||
const list = [
|
|
||||||
{ name: '科技有限公司', amount: 18888, percent: '50' },
|
|
||||||
{ name: '科技有限公司', amount: 18888, percent: '50' },
|
|
||||||
{ name: '科技有限公司', amount: 18888, percent: '50' },
|
|
||||||
{ name: '科技有限公司', amount: 18888, percent: '50' },
|
|
||||||
{ name: '科技有限公司', amount: 18888, percent: '50' },
|
|
||||||
];
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="data-analyse-left__center">
|
|
||||||
<PanelTitle1 title="销售公司销售设备数量占比" />
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li v-for="(item, index) in list" :key="index">
|
|
||||||
<div class="info">
|
|
||||||
<span>{{ item.name }}</span>
|
|
||||||
<div class="info-left">
|
|
||||||
<span class="mr-[14px]">{{ item.amount }}台</span>
|
|
||||||
<span class="mr-[9px] c-primary-secondary">环比 {{ item.percent }} %</span>
|
|
||||||
<i class="i-mdi-trending-up">s</i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<Progress1 :progress="50" />
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.data-analyse-left__center {
|
|
||||||
li {
|
|
||||||
margin: 0 0 27px 0;
|
|
||||||
|
|
||||||
&:nth-child(1) {
|
|
||||||
margin: 35px 0 27px 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.info {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
.info-left {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
i {
|
|
||||||
fonst-size: 15px;
|
|
||||||
color: var(--color-primary-secondary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,37 +0,0 @@
|
||||||
<script lang="ts" setup></script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="data-analyse-left__top">
|
|
||||||
<div>
|
|
||||||
<h1>销售设备总量(台)</h1>
|
|
||||||
<span>
|
|
||||||
环比去年增长 52%
|
|
||||||
<i class="i-mdi-trending-up">s</i>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.data-analyse-left__top {
|
|
||||||
width: 248px;
|
|
||||||
height: 53px;
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
span {
|
|
||||||
font-size: 15px;
|
|
||||||
color: var(--color-primary-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
i {
|
|
||||||
position: absolute;
|
|
||||||
top: 18px;
|
|
||||||
left: 23px;
|
|
||||||
font-size: 24px;
|
|
||||||
color: var(--color-primary-secondary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,12 +1,68 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import LeftCenter from '@/views/data-analyse/components/data-analyse-left/components/left-center.vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import LeftTop from '@/views/data-analyse/components/data-analyse-left/components/left-top.vue';
|
|
||||||
|
import PanelTitle1 from '@/components/PanelItem/PanelTitle/PanelTitle1.vue';
|
||||||
|
import Progress1 from '@/components/PanelItem/Progress/Progress1.vue';
|
||||||
|
import { renderEcharts } from '@/views/data-analyse/charts/left-brand';
|
||||||
|
|
||||||
|
const brandChartRef = ref();
|
||||||
|
const deviceTotal = ref('1010');
|
||||||
|
|
||||||
|
const companyList = [
|
||||||
|
{ name: '科技有限公司', amount: 18888, percent: '40' },
|
||||||
|
{ name: '科技有限公司', amount: 18888, percent: '50' },
|
||||||
|
{ name: '科技有限公司', amount: 18888, percent: '10' },
|
||||||
|
{ name: '科技有限公司', amount: 18888, percent: '80' },
|
||||||
|
{ name: '科技有限公司', amount: 18888, percent: '50' },
|
||||||
|
];
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
renderEcharts(brandChartRef);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<!--顶部-->
|
||||||
<div class="data-analyse-left">
|
<div class="data-analyse-left">
|
||||||
<left-top />
|
<div class="data-analyse-left__top">
|
||||||
<left-center />
|
<div>
|
||||||
|
<h1 class="font-size-[21px]">销售设备总量(台)</h1>
|
||||||
|
<div class="data-analyse-left__top-percent">
|
||||||
|
<span>环比去年增长 52%</span>
|
||||||
|
<i class="i-mdi-trending-up">s</i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ul class="flex">
|
||||||
|
<li v-for="(num, index) in deviceTotal" :key="index">{{ num }}</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--中心区域-->
|
||||||
|
<div class="data-analyse-left__center">
|
||||||
|
<PanelTitle1 title="销售公司销售设备数量占比" />
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li v-for="(item, index) in companyList" :key="index">
|
||||||
|
<div class="data-analyse-left__center-info">
|
||||||
|
<span>{{ item.name }}</span>
|
||||||
|
<div class="info-left">
|
||||||
|
<span class="mr-[14px]">{{ item.amount }}台</span>
|
||||||
|
<span class="mr-[9px] c-primary-secondary">环比 {{ item.percent }} %</span>
|
||||||
|
<i class="i-mdi-trending-up" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Progress1 :progress="parseInt(item.percent)" />
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--底部区域-->
|
||||||
|
<div class="data-analyse-left__bottom">
|
||||||
|
<PanelTitle1 title="品牌占有率" />
|
||||||
|
|
||||||
|
<div ref="brandChartRef" class="data-analyse-left__bottom-chart" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -15,5 +71,82 @@ import LeftTop from '@/views/data-analyse/components/data-analyse-left/component
|
||||||
width: 496px;
|
width: 496px;
|
||||||
height: 970px;
|
height: 970px;
|
||||||
color: white;
|
color: white;
|
||||||
|
|
||||||
|
/* 顶部 */
|
||||||
|
&__top {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 496px;
|
||||||
|
height: 100px;
|
||||||
|
|
||||||
|
&-percent {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
color: var(--color-primary-secondary);
|
||||||
|
font-size: 16px;
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 21px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin: 0 4px;
|
||||||
|
width: 56px;
|
||||||
|
height: 53px;
|
||||||
|
line-height: 53px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 47px;
|
||||||
|
border: 1px solid var(--color-primary-secondary);
|
||||||
|
background-color: rgba(39, 63, 86, 0.34);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 中心区域 */
|
||||||
|
&__center {
|
||||||
|
margin: 47px 0 0 0;
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin: 0 0 27px 0;
|
||||||
|
|
||||||
|
&:nth-child(1) {
|
||||||
|
margin: 35px 0 27px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-info {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.info-left {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: var(--color-primary-secondary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 底部区域 */
|
||||||
|
&__bottom {
|
||||||
|
margin: 25px 0 0 0;
|
||||||
|
width: 468px;
|
||||||
|
height: 387px;
|
||||||
|
|
||||||
|
&-chart {
|
||||||
|
margin: 0 0 25px 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,13 +1,67 @@
|
||||||
<script lang="ts" setup></script>
|
<script lang="ts" setup>
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
|
||||||
|
import PanelTitle1 from '@/components/PanelItem/PanelTitle/PanelTitle1.vue';
|
||||||
|
import { renderEcharts } from '@/views/data-analyse/charts/right-header';
|
||||||
|
|
||||||
|
const footerChartRef = ref();
|
||||||
|
const renderFooterChart = () => {
|
||||||
|
renderEcharts(footerChartRef);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
renderFooterChart();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="data-analyse-right">data-analyse-right</div>
|
<div class="data-analyse-right">
|
||||||
|
<header class="data-analyse-right__header">
|
||||||
|
<PanelTitle1 title="数据占有率" />
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main class="data-analyse-right__body">
|
||||||
|
<PanelTitle1 title="数据分析展示" />
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="data-analyse-right__footer">
|
||||||
|
<PanelTitle1 title="数据展示统计" />
|
||||||
|
|
||||||
|
<div ref="footerChartRef" class="data-analyse-right__footer-chart" />
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.data-analyse-right {
|
.data-analyse-right {
|
||||||
width: 496px;
|
width: 496px;
|
||||||
height: 970px;
|
height: 970px;
|
||||||
background: palegoldenrod;
|
|
||||||
|
h1 {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__header {
|
||||||
|
margin: 10px 0 0 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 305px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__body {
|
||||||
|
margin: 10px 0 0 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 350px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__footer {
|
||||||
|
margin: 10px 0 0 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 257px;
|
||||||
|
|
||||||
|
&-chart {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -20,7 +20,5 @@ import DataAnalyseRight from '@/views/data-analyse/components/data-analyse-right
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
background: cadetblue;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, onUnmounted, ref } from 'vue';
|
import { useIntervalFn } from '@vueuse/core';
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
|
||||||
import { renderEcharts, updateChart } from '@/views/smart-park/charts/right-sidebar';
|
import { renderEcharts, updateChart } from '@/views/smart-park/charts/right-sidebar';
|
||||||
|
|
||||||
const weekDataChart = ref<HTMLDivElement>();
|
const weekDataChart = ref<HTMLDivElement>();
|
||||||
|
|
||||||
const timer = ref(null);
|
|
||||||
|
|
||||||
/** 随机数据 */
|
/** 随机数据 */
|
||||||
const randomData = () => {
|
const randomData = () => {
|
||||||
function random() {
|
function random() {
|
||||||
|
@ -18,7 +17,7 @@ const randomData = () => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
timer.value = setInterval(() => {
|
useIntervalFn(() => {
|
||||||
updateChart({ data1: random(), data2: random() });
|
updateChart({ data1: random(), data2: random() });
|
||||||
}, 1000);
|
}, 1000);
|
||||||
};
|
};
|
||||||
|
@ -27,11 +26,6 @@ onMounted(() => {
|
||||||
renderEcharts(weekDataChart);
|
renderEcharts(weekDataChart);
|
||||||
randomData();
|
randomData();
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
clearInterval(timer.value);
|
|
||||||
timer.value = null;
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
Loading…
Reference in New Issue