一步步完整搭建一个图纸管理系统(Django+Vue3)——2、前端页面初步构建,vue初探

1,991 阅读21分钟

前言: 网上Django项目要么太老,要么不全。正好手里有个需求,借这个机会用django3.2加vue3(TS)一步步完整搭建一个图纸管理系统。一方面是记录,另一方面也回馈开源精神。希望和大家一起学习一起进步。本篇为前端相关知识和项目页面构建(最近更新7.7)

二、构建前端页面

1、工具的准备

vs code(Visual Studio Code - Code Editing. Redefined)

node.js(Node.js (nodejs.org))

image.png

vs code插件:

(1)、Chinese Language Pack——中文语言包

(2)、禁用vetur,安装Vue Language Features(Volar)

(3)、安装Element UI Snippets

2、创建项目

cmd进入自己的目标文件夹下输入 npm init vite@latest后选择输入项目名称,包,选择vue,选择ts

image.png

创建后目录如下:

image.png

用vs code打开,并运行npm install更新依赖

image.png

随后运行npm run dev测试项目是否运行成功。

image.png

运行成功后打开网页为:

image.png

3、Vue3项目介绍

项目目录结构介绍

image.png

修改访问地址

在vite.config.ts中加入server配置

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  server:{
    host:'localhost', // 也可以是192.XX.XXX.X类似的
    port:8080, //随便用哪个都可以
    open:true
  }
})

npm常用指令

npm install XXX (安装某个包)
npm uninstall XXX (卸载某个包)
​
npm install vuex --save 开发环境中
npm install vuex --save-dev
​
npm run dev (运行测试环境)
npm run build (打包)
​
npm install (新项目安装依赖)

简单说下页面如何加载

主要分三个重要的文件

index.html---静态页面

main.ts---自动运行的脚本文件

app.vue---主组件,是页面入口文件

在main.ts中主要就2个

import { createApp } from 'vue' // 导入CreateApp的函数
import './style.css' // 引入App.vue -- 模块的主入口文件!
import App from './App.vue'createApp(App).mount('#app') // 使用vue中的CreateApp方法创建一个app.vue的组件,并放置到index.html的id为app的div中

我们可以在components下新建一个Demo.vue

<script lang="ts">
// 浏览器中的script部分 响应用户的操作
</script><template>
<!-- 相当于html中的标签,用户呈现页面的内容 -->
</template><style scoped>
/* 相当于html中的样式 */
</style>

此外我们可以看到在app.vue中就像引用标签一样<h1...>引用写的helloworld.vue:

一个vue文件就是一个组件,可以被其他的vue引用

image.png

我们还可以看到父组件给子组件传递数据

image.png

这边可以在Demo.vue中写入一些

<script lang="ts" setup>
// 浏览器中的script部分 响应用户的操作
</script><template>
<!-- 相当于html中的标签,用户呈现页面的内容 -->
    <h1>Demo中的标签</h1>
</template><style scoped>
/* 相当于html中的样式 */
h1{
    color: blue;
}
</style>

在App.vue进行引用

image.png

我们可以看到Demo中的标签引入到了主页面中

image.png

PS:scoped 是 Vue 单文件组件中的一个特殊语法,它的作用是将样式作用域限定在当前组件内部,避免样式污染和命名冲突。

Setup语法大大简化了脚本的代码,现在是不用注册,引入即注册。Setup语法糖还有定义组件props,定义响应式变量、函数、监听、计算属性。。。

4、使用Element Plus

第一步:npm install element-plus --save

我这里安装的是2.1.4版本

image.png

在package.json就可以看到安装成功

image.png

因为所以的页面都有可能引用,所以要全局设置下

第二步:在main.ts中注册

import { createApp } from 'vue' // 导入CreateApp的函数
import './style.css' // 引入App.vue -- 模块的主入口文件!
import App from './App.vue'
import ElementPlus from 'element-plus' // 引入ElementPlus
import 'element-plus/dist/index.css' // 引入ElementPlus的CSScreateApp(App).use(ElementPlus).mount('#app') // 使用vue中的CreateApp方法创建一个app.vue的组件,并放置到index.html的id为app的div中

验证

如何验证呢,打开element-plus组件页面

Button 按钮 | Element Plus (gitee.io)

就选择一个按钮组件:

image.png

放到demo下

image.png

我们可以看见页面有此效果了

image.png

稍微加点佐料(提示框)

<script lang="ts" setup>
// 浏览器中的script部分 响应用户的操作
import { ElMessage, ElMessageBox } from 'element-plus'
const queryStudent=()=>{
     ElMessageBox.alert('点击成功!', 'Title', {
    confirmButtonText: 'OK',  
     });
};
</script><template>
<!-- 相当于html中的标签,用户呈现页面的内容 -->
    <h1>Demo中的标签</h1>
     <el-row class="mb-4">
    <el-button>Default</el-button>
    <el-button type="primary" @click="queryStudent">查询</el-button>
    <el-button type="success">添加</el-button>
    <el-button type="info">Info</el-button>
    <el-button type="warning">Warning</el-button>
    <el-button type="danger">Danger</el-button>
  </el-row></template><style scoped>
/* 相当于html中的样式 */
h1{
    color: blue;
}
</style>

image.png

5、vue-router

vue-router使用步骤

第一步:npm install vue-router@4.0.14

image.png

第二步:新建路由匹配文件(是不是很像django的urls.py)

第三步:在main.ts中注册

import router from './router'

createApp(App).use(router).mount('#app')

在src文件下新建router文件夹,在放上一个加index.ts的脚本文件

例子

// 导入组件
import { createRouter,createWebHistory,RouteRecordRaw } from "vue-router"
// 导入组件
import HelloWorld from '../components/HelloWorld.vue'
import Demo from '../components/Demo.vue'// 创建路由匹配的数据集合 -- Array
const routes:Array<RouteRecordRaw> = [
    {
        path:"/",
        component:HelloWorld,
    },
    {
        path:"/demo",
        component:Demo,
    }
]
​
// 创建一个vue-router的对象
const router = createRouter({
    history:createWebHistory(),
    routes,
})
​
// 暴露
export default router

main.ts导入

image.png

在app.vue中template中注释,引入

image.png

这个时候我们就发现页面地址变化会导致页面切换

image.png

image.png

PS:createWebHistory路由模式路径不带#号 createWebHashHistory路由模式路径带#号

6、管理系统后台主界面框架搭建

