项目4:后台管理的开发和使用(前端)

news2024/11/19 22:45:24

项目4:后台管理的开发和使用(前端)

1.npm包管理器的基本学习

2.利用现成后台管理系统开发

3.后台管理系统的路由配置

4.后台管理系统的地址访问配置

5.前后端联调

6.完善积分等级的前端系统

7.对前端系统的全面分析(Vue组件)

项目4:积分等级表接口的开发和使用(前端)

1.npm包管理器基本学习

①npm是什么?

  • npm类似于后端的maven,用于管理前端依赖包的

②npm常用命令

  • npm init -y
    初始化一个项目,生成一个package.json,里面包含依赖管理
  • npm i axios@0.08.x
    i为install的简写,下载axios的具体版本号,放在node_modules
  • npm i -D mockjs
    -D为–save-dev的简写,即开发环境时导入的包,打包时不导入
  • npm i
    如果只有package.json而没有具体的node_modules,可以使用此命令下载包
  • 注意npm修改下载镜像
#经过下面的配置,以后所有的 npm install 都会经过淘宝的镜像地址下载
npm config set registry https://registry.npm.taobao.org 

#查看npm配置信息
npm config list

2.利用现成后台管理系统开发

①vue-element-admin

  • 简化版(提供较少功能组件)
  • 全面版(提供完整的功能组件)

②安装和运行

  • 下载vue-admin-template-permission-control.zip
  • 解压并进入目录
  • 安装依赖并启动
    npm install
    npm run dev

③配置前端页面

  • 禁用ESLint语法检查(过于严格)
  • 使用prettiert格式化配置(单引号格式,无分号格式)
  • vue.config.js中30行禁用ESLint语法检查
lintOnSave: false, 
  • 在根目录下创建.prettierrc文件
{
  "semi": false,
  "singleQuote": true,
  "htmlWhitespaceSensitivity": "ignore"
}
  • 简单修改配置
    修改首页名称
    src/settings.js 第3行处修改页面标题
    在这里插入图片描述
    国际化配置
    rc/main.js 第7行处修改语言(为引入的插件语言而不是网页本身,网页本身组件的名称为英语都是写死的,需要手动修改)
    在这里插入图片描述
    下拉菜单修改
    src/layout/components/Navbar.vue
    在这里插入图片描述
    登录页的修改
    src/views/login/index.vue修改标题为中文和登录为中文并删除无关组件
    在这里插入图片描述
    在这里插入图片描述

3.后台管理系统的路由配置

①简介路由配置

  • 即通过点击对应的路由标题
  • 跳转到对应的模板中

②路由配置

  • 定义模板
    在src/views文件夹下创建core/integral-grade/list.vue和core/integral-grade/form.vue
  • 编写模板内容
    list.vue
<template>
  <div class="app-container">
    积分等级列表
  </div>
</template>

form.vue

<template>
  <div class="app-container">
    积分等级表单
  </div>
</template>
  • 编写路由跳转
    修改 src/router/index.js 文件,重新定义constantRoutes,
import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

//在整个路由中匹配,匹配到了跳转,没有匹配到有*跳转到404
/* Layout */
import Layout from '@/layout'

/**
 * Note: sub-menu only appear when route children.length >= 1
 * Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html
 *
 * hidden: true                   if set true, item will not show in the sidebar(default is false)
 * alwaysShow: true               if set true, will always show the root menu
 *                                if not set alwaysShow, when item has more than one children route,
 *                                it will becomes nested mode, otherwise not show the root menu
 * redirect: noRedirect           if set noRedirect will no redirect in the breadcrumb
 * name:'router-name'             the name is used by <keep-alive> (must set!!!)
 * meta : {
    roles: ['admin','editor']    control the page roles (you can set multiple roles)
    title: 'title'               the name show in sidebar and breadcrumb (recommend set)
    icon: 'svg-name'/'el-icon-x' the icon show in the sidebar
    breadcrumb: false            if set false, the item will hidden in breadcrumb(default is true)
    activeMenu: '/example/list'  if set path, the sidebar will highlight the path you set
  }
 */

/**
 * constantRoutes
 * a base page that does not have permission requirements
 * all roles can be accessed
 */
