目录
1-需求页面
2-头部需求分析
3-中间部分需求分析
3.1-mock数据
3.2-动态渲染数据
4-底部需求分析
1-需求页面
2-头部需求分析
上面头部有四个card,card分为上中下三部分,其中上都是文字描述和一个小图标;中间部分有文字,折线图,柱状图和类似进度条之类的,中间部分不一样,使用插槽slot进行;下面结构有文字和上下箭头,我们也使用插槽进行。我们将单个card封装为一个组件。
结构代码:
js和样式代码如下:
<script>
export default {
name: '',
props:['title','count']
}
</script>
<style scoped>
.card-header{
display: flex;
justify-content: space-between;
color:#d9d9d9;
}
.card-content{
font-size: 30px;
padding: 10px 0px;
}
.card-charts{
height: 50px;
}
.card-footer{
border-top: 1px solid #eee;
padding-top: 10px;
}
</style>
父组件中使用
card里面使用detail子组件
第二个card里面需要插入折线图
中间部分折线图,柱状图和进度条使用子组件的形式。
折线图组件:src\views\dashboard\Card\lineChart\index.vue
<template>
<!-- 容器 -->
<div class="charts" ref="charts"></div>
</template>
<script>
//引入echarts
import echarts from "echarts";
export default {
name: "",
mounted() {
//初始化echarts实例
let lineCharts = echarts.init(this.$refs.charts);
//配置数据
lineCharts.setOption({
xAxis: {
//隐藏x轴
show: false,
type: "category",
},
yAxis: {
//隐藏y轴
show: false,
},
//系列
series: [
{
type: "line",
data: [10, 7, 33, 12, 48, 9,29,10,44],
//拐点的样式的设置
itemStyle: {
opacity: 0,
},
//线条的样式
lineStyle: {
color: "purple",
},
//填充颜色设置
areaStyle: {
color: {
type: "linear",
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: "purple", // 0% 处的颜色
},
{
offset: 1,
color: "#fff", // 100% 处的颜色
},
],
global: false, // 缺省为 false
},
},
},
],
//布局调试
grid: {
left: 0,
top: 0,
right: 0,
bottom: 0,
},
});
},
};
</script>
<style scoped>
.charts {
width: 100%;
height: 100%;
}
</style>
柱状图组件:src\views\dashboard\Card\barCharts\index.vue
<template>
<!-- 容器 -->
<div class="charts" ref="charts"></div>
</template>
<script>
//引入echarts
import echarts from "echarts";
export default {
name: "",
mounted() {
//初始化echarts实例
let lineCharts = echarts.init(this.$refs.charts);
//配置数据
lineCharts.setOption({
xAxis: {
//隐藏x轴
show: false,
//均分
type: "category",
},
yAxis: {
//隐藏y轴
show: false,
},
//系列
series: [
{
//图标形式-柱状图
type: "bar",
data: [10, 7, 33, 12, 48, 9,29,10,44,33,22,8],
color:'cyan'
},
],
//布局调试
grid: {
left: 0,
top: 0,
right: 0,
bottom: 0,
},
tooltip:{}
});
},
};
</script>
<style scoped>
.charts {
width: 100%;
height: 100%;
}
</style>
进度条组件:src\views\dashboard\Card\progressCharts\index.vue
<template>
<!-- 容器 -->
<div class="charts" ref="charts"></div>
</template>
<script>
//引入echarts
import echarts from "echarts";
export default {
name: "",
mounted() {
//初始化echarts实例
let lineCharts = echarts.init(this.$refs.charts);
//配置数据
lineCharts.setOption({
xAxis: {
//隐藏x轴
show: false,
//最小值与最大值的设置
min: 0,
max: 100,
},
yAxis: {
//隐藏y轴
show: false,
//均分
type: "category",
},
//系列
series: [
{
//图标形式-柱状图
type: "bar",
data: [78],
color: "cyan",
//柱状图的宽度
barWidth: 10,
color: "yellowgreen",
//背景颜色设置
showBackground: true,
//设置背景颜色
backgroundStyle: {
color: "#eee",
},
//文本标签
label:{
show:true,
//改变文本内容
formatter:'|',
//文本标签位置调试
position:'right'
}
},
],
//布局调试
grid: {
left: 0,
top: 0,
right: 0,
bottom: 0,
},
});
},
};
</script>
<style scoped>
.charts {
width: 100%;
height: 100%;
}
</style>
3-中间部分需求分析
中间部分分为左侧和右侧两部分,默认展示销售额数据,切换tab的时候要展示访问量的数据;这部分数据我们通过mock来获取,动态展示。
3.1-mock数据
之前的数据我们都是通过请求后端服务器来获取的,现在首页这块数据我们需要通过mock来获取。
1-准备需要mock的数据;新建文件:mock\data.json;
2-由于首页组件嵌套比较多,我们父子传输数据层次多,我们采用vuex来从仓库获取数据。src\store\modules\home.js新建仓库;注册仓库;
我们发送请求是发送到mock里面
首页挂载完成的时候发送action
3.2-动态渲染数据
销售组件:src\views\dashboard\Sale\index.vue
组件中我们分左右两侧内容,柱状图和排名宽度大小分别占18和6,因为一共是24。默认展示销售额。通过计算和监听来动态渲染数据是销售额还是访问量。
<template>
<el-card class="box-card" style="margin: 10px 0px">
<div slot="header" class="clearfix">
<!-- @tab-click="handleClick" -->
<!-- 头部左侧内容 -->
<el-tabs class="tab" v-model="activeName">
<el-tab-pane label="销售额" name="sale"></el-tab-pane>
<el-tab-pane label="访问量" name="visite"></el-tab-pane>
</el-tabs>
<!-- 头部右侧内容 -->
<div class="right">
<span @click="setDay">今日</span><span @click="setWeek">本周</span>
<span @click="setMonth">本月</span><span @click="setYear">本年</span>
<!-- v-model="value1" -->
<el-date-picker
v-model="date" class="date" type="daterange" range-separator="-"
start-placeholder="开始日期" end-placeholder="结束日期" value-format="yyyy-MM-dd">
</el-date-picker>
</div>
</div>
<div>
<el-row :gutter="10">
<el-col :span="18">
<!-- 容器 -->
<div class="charts" ref="charts"></div>
</el-col>
<el-col :span="6" class="right">
<h3>门店{{ title }}排名</h3>
<ul>
<li>
<span class="rindex">1</span><span>门店1</span><span class="rvalue">123950</span>
</li>
<li>
<span class="rindex">2</span><span>门店2</span><span class="rvalue">123850</span>
</li>
<li>
<span class="rindex">3</span><span>门店3</span><span class="rvalue">123750</span>
</li>
<li>
<span>4</span><span>门店4</span><span class="rvalue">123650</span>
</li>
<li>
<span>5</span><span>门店5</span><span class="rvalue">123550</span>
</li>
<li>
<span>6</span><span>门店6</span><span class="rvalue">123450</span>
</li>
<li>
<span>7</span><span>门店7</span><span class="rvalue">123350</span>
</li>
</ul>
</el-col>
</el-row>
</div>
</el-card>
</template>
<script>
//引入echarts
import echarts from "echarts";
import dayjs from "dayjs";
import { mapState } from "vuex";
export default {
name: "",
data() {
return {
activeName: "sale",
mycharts: null,
//收集日历数据
date: [],
};
},
mounted() {
//初始化echarts实例
this.mycharts = echarts.init(this.$refs.charts);
//配置数据
this.mycharts.setOption({
title: {
text: this.title + "趋势",
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
},
grid: {
left: "3%",
right: "4%",
bottom: "3%",
containLabel: true,
},
xAxis: [
{
type: "category",
data: [],
axisTick: {
alignWithLabel: true,
},
},
],
yAxis: [
{
type: "value",
},
],
series: [
{
name: "Direct",
type: "bar",
barWidth: "60%",
data: [],
color: "yellowgreen",
},
],
});
//顶部是mounted:为什么第一次没有数据,没有数据因此不显示
},
computed: {
//计算属性-标题
title() {
//重新设置配置项
return this.activeName == "sale" ? "销售额" : "访问量";
},
...mapState({
listState: (state) => state.home.list || {},
}),
},
//监听属性
watch: {
title() {
console.log("修改配置数据");
//重新修改图标的配置数据
//图标配置数据可以再次修改,如果有新的数值,新的数值,没有新的数值,还是用以前的
this.mycharts.setOption({
title: {
text: this.title,
},
xAxis: {
data:
this.title == "销售额"
? this.listState.orderFullYearAxis
: this.listState.userFullYearAxis,
},
series: [
{
name: "Direct",
type: "bar",
barWidth: "60%",
data:
this.title == "销售额"
? this.listState.orderFullYear
: this.listState.userFullYear,
color: "yellowgreen",
},
],
});
},
listState(){
this.mycharts.setOption({
title: {
text: this.title + "趋势",
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
},
grid: {
left: "3%",
right: "4%",
bottom: "3%",
containLabel: true,
},
xAxis: [
{
type: "category",
data: this.listState.orderFullYearAxis,
axisTick: {
alignWithLabel: true,
},
},
],
yAxis: [
{
type: "value",
},
],
series: [
{
name: "Direct",
type: "bar",
barWidth: "60%",
data: this.listState.orderFullYear,
color: "yellowgreen",
},
],
});
}
},
methods: {
//本天
setDay() {
const day = dayjs().format("YYYY-MM-DD");
this.date = [day, day];
},
//本周
setWeek() {
const start = dayjs().day(1).format("YYYY-MM-DD");
const end = dayjs().day(7).format("YYYY-MM-DD");
this.date = [start, end];
},
//本月
setMonth() {
const start = dayjs().startOf("month").format("YYYY-MM-DD");
const end = dayjs().endOf("month").format("YYYY-MM-DD");
this.date = [start, end];
},
//本年
setYear() {
const start = dayjs().startOf("year").format("YYYY-MM-DD");
const end = dayjs().endOf("year").format("YYYY-MM-DD");
this.date = [start, end];
},
},
};
</script>
<style scoped>
.clearfix {
position: relative;
display: flex;
justify-content: space-between;
}
.tab {
width: 100%;
}
.right {
position: absolute;
right: 0px;
}
.date {
width: 250px;
margin: 0px 20px;
}
.right span {
margin: 0px 10px;
}
.charts {
width: 100%;
height: 300px;
}
ul {
list-style: none;
width: 100%;
height: 300px;
padding: 0px;
}
ul li {
height: 8%;
margin: 10px 0px;
}
.rindex {
float: left;
width: 20px;
height: 20px;
border-radius: 50%;
background: black;
color: white;
text-align: center;
}
.rvalue {
float: right;
}
</style>
4-底部需求分析
由于底部左侧的折线图,我们上面已经实现了类似的功能,左侧我们忽略;主要看右侧的饼状图。首先需要展示饼状图,然后鼠标移动上去,显示对应的数据。并且圆圈内部显示对应的文本标题。子组件:src\views\dashboard\Observe\Category\index.vue;
<template>
<el-card>
<div slot="header" class="header">
<div class="category-header">
<span>销售额类别占比</span>
<el-radio-group v-model="value">
<el-radio-button label="全部渠道"></el-radio-button>
<el-radio-button label="线上"></el-radio-button>
<el-radio-button label="门店"></el-radio-button>
</el-radio-group>
</div>
</div>
<div>
<div class="charts" ref="charts"></div>
</div>
</el-card>
</template>
<script>
import echarts from "echarts";
export default {
name: "",
data() {
return {
value: "全部渠道",
};
},
mounted() {
//饼图
let mychart = echarts.init(this.$refs.charts);
mychart.setOption({
title: {
text: "视频",
subtext: 1048,
left: "center",
top: "center",
},
tooltip: {
trigger: "item",
},
series: [
{
name: "Access From",
type: "pie",
radius: ["40%", "70%"],
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 10,
borderColor: "#fff",
borderWidth: 2,
},
label: {
show: true,
position: "outsize",
},
labelLine: {
show: true,
},
data: [
{ value: 1048, name: "视频" },
{ value: 735, name: "Direct" },
{ value: 580, name: "Email" },
{ value: 484, name: "Union Ads" },
{ value: 300, name: "Video Ads" },
],
},
],
});
//绑定事件
mychart.on("mouseover",(params)=>{
//获取鼠标移上去那条数据
const {name,value} = params.data;
//重新设置标题
mychart.setOption({
title:{
text:name,
subtext:'value'
}
})
});
},
};
</script>
<style scoped>
.category-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.header {
border-bottom: 1px solid #eee;
}
.charts {
width: 100%;
height: 300px;
}
</style>