6.1 后台系统主界面的搭建

先在src下新建目录

image.png

然后在element-plus选择下布局容器

Container 布局容器 | Element Plus (element-plus.org)

image.png

因为我们页面分三部分选择这个。

layout的index.vue写为:

<script lang="ts" setup></script><template>
    <el-container class="layout">
      <el-aside class="aside" width="200px">Aside</el-aside>
      <el-container>
        <el-header class="header">Header</el-header>
        <el-main class="main">Main</el-main>
      </el-container>
    </el-container>
</template><style scoped></style>

将router的index.ts修改

// 导入组件
import { createRouter,createWebHistory,RouteRecordRaw } from "vue-router"
// 导入组件
import Index from '../layout/Index.vue'// 创建路由匹配的数据集合 -- Array
const routes:Array<RouteRecordRaw> = [
    {
        path:"/",
        name:'Index',
        component:Index,
    },
    
]
​
// 创建一个vue-router的对象
const router = createRouter({
    history:createWebHistory(),
    routes,
})
​
// 暴露
export default router

app.vue

<script setup lang="ts">
</script><template>
  
  <router-view></router-view>
</template>
 
<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  
}
</style>

主页面现在为:

image.png

为了显示清晰index.vue修改下

<script lang="ts" setup></script><template>
    <el-container class="layout">
      <el-aside class="aside" width="200px">Aside</el-aside>
      <el-container>
        <el-header class="header">Header</el-header>
        <el-main class="main">Main</el-main>
      </el-container>
    </el-container>
</template><style scoped>
.layout{
  height: 100%;
}
.aside{
    background-color: antiquewhite;
}
.header{
    background-color: aquamarine;
}
.main{
    background-color: azure;
}
</style>

image.png

对index.html进行修改

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>信息管理系统</title>
    <style>
      html,body,#app{
        padding: 0px;
        margin: 0px;
        height: 100%;
        width: 100%;
      }
    </style>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>

image.png

发现还是有边框

打开浏览器的F12发现多引入了一个style.css样式,去源项目寻找。果然!

image.png

这个时候去main.ts寻找发现果然多引入了

image.png

注释还写错了

修改下:

import { createApp } from 'vue' // 导入CreateApp的函数
import App from './App.vue' // 引入App.vue -- 模块的主入口文件!
import ElementPlus from 'element-plus' // 引入ElementPlus
import 'element-plus/dist/index.css' // 引入ElementPlus的CSS
import router from './router' // 导入router文件createApp(App).use(router).use(ElementPlus).mount('#app') // 使用vue中的CreateApp方法创建一个app.vue的组件,并放置到index.html的id为app的div中

这样显示就正常了。

image.png

搭建侧边栏

image.png

选择暗色部分代码:

 <el-menu
        active-text-color="#ffd04b"
        background-color="#545c64"
        class="el-menu-vertical-demo"
        default-active="2"
        text-color="#fff"
        @open="handleOpen"
        @close="handleClose"
      >
        <el-sub-menu index="1">
          <template #title>
            <el-icon><location /></el-icon>
            <span>Navigator One</span>
          </template>
          <el-menu-item-group title="Group One">
            <el-menu-item index="1-1">item one</el-menu-item>
            <el-menu-item index="1-2">item two</el-menu-item>
          </el-menu-item-group>
          <el-menu-item-group title="Group Two">
            <el-menu-item index="1-3">item three</el-menu-item>
          </el-menu-item-group>
          <el-sub-menu index="1-4">
            <template #title>item four</template>
            <el-menu-item index="1-4-1">item one</el-menu-item>
          </el-sub-menu>
        </el-sub-menu>
        <el-menu-item index="2">
          <el-icon><icon-menu /></el-icon>
          <span>Navigator Two</span>
        </el-menu-item>
        <el-menu-item index="3" disabled>
          <el-icon><document /></el-icon>
          <span>Navigator Three</span>
        </el-menu-item>
        <el-menu-item index="4">
          <el-icon><setting /></el-icon>
          <span>Navigator Four</span>
        </el-menu-item>
      </el-menu>

导入到menu.vue中

<script lang="ts" setup>
// 引入组件
​
​
</script>
<template>
     <el-menu
        active-text-color="#ffd04b"
        background-color="#545c64"
        class="el-menu-vertical-demo"
        default-active="2"
        text-color="#fff"
      >
        <el-sub-menu index="1">
          <template #title>
            <el-icon><location /></el-icon>
            <span>Navigator One</span>
          </template>
          <el-menu-item-group title="Group One">
            <el-menu-item index="1-1">item one</el-menu-item>
            <el-menu-item index="1-2">item two</el-menu-item>
          </el-menu-item-group>
          <el-menu-item-group title="Group Two">
            <el-menu-item index="1-3">item three</el-menu-item>
          </el-menu-item-group>
          <el-sub-menu index="1-4">
            <template #title>item four</template>
            <el-menu-item index="1-4-1">item one</el-menu-item>
          </el-sub-menu>
        </el-sub-menu>
        <el-menu-item index="2">
          <el-icon><icon-menu /></el-icon>
          <span>Navigator Two</span>
        </el-menu-item>
        <el-menu-item index="3" disabled>
          <el-icon><document /></el-icon>
          <span>Navigator Three</span>
        </el-menu-item>
        <el-menu-item index="4">
          <el-icon><setting /></el-icon>
          <span>Navigator Four</span>
        </el-menu-item>
      </el-menu>
</template>
<style scoped></style>

在layout下的index.vue中引用

<script lang="ts" setup>
// 引用Header和Menu的组件
import HeaderVue from './header/Header.vue'
import MenuVue from './menu/Menu.vue'
</script><template>
    <el-container class="layout">
      <el-aside class="aside" width="200px"><MenuVue></MenuVue></el-aside>
      <el-container>
        <el-header class="header"><HeaderVue></HeaderVue></el-header>
        <el-main class="main">Main</el-main>
      </el-container>
    </el-container>
</template><style scoped>
.layout{
  height: 100%;
}
.aside{
    background-color: antiquewhite;
}
.header{
    background-color: aquamarine;
}
.main{
    background-color: azure;
}
</style>

此时我们就可以看到页面变化

image.png

对menu简单修改下