export const constantRoutes = [
  {
    //路径是/login
    path: '/login',
    //登录页的路由
    component: () => import('@/views/login/index'),
    hidden: true,
  },

  //直接可以进入/404页
  {
    path: '/404',
    component: () => import('@/views/404'),
    hidden: true,
  },

  //只展示首页访问/跳转到/dashboard等于跳转到/src/views/dashboard/index
  {
    path: '/',
    component: Layout,
    redirect: '/dashboard',
    children: [
      {
        path: 'dashboard',
        name: 'Dashboard',
        component: () => import('@/views/dashboard/index'),
        meta: { title: '首页', icon: 'dashboard' },
      },
    ],
  },
  {
    //父路由 ,最终完整的路由为/core/integral-grade+子路由的path
    path: '/core/integral-grade',
    //布局组件,在大布局组件下的右侧为路由出口
    component: Layout,
    //访问/core/integral-grade后默认发跳转/core/integral-grade/list
    redirect: '/core/integral-grade/list',
    //名称都不能相同
    name: 'coreIntegralGrade',
    //显示节点名称和图标
    meta: { title: '积分等级管理', icon: 'el-icon-s-marketing' },
    //true任何时候都显示父节点和子节点,false如果只有一个子节点则只显示子节点不显示父节点
    alwaysShow: true,
    //三个子节点,只有两个子节点
    children: [
      {
        path: 'list',
        //为组件节点的定义名称,每个节点的name节点不能相同
        name: 'coreIntegralGradeList',
        //组件节点,引入模块 指向src/views/core/integral-grade/list
        component: () => import('@/views/core/integral-grade/list'),
        meta: { title: '积分等级列表' },
      },
      {
        path: 'create',
        name: 'coreIntegralGradeCreate',
        component: () => import('@/views/core/integral-grade/form'),
        meta: { title: '新增积分等级' },
      },
      {
        //:id是一个占位符,表示这部分url是任何一个id
        path: 'edit/:id',
        name: 'coreIntegralGradeEdit',
        component: () => import('@/views/core/integral-grade/form'),
        meta: { title: '编辑积分等级' },
        //隐藏子节点,希望通过新增积分等级的按钮进入该子节点
        hidden: true,
      },
    ],
  },

  {
    path: '/example',
    component: Layout,
    redirect: '/example/table',
    name: 'Example',
    meta: { title: '例子', icon: 'el-icon-s-help' },
    children: [
      {
        path: 'table',
        name: 'Table',
        component: () => import('@/views/table/index'),
        meta: { title: 'Table', icon: 'table' },
      },
      {
        path: 'tree',
        name: 'Tree',
        component: () => import('@/views/tree/index'),
        meta: { title: 'Tree', icon: 'tree' },
      },
    ],
  },

  {
    path: '/form',
    component: Layout,
    children: [
      {
        path: 'index',
        name: 'Form',
        component: () => import('@/views/form/index'),
        meta: { title: '表单', icon: 'el-icon-goods' },
      },
    ],
  },
]

/**
 * asyncRoutes
 * the routes that need to be dynamically loaded based on user roles
 */
export const asyncRoutes = [
  {
    path: '/nested',
    component: Layout,
    redirect: '/nested/menu1',
    name: 'Nested',
    meta: {
      title: 'Nested',
      icon: 'nested',
    },
    children: [
      {
        path: 'menu1',
        component: () => import('@/views/nested/menu1/index'), // Parent router-view
        name: 'Menu1',
        meta: { title: 'Menu1' },
        children: [
          {
            path: 'menu1-1',
            component: () => import('@/views/nested/menu1/menu1-1'),
            name: 'Menu1-1',
            meta: { title: 'Menu1-1' },
          },
          {
            path: 'menu1-2',
            component: () => import('@/views/nested/menu1/menu1-2'),
            name: 'Menu1-2',
            meta: { title: 'Menu1-2' },
            children: [
              {
                path: 'menu1-2-1',
                component: () =>
                  import('@/views/nested/menu1/menu1-2/menu1-2-1'),
                name: 'Menu1-2-1',
                meta: { title: 'Menu1-2-1' },
              },
              {
                path: 'menu1-2-2',
                component: () =>
                  import('@/views/nested/menu1/menu1-2/menu1-2-2'),
                name: 'Menu1-2-2',
                meta: { title: 'Menu1-2-2' },
              },
            ],
          },
          {
            path: 'menu1-3',
            component: () => import('@/views/nested/menu1/menu1-3'),
            name: 'Menu1-3',
            meta: { title: 'Menu1-3' },
          },
        ],
      },
      {
        path: 'menu2',
        component: () => import('@/views/nested/menu2/index'),
        meta: { title: 'menu2' },
      },
    ],
  },

  {
    path: 'external-link',
    component: Layout,
    children: [
      {
        path: 'https://panjiachen.github.io/vue-element-admin-site/#/',
        meta: { title: 'External Link', icon: 'link' },
      },
    ],
  },

  // 404 page must be placed at the end !!!
  { path: '*', redirect: '/404', hidden: true },
]

const createRouter = () =>
  new Router({
    // mode: 'history', // require service support
    scrollBehavior: () => ({ y: 0 }),
    routes: constantRoutes,
  })

