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)
{{ item.authName }}
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 svg-sprite-loader@6.0.9
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
{{ item.authName }}
{{ it.authName }}
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 面包屑导航
{{
item.name
}}
{{
item.name
}}
3、screenFull.vue 全屏组件
1、安装
cnpm i screenfull --save
2、使用
4、driver引导组件
1、安装
cnpm i driver.js --save
2、使用
5、头像下拉 退出
退出
4、用户管理开发
1、搜索功能 、结果列表展示
查询
新增用户
{{$filters.filterTimes(row.create_time)}}
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、使用
{{$filters.filterTimes(row.create_time)}}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)