<script lang="ts" setup></script>
<template>
     <el-menu
        active-text-color="#ffd04b"
        background-color="#545c64"
        class="el-menu-vertical-demo"
        default-active="2"
        text-color="#fff"
      >
        <el-sub-menu index="1">
          <template #title>
            <el-icon><location /></el-icon>
            <span>组1</span>
          </template>
            <el-menu-item index="1-1">功能1</el-menu-item>
            <el-menu-item index="1-2">功能2</el-menu-item>         
            <el-menu-item index="1-3">功能3</el-menu-item>
        </el-sub-menu>
        <el-sub-menu index="2">
          <template #title>
            <el-icon><location /></el-icon>
            <span>组2</span>
          </template>
            <el-menu-item index="1-1">功能1</el-menu-item>
            <el-menu-item index="1-2">功能2</el-menu-item>         
            <el-menu-item index="1-3">功能3</el-menu-item>
        </el-sub-menu>
      </el-menu>
</template>
<style scoped>
.el-menu-item{
    display: block;
    text-align: center;
}
</style>

结果为:

image.png

一般来说菜单是动态生成的,后面也会演示

6.2 添加侧边栏的Logo部分

在menu中新建一个MenuLogo.vue

<script lang="ts" setup></script>
<template>
    <div class="logo">
        <!-- 图片 -->
        <img src="../../assets/vue.svg" alt="Logo">
        <span class="title">信息管理系统</span>
    </div>
</template>
<style scoped></style>

将MenuLogo.vue导入到Menu.vue中

<script lang="ts" setup>
// 导入组件
import MenuLogoVue from "./MenuLogo.vue";
​
</script>
<template>
 <!-- Logo区域 -->
<MenuLogoVue></MenuLogoVue>
</template>

可以看到效果如下 logo可以自行选择喜欢的图案

image.png 再给menu.vue加点细节

<script lang="ts" setup>
// 导入vue
import { ref,computed } from 'vue';
import MenuItemVue from './MenuItem.vue';
import MenuLogoVue from './MenuLogo.vue';
// 定义一个响应式的变量
// let isCollapse = ref(false);
import { useStore } from 'vuex'
// 获取当前vuex中的store对象
const store = useStore()
​
// 获取store->state中的collapse值
const isCollapse = computed(() => {
  return store.getters['getCollapse']
})
​
​
</script>
<template>
<!-- Logo区域 -->
<MenuLogoVue v-if="!isCollapse" class="layout-logo" ></MenuLogoVue>
<!-- 侧边栏导航 -->
    <el-menu
        active-text-color="#ffd04b"
        background-color="#304156"
        class="el-menu-vertical-demo"
        default-active="2"
        text-color="#fff"
        :collapse = "isCollapse"
        router
      >
        <MenuItemVue></MenuItemVue>
      </el-menu>
</template>
<style scoped>
.el-menu-item {
  display: block;
  text-align: center;
}
​
.el-menu-vertical-demo:not(.el-menu--collapse) {
  width: 230px;
  min-height: 400px;
}
​
.el-menu {
  border-right: none;
}
​
.el-menu-item {
  color: #f4f4f5 !important;
}
​
:deep(.el-sub-menu .el-sub-menu__title) {
  color: #f4f4f5 !important;
}
/* .el-submenu .is-active .el-submenu__title {
  border-bottom-color: #1890ff;
} */
:deep(.el-menu .el-menu-item) {
  color: #bfcbd9;
}
​
/* 菜单点中文字的颜色 */
:deep(.el-menu-item.is-active) {
  color: #409eff !important;
}
/* 当前打开菜单的所有子菜单颜色 */
:deep(.is-opened .el-menu-item) {
  background-color: #1f2d3d !important;
}
/* 鼠标移动菜单的颜色 */
:deep(.el-menu-item:hover) {
  background-color: #001528 !important;
}
​
/* Logo CSS部分的动画 */
@keyframes logoAnimation {
  0% {
    transform: scale(0);
  }
  50% {
    transform: scale(1);
  }
  100% {
    transform: scale(1);
  }
}
​
.layout-logo {
  animation: logoAnimation 1s ease-out;
}
</style>

MenuLogo.vue加点细节

<style scoped>
.logo{
    background-color: #2b2f3a;
    height: 50px;
    border: none;
    line-height: 50px;
    display: flex;
    align-items: center;
    padding-left: 15px;
    color: #FFF;
}
.logo img{
    width: 32px;
    height: 32px;
    margin-right: 12px;
}
.logo span{
    font-weight: 600;
    line-height: 50px;
    font-size: 16px;
    font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
    vertical-align: middle;
}
</style>

把index.vue中的200px改成auto

image.png

此外之前为了展示页面的底色也不要了,未来配合再修改个底色

<style scoped>
.layout{
  height: 100%;
}
.aside{
  background-color: #304156;
}
</style>

修改页面后,效果如何

image.png

6.3 动态生成侧边栏菜单

修复个小bug

image.png

这样侧边栏会好看很多

image.png 侧边栏有可能是从数据库取的,这边说明下动态如何生成

创建MenuItem.vue

<script lang="ts" setup></script>
<template>
     <el-sub-menu index="1">
          <template #title>
            <el-icon><location /></el-icon>
            <span>组1</span>
          </template>
            <el-menu-item index="1-1">功能1</el-menu-item>
            <el-menu-item index="1-2">功能2</el-menu-item>         
            <el-menu-item index="1-3">功能3</el-menu-item>
        </el-sub-menu>
        <el-sub-menu index="2">
          <template #title>
            <el-icon><location /></el-icon>
            <span>组2</span>
          </template>
            <el-menu-item index="2-1">功能1</el-menu-item>
            <el-menu-item index="2-2">功能2</el-menu-item>         
            <el-menu-item index="2-3">功能3</el-menu-item>
        </el-sub-menu>
</template>
<style scoped>
    .el-menu-item{
    display: block;
    text-align: center;
    padding-right: 80px;
}
</style>

引入下:

image.png

发现效果和之前一样的。进行修改

