数据看板
静态结构
vue
<template>
<div class="dashboard-page">
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item>面经后台</el-breadcrumb-item>
<el-breadcrumb-item>数据看板</el-breadcrumb-item>
</el-breadcrumb>
<el-row :gutter="20">
<el-col :span="6">
<el-card style="height: 140px" shadow="never">
<i class="el-icon-user"></i>
<h5 class="tit">活跃用户</h5>
<h2 class="num">802</h2>
<p class="tag"><i>↑ 5.23%</i> 最近一个月</p>
</el-card>
<el-card style="height: 140px" shadow="never">
<i class="el-icon-tickets"></i>
<h5 class="tit">平均访问量</h5>
<h2 class="num">1298</h2>
<p class="tag"><i class="red">↓ 8.56%</i> 截止最近一周</p>
</el-card>
<el-card class="row" style="height: 180px" shadow="never">
<h4>Enhance your Campaign for better outreach →</h4>
<img src="@/assets/img.svg" alt="" />
</el-card>
</el-col>
<el-col :span="18">
<el-card style="height: 504px" shadow="never">
<div class="chart-box" style="height: 500px"></div>
</el-card>
</el-col>
<el-col :span="8">
<el-card style="height: 420px" shadow="never">
<h4>性别分布情况</h4>
<img style="margin-top: 60px" src="@/assets/chart-03.png" alt="" />
</el-card>
</el-col>
<el-col :span="8">
<el-card style="height: 420px" shadow="never">
<h4>浏览访问情况</h4>
<img src="@/assets/chart-01.svg" alt="" />
</el-card>
</el-col>
<el-col :span="8">
<el-card style="height: 420px" shadow="never">
<h4>设备系统访问情况</h4>
<img style="margin-top: 20px" src="@/assets/chart-02.svg" alt="" />
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
export default {
name: 'dashboard-page',
data () {
return {
loading: true
}
},
created () {},
methods: {}
}
</script>
<style lang="scss" scoped>
.dashboard-page {
.el-breadcrumb {
margin-top: 10px;
margin-bottom: 25px;
}
.el-card {
margin-bottom: 20px;
position: relative;
&.row {
h4 {
width: 40%;
float: left;
font-size: 18px;
margin-left: 5%;
}
img {
width: 40%;
float: left;
margin-left: 10%;
margin-top: 30px;
}
}
[class^="el-icon"] {
font-size: 30px;
color: #ccc;
position: absolute;
right: 25px;
top: 30px;
font-weight: bold;
}
.tit {
color: #6c757d;
font-size: 14px;
margin: 6px 0;
}
.num {
color: #6c757d;
font-size: 30px;
margin: 6px 0;
}
.tag {
color: #999;
margin: 0;
font-size: 14px;
> i {
font-style: normal;
margin-right: 10px;
color: rgb(10, 207, 151);
&.red {
color: #fa5c7c;
}
}
}
img {
width: 100%;
height: 100%;
}
h4 {
margin: 0;
padding-bottom: 20px;
color: #6c757d;
}
}
}
</style>
javascript
const myChart = echarts.init(this.$refs.box)
// 绘制图表
myChart.setOption({
title: {
text: '职业方向访问热度'
},
tooltip: {},
xAxis: {
data: ['体育', '医疗', '科技', '电商', '土木', '金融']
},
yAxis: {},
series: [
{
name: '人数',
type: 'bar',
data: [5, 20, 36, 10, 10, 26]
}
]
})
表格-发送请求
api/article.js
javascript
import request from '@/utils/request'
// 1. 获取文章列表
export const getArticleList = ({ current, pageSize }) => {
return request.get('/admin/interview/query', {
params: {
current,
pageSize
}
})
}
article/index.vue
vue
<template>
<div class="article-page">
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item>面经后台</el-breadcrumb-item>
<el-breadcrumb-item>面经管理</el-breadcrumb-item>
</el-breadcrumb>
<el-card shadow="never" border="false">
<template #header>
<div class="header">
<span>共 300 条记录</span>
<el-button
icon="el-icon-plus"
size="small"
type="primary"
round
>
添加面经
</el-button>
</div>
</template>
</el-card>
</div>
</template>
<script>
import { getArticleList } from '@/api/article'
export default {
name: 'article-page',
data() {
return {
current: 1,
pageSize: 10,
list: [],
total: 0 // 总条数
}
},
created() {
this.initData()
},
methods: {
// 请求列表
async initData() {
const { data } = await getArticleList({
current: this.current,
pageSize: this.pageSize
})
this.list = data.rows
this.total = data.total
console.log(data)
}
}
}
</script>
<style lang="scss" scoped>
.el-card {
margin-top: 25px;
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding-right: 16px;
}
.actions {
font-size: 18px;
display: flex;
justify-content: space-around;
color: #666;
> i:hover {
color: rgba(114, 124, 245, 1);
cursor: pointer;
}
}
}
.el-pagination {
margin-top: 20px;
text-align: center;
}
.el-breadcrumb {
margin-top: 10px;
}
.el-form {
padding-right: 40px;
}
.quill-editor {
::v-deep .ql-editor {
height: 300px;
}
}
.el-rate {
padding: 10px 0;
}
.article-preview {
padding: 0 40px 40px 40px;
> h5 {
font-size: 20px;
color: #666;
border-bottom: 1px dashed #ccc;
padding-bottom: 30px;
margin: 0 0 20px 0;
}
}
</style>
表格-渲染-自定义列
javascript
<el-table :data="list" style="width: 100%">
<el-table-column prop="stem" label="标题" width="400">
</el-table-column>
<el-table-column prop="creator" label="作者"> </el-table-column>
<el-table-column prop="likeCount" label="点赞"> </el-table-column>
<el-table-column prop="views" label="浏览数"> </el-table-column>
<el-table-column prop="createdAt" label="更新时间" width="200">
</el-table-column>
<el-table-column label="操作">
<!-- slot-scope相当于是我们的具名插槽,default -->
<template #default>
<div class="actions">
<i class="el-icon-view"></i>
<i class="el-icon-edit-outline"></i>
<i class="el-icon-delete"></i>
</div>
</template>
</el-table-column>
</el-table>
作用域插槽
javascript
<!-- 组件内部相当于是写了作用域插槽,把item数据传回去 -->
<!-- <div v-for="(item, index) in data" :key="item.id">
<slot name="default" :row="item" :$index="index"></slot>
</div> -->
<!-- slot-scope相当于是我们的具名插槽,default -->
<!-- # => v-slot:default = "obj" -->
<!-- $index 下标 -->
<!-- row 相当于是一行的数据对象-->
javascript
<el-table-column label="操作">
<template #default="{ row }">
<div class="actions">
<i class="el-icon-view"></i>
<i class="el-icon-edit-outline"></i>
<i class="el-icon-delete" @click="del(row.id)"></i>
</div>
</template>
</el-table-column>
分页组件
vue
<!-- 分页组件 -->
<!-- 分页容器的位置
@size-change 监听每页条数的变化 --用得少 [100,200,300]变化时触发
@current-change 监听当前页的变化
:page-sizes 可供选择的每页条数下拉菜单 [100, 200, 300]
:page-size 每页显示的条数
:current-page 设置当前生效的【当前页】
:total 设置【总条数】
background 按钮底色
-->
<el-pagination
background
@current-change="handleCurrentChange"
:current-page="current"
:page-size="pageSize"
:total="total"
layout="prev, pager, next"
>
</el-pagination>
抽屉组件drawer
添加,预览,编辑 三个地方点击 ,都需要打开右侧盒子
javascript
<div class="header">
<span>共 {{ total }} 条记录</span>
<el-button
icon="el-icon-plus"
size="small"
type="primary"
round
@click="openDrawer('add')"
>
添加面经
</el-button>
</div>
<template #default="{ row }">
<div class="actions">
<i
class="el-icon-view"
@click="openDrawer('preview', row.id)"
></i>
<i
class="el-icon-edit-outline"
@click="openDrawer('edit', row.id)"
></i>
<i class="el-icon-delete" @click="del(row.id)"></i>
</div>
</template>
vue
<!-- 抽屉组件 放到el-card下方-->
1. title 标题
2. :visible 控制显示隐藏
3. direction 控制方向
4. before-close 关闭前要做什么
<el-drawer
title="我是标题"
:visible.sync="drawer"
direction="rtl"
:before-close="handleClose"
>
<span>我来啦!</span>
</el-drawer>
javascript
handleClose() {
this.drawer = false
},
openDrawer(type, id) {
console.log(type, id)
this.drawer = true
}
删除一条数据
javascript
// article/js 删除封装
export const removeArticle = id => {
return request.delete('/admin/interview/remove', {
data: {
id
}
})
}
// 删除
del(id) {
// 删除 一定要和后端交互
removeArticle(id)
// 重新渲染
this.$message.success('删除成功')
// 假装删除一下
this.list = this.list.filter((el) => el.id != id)
// this.initData()
},
计算属性-title
drawer
javascript
<el-drawer
:title="drawerTitle"
:visible.sync="drawer"
direction="rtl"
:before-close="handleClose"
size="60%"
>
<el-form :model="form" ref="form" label-width="80px">
<el-form-item label="标题" prop="stem">
<el-input v-model="form.stem" placeholder="输入面经标题"></el-input>
</el-form-item>
<el-form-item label="内容" prop="content"> 富文本编辑器 </el-form-item>
<el-form-item>
<el-button type="primary">确认</el-button>
<el-button>取消</el-button>
</el-form-item>
</el-form>
</el-drawer>
form: {
stem: '', // 标题
content: '' // 内容
}
quill-editor编辑器
bash
pnpm i vue-quill-editor
javascript
import vue from '@vitejs/plugin-vue2'
import { resolve } from 'path'
export default {
plugins: [vue()],
resolve: {
alias: {
'@': resolve(__dirname, './src'),
'@pnpm': resolve(__dirname, 'node_modules/.pnpm/quill@1.3.7/node_modules')
}
}
}
组件内使用
javascript
<el-form-item label="内容" prop="content">
<quill-editor v-model="form.content"></quill-editor>
</el-form-item>
import '@pnpm/quill/dist/quill.core.css'
import '@pnpm/quill/dist/quill.snow.css'
import '@pnpm/quill/dist/quill.bubble.css'
import { quillEditor } from 'vue-quill-editor'