const router = createRouter()

// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter() {
  const newRouter = createRouter()
  router.matcher = newRouter.matcher // reset router
}

export default router

④结果展示

点击对应的模块,跳转对应的路由,前端访问对应的模板
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4.后台管理系统的地址访问配置

①需求

  • 由于系统是由mock服务器模拟返回的数据的,故我们需要真实发送数据给我们的服务器
  • 故需要改变地址,但是我们不写登录的逻辑,即登录的逻辑仍然用原来的mock服务器
  • 访问后台时,用nginx服务器
    在nginx.conf配置
server {
	listen       80;
	server_name  localhost;

	location ~ /core/ {           
	    proxy_pass http://localhost:8110;
	}
	location ~ /sms/ {           
	    proxy_pass http://localhost:8120;
	}
	location ~ /oss/ {           
            proxy_pass http://localhost:8130;
	}
}

②实际地址更改

  • 修改全局访问地址,此时所有的访问默认给到nginx服务器
    srb-admin.env.development
# just a flag
ENV = 'development'

# base api
#VUE_APP_BASE_API = '/dev-api'

#原来访问login: http://localhost:8528/dev-api/vue-admin-template/user/login
#更改后访问login:http://localhost/vue-admin-template/user/login
#登录不了,因为更改了

#登录登出为原来的登录登出的模拟(登录登出硬编码)
#其他为访问我们的nginx服务器(其他的)


#将地址更改为实际的nginx服务器端口80
#为真正的界面配置的
VUE_APP_BASE_API = 'http://localhost'
  • 修改mock服务器的地址
    srb-admin\mock\mock-server.js防止连接不了mock服务器