<script lang="ts" setup>
// 导入基本模块
import {reactive} from "vue";
​
// 初始化数据
let menuList = reactive([
  {
    path: "/",
    meta: {
      title: "首页",
      icon: "HomeFilled",
    },
  },
  {
    path: "/datasys",
    meta: {
      title: "数据管理",
      icon: "UserFilled",
    },
    children: [
      {
        path: "/datasys/DrawingManagementSystem",
        meta: {
          title: "图纸信息",
          icon: "VideoCameraFilled",
        },
      },
      {
        path: "/datasys/ProjectSystem",
        meta: {
          title: "项目管理",
          icon: "OfficeBuilding",
        },
      },
      {
        path: "/datasys/FileSystem",
        meta: {
          title: "资料存储",
          icon: "TakeawayBox",
        },
      },
    ],
  },
  {
    path: "/user",
    meta: {
      title: "用户角色",
      icon: "Ticket",
    },
    children: [
      {
        path: "/user/account",
        meta: {
          title: "登录账号",
          icon: "Coordinate",
        },
      },
      {
        path: "/user/roles",
        meta: {
          title: "角色信息",
          icon: "CreditCard",
        },
      },
      {
        path: "/user/menu",
        meta: {
          title: "菜单管理",
          icon: "DeleteLocation",
        },
      },
      {
        path: "/user/permission",
        meta: {
          title: "权限管理",
          icon: "Goods",
        },
      },
    ],
  },
]);
</script>
<template>
<template v-for="menu in menuList">
      <!-- 如果有children并且children不为空,表示是二级菜单数据,先新建el-sub-menu -->
      <el-sub-menu v-if="menu.children && menu.children.length > 0" :index="menu.path">
        <template #title style="padding-left: 40px">
          <el-icon>
            <component class="icons" :is="menu.meta.icon"></component>
          </el-icon>
          <span >{{ menu.meta.title }}</span>
        </template>
  
        <!-- 展示二级菜单的第二层 -->
        <template v-for="child in menu.children">
          <el-menu-item :index="child.path">
            <el-icon>
              <component class="icons" :is="child.meta.icon"></component>
            </el-icon>
            <span>{{ child.meta.title }}</span>
          </el-menu-item>
        </template>
      </el-sub-menu>
      <!-- 否则是一级菜单,直接新建el-sub-item -->
      <el-menu-item v-else :index="menu.path">
        <el-icon>
          <component class="icons" :is="menu.meta.icon"></component>
        </el-icon>
        <span>{{ menu.meta.title }}</span>
      </el-menu-item>
    </template>
</template>
<style scoped>
.el-menu-item{
    display: block;
    text-align: center;
    padding-right: 80px;
}
</style>

效果为:

image.png

6.4 为侧边栏菜单加图标

点击官网找到图标区域

image.png

由于我们在上面动态生成中,已经提前加入需要的图标样式

image.png

我们只需要全局引入图标就好了

先安装包

image.png

对layout的index.vue进行修改

image.png

image.png

我们可以看到主页面果然出现了图片

但是想一想如果都是这样导入,未免有点繁琐。我们可以批量导入

对main.ts进行修改:

import { createApp } from 'vue' // 导入CreateApp的函数
import App from './App.vue' // 引入App.vue -- 模块的主入口文件!
import ElementPlus from 'element-plus' // 引入ElementPlus
import 'element-plus/dist/index.css' // 引入ElementPlus的CSS
import router from './router' // 导入router文件
import * as Icons from '@element-plus/icons-vue' // 导入所有的icon的图标// 创建一个app
const app = createApp(App)
app.use(router).use(router).use(ElementPlus).mount('#app') // 使用vue中的CreateApp方法创建一个app.vue的组件,并放置到index.html使用vue中的CreateApp方法创建一个app.vue的组件,并放置到index.html的id为app的div中
// 遍历所有的icon,把每个icon图标以组件的方式加载到app中 
Object.keys(Icons).forEach((key) =>{
    app.component(key, Icons[key as keyof typeof Icons])
})

页面就批量显示出来了

image.png

6.5 Header区域的基本布局

先创建三个模块

image.png

在Header.vue中导入新建的组件

<script lang="ts" setup>
// 引入组件import BredCumVue from "./BredCum.vue";
import CollaspeVue from "./Collaspe.vue";
import UserInfoVue from "./UserInfo.vue";
​
</script>
<template>
   <CollaspeVue></CollaspeVue>
   <BredCumVue></BredCumVue>
   <UserInfoVue></UserInfoVue>
</template>
<style scoped></style>

对Collapse.vue进行修改

<script lang="ts" setup></script>
<template>
    <!-- 使用全局图标 -->
    <el-icon>
        <component class="icons" is="Fold"></component>
    </el-icon>
</template>
<style scoped>
    .el-icon{
    font-size: 22px;
    margin-right: 20px;
}
</style>

image.png

对index.vue进行修改(对上边框修改)

<script lang="ts" setup>
// 引用Header和Menu的组件
import HeaderVue from './header/Header.vue'
import MenuVue from './menu/Menu.vue'</script><template>
    <el-container class="layout">
      <el-aside class="aside" width="auto"><MenuVue></MenuVue></el-aside>
      <el-container>
        <el-header class="header"><HeaderVue></HeaderVue></el-header>
        <el-main class="main">Main
        </el-main>
      </el-container>
    </el-container>
</template><style scoped>
.layout{
  height: 100%;
}
.aside{
  background-color: #304156;
}
.header{
  height: 50px;
    border-bottom: 1px solid #e5e5e5;
    display: flex;
    align-items: center;
    justify-content: space-between;
}
</style>

效果为

image.png

导入面包屑

image.png

BredCum.vue修改为:

<script lang="ts" setup></script>
<template>
  <el-breadcrumb separator="/">
    <el-breadcrumb-item>A1</el-breadcrumb-item>
    <el-breadcrumb-item>B1</el-breadcrumb-item>
    <el-breadcrumb-item>C1</el-breadcrumb-item>
​
  </el-breadcrumb>
</template>
<style scoped></style>

对Useinfo.vue进行修改

实际上就是个下拉菜单

<script lang="ts" setup></script>
<template>
    <el-dropdown>
      <span class="el-dropdown-link">
        <el-icon style="margin-right:10px;"><user-filled /></el-icon>
        <!-- <span>{{username}}</span> -->
        <span>管理员</span>
        <el-icon class="el-icon--right" style="margin-left:10px;">
          <arrow-down />
        </el-icon>
      </span>
      <template #dropdown>
        <el-dropdown-menu>
          <el-dropdown-item>用户信息</el-dropdown-item>
          <el-dropdown-item>更改密码</el-dropdown-item>
          <el-dropdown-item>安全退出</el-dropdown-item>
        </el-dropdown-menu>
      </template>
    </el-dropdown>
</template>
<style scoped></style>

我们需要把面包屑和缩菜单的放到一个div下 这样更好看点

