vue3.2后台管理系统搭建学习笔记

vue3.2后台管理系统搭建学习笔记,第1张

1、创建项目更改版本 1-1、创建项目
vue create vue3-admin

1-2、更改vue版本

更改前

更改后

 

2、开发项目 1、按需引入element-plus 1、安装
npm install element-plus --save
2、按需导入(自动导入)
cnpm install -D unplugin-vue-components unplugin-auto-import
3、Webpack配置(vue.config.js)
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')

module.exports = {
intOnSave:false,
  devServer:{
    open:true,
    port:9000,
  },
  configureWebpack: {
    plugins: [
      AutoImport({
        resolvers: [ElementPlusResolver()],
      }),
      Components({
        resolvers: [ElementPlusResolver()],
      }),
    ]
  },
}
4、使用

tips:在main.js中引入样式(避免d出框等组件样式错乱)

import 'element-plus/dist/index.css'
2、使用element-plus Icon图标  1、安装
cnpm install @element-plus/icons-vue
2、注册全局组件
//main.js
import * as ELIcons from '@element-plus/icons-vue'
for (const iconName in ELIcons) {
  app.component(iconName, ELIcons[iconName])
}
 3、使用(左侧菜单icon)
3、样式初始化,使用scss变量 1、导入初始样式,导出变量值

 2、在main.js中引入
import '@/styles/index.scss'
3、配置webpack
css: {
    loaderOptions: {
      sass: {
        // 8版本用prependData:
        prependData: `
          @import "@/styles/variables.scss";  // scss文件地址
          @import "@/styles/mixin.scss";     // scss文件地址
        `
      }
    }
  }
4、使用svg,全局注册 1、svg图标导入到项目

 2、在components文件夹下创建SvgIcon组件





4、在icons 文件夹下新建index.js
import SvgIcon from '@/components/SvgIcon'

const svgRequired = require.context('./svg', false, /\.svg$/)
svgRequired.keys().forEach((item) => svgRequired(item))

export default (app) => {
  app.component('svg-icon', SvgIcon)
}
5、在main.js中引入
import SvgIcon from '@/icons'
const app=createApp(App)
SvgIcon(app)
6、安装依赖
cnpm i --save-dev [email protected]
7、配置webpack
const path = require('path')
function resolve(dir) {
  return path.join(__dirname, dir)
}
const webpack = require('webpack')

module.exports = {
chainWebpack(config) {
    // 设置 svg-sprite-loader
    // config 为 webpack 配置对象
    // config.module 表示创建一个具名规则,以后用来修改规则
    config.module
      // 规则
      .rule('svg')
      // 忽略
      .exclude.add(resolve('src/icons'))
      // 结束
      .end()
    // config.module 表示创建一个具名规则,以后用来修改规则
    config.module
      // 规则
      .rule('icons')
      // 正则,解析 .svg 格式文件
      .test(/\.svg$/)
      // 解析的文件
      .include.add(resolve('src/icons'))
      // 结束
      .end()
      // 新增了一个解析的loader
      .use('svg-sprite-loader')
      // 具体的loader
      .loader('svg-sprite-loader')
      // loader 的配置
      .options({
        symbolId: 'icon-[name]'
      })
      // 结束
      .end()
    config
      .plugin('ignore')
      .use(
        new webpack.ContextReplacementPlugin(/moment[/\]locale$/, /zh-cn$/)
      )
    config.module
      .rule('icons')
      .test(/\.svg$/)
      .include.add(resolve('src/icons'))
      .end()
      .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      .options({
        symbolId: 'icon-[name]'
      })
      .end()
  },
}
8、使用
5、请求封装 1、安装axios 
cnpm i axios --save
 2、新建utils文件夹,新建auth.js设置过期时间
const TOKEN_TIME = 'tokenTime'

const TOKEN_TIME_VALUE = 2 * 60 * 60 * 1000

// 登录时设置时间
export const setTokenTime = () => {
  localStorage.setItem(TOKEN_TIME, Date.now())
}

// 获取
export const getTokenTime = () => {
  return localStorage.getItem(TOKEN_TIME)
}