// for mock server
const responseFake = (url, type, respond) => {
  return {
    //连接mock服务器
    //动态获取登录地址,此时硬编码写死
    //原来是${process.env.VUE_APP_BASE_API}${url}
    url: new RegExp(`/dev-api${url}`),
  • 硬编码登录登出的地址
    srb-admin\src\api\user.js
//request中仍然引的是VUE_APP_BASE_API 
import request from '@/utils/request'

export function login(data) {
  return request({
    //原来的baseURL:ocess.env.VUE_APP_BASE_API-->VUE_APP_BASE_API = 'http://localhost'
    //给模拟登录的路径配置的
    baseURL: '/dev-api',
    url: '/vue-admin-template/user/login',
    method: 'post',
    data,
  })
}

export function getInfo(token) {
  return request({
    baseURL: '/dev-api',
    url: '/vue-admin-template/user/info',
    method: 'get',
    params: { token },
  })
}

export function logout() {
  return request({
    baseURL: '/dev-api',
    url: '/vue-admin-template/user/logout',
    method: 'post',
  })
}

③最终实现逻辑

  • 访问登录登出时
    在这里插入图片描述
  • 其他访问
    前缀为http://localhost:80然后通过nginx转发

5.前后端联调

①原理

  • 后端接口开发完毕
  • 路由开发完毕(点击模块调到指定的页面)
  • 页面开发(编写template页面的渲染,script引入api模块,css为样式)
  • 前端api(编写axios具体api发送)
    在这里插入图片描述

②流程

  • 利用已提供的request模板写axios请求
  • 在具体的页面组件中script引入request模板,然后利用template渲染
  • 最后再路由调用模块时获取数据

③代码

  • request模板
    在此路径下编写srb-admin\src\api\core\integral-grade.js
//引入axios的初始化模块
import request from '@/utils/request'

//导出默认模块
export default {
  //定义模块成员

  //成员方法:获取积分等级列表
  list() {
    //调用axios的初始化模块,发送远程ajax请求
    return request({
      //baseURL我们配置过为http://localhost
      url: '/admin/core/integralGrade/list',
      method: 'get',
    })
  },
}

  • 页面组件的编写
    srb-admin\src\views\core\integral-grade\list.vue
<template>
  <div class="app-container">
    <!-- 表格 -->
    <el-table :data="list" border stripe>
      <el-table-column type="index" width="50" />
      <el-table-column prop="borrowAmount" label="借款额度" />
      <el-table-column prop="integralStart" label="积分区间开始" />
      <el-table-column prop="integralEnd" label="积分区间结束" />
    </el-table>
  </div>
</template>

<script>
//引入api模块
import integralGradeApi from '@/api/core/integral-grade'

export default {
  data() {
    return {
      list: [], //积分等级列表
    }
  },

  created() {
    this.fetchData()
  },

  methods: {
    fetchData() {
      integralGradeApi.list().then((response) => {
        this.list = response.data.list
      })
    },
  },
}
</script>

  • 路由前面已编辑好
    注意,由于mock服务器的响应码和我们的服务器响应码不同,需要更改srb-admin\src\utils\request.js模板,过滤器的更改,原理mock服务器访问成功只响应20000,现在需要更改为我们的服务器响应0,但是由于登录也需要20000,故20000和0都可以成功
  (response) => {
    const res = response.data

    // if the custom code is not 20000, it is judged as an error.
    //mockserver 访问成功返回20000,自己的结果成功返回0
    if (res.code !== 20000 && res.code != 0) {
      Message({
        message: res.message || 'Error',
        type: 'error',
        duration: 5 * 1000,
      })

6.完善积分等级的前端系统

①积分等级的需求

  • 查询列表
  • 增加积分
  • 保存积分
  • 删除积分

②实现思路

  • 在引入路由后,只需编码api和页面即可。
    三个路由块。
    第一个 访问list页面 积分等级列表
    第二个 访问form页面 新增积分等级
    第三个 访问form页面 编辑积分等级(默认不显示)
  • 通过form页面完成新增积分和编辑积分
    新增积分功能直接在新增积分等级路由中更改。
    编辑积分通过在积分等级列表路由中点击修改按钮跳到编辑积分等级路由。
    通过判断是否有id来决定修改还是增加(如果是新增则id为空,如果是编辑则会自带$route对象中的占位符id属性)

③代码总编辑

  • 新增路由块(前面做过)
    srb-admin\src\router\index.js
{
    //父路由 ,最终完整的路由为/core/integral-grade+子路由的path
    path: '/core/integral-grade',
    //布局组件,在大布局组件下的右侧为路由出口
    component: Layout,
    //访问/core/integral-grade后默认发跳转/core/integral-grade/list
    redirect: '/core/integral-grade/list',
    //名称都不能相同
    name: 'coreIntegralGrade',
    //显示节点名称和图标
    meta: { title: '积分等级管理', icon: 'el-icon-s-marketing' },
    //true任何时候都显示父节点和子节点,false如果只有一个子节点则只显示子节点不显示父节点
    alwaysShow: true,
    //三个子节点,只有两个子节点
    children: [
      {
        path: 'list',
        //为组件节点的定义名称,每个节点的name节点不能相同
        name: 'coreIntegralGradeList',
        //组件节点,引入模块 指向src/views/core/integral-grade/list
        component: () => import('@/views/core/integral-grade/list'),
        meta: { title: '积分等级列表' },
      },
      {
        path: 'create',
        name: 'coreIntegralGradeCreate',
        component: () => import('@/views/core/integral-grade/form'),
        meta: { title: '新增积分等级' },
      },
      {
        //:id是一个占位符,表示这部分url是任何一个id
        path: 'edit/:id',
        name: 'coreIntegralGradeEdit',
        component: () => import('@/views/core/integral-grade/form'),
        meta: { title: '编辑积分等级' },
        //隐藏子节点,希望通过新增积分等级的按钮进入该子节点
        hidden: true,
      },
    ],
  },

  • 添加api(调用具体接口的axios)
    srb-admin\src\api\core\integral-grade.js
//引入axios的初始化模块
import request from '@/utils/request'

//导出默认模块
export default {
  //定义模块成员

  //成员方法:获取积分等级列表
  list() {
    //调用axios的初始化模块,发送远程ajax请求
    return request({
      //baseURL我们配置过为http://localhost
      url: '/admin/core/integralGrade/list',
      method: 'get',
    })
  },

  removeById(id) {
    return request({
      url: '/admin/core/integralGrade/remove/' + id,
      method: 'delete',
    })
  },
  save(integralGrade) {
    return request({
      url: '/admin/core/integralGrade/save',
      method: 'post',
      //如果数据类型为json,需要data
      data: integralGrade,
    })
  },
  getById(id) {
    return request({
      url: '/admin/core/integralGrade/get/' + id,
      method: 'get',
    })
  },
  updateById(integralGrade) {
    return request({
      url: '/admin/core/integralGrade/update',
      method: 'put',
      data: integralGrade,
    })
  },
}

  • list组件
    srb-admin\src\views\core\integral-grade\list.vue
<template>
  <div class="app-container">
    <!-- 表格 -->
    <el-table :data="list" border stripe>
      <el-table-column type="index" width="50" />
      <el-table-column prop="borrowAmount" label="借款额度" />
      <el-table-column prop="integralStart" label="积分区间开始" />
      <el-table-column prop="integralEnd" label="积分区间结束" />
      <el-table-column label="操作" width="200" align="center">
        <!-- 自定义模板内容 -->
        <!-- slot-scope="scope"能够获得当前行的所有数据的id -->
        <template slot-scope="scope">
          <router-link
            :to="'/core/integral-grade/edit/' + scope.row.id"
            style="margin-right: 5px"
          >
            <el-button type="primary" size="mini" icon="el-icon-edit">
              修改
            </el-button>
          </router-link>
          <el-button
            type="danger"
            size="mini"
            icon="el-icon-delete"
            @click="removeById(scope.row.id)"
          >
            删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
//引入api模块
import integralGradeApi from '@/api/core/integral-grade'

export default {
  data() {
    return {
      list: [], //积分等级列表
    }
  },

  created() {
    this.fetchData()
  },

  methods: {
    fetchData() {
      integralGradeApi.list().then((response) => {
        this.list = response.data.list
      })
    },

    removeById(id) {
      //debugger自动设置断点调试

      this.$confirm('此操作将永久删除该记录, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(() => {
          return integralGradeApi.removeById(id)
        })
        .then((response) => {
          //调用message的模块
          this.$message({
            showClose: true,
            message: response.message,
            type: 'success',
          })
          //删除成功后重新获取list
          this.fetchData()
        })
        .catch((error) => {
          //因为response的模板里面也会有catch的模块,在例如url发生错误时但是又点击删除
          //由于response模板先捕获删除,显示network error,又返回error对象
          //此时进入这里的catch,那个error类型为'network error',故又会显示 已取消删除
          //解决:加入判断error类型,如果error类型为前面的cancel则执行,如果为response里抛出的error则不执行
          if (error == 'cancel') {
            this.$message({
              type: 'info',
              message: '已取消删除',
            })
          }
        })
    },
  },
}
</script>

  • form组件
    srb-admin\src\views\core\integral-grade\form.vue
<template>
  <div class="app-container">
    <!-- 输入表单 -->
    <el-form label-width="120px">
      <el-form-item label="借款额度">
        <!-- 数字输入框 -->
        <el-input-number v-model="integralGrade.borrowAmount" :min="0" />
      </el-form-item>
      <el-form-item label="积分区间开始">
        <el-input-number v-model="integralGrade.integralStart" :min="0" />
      </el-form-item>
      <el-form-item label="积分区间结束">
        <el-input-number v-model="integralGrade.integralEnd" :min="0" />
      </el-form-item>
      <el-form-item>
        <el-button
          :disabled="saveBtnDisabled"
          type="primary"
          @click="saveOrUpdate()"
        >
          保存
        </el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
import integralGradeApi from '@/api/core/integral-grade'
export default {
  data() {
    return {
      saveBtnDisabled: false, //是否禁用保存按钮,防止表单重复提交
      integralGrade: {}, //积分等级对象
    }
  },
  created() {
    //当id存在时回显,id不存在时新增
    //route对象是在发送response时自带对象route,能够获得前面url占位符id的值,没有则不调用
    if (this.$route.params.id) {
      this.fetchById(this.$route.params.id)
    }
  },
  methods: {
    fetchById(id) {
      integralGradeApi.getById(id).then((response) => {
        this.integralGrade = response.data.record
      })
    },
    //保存或者更新
    saveOrUpdate() {
      //禁用保存按钮
      this.saveBtnDisabled = true
      if (!this.integralGrade.id) {
        this.saveData()
        this.$router.push('/core/integral-grade/list')
      } else {
        //调用更新
        this.updateData()
      }
      //调用新增,调用完之后路由跳转
    },
    saveData() {
      integralGradeApi.save(this.integralGrade).then((response) => {
        this.$message({
          type: 'success',
          message: response.message,
        })
      })
    },
    // 根据id更新记录
    updateData() {
      // 数据的获取
      integralGradeApi.updateById(this.integralGrade).then((response) => {
        this.$message({
          type: 'success',
          message: response.message,
        })
        //重新加载list数据,跳转页面
        this.$router.push('/core/integral-grade/list')
      })
    },
  },
}
</script>

7.对前端系统的全面分析(Vue组件)

①一个页面有的(Vue组件)

  • html数据
  • Vue对象

②Vue项目的全局渲染流程

  • 有唯一html文件(动态渲染,访问什么都是进入该html文件,包含一个div的id为app)
    srb-admin\public\index.html

  • 有唯一Vue对象(引入了路由并且动态渲染html中的id为app)
    srb-admin\src\main.js

  • Vue对象渲染根组件
    srb-admin\src\App.vue(定义了路由的出口)

  • 通过路由渲染子组件(views视图–>侧边栏,导航栏,主内容栏)
    srb-admin\src\router\index.js(路由)
    srb-admin\src\layout\index.vue(要渲染的组件侧边栏,导航栏,主内容栏)

  • 通过路由中定义的子节点来渲染主内容栏(获取积分数据)
    srb-admin\src\layout\components\AppMain.vue(主内容栏定义了子路由的出口)
    srb-admin\src\views\core\integral-grade\form.vue(路由子节点声明的模板渲染主内容栏)

  • 难理解的问题
    两个路由出口,第一次是路由整体渲染全部子节点的出口,第二次是子路由渲染子节点的出口。即父路由出口的位置和父路由+子路由渲染的出口的位置。

③分析Vue项目结构

  • 入口的html
    srb-admin\public\index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
     <!--定义图标 -->
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
     <!-- 定义项目名称 -->
    <title><%= webpackConfig.name %></title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but <%= webpackConfig.name %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
     <!-- 动态生成app.js代码并且自动嵌入到此 -->
    <!-- built files will be auto injected -->
  </body>
</html>
  • 入口的js脚本
    srb-admin\src\main.js
    全局唯一Vue对象,初始化了Rout路由,渲染了根组件
import Vue from 'vue' //Vue

import 'normalize.css/normalize.css' // A modern alternative to CSS resets//基础CSS样式

import ElementUI from 'element-ui' //element-ui
import 'element-ui/lib/theme-chalk/index.css'
import locale from 'element-ui/lib/locale/lang/zh-CN' // lang i18n

import '@/styles/index.scss' // global css//全局css样式定义

import App from './App' //根组件
import store from './store' //前端信息存储工具
import router from './router' //路由模块

import '@/icons' // icon //扩展图标系统
import '@/permission' // permission control//角色控制权限系统

//mock为模拟接口(模拟接口服务器)
/**
 * If you don't want to use mock-server
 * you want to use MockJs for mock api
 * you can execute: mockXHR()
 *
 * Currently MockJs will be used in the production environment,
 * please remove it before going online ! ! !
 */
if (process.env.NODE_ENV === 'production') {
  const { mockXHR } = require('../mock')
  mockXHR()
}

//将elemeneUI挂载到Vue中

// set ElementUI lang to EN
Vue.use(ElementUI, { locale })
// 如果想要中文版 element-ui,按如下方式声明
// Vue.use(ElementUI)

Vue.config.productionTip = false

//创建Vue对象(核心Vue对象,指定渲染的节点,app,渲染public/index.html中的id为app的div)
new Vue({
  el: '#app',
  //挂载路由(将srb-admin\src\router\index.js的路由挂载到这)
  router,
  store,
  //页面中展示的内容,组件(srb-admin\src\App.vue为根组件,最后所有组件都会嵌入)
  render: (h) => h(App),
})

  • 根组件
    srb-admin\src\App.vue
<template>
  <div id="app">
    <!--路由出口显式模板,模板都是由srb-admin\src\views下的文件来定义的-->
    <router-view />
  </div>
</template>

<script>
export default {
  name: 'App',
}
</script>
  • 路由定义
    srb-admin\src\router\index.js
    其中的Layout为真正的布局组件,然后下面路由和其子节点的都是渲染Layout布局
{
    //父路由 ,最终完整的路由为/core/integral-grade+子路由的path
    path: '/core/integral-grade',
    //布局组件,在大布局组件下的右侧为路由出口
    component: Layout,
    //访问/core/integral-grade后默认发跳转/core/integral-grade/list
    redirect: '/core/integral-grade/list',
    //名称都不能相同
    name: 'coreIntegralGrade',
    //显示节点名称和图标
    meta: { title: '积分等级管理', icon: 'el-icon-s-marketing' },
    //true任何时候都显示父节点和子节点,false如果只有一个子节点则只显示子节点不显示父节点
    alwaysShow: true,
    //三个子节点,只有两个子节点
    children: [
      {
        path: 'list',
        //为组件节点的定义名称,每个节点的name节点不能相同
        name: 'coreIntegralGradeList',
        //组件节点,引入模块 指向src/views/core/integral-grade/list
        component: () => import('@/views/core/integral-grade/list'),
        meta: { title: '积分等级列表' },
      },
      {
        path: 'create',
        name: 'coreIntegralGradeCreate',
        component: () => import('@/views/core/integral-grade/form'),
        meta: { title: '新增积分等级' },
      },
      {
        //:id是一个占位符,表示这部分url是任何一个id
        path: 'edit/:id',
        name: 'coreIntegralGradeEdit',
        component: () => import('@/views/core/integral-grade/form'),
        meta: { title: '编辑积分等级' },
        //隐藏子节点,希望通过新增积分等级的按钮进入该子节点
        hidden: true,
      },
    ],
  },

  {
    path: '/example',
    component: Layout,
    redirect: '/example/table',
    name: 'Example',
    meta: { title: '例子', icon: 'el-icon-s-help' },
    children: [
      {
        path: 'table',
        name: 'Table',
        component: () => import('@/views/table/index'),
        meta: { title: 'Table', icon: 'table' },
      },
      {
        path: 'tree',
        name: 'Tree',
        component: () => import('@/views/tree/index'),
        meta: { title: 'Tree', icon: 'tree' },
      },
    ],
  },

  {
    path: '/form',
    component: Layout,
    children: [
      {
        path: 'index',
        name: 'Form',
        component: () => import('@/views/form/index'),
        meta: { title: '表单', icon: 'el-icon-goods' },
      },
    ],
  },
]
  • LayOut组件
    srb-admin\src\layout\index.vue
    <div
      v-if="device === 'mobile' && sidebar.opened"
      class="drawer-bg"
      @click="handleClickOutside"
    />
    <!--侧边栏-->
    <sidebar class="sidebar-container" />
    <div class="main-container">
      <div :class="{ 'fixed-header': fixedHeader }">
        <!--导航栏-->
        <navbar />
      </div>
      <!--主内容区-->
      <app-main />
    </div>
  </div>

未更新

未更新

未更新

未更新

未更新

未更新

未更新

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/418882.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

跳槽进阿里了,其实也没那么难...

对于很多没有学历优势的人来说&#xff0c;面试大厂是非常困难的&#xff0c;这对我而言&#xff0c;也是一样&#xff0c;出身于二本&#xff0c;原本以为就三点一线的生活度过一生&#xff0c;直到生活上的变故&#xff0c;才让我有了新的想法和目标&#xff0c;因此我这个二…

【C++ -模块一 常量变量、关键字、数据类型】

C 模块一C框架代码&#xff1a;第一个C程序&#xff0c;打印hello C &#xff01;代码注释&#xff1a;一 变量和常量&#xff1a;1.1变量变量创建语法&#xff1a;1.2 常量&#xff1a;不能被修改的数据&#xff08;1&#xff09; #define定义的宏常量&#xff1a;一般写在文件…

排序(3)之交换排序

目录 前言 交换排序 1.冒泡排序 1.1冒泡排序的实现 1.2 特性总结 2.快速排序 2.1hoare版本 2.2 挖坑法 2.3 前后指针版本 3.快速排序的优化 3.1 三数取中法 3.2 小区间优化 4.快速排序的非递归实现 前言 今天小编给大家带来交换排序的内容&#xff0c;对于交换排序…

C-关键字(下)

文章目录循环控制switch-case-break-defaultdo-while-forgetchar()break-continuegotovoidvoid*returnconstconst修饰变量const修饰数组const修饰指针指针补充const 修饰返回值volatilestruct柔型数组union联合体联合体空间开辟问题利用联合体的性质,判断机器是大端还是小端enu…

力扣javascript刷题343——动态规划之整数拆分

这几天有在开始投暑期实习的简历&#xff0c;可能确实是投的太晚了&#xff0c;好多厂都没有hc了&#xff0c;阿里简历面都没过&#xff08;感觉是kpi面试&#xff09;&#xff0c;被深深打击到了呜呜呜&#xff0c;花了两天整理情绪&#xff0c;重新出发&#xff0c;下篇文章针…

mysql 索引详解

mysql 索引索引分类1. 普通索引和唯一索引2. 单列索引和组合索引3. 全文索引4&#xff0e;空间索引操作使用索引1. 在已有表中添加索引2. 删除索引索引是一个单独存储在磁盘上的数据库结构&#xff0c;使用索引可以快速找出在某个或多个列中有一特定值的行&#xff0c;提高查询…

【C语言 -结构体 结构体声明、定义、初始化、结构体成员访问、结构体传参】

C语言 - 结构体声明、定义、初始化、结构体成员访问、结构体传参一 结构体类型的声明&#xff1a;声明格式&#xff1a;二 结构体的定义并初始化2.1用结构体创建&#xff08;定义&#xff09;结构体变量&#xff08;对象&#xff09;的两种方式&#xff1a;&#xff08;1&#…

WebRTC 系列(三、点对点通话,H5、Android、iOS)

WebRTC 系列&#xff08;二、本地 demo&#xff0c;H5、Android、iOS&#xff09; 上一篇博客中&#xff0c;我已经展示了各端的本地 demo&#xff0c;大家应该知道 WebRTC 怎么用了。在本地 demo 中是用了一个 RemotePeerConnection 来模拟远端&#xff0c;可能理解起来还有点…

HTTP协议:当下最主流的应用层协议之一,你确定不了解一下吗?

一.HTTP协议的含义http是什么&#xff1f;超文本传输协议&#xff08;Hyper Text Transfer Protocol&#xff0c;HTTP&#xff09;是一个简单的请求-响应协议&#xff0c;它通常运行在TCP之上。‘超’可以理解为除了文本之外的图片&#xff0c;音频和视频&#xff0c;和一些其他…

硬盘、文件系统相关常识

1.硬盘 以机械硬盘为例&#xff0c;下面是机械硬盘的外形结构。 结构图&#xff1a; 每个磁盘分为两个盘面&#xff0c;每个盘面中有很多磁道(Disk Track)&#xff0c;每个磁道上有很多扇区(Sector)&#xff0c;磁道上的一段一段的就是扇区。 扇区是最小的单位&#xff0c;…

Flutter开发日常练习-黑白主题

1.添加了白天黑夜模式 2.country_picker: ^2.0.20 城市信息框架 3.image_picker: ^0.8.53 photo_manager: ^2.3.0 相机和相册的调用 4.shared_preferences: ^2.0.8 sqflite: ^1.3.1 path: 数据异步持久化到磁盘 注:登录的时候记录一下登录状态isLogin,通过isLogin来标记是否…

OCR之论文笔记TrOCR

文章目录TrOCR: Transformer-based Optical Character Recognition with Pre-trained Models一. 简介二. TrOCR2.1. Encoder2.2 Decoder2.3 Model Initialiaztion2.4 Task Pipeline2.5 Pre-training2.6 Fine-tuning2.7 Data Augmentation三. 实验3.1 Data3.2 Settings3.2 Resul…

如何战胜AI?唯努力尔-- DSP算法的FPGA实现指南

如何战胜AI?唯努力尔! DSP算法的FPGA实现指南! 来一集番外。 而这 也是开坑的第一个算法&#xff01;我们先讲案例再谈实现指南 文章目录如何战胜AI?唯努力尔! DSP算法的FPGA实现指南!观前提醒实用算法原理数学原理代码模块划分与实现FIR滤波器误差计算与系数更新模块最终代…

算法 贪心2 || 122.买卖股票的最佳时机II 55. 跳跃游戏 45.跳跃游戏II

122.买卖股票的最佳时机II 如果想到其实最终利润是可以分解的&#xff0c;那么本题就很容易了&#xff01; 如何分解呢&#xff1f; 假如第0天买入&#xff0c;第3天卖出&#xff0c;那么利润为&#xff1a;prices[3] - prices[0]。 相当于(prices[3] - prices[2]) (prices[2…

HBuilderX 开发工具

介绍 uni-app 官方推荐使用 HBuilderX 来开发 uni-app 类型的项目。 主要好处&#xff1a; 模板丰富完善的智能提示一键运行 下载 HBuilderX 1、官网下载地址&#xff1a;https://www.dcloud.io/hbuilderx.html 2、下载正式版&#xff08;根据自己电脑选&#xff09; 安装…

( “树” 之 DFS) 112. 路径总和 ——【Leetcode每日一题】

112. 路径总和 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;这条路径上所有节点值相加等于目标和 targetSum 。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 叶子节点…

虚假评论检测可视化系统的实现

菜鸟一枚&#xff0c;大佬勿喷&#xff0c;主要是想分享&#xff0c;希望能帮到像我一样的人。 主要代码是参考&#xff1a;https://github.com/SoulDGXu/NLPVisualizationSystem/tree/master/frontend 他这个代码实现了词云、摘要生成等功能吧。因为我做的是虚假评论检测系统&…

星环科技自研技术,加速大数据从持久化、统一化、资产化、业务化到生态化

从2013年成立开始&#xff0c;星环科技就专注于大数据基础技术与企业数据业务的更好结合&#xff0c;同时面对中国更为复杂的数据应用场景&#xff0c;研发了多种更贴合国内大数据应用需求的大数据管理技术&#xff0c;在大数据技术领域有多项基础技术突破。星环科技在坚持技术…

尚硅谷大数据技术Zookeeper教程-笔记02【服务器动态上下线监听案例、ZooKeeper分布式锁案例、企业面试真题】

视频地址&#xff1a;【尚硅谷】大数据技术之Zookeeper 3.5.7版本教程_哔哩哔哩_bilibili 尚硅谷大数据技术Zookeeper教程-笔记01【Zookeeper(入门、本地安装、集群操作)】尚硅谷大数据技术Zookeeper教程-笔记02【服务器动态上下线监听案例、ZooKeeper分布式锁案例、企业面试真…

Vue3 关于setup与自定义指令

setup语法糖 最大好处就是所有声明部分皆可直接使用&#xff0c;无需return出去 注意&#xff1a;部分功能还不完善&#xff0c;如&#xff1a;name、render还需要单独加入script标签按compositionAPI方式编写 // setup 下还可以附加<script> setup语法糖独有 &…