<script lang="ts" setup>
// 引入组件import BredCumVue from "./BredCum.vue";
import CollaspeVue from "./Collaspe.vue";
import UserInfoVue from "./UserInfo.vue";
​
</script>
<template>
   <div style="display:flex;align-items:center;">
        <CollaspeVue></CollaspeVue>
        <BredCumVue></BredCumVue>
    </div>
   <UserInfoVue></UserInfoVue>
</template>
<style scoped></style>

image.png

6.6 侧边栏收缩

对Menu.vue进行简单修改,我们就会发现页面发生了变化。

image.png

变化:

image.png

修改下:

<script lang="ts" setup>
// 导入vue
import { ref } from "vue";
// 导入组件
import MenuItemVue from "./MenuItem.vue";
import MenuLogoVue from "./MenuLogo.vue";
// 定义一个响应式的变量
let isCollapse = ref(true);
​
</script>
<template>
 <!-- Logo区域 -->
<MenuLogoVue class="layout-logo" style="display:none;"></MenuLogoVue>
 <!-- 侧边栏导航 -->
     <el-menu
        active-text-color="#ffd04b"
        background-color="#30415"
        class="el-menu-vertical-demo"
        default-active="2"
        text-color="#fff"
        :collapse = isCollapse
      >
      <MenuItemVue></MenuItemVue>
      </el-menu>

image.png

这个时候发现我们是希望通过Collapse.vue点击后,发生menu.vue的菜单收缩。

可以简单修改下:

<script lang="ts" setup>
// 导入vue
import { ref } from 'vue'
// 导入vue组件
import Components from '../../components/Index.vue';
​
let isCollapse = ref(false)
​
// 改变值的isCollapsge值
const changeCollapse=()=>{
    // 改变值
    isCollapse.value = ! isCollapse.value
    console.log(isCollapse.value)
};
</script>
<template>
    <!-- 使用全局图标 -->
    <el-icon>
        <component class="icons" is="Fold" @click="changeCollapse"></component>
    </el-icon>
</template>
<style scoped>
    .el-icon{
    font-size: 22px;
    margin-right: 20px;
}
</style>

这个时候我们就需要组件传值

父子组件——直接传值

兄弟组件——vuex

vuex是基于vue框架的一个状态管理库。可以管理复杂应用的数据状态,比如兄弟组件的通信、多层嵌套的组件的传值等等。

vuex有这么几个核心概念——State、Getter、Mutation、Action、Module。

store——store是vuex的核心对象,它记录了整个vue应用的数据状态以及操作数据的方式。

state——就是store操作的数据状态对象。

mutation——提供了一种简单易用的同步的方式改变state的状态,

getter——获取state中数据对象

6.7 vuex安装和store对象的创建、注册

npm install vuex@4.0.2

在src下新建一个store/index.ts

// 导入vuex模块
import { createStore } from "vuex"// 定义一个存储数据的结构 ——实体类
export interface MyState {
    collapse:boolean, // 控制侧边栏的收缩
}
​
// 创建一个store对象
const store = createStore<MyState>({
    // state --- 存储了具体的值
    state:{
        collapse:false,
    },
    // mutations --- 修改state中值的函数
    mutations:{
        setCollapse(state:MyState,collapse:boolean){
            state.collapse = collapse;
        }
    },
    // getter --- 获取state值中的函数
    getters:{
        getCollapse(state:MyState){
            return state.collapse;
        }
    }
})
​
// 暴露
export default store

这里将 store 对象暴露出来,使得其他组件可以通过 import 导入该对象,以便在其他组件中使用存储在 Vuex store 中的数据。如果没有暴露 store 对象,则其他组件无法访问该对象,也就无法使用其中存储的数据。

把我们简历的遍历全局应用

main.ts

import { createApp } from 'vue' // 导入CreateApp的函数
import App from './App.vue' // 引入App.vue -- 模块的主入口文件!
import ElementPlus from 'element-plus' // 引入ElementPlus
import 'element-plus/dist/index.css' // 引入ElementPlus的CSS
import router from './router' // 导入router文件
import * as Icons from '@element-plus/icons-vue' // 导入所有的icon的图标
import store from './store' // 导入创建的store对象// 创建一个app
const app = createApp(App)
app.use(store).use(router).use(router).use(ElementPlus).mount('#app') // 使用vue中的CreateApp方法创建一个app.vue的组件,并放置到index.html使用vue中的CreateApp方法创建一个app.vue的组件,并放置到index.html的id为app的div中
// 遍历所有的icon,把每个icon图标以组件的方式加载到app中 
Object.keys(Icons).forEach((key) =>{
    app.component(key, Icons[key as keyof typeof Icons])
})

6.8 完成侧边栏收缩的功能

先在menu中把组件引用进来

<script lang="ts" setup>
// 导入vue
import { ref,computed } from "vue";
// 导入组件
import MenuItemVue from "./MenuItem.vue";
import MenuLogoVue from "./MenuLogo.vue";
// 导入usestore的方法
import { useStore } from 'vuex'
// 获取当前vuex中的store对象
const store = useStore()
​
// 获取store->state中的collapse值
const isCollapse = computed(()=>{
  return store.getters['getCollapse']
})
​
</script>
<template>
 <!-- Logo区域 -->
<MenuLogoVue v-if="!isCollapse" class="layout-logo" ></MenuLogoVue>
 <!-- 侧边栏导航 -->
     <el-menu
        active-text-color="#ffd04b"
        background-color="#304156"
        class="el-menu-vertical-demo"
        default-active="2"
        text-color="#fff"
        :collapse = "isCollapse"
        router
      >
      <MenuItemVue></MenuItemVue>
      </el-menu>
</template>
<style scoped>
.el-menu-item{
    display: block;
    text-align: center;
}
.el-menu-vertical-demo:not(.el-menu--collapse) {
  width: 230px;
  min-height: 400px;
}
​
.el-menu {
  border-right: none;
}
​
.el-menu-item {
  color: #f4f4f5 !important;
}
​
:deep(.el-sub-menu .el-sub-menu__title) {
  color: #f4f4f5 !important;
}
/* .el-submenu .is-active .el-submenu__title {
  border-bottom-color: #1890ff;
} */
:deep(.el-menu .el-menu-item) {
  color: #bfcbd9;
}
​
/* 菜单点中文字的颜色 */
:deep(.el-menu-item.is-active) {
  color: #409eff !important;
}
/* 当前打开菜单的所有子菜单颜色 */
:deep(.is-opened .el-menu-item) {
  background-color: #1f2d3d !important;
}
/* 鼠标移动菜单的颜色 */
:deep(.el-menu-item:hover) {
  background-color: #001528 !important;
}
​
/* Logo CSS部分的动画 */
@keyframes logoAnimation {
  0% {
    transform: scale(0);
  }
  50% {
    transform: scale(1);
  }
  100% {
    transform: scale(1);
  }
}
​
.layout-logo {
  animation: logoAnimation 1s ease-out;
}
</style>