// 是否已经过期
export const diffTokenTime = () => {
  const currentTime = Date.now()
  const tokenTime = getTokenTime()
  return currentTime - tokenTime > TOKEN_TIME_VALUE
}
3、新建api文件夹,新建request.js文件
import axios from 'axios'
import { ElMessage } from 'element-plus'
import { diffTokenTime } from '@/utils/auth'
import store from '@/store'
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API,
  timeout: 5000
})

service.interceptors.request.use(
  (config) => {
    if (localStorage.getItem('token')) {
      if (diffTokenTime()) {
        store.dispatch('app/logout')
        return Promise.reject(new Error('token 失效了'))
      }
    }
    config.headers.Authorization = localStorage.getItem('token')
    return config
  },
  (error) => {
    return Promise.reject(new Error(error))
  }
)

service.interceptors.response.use(
  (response) => {
    const { data, meta } = response.data
    if (meta.status === 200 || meta.status === 201) {
      return data
    } else {
      ElMessage.error(meta.msg)
      return Promise.reject(new Error(meta.msg))
    }
  },
  (error) => {
    console.log(error.response)
    error.response && ElMessage.error(error.response.data)
    return Promise.reject(new Error(error.response.data))
  }
)
export default service
4、本地跨域配置
  devServer: {
    https: false,
    hotOnly: false,
    open:true,
    port:9000,
    proxy: {
      '/api': {
        target: 'https://*******/api/private/v1/',
        changeOrigin: true,
        pathRewrite: {
          '^/api': ''
        }
      }
    }
  },
5、全局坏境变量定义

 新建 .env.development、.env.production文件

ENV = 'development'

VUE_APP_BASE_API = '/api'
ENV = 'production'

VUE_APP_BASE_API = '/prod-api'
6、全局导航守卫 
import { createRouter, createWebHashHistory } from 'vue-router'

const routes = [
  {
    path: '/login',
    name: 'Login',
    component: () => import('../views/login/index.vue')
  },
  {
    path: '/',
    name: '/',
    component: () => import('../layout'),
    redirect: '/users',
    children: [
      {
        path: 'users',
        name: 'users',
        component: () => import('@/views/users/index.vue')
      },
      {
        path: 'categories',
        name: 'categories',
        component: () => import('@/views/categories/index.vue')
      },
      {
        path: 'goods',
        name: 'goods',
        component: () => import('@/views/goods/index.vue')
      },
      {
        path: 'orders',
        name: 'orders',
        component: () => import('@/views/orders/index.vue')
      },
      {
        path: 'params',
        name: 'params',
        component: () => import('@/views/params/index.vue')
      },
      {
        path: 'reports',
        name: 'reports',
        component: () => import('@/views/reports/index.vue')
      },
      {
        path: 'rights',
        name: 'rights',
        component: () => import('@/views/rights/index.vue')
      },
      {
        path: 'roles',
        name: 'roles',
        component: () => import('@/views/roles/index.vue')
      }
    ]
  }
]


const router = createRouter({
  history: createWebHashHistory(),
  routes
})

export default router
1、新建router/permission.js
import router from './index'
import store from '@/store'

const whiteList = ['/login']
router.beforeEach((to, from, next) => {
  if (store.getters.token) {
    if (to.path === '/login') {
      next('/')
    } else {
      next()
    }
  } else {
    if (whiteList.includes(to.path)) {
      next()
    } else {
      next('/login')
    }
  }
})
2、main.js引入 
import '@/router/permission'
5、登录  1、新增登录界面login/index.vue





2、新建api/login.js
import request from './request'

