Vue2项目练手——通用后台管理项目
- 数据的请求
- mock数据模拟实战
- 文件目录
- src/api/mock.js
- src/api/mockServeData/home.js
- main.js
- 首页组件布局
- 可视化图表
- 可视化图表布局
- Home.vue
- echarts表
- Home.vue
数据的请求
mock数据模拟实战
mock官方文档
前端用来模拟后端接口的工具,通过拦截前端发起的请求,自己定义一些数据
npm i mockjs
文件目录
src/api/mock.js
import Mock from 'mockjs'
import homeApi from "@/api/mockServeData/home";
/*//定义请求拦截
Mock.mock('/api/home/getData',function (){
//拦截到请求后处理的逻辑
console.log("拦截到了")
})*/
//定义请求拦截
Mock.mock('/api/home/getData',homeApi.getStatisticalData())
src/api/mockServeData/home.js
// mock数据模拟
import Mock from 'mockjs'
// 图表数据
let List = []
export default {
getStatisticalData: () => {
//Mock.Random.float 产生随机数100到8000之间 保留小数 最小0位 最大0位
for (let i = 0; i < 7; i++) {
List.push(
Mock.mock({
苹果: Mock.Random.float(100, 8000, 0, 0),
vivo: Mock.Random.float(100, 8000, 0, 0),
oppo: Mock.Random.float(100, 8000, 0, 0),
魅族: Mock.Random.float(100, 8000, 0, 0),
三星: Mock.Random.float(100, 8000, 0, 0),
小米: Mock.Random.float(100, 8000, 0, 0)
})
)
}
return {
code: 20000,
data: {
// 饼图
videoData: [
{
name: '小米',
value: 2999
},
{
name: '苹果',
value: 5999
},
{
name: 'vivo',
value: 1500
},
{
name: 'oppo',
value: 1999
},
{
name: '魅族',
value: 2200
},
{
name: '三星',
value: 4500
}
],
// 柱状图
userData: [
{
date: '周一',
new: 5,
active: 200
},
{
date: '周二',
new: 10,
active: 500
},
{
date: '周三',
new: 12,
active: 550
},
{
date: '周四',
new: 60,
active: 800
},
{
date: '周五',
new: 65,
active: 550
},
{
date: '周六',
new: 53,
active: 770
},
{
date: '周日',
new: 33,
active: 170
}
],
// 折线图
orderData: {
date: ['20191001', '20191002', '20191003', '20191004', '20191005', '20191006', '20191007'],
data: List
},
tableData: [
{
name: 'oppo',
todayBuy: 500,
monthBuy: 3500,
totalBuy: 22000
},
{
name: 'vivo',
todayBuy: 300,
monthBuy: 2200,
totalBuy: 24000
},
{
name: '苹果',
todayBuy: 800,
monthBuy: 4500,
totalBuy: 65000
},
{
name: '小米',
todayBuy: 1200,
monthBuy: 6500,
totalBuy: 45000
},
{
name: '三星',
todayBuy: 300,
monthBuy: 2000,
totalBuy: 34000
},
{
name: '魅族',
todayBuy: 350,
monthBuy: 3000,
totalBuy: 22000
}
]
}
}
}
}
main.js
import Vue from 'vue'
import App from './App.vue'
import VueRouter from "vue-router";
import router from "@/router";
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css'
import store from '@/store'
//引入mock模拟
import '@/api/mock'
Vue.config.productionTip = false
Vue.use(VueRouter)
Vue.use(ElementUI)
new Vue({
store,
router,
render: h => h(App),
}).$mount('#app')
首页组件布局
可视化图表
可视化图表布局
Home.vue
<template>
<div>
<el-row>
<el-col :span="8" style="padding-right: 10px">
<el-card class="box-card">
<div class="user">
<img src="@/assets/user.webp" alt="">
<div class="userinfo">
<p class="name">Admin</p>
<p class="access">超级管理员</p>
</div>
</div>
<div class="login-info">
<p>上次登录的时间:<span>2023-08-30</span></p>
<p>上次登录的地点:<span>北京</span></p>
</div>
</el-card>
<el-card style="margin-top: 20px;height: 460px;">
<el-table
:data="tableData"
style="width: 100%;">
<el-table-column v-for="(val,key) in tableLabel" :prop="key" :label="val" />
</el-table>
</el-card>
</el-col>
<el-col :span="16" style="padding-left: 10px">
<div class="num">
<el-card v-for="item in countData" :key="item.name" :body-style="{display:'flex',padding:0}">
<i class="icon" :class="`el-icon-${item.icon}`" :style="{background:item.color}"></i>
<div class="detail">
<p class="price">¥{{item.value}}</p>
<p class="desc">{{item.name}}</p>
</div>
</el-card>
</div>
<el-card style="height: 280px">
<!-- 折线图-->
</el-card>
<div class="graph">
<el-card style="height: 260px;"></el-card>
<el-card style="height: 260px;"></el-card>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import {getData} from "@/api";
export default {
name: "Home",
data(){
return{
tableData:[],
tableLabel:{
name:'课程',
todayBuy:'今日购买',
monthBuy:'本月购买',
totalBuy:'总共购买'
},
countData:[
{
name: "今日支付订单",
value: 1234,
icon: "success",
color: "#2ec7c9",
},
{
name: "今日收藏订单",
value: 210,
icon: "star-on",
color: "#ffb980",
},
{
name: "今日未支付订单",
value: 1234,
icon: "s-goods",
color: "#5ab1ef",
},
{
name: "本月支付订单",
value: 1234,
icon: "success",
color: "#2ec7c9",
},
{
name: "本月收藏订单",
value: 210,
icon: "star-on",
color: "#ffb980",
},
{
name: "本月未支付订单",
value: 1234,
icon: "s-goods",
color: "#5ab1ef",
},
],
}
},
mounted(){
getData().then(({data})=>{
console.log(data)
// data.data
const {tableData}=data.data
this.tableData=tableData
})
}
}
</script>
<style scoped lang="less">
.user{
display: flex;
align-items: center;
padding-bottom: 20px;
margin-bottom: 20px;
border-bottom: 1px solid #ccc;
img{
margin-right: 40px;
width: 150px;
height: 150px;
border-radius: 50%;
}
.userinfo{
.name{
font-size: 32px;
margin-bottom: 10px;
}
.access{
color: #999;
}
}
}
.login-info{
p{
line-height: 28px;
font-size: 14px;
color: #999;
span{
color: #666;
margin-left: 60px;
}
}
}
.num{
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.icon{
width: 80px;
height: 80px;
color: #fff;
line-height: 80px;
text-align: center;
font-size: 30px;
}
.detail{
margin-left: 15px;
display: flex;
flex-direction: column;
justify-content: center;
.price{
font-size: 30px;
margin-bottom: 10px;
line-height: 30px;
}
.desc{
color: #999;
font-size: 14px;
text-align: center;
}
}
.el-card{
margin-bottom: 20px;
width: 32%;
}
}
.graph{
display: flex;
margin-top: 20px;
justify-content: space-between;
.el-card{
width: 48%;
}
}
</style>
echarts表
安装echarts
npm i echarts@5.1.2
Home.vue
- 折线图
mounted(){
getData().then(({data})=>{
console.log(data)
// data.data
const {tableData}=data.data
this.tableData=tableData
//折线图
// 基于准备好的dom,初始化echarts实例
const echarts1 = echarts.init(this.$refs.echarts1)
// 指定图表的配置项和数据
var lineOption={}
// 处理数据
const {orderData,userData,videoData}=data.data
const xAxis=orderData.date
const xMore=Object.keys(orderData.data[0])
lineOption.xAxis={data:xAxis}
lineOption.yAxis={
type: "value",
axisLine: {
lineStyle: {
color: "#17b3a3",
},
},
}
lineOption.legend={
data:xMore
}
lineOption.tooltip={
trigger:'axis'
}
lineOption.series=[]
console.log(lineOption)
xMore.forEach(key=>{
lineOption.series.push({
name:key,
data:orderData.data.map(item=>item[key]),
type:'line'
})
})
// console.log(lineOption)
// 使用刚指定的配置项和数据显示图表
echarts1.setOption(lineOption)
})
}
<el-card style="height: 280px">
<!-- 折线图-->
<div ref="echarts1" style="height: 280px"></div>
</el-card>
- 柱状图:
<el-card style="height: 260px;">
<!-- 柱状图-->
<div ref="echarts2" style="height: 260px;"></div>
</el-card>
//柱状图
const echarts2 = echarts.init(this.$refs.echarts2)
var barOption={
legend: {
// 图例文字颜色
textStyle: {
color: "#333",
},
},
grid: {
left: "20%",
},
// 提示框
tooltip: {
trigger: "axis",
},
xAxis: {
type: "category", // 类目轴
data: userData.map(item=>item.date),
axisLine: {
lineStyle: {
color: "#17b3a3",
},
},
axisLabel: {
interval: 0,
color: "#333",
},
},
yAxis: [
{
type: "value",
axisLine: {
lineStyle: {
color: "#17b3a3",
},
},
},
],
color: ["#2ec7c9", "#b6a2de", "#5ab1ef", "#ffb980", "#d87a80", "#8d98b3"],
series: [
{
name:"新增用户",
data:userData.map(item=>item.new),
type:'bar'
},
{
name:"活跃用户",
data:userData.map(item=>item.active),
type:'bar'
}
],
}
echarts2.setOption(barOption)
- 饼状图
<el-card style="height: 260px;">
<!-- 饼状图-->
<div ref="echarts3" style="height: 240px"></div>
</el-card>
//饼状图
const echarts3=echarts.init(this.$refs.echarts3)
var pieOption = {
tooltip: {
trigger: "item",
},
color: [
"#0f78f4",
"#dd536b",
"#9462e5",
"#a6a6a6",
"#e1bb22",
"#39c362",
"#3ed1cf",
],
series: [
{
data:videoData,
type:'pie'
}
],
}
echarts3.setOption(pieOption)
全部代码:
<template>
<div>
<el-row>
<el-col :span="8" style="padding-right: 10px">
<el-card class="box-card">
<div class="user">
<img src="@/assets/user.webp" alt="">
<div class="userinfo">
<p class="name">Admin</p>
<p class="access">超级管理员</p>
</div>
</div>
<div class="login-info">
<p>上次登录的时间:<span>2023-08-30</span></p>
<p>上次登录的地点:<span>北京</span></p>
</div>
</el-card>
<el-card style="margin-top: 20px;height: 460px;">
<el-table
:data="tableData"
style="width: 100%;">
<el-table-column v-for="(val,key) in tableLabel" :prop="key" :label="val" />
</el-table>
</el-card>
</el-col>
<el-col :span="16" style="padding-left: 10px">
<div class="num">
<el-card v-for="item in countData" :key="item.name" :body-style="{display:'flex',padding:0}">
<i class="icon" :class="`el-icon-${item.icon}`" :style="{background:item.color}"></i>
<div class="detail">
<p class="price">¥{{item.value}}</p>
<p class="desc">{{item.name}}</p>
</div>
</el-card>
</div>
<el-card style="height: 280px">
<!-- 折线图-->
<div ref="echarts1" style="height: 280px"></div>
</el-card>
<div class="graph">
<el-card style="height: 260px;">
<!-- 柱状图-->
<div ref="echarts2" style="height: 260px;"></div>
</el-card>
<el-card style="height: 260px;">
<!-- 饼状图-->
<div ref="echarts3" style="height: 240px"></div>
</el-card>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import {getData} from "@/api";
import * as echarts from 'echarts'
export default {
name: "Home",
data(){
return{
tableData:[],
tableLabel:{
name:'课程',
todayBuy:'今日购买',
monthBuy:'本月购买',
totalBuy:'总共购买'
},
countData:[
{
name: "今日支付订单",
value: 1234,
icon: "success",
color: "#2ec7c9",
},
{
name: "今日收藏订单",
value: 210,
icon: "star-on",
color: "#ffb980",
},
{
name: "今日未支付订单",
value: 1234,
icon: "s-goods",
color: "#5ab1ef",
},
{
name: "本月支付订单",
value: 1234,
icon: "success",
color: "#2ec7c9",
},
{
name: "本月收藏订单",
value: 210,
icon: "star-on",
color: "#ffb980",
},
{
name: "本月未支付订单",
value: 1234,
icon: "s-goods",
color: "#5ab1ef",
},
],
}
},
mounted(){
getData().then(({data})=>{
console.log(data)
// data.data
const {tableData}=data.data
this.tableData=tableData
// 基于准备好的dom,初始化echarts实例
const echarts1 = echarts.init(this.$refs.echarts1)
// 指定图表的配置项和数据
var lineOption={}
// 处理数据
const {orderData,userData,videoData}=data.data
const xAxis=orderData.date
const xMore=Object.keys(orderData.data[0])
lineOption.xAxis={data:xAxis}
lineOption.yAxis={
type: "value",
axisLine: {
lineStyle: {
color: "#17b3a3",
},
},
}
lineOption.legend={
data:xMore
}
lineOption.tooltip={
trigger:'axis'
}
lineOption.series=[]
console.log(lineOption)
xMore.forEach(key=>{
lineOption.series.push({
name:key,
data:orderData.data.map(item=>item[key]),
type:'line'
})
})
// console.log(lineOption)
// 使用刚指定的配置项和数据显示图表
echarts1.setOption(lineOption)
//柱状图
const echarts2 = echarts.init(this.$refs.echarts2)
var barOption={
legend: {
// 图例文字颜色
textStyle: {
color: "#333",
},
},
grid: {
left: "20%",
},
// 提示框
tooltip: {
trigger: "axis",
},
xAxis: {
type: "category", // 类目轴
data: userData.map(item=>item.date),
axisLine: {
lineStyle: {
color: "#17b3a3",
},
},
axisLabel: {
interval: 0,
color: "#333",
},
},
yAxis: [
{
type: "value",
axisLine: {
lineStyle: {
color: "#17b3a3",
},
},
},
],
color: ["#2ec7c9", "#b6a2de", "#5ab1ef", "#ffb980", "#d87a80", "#8d98b3"],
series: [
{
name:"新增用户",
data:userData.map(item=>item.new),
type:'bar'
},
{
name:"活跃用户",
data:userData.map(item=>item.active),
type:'bar'
}
],
}
echarts2.setOption(barOption)
//饼状图
const echarts3=echarts.init(this.$refs.echarts3)
var pieOption = {
tooltip: {
trigger: "item",
},
color: [
"#0f78f4",
"#dd536b",
"#9462e5",
"#a6a6a6",
"#e1bb22",
"#39c362",
"#3ed1cf",
],
series: [
{
data:videoData,
type:'pie'
}
],
}
echarts3.setOption(pieOption)
})
}
}
</script>
<style scoped lang="less">
.user{
display: flex;
align-items: center;
padding-bottom: 20px;
margin-bottom: 20px;
border-bottom: 1px solid #ccc;
img{
margin-right: 40px;
width: 150px;
height: 150px;
border-radius: 50%;
}
.userinfo{
.name{
font-size: 32px;
margin-bottom: 10px;
}
.access{
color: #999;
}
}
}
.login-info{
p{
line-height: 28px;
font-size: 14px;
color: #999;
span{
color: #666;
margin-left: 60px;
}
}
}
.num{
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.icon{
width: 80px;
height: 80px;
color: #fff;
line-height: 80px;
text-align: center;
font-size: 30px;
}
.detail{
margin-left: 15px;
display: flex;
flex-direction: column;
justify-content: center;
.price{
font-size: 30px;
margin-bottom: 10px;
line-height: 30px;
}
.desc{
color: #999;
font-size: 14px;
text-align: center;
}
}
.el-card{
margin-bottom: 20px;
width: 32%;
}
}
.graph{
display: flex;
margin-top: 20px;
justify-content: space-between;
.el-card{
width: 48%;
}
}
</style>