head/collaspe.vue

<script lang="ts" setup>
// 导入vue
import { ref,computed } from 'vue'
// 导入vue组件
import Components from '../../components/Index.vue';
// 导入useStore
import {useStore} from 'vuex'
// 获取store对象
const store = useStore();
// 获取collapse值
const isCollapse = computed(()=>{
    return store.getters['getCollapse']
})
</script>
<template>
    <!-- 使用全局图标 -->
    <el-icon>
        <component class="icons" is="Fold" @click="changeCollapse"></component>
    </el-icon>
</template>
<style scoped>
    .el-icon{
    font-size: 22px;
    margin-right: 20px;
}
</style>

因为我们需要点击后图标还要变换 所以我们需要用三元操作符

表达式?值1:值2

使用三元表达式 全局导入图标就没用了,需要单独导入

<script lang="ts" setup>
// 导入vue
import { ref,computed } from 'vue'
// 导入图标
import {Fold,Expand} from '@element-plus/icons-vue'
// 导入vue组件
import Components from '../../components/Index.vue';
// 导入useStore
import {useStore} from 'vuex'
// 获取store对象
const store = useStore();
// 定义一个响应式的变量
const localCollapse = ref(false);
// 获取collapse值
const isCollapse = computed(()=>{
    // 赋值localCollapse
    localCollapse.value = store.getters["getCollapse"];
    return store.getters['getCollapse'];
})
​
// 定义函数实现修改
const changeCollapes =()=>{
    // 更改localCollapse的值--取反
    localCollapse.value = !localCollapse.value;
    // 修改Store->state中的collapse值
    store.commit('setCollapse',localCollapse.value)
}
</script>
<template>
    <!-- 使用全局图标 -->
    <el-icon>
        <component class="icons" :is="isCollapse ? Expand:Fold" @click="changeCollapes"></component>
    </el-icon>
</template>
<style scoped>
    .el-icon{
    font-size: 22px;
    margin-right: 20px;
}
</style>

这样就可以通过点击完成收缩。

image.png

6.9 实现侧边栏的导航

首先建立所有的分页vue

image.png

那么我们的路由就要绑定这些vue

router/index.ts修改为:

// 导入组件
import { createRouter,createWebHistory,RouteRecordRaw } from "vue-router"
// 导入组件
import Layout from '../layout/Index.vue'
​
// 创建路由匹配的数据集合 -- Array
const routes : Array<RouteRecordRaw> = [
​
    // 首页 ———> /dashboard/
    {
        path:'/',
        component:Layout,
        name:'Layout',
        redirect:'/dashboard', //自动跳转
        children:[
            {
                path: '/dashboard',
                component: ()=>import('../views/index/Dashboard.vue'),
                name:'Dashboard',
                meta:{
                    title:'首页'
                },
            }
        ]
    },
    // 数据管理【图纸管理系统、项目管理系统、资料存储系统】
    {
        path:'/datasys',
        component:Layout,
        name:'Datasys',
        meta:{
            title:'数据管理'
        },
        children:[
            {
                path:'/datasys/DrawingManagementSystem',
                component:()=>import('../views/datasys/DrawingMS.vue'),
                name:'DrawingMS',
                meta:{
                    title:'图纸管理系统'
                },
            },
            {
                path:'/datasys/ProjectSystem',
                component:()=>import('../views/datasys/ProjectS.vue'),
                name:'ProjectS',
                meta:{
                    title:'项目管理系统'
                },
            },
            {
                path:'/datasys/FileSystem',
                component:()=>import('../views/datasys/FileS.vue'),
                name:'FileS',
                meta:{
                    title:'资料存储系统'
                },
            },
        ]
    },
​
    // 用户角色【登录账号、角色信息、菜单管理、权限管理】
    {
        path:'/user',
        component:Layout,
        name:'User',
        meta:{
            title:'用户角色'
        },
        children:[
            {
                path: '/user/account',
                component: ()=>import('../views/user/Account.vue'),
                name:'Account',
                meta:{
                    title:'登陆账号'
                },
            },
            {
                path: '/user/menu',
                component: ()=>import('../views/user/Menu.vue'),
                name:'Menu',
                meta:{
                    title:'角色信息'
                },
            },
            {
                path: '/user/permission',
                component: ()=>import('../views/user/Permission.vue'),
                name:'Permission',
                meta:{
                    title:'菜单管理'
                },
            },
            {
                path: '/user/roles',
                component: ()=>import('../views/user/Roles.vue'),
                name:'Roles',
                meta:{
                    title:'权限管理'
                },
            },
        ]
    },
]
​
// 创建一个vue-router的对象
const router = createRouter({
    history:createWebHistory(),
    routes,
})
​
// 暴露
export default router

在menu/index.vue中加main标签加入

<script lang="ts" setup>
// 引用Header和Menu的组件
import HeaderVue from './header/Header.vue'
import MenuVue from './menu/Menu.vue'</script><template>
    <el-container class="layout">
      <el-aside class="aside" width="auto"><MenuVue></MenuVue></el-aside>
      <el-container>
        <el-header class="header"><HeaderVue></HeaderVue></el-header>
        <el-main class="main"><router-view></router-view>
        </el-main>
      </el-container>
    </el-container>
</template><style scoped>
.layout{
  height: 100%;
}
.aside{
  background-color: #304156;
}
.header{
  height: 50px;
    border-bottom: 1px solid #e5e5e5;
    display: flex;
    align-items: center;
    justify-content: space-between;
}
</style>

这样我们就可以看到

image.png

切换效果 并显示我们的vue标签

image.png

views/index/Dashboard.vue

<script lang="ts" setup>
</script><template>
    <div class="container">
    <div class="center">
         
         <h1>欢迎使用GVE信息管理系统</h1>
    </div>
    </div>
</template><style scoped>
.container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 50vh;
}
​
.center {
  text-align: center;
}
</style>

views/datasys/DrawingMS.vue

<script lang="ts" setup>
</script><template>
    <h1>DrawingManagementSystem</h1>