export const login = (data) => {
  return request({
    url: '/login',
    method: 'POST',
    data
  })
}
3、新建store/modules/app.js
import { login as loginApi } from '@/api/login'
import router from '@/router'
import { setTokenTime } from '@/utils/auth'
export default {
  namespaced: true,
  state: () => ({
    token: localStorage.getItem('token') || '',
    siderType: true,
  }),
  mutations: {
    setToken(state, token) {
      state.token = token
      localStorage.setItem('token', token)
    },
    changeSiderType(state) {
      state.siderType = !state.siderType
    },
  },
  actions: {
    login({ commit }, userInfo) {
      return new Promise((resolve, reject) => {
        loginApi(userInfo)
          .then((res) => {
            console.log(res)
            commit('setToken', res.token)
            setTokenTime()
            router.replace('/')
            resolve()
          })
          .catch((err) => {
            reject(err)
          })
      })
    },
    // 退出
    logout({ commit }) {
      commit('setToken', '')
      localStorage.clear()
      router.replace('/login')
    }
  }
}
4、store/getters.js、store/index.js
export default {
  token: (state) => state.app.token,
  siderType: (state) => state.app.siderType,
}
import { createStore } from 'vuex'
import app from './modules/app'
import getters from './getters'
export default createStore({
  modules: {
    app
  },
  getters
})

3、Layout 布局







1、左侧菜单 新建layout/Menu/index.vue





menu数据 

{
  "data": [
    {
      "id": 125,
      "authName": "用户管理",
      "path": "users",
      "children": [
        {
          "id": 110,
          "authName": "用户列表",
          "path": "users",
          "children": [
            
          ],
          "order": null
        }
      ],
      "order": 1
    },
    {
      "id": 103,
      "authName": "权限管理",
      "path": "rights",
      "children": [
        {
          "id": 111,
          "authName": "角色列表",
          "path": "roles",
          "children": [
            
          ],
          "order": null
        },
        {
          "id": 112,
          "authName": "权限列表",
          "path": "rights",
          "children": [
            
          ],
          "order": null
        }
      ],
      "order": 2
    },
    {
      "id": 101,
      "authName": "商品管理",
      "path": "goods",
      "children": [
        {
          "id": 104,
          "authName": "商品列表",
          "path": "goods",
          "children": [
            
          ],
          "order": 1
        },
        {
          "id": 115,
          "authName": "分类参数",
          "path": "params",
          "children": [
            
          ],
          "order": 2
        },
        {
          "id": 121,
          "authName": "商品分类",
          "path": "categories",
          "children": [
            
          ],
          "order": 3
        }
      ],
      "order": 3
    },
    {
      "id": 102,
      "authName": "订单管理",
      "path": "orders",
      "children": [
        {
          "id": 107,
          "authName": "订单列表",
          "path": "orders",
          "children": [
            
          ],
          "order": null
        }
      ],
      "order": 4
    },
    {
      "id": 145,
      "authName": "数据统计",
      "path": "reports",
      "children": [
        {
          "id": 146,
          "authName": "数据报表",
          "path": "reports",
          "children": [
            
          ],
          "order": null
        }
      ],
      "order": 5
    }
  ],
  "meta": {
    "msg": "获取菜单列表成功",
    "status": 200
  }
}

2、右侧头部





1、hamburger.vue 控制左侧菜单折叠展开





2、breadcrumb.vue 面包屑导航





3、screenFull.vue 全屏组件

1、安装

cnpm i screenfull --save

2、使用






4、driver引导组件

1、安装

cnpm i driver.js --save

2、使用






 5、头像下拉 退出






4、用户管理开发 1、搜索功能 、结果列表展示





2、新建components/dialog.vue 新增、编辑用户d框组件



3、新建全局时间过滤器 1、安装dayjs
cnpm i dayjs --save
2、新建utils/filters.js

import dayjs from 'dayjs'

const filterTimes = (val,format='YYYY-MM-DD') =>{
  if(!isNull(val)){
    val = parseInt(val)*1000
    return dayjs(val).format(format)
  }else{
    return '--'
  }
}

export const isNull = (val)=>{
  if(!val) return true
  if(JSON.stringify(val)==="{}") return true
  if(JSON.stringify(val)==="[]") return true
}

export default (app)=>{
  app.config.globalProperties.$filters={
    filterTimes
  }
}
3、main.js传入app
import filters from './utils/filters'
filters(app)
4、使用

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/web/1322958.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-12
下一篇 2022-06-12

发表评论

登录后才能评论

评论列表(0条)

保存