Skip to content

数据看板

https://apifox.com/apidoc/project-934563/api-19465920

静态结构

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

image.png

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'