</template><style scoped></style>

6.10 自动生成面包屑

既然我们路由没问题了,那就可以更新面包屑了

GveInfomationSystemFE\src\layout\header\BredCum.vue

<script lang="ts" setup>
// 导入vue
import {Ref,ref,watch} from 'vue'
// 定义useRoute模块
import { useRoute,RouteLocationMatched } from "vue-router";
​
// 定义一个面包屑的集合
const tabs:Ref<RouteLocationMatched[]> = ref([])
​
// 获取当前路由的信息
const route = useRoute();
​
// 定义一个函数getBredCum
const getBredCum = () => {
  // 过滤路由匹配的信息 --route.matched --meta,meta.title
  let matched = route.matched.filter((item) => item.meta && item.meta.title);
  // 获取matched中的第一条
  const first = matched[0]
  // 判断是不是首页
  if(first.path !== '/dashboard'){
    matched = [{path:'/dashboard',meta:{'title':'首页'}}as any].concat(matched)
  }
  // 把拼接好的值给tabs
  tabs.value = matched;
};
​
// 自动调用getBredCum
getBredCum();
​
// 当请求的url的path变化,自动执行getBredCum
watch(()=>route.path,()=>getBredCum());
</script>
<template>
  <el-breadcrumb separator="/">
     <el-breadcrumb-item v-for="item in tabs">
      {{item.meta.title}}
    </el-breadcrumb-item>
​
  </el-breadcrumb>
</template>
<style scoped></style>

image.png

6.11 图纸信息布局

对DrawingMS.vue进行修改

<script lang="ts" setup>
import { Tree } from 'element-ui';
​
// 定义树的数据
const treeData = [
  {
    label: 'Level one 1',
    children: [
      {
        label: 'Level two 1-1',
        children: [
          {
            label: 'Level three 1-1-1',
          },
        ],
      },
    ],
  },
  {
    label: 'Level one 2',
    children: [
      {
        label: 'Level two 2-1',
        children: [
          {
            label: 'Level three 2-1-1',
          },
        ],
      },
      {
        label: 'Level two 2-2',
        children: [
          {
            label: 'Level three 2-2-1',
          },
        ],
      },
    ],
  },
  
];
​
</script><template>
    <h1>图纸管理系统页面</h1>
  <div class="container">
    <div class="tree-container">
      <el-tree :data="treeData"></el-tree>
    </div>
     <h1>表格区域</h1>
  </div>
</template><style scoped>
.container {
  display: flex;
}
​
.tree-container {
  width: 200px;
  padding: 10px;
}
​
</style>

image.png

加入搜索部分:

<script lang="ts" setup>
import { Tree } from "element-ui";
// 导入vue
import { ref,reactive } from 'vue'// 定义存储的集合=====
var Data = reactive({
  // 输入的查询条件
  q_str:ref(""),
  // 存储从后台获取的所有传感器信息
  sensorOptions:reactive([
      {value:1,label:'角度传感器'},
      {value:2,label:'大气压力传感器'},
      {value:3,label:'温度传感器'},
  ]),
  // 存储选择院系后的值
  sensorSelected:ref(""),
  // 存储从后台获取的所有项目
  projectOptions:reactive([
      {value:1,label:'项目A'},
      {value:2,label:'项目B'},
      {value:3,label:'项目C'},
  ]),
  projectSelected:ref(""),
  // 存储从后台获取的所有资料
  dataOptions:reactive([
      {value:1,label:'资料A'},
      {value:2,label:'资料B'},
      {value:3,label:'资料C'},
  ]),
  dataSelected:ref(""),
​
})
// 定义树的数据
const treeData = [
  {
    label: "Level one 1",
    children: [
      {
        label: "Level two 1-1",
        children: [
          {
            label: "Level three 1-1-1",
          },
        ],
      },
    ],
  },
  {
    label: "Level one 2",
    children: [
      {
        label: "Level two 2-1",
        children: [
          {
            label: "Level three 2-1-1",
          },
        ],
      },
      {
        label: "Level two 2-2",
        children: [
          {
            label: "Level three 2-2-1",
          },
        ],
      },
    ],
  },
];
</script><template>
  <div class="container">
    <div class="sidebar">
      <!-- 侧边栏 -->
      <div class="tree-container">
        <el-tree :data="treeData"></el-tree>
      </div>
    </div>
    <div class="main">
      <!-- 查询区域 -->
      <el-form :inline="true" class="demo-form-inline" style="display: flex">
        <el-form-item label="查询条件:">
          <el-input v-model="Data.q_str" placeholder="请输入查询条件" clearable/>
        </el-form-item>
        <el-form-item label="传感器:">
          <el-select v-model="Data.sensorSelected" placeholder="请选择传感器" clearable>
            <el-option 
            v-for="item in Data.sensorOptions"
            :key="item.value"
            :label="item.label"
            :value="item.value" />
          </el-select>
        </el-form-item>
        <el-form-item label="项目:">
          <el-select v-model="Data.projectSelected" placeholder="请选择项目" clearable>
             <el-option 
            v-for="item in Data.projectOptions"
            :key="item.value"
            :label="item.label"
            :value="item.value" />
          </el-select>
        </el-form-item>
        <el-form-item label="资料:">
          <el-select v-model="Data.dataSelected" placeholder="请选择资料" clearable>
            <el-option 
            v-for="item in Data.dataOptions"
            :key="item.value"
            :label="item.label"
            :value="item.value" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary">
          <el-icon><component class="icons" is="Search"></component></el-icon>
          <span>查询</span>
          </el-button>
          <el-button type="primary">
          <el-icon><component class="icons" is="List"></component></el-icon>
          <span>全部</span>
          </el-button>
          <el-button type="primary">
          <el-icon><component class="icons" is="CirclePlus"></component></el-icon>
          <span>添加</span>
          </el-button>
        </el-form-item>
      </el-form>
    </div>
  </div>
</template><style scoped>
.container {
  display: flex;
}
​
.sidebar {
  width: 200px;
  padding: 5px;
}
​
.main {
  flex: 1;
  padding: 10px;
}
</style>

效果为:

image.png

加入表格和分页

<script lang="ts" setup>
import { Tree } from "element-ui";
// 导入vue
import { ref,reactive } from 'vue'
// 导入图标
import {Edit,More,Delete} from '@element-plus/icons-vue'// 定义存储的集合=====
var Data = reactive({
  // =========== 查询区域 =============
  // 输入的查询条件
  q_str:ref(""),
  // 存储从后台获取的所有传感器信息
  sensorOptions:reactive([
      {value:1,label:'角度传感器'},
      {value:2,label:'大气压力传感器'},
      {value:3,label:'温度传感器'},
  ]),
  // 存储选择院系后的值
  sensorSelected:ref(""),
  // 存储从后台获取的所有项目
  projectOptions:reactive([
      {value:1,label:'项目A'},
      {value:2,label:'项目B'},
      {value:3,label:'项目C'},
  ]),
  projectSelected:ref(""),
  // 存储从后台获取的所有资料
  dataOptions:reactive([
      {value:1,label:'资料A'},
      {value:2,label:'资料B'},
      {value:3,label:'资料C'},
  ]),
  dataSelected:ref(""),
  // =========== 表格区域 =============
  drawing:reactive([
    {material_code:'1011',drawing_name:'设计图纸',drawing_spec:'GVE1',drawing_page:'1',drawing_client_id:'D1',
    drawing_version:'0001',drawing_remark:'备注',modified:'2023-05-24 15:07:32'},
    {material_code:'1011',drawing_name:'设计图纸',drawing_spec:'GVE1',drawing_page:'1',drawing_client_id:'D1',
    drawing_version:'0001',drawing_remark:'备注',modified:'2023-05-24 15:07:32'}
  ]),
   // ====================== 分页 =======================
    // 当前页
    currentPage: ref(1),
    // 每页大小
    pageSize: ref(15),
    // 所有的记录条数
    total: ref(0),
});
//分页中修改pagesize
const handleSizeChange=(size:any)=>{
​
}
//分页中修改pagepage
const handleCurrentChange=(page:any)=>{
​
}
// 定义树的数据
const treeData = [
  {
    label: "Level one 1",
    children: [
      {
        label: "Level two 1-1",
        children: [
          {
            label: "Level three 1-1-1",
          },
        ],
      },
    ],
  },
  {
    label: "Level one 2",
    children: [
      {
        label: "Level two 2-1",
        children: [
          {
            label: "Level three 2-1-1",
          },
        ],
      },
      {
        label: "Level two 2-2",
        children: [
          {
            label: "Level three 2-2-1",
          },
        ],
      },
    ],
  },
];
</script><template>
  <div class="container">
    <div class="sidebar">
      <!-- 侧边栏 -->
      <div class="tree-container">
        <el-tree :data="treeData"></el-tree>
      </div>
    </div>
    <div class="main">
      <!-- 1.查询区域 -->
      <el-form :inline="true" class="demo-form-inline" style="display: flex">
        <el-form-item label="查询条件:">
          <el-input v-model="Data.q_str" placeholder="请输入查询条件" clearable/>
        </el-form-item>
        <el-form-item label="传感器:">
          <el-select v-model="Data.sensorSelected" placeholder="请选择传感器" clearable>
            <el-option 
            v-for="item in Data.sensorOptions"
            :key="item.value"
            :label="item.label"
            :value="item.value" />
          </el-select>
        </el-form-item>
        <el-form-item label="项目:">
          <el-select v-model="Data.projectSelected" placeholder="请选择项目" clearable>
             <el-option 
            v-for="item in Data.projectOptions"
            :key="item.value"
            :label="item.label"
            :value="item.value" />
          </el-select>
        </el-form-item>
        <el-form-item label="资料:">
          <el-select v-model="Data.dataSelected" placeholder="请选择资料" clearable>
            <el-option 
            v-for="item in Data.dataOptions"
            :key="item.value"
            :label="item.label"
            :value="item.value" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary">
          <el-icon><component class="icons" is="Search"></component></el-icon>
          <span>查询</span>
          </el-button>
          <el-button type="primary">
          <el-icon><component class="icons" is="List"></component></el-icon>
          <span>全部</span>
          </el-button>
          <el-button type="primary">
          <el-icon><component class="icons" is="CirclePlus"></component></el-icon>
          <span>添加</span>
          </el-button>
        </el-form-item>
      </el-form>
      <!-- 2.表格部分 -->
      <el-table :data="Data.drawing" border style="width: 100%" :header-cell-style="{ backgroundColor:'#409EFF',color:'#FFF',fontSize:'14px' }">
      <el-table-column label="序号" type="index" align="center" width="60" />
      <el-table-column prop="material_code" label="物料编号" width="180" />
      <el-table-column prop="drawing_name" label="材料名称" width="160" />
      <el-table-column prop="drawing_spec" label="规格/图纸号" width="180" />
      <el-table-column prop="drawing_page" label="图纸页数" width="60" />
      <el-table-column prop="drawing_client_id" label="客户编号" width="180" />
      <el-table-column prop="drawing_version" label="版本号" width="70" />
      <el-table-column prop="drawing_remark" label="备注" width="180" />
      <el-table-column prop="modified" label="最后上传日期" width="160" />
      <el-table-column label="操作" align="center">
        <el-button type="primary" :icon="More" circle size="small"/>
        <el-button type="warning" :icon="Edit" circle size="small"/>
        <el-button type="danger" :icon="Delete" circle size="small"/>
      </el-table-column>
      </el-table>
​
      <!-- 3.分页 -->
      <!-- currentPage4【当前页】 pageSize4【每页大小】 total【记录条数】
handleSizeChange【改变pagesize】
currentPage4【当前页】
-->
      <el-pagination style="margin-top:20px;"
    background
      v-model:current-page="Data.currentPage"
      v-model:page-size="Data.pageSize"
      :page-sizes="[5, 10, 15, 20]"
      layout="total, sizes, prev, pager, next, jumper"
      :total="Data.total"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
/>
    </div>
  </div>
</template><style scoped>
.container {
  display: flex;
}
​
.sidebar {
  width: 200px;
  padding: 5px;
}
​
.main {
  flex: 1;
  padding: 10px;
}
</style>

效果为:

image.png

我们这时候发现页面插件是英文,一般element plus需要国际化

6.12 Element Plus国际化

直接做全局配置就好

在main.ts下

image.png

效果为:

image.png

至此前端页面的布局就完成,后面还有前后端数据交互、数据展示等。我们放在下一章编写

2023.10.7补漏:6.8需要加上

   <!-- Logo区域 -->
<MenuLogoVue v-if="!isCollapse" class="layout-logo" ></MenuLogoVue>
这样就可以实现logo跳跃