vue-element-admin遇到的问题和解决记录

简介

vue-element-admin 是一个后台前端解决方案,它基于 vue 和 element-ui实现。

官网地址:https://panjiachen.github.io/vue-element-admin-site/zh/guide/#功能

遇到问题

顶部搜索栏获取信息

html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<div :class="{'show':show}" class="header-search">
<div class="search">
<div
id="input"
ref="input"
:placeholder="placeholder"
contenteditable="plaintext-only"
@keydown="toSearch($event)"
/>
<i class="el-icon-search" @click="toSearchClick()" />
</div>
</div>
</template>

js this.$root.$emit(‘tosearch’, this.search)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
methods: {
toSearch(e) {
// console.log(e.isComposing); // return false
const search = this.$refs.input.innerText.trim()
if (!e.isComposing && e.code === 'Enter' && search) {
e.preventDefault()
this.$root.$emit('tosearch', this.search)
}
},
toSearchClick() {
const search = this.$refs.input.innerText.trim()
if (search) {
this.$root.$emit('tosearch', this.search)
}
}
}

其他页面获取搜索参数

1
2
3
this.$root.$on('tosearch', (e) => {
console.log(e)
})

安装-失败bug

1
2
3
4
5
6
7
8
9
10
11
12
13
# 克隆项目
git clone https://github.com/PanJiaChen/vue-element-admin.git

# 进入项目目录
cd vue-element-admin


# 安装依赖
npm install


遇到报错了
nodejs报错解决: EBUSY: resource busy or locked 和 npm ERR! errno -4082

建议不要用 cnpm 安装 会有各种诡异的bug 可以通过如下操作解决 npm 下载速度慢的问题

npm install –registry=https://registry.npmmirror.com

1
2
3
4
5
6
7
8
9
10
11
12
13
# 本地开发 启动项目
npm run dev


安装失败 清缓存 后从新安装 成功了
npm cache clean --force

# 安装依赖
npm install

# 本地开发 启动项目
npm run dev

左侧菜单配置路由

找到路由配置文件 src\router\index.js

1
2
3
4
5
6
7
8
9
10
11
export const constantRoutes   基础路由配置


export const asyncRoutes 异步加载路由配置


可以注释掉然后引入自己的路由配置

import myrouter from './modules/myrouter'

export const asyncRoutes = myrouter

案例 myrouter.js 只显示父级 显示子集 详情页路由//详情页路由,面包屑无法追加问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
mport Layout from '@/layout'
const componentsRouter = [
{
path: '/',
component: Layout,
redirect: '/homepage',
children: [
{
path: 'homepage',
component: () => import('@/myViews/homepage/homepage'),
name: 'homepage',
meta: { title: '首页', icon: 'dashboard', affix: true }
}
]
},
{
path: '/xtgl',
component: Layout,
redirect: '/xtgl/bmgl',
alwaysShow: true, // will always show the root menu
name: 'xtgl',
meta: {
title: '系统管理',
// icon: 'lock',
icon: 'icon-gengduo',
roles: ['admin', 'editor'] // you can set roles in root nav
},
children: [
{
path: 'bmgl',
component: () => import('@/myViews/xtgl/bmgl'),
name: 'bmgl',
meta: {
title: '部门管理',
roles: ['admin'] // or you can only set roles in sub nav
}
},
{
path: 'yhgl',
component: () => import('@/myViews/xtgl/yhgl'),
name: 'yhgl',
meta: {
title: '用户管理'
// if do not set roles, means: this page does not require permission
}
},
{
path: 'qxgl',
component: () => import('@/myViews/xtgl/qxgl'),
name: 'qxgl',
meta: {
title: '权限管理',
roles: ['admin']
}
},
{
path: 'gzrz',
component: () => import('@/myViews/xtgl/gzrz'),
name: 'gzrz',
meta: {
title: '工作日志',
roles: ['admin']
}
},
]
},
{
path: '/nrgl',
component: Layout,
redirect: '/index',
children: [
{
path: 'index',
component: () => import('@/views/myview/nrgl/index'),
name: 'nrgl',
meta: { title: '内容管理', icon: 'dashboard', affix: true }
},
{
path: 'detail',
component: () => import('@/views/myview/nrgl/detail'),
name: 'nrgl',
meta: { title: '内容详情', icon: 'dashboard', affix: true },
hidden: true
},
]
},


//详情页路由,面包屑无法追加问题
{
path: '/nrgl',
component: Layout,
redirect: '/nrgl/index',
meta: {
title: '内容管理',
icon: 'el-icon-s-help'
},
children: [
{
path: 'index',
component: () => import('@/views/myview/nrgl/index'),
name: 'index',
meta: { title: '内容列表', icon: 'dashboard' }
},
{
path: 'detail',
component: () => import('@/views/myview/nrgl/detail'),
name: 'detail',
meta: { title: '内容详情', icon: 'dashboard', noCache: true, activeMenu: '/nrgl/index' },
hidden: true
},
]
},
//详情路由追加 meta: { title: '内容详情', icon: 'dashboard', noCache: true, activeMenu: '/nrgl/index' }, 路径定向到列表页
{
path: '/jcxm',
component: Layout,
redirect: '/jcxm',
children: [
{
path: 'jcxm',
component: () => import('@/myViews/jcxm'),
name: 'jcxm',
meta: { title: '检测项目', icon: 'dashboard', affix: true }
}
]
},
{
path: '/htgl',
component: Layout,
redirect: '/htgl',
children: [
{
path: 'htgl',
component: () => import('@/myViews/htgl'),
name: 'htgl',
meta: { title: '合同管理', icon: 'dashboard', affix: true }
}
]
},
]
export default componentsRouter

只显示父级

1
2
3
4
5
6
7
8
9
10
11
12
13
{
path: '/',
component: Layout,
redirect: '/homepage',
children: [
{
path: 'homepage',
component: () => import('@/myViews/homepage/homepage'),
name: 'homepage',
meta: { title: '首页', icon: 'dashboard', affix: true }
}
]
},

显示子集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
path: '/xtgl',
component: Layout,
redirect: '/xtgl/bmgl',
alwaysShow: true, // will always show the root menu
name: 'xtgl',
meta: {
title: '系统管理',
// icon: 'lock',
icon: 'icon-gengduo',
roles: ['admin', 'editor'] // you can set roles in root nav
},
children: [
{
path: 'bmgl',
component: () => import('@/myViews/xtgl/bmgl'),
name: 'bmgl',
meta: {
title: '部门管理',
roles: ['admin'] // or you can only set roles in sub nav
}
},

详情页路由

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
path: '/nrgl',
component: Layout,
redirect: '/index',
children: [
{
path: 'index',
component: () => import('@/views/myview/nrgl/index'),
name: 'nrgl',
meta: { title: '内容管理', icon: 'dashboard', affix: true }
},
{
path: 'detail',
component: () => import('@/views/myview/nrgl/detail'),
name: 'nrgl',
meta: { title: '内容详情', icon: 'dashboard', affix: true },
hidden: true
},
]
},

详情页路由,面包屑无法追加问题

noCache: true, activeMenu: ‘/nrgl/index’ },

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//详情页路由,面包屑无法追加问题
{
path: '/nrgl',
component: Layout,
redirect: '/nrgl/index',
meta: {
title: '内容管理',
icon: 'el-icon-s-help'
},
children: [
{
path: 'index',
component: () => import('@/views/myview/nrgl/index'),
name: 'index',
meta: { title: '内容列表', icon: 'dashboard' }
},
{
path: 'detail',
component: () => import('@/views/myview/nrgl/detail'),
name: 'detail',
meta: { title: '内容详情', icon: 'dashboard', noCache: true, activeMenu: '/nrgl/index' },
hidden: true
},
]
},

//详情路由追加 meta: { title: ‘内容详情’, icon: ‘dashboard’, noCache: true, activeMenu: ‘/nrgl/index’ }, 路径定向到列表页

路由详情页左侧没有高亮问题

详情页路由加上

meta: { title: ‘内容详情’, icon: ‘dashboard’, noCache: true, activeMenu: ‘/nrgl/index’ },

左侧菜单图标自定义

1 去阿里图表库下载
https://www.iconfont.cn/collections/index?spm=a313x.7781069.1998910419.42

购物车 》 下载代码

2 src\assets 文件下新建 icon 文件夹 将下载好的文件放进去

src\assets\icon demo_index.html。。。。等

3 src\main.js 文件下引入

import ‘@/assets/icon/iconfont.css’

4 找到 Item.vue文件 src\layout\components\Sidebar\Item.vue

1
2
3
4
5
6
7
8
9
10
11
12
if (icon) {
console.log('icon',icon);
if (icon.includes('el-icon')) {
vnodes.push(<i class={[icon, 'sub-el-icon']} />)
} else if (icon.includes('icon-')) {
vnodes.push(<i class={[icon, 'iconfont']} style="margin-right:10px" />)
} else {
vnodes.push(<svg-icon icon-class={icon} />)
}
}


加 下面的代码

1
2
3
else if (icon.includes('icon-')) {
vnodes.push(<i class={[icon, 'iconfont']} style="margin-right:10px" />)
}

当 icon.includes(‘icon-‘ 根据 路由配置里的

1
2
3
4
5
meta: {
title: '系统管理',
icon: 'icon-gengduo',
roles: ['admin', 'editor'] // you can set roles in root nav
},

去判断
执行

1
vnodes.push(<i class={[icon, 'iconfont']} style="margin-right:10px" />)

5去配置路由 src\router\index.js 路由配置文件

左侧菜单折叠后对不齐问题

修改这个文件 src\styles\sidebar.scss

加这么一个样式

1
2
3
4
5
6
#app .hideSidebar .el-scrollbar__view .iconfont{
margin-right: 16px !important;
margin-left: 20px !important;

}

后来发现在这里控制 加入新的图标类名 和样式 原来的是.svg-icon 加新图标后 类名变了 所以之前的样式不生效了

1
2
3
.iconfont {
margin-left: 16px;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
src\styles\sidebar.scss

.hideSidebar {
.sidebar-container {
width: 54px !important;
}

.main-container {
margin-left: 54px;
}

.submenu-title-noDropdown {
padding: 0 !important;
position: relative;

.el-tooltip {
padding: 0 !important;
display: flex !important;
justify-content: center !important;

.iconfont {
margin-left: 16px;
}
.svg-icon {
margin-left: 20px;
}

修改框架布局

找到这个文件 src\layout\index.vue

进行布局 修改

样式修改

1
2
3
4
5
6
7
8
<style scoped lang="scss">
  .form {
    background-color: #fff;
    /deep/ .list{
      font-size: 18px;
    }
  }
</style>

scss文件中使用深度选择器/deep/报错 Expected selector解决方法
记得sass中使用/deep/没问题,但是在scss中使用/deep/报错了。
找到vue官网关于深度选择器是这样说的:

有些像 Sass 之类的预处理器无法正确解析 >>>。这种情况下你可以使用 /deep/ 或 ::v-deep 操作符取而代之——两者都是 >>> 的别名,同样可以正常工作。

于是用 ::v-deep 就可以了

1
2
3
::v-deep .el-checkbox__input{
display: none;
}

Cookies 存储 配合 vuex

src\utils\auth.js 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import Cookies from 'js-cookie'

const TokenKey = 'Admin-Token'

export function getToken() {
return Cookies.get(TokenKey)
}

export function setToken(token) {
return Cookies.set(TokenKey, token)
}

export function removeToken() {
return Cookies.remove(TokenKey)
}

src\permission.js 文件 使用

1
2
3
4
import { getToken } from '@/utils/auth' // get token from cookie


const hasToken = getToken()

src\store\modules\user.js vuex文件

1
2
3
4
5
6
7
8
9
10
11
12
13
import { login, logout, getInfo } from '@/api/user'
import { getToken, setToken, removeToken, getMenuEd } from '@/utils/auth'
import router, { resetRouter } from '@/router'

const state = {
token: getToken(),
name: '',
avatar: '',
introduction: '',
roles: [],
xtMenuEd: 'xtsz',
}

跨域代理配置

vue.config.js

1
2
3
'/api': { // 拦截以 /api 开头的url接口
// target: 'http://192.168.1.22:8088/meeting',//代理的地址和端口 志阳
target: process.env.VUE_APP_BASE_FILE_API,//冀川
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
devServer: {
// port: port,
// open: true,
// overlay: {
// warnings: false,
// errors: true
// },
// before: require('./mock/mock-server.js')
// 新。。。。。。。。。。。。。。。。。。。
host: '0.0.0.0',//本地ip0.0.0.0'==192.168.1.18(我的)
port: 3001,//本地端口
https: false, //是否启用HTTPS协议
// // hot: true, //是否开启热加载
open: true, //配置自动启动浏览器
proxy: { //目的是解决跨域,若测试环境不需要跨域,则不需要进行该配置
'/api': { // 拦截以 /api 开头的url接口
// target: 'http://192.168.1.22:8088/meeting',//代理的地址和端口 志阳
target: process.env.VUE_APP_BASE_FILE_API,//冀川
changeOrigin: true, //是否跨域
ws: true, //如果要代理 websockets,配置这个参数
secure: false, // 如果是https接口,需要配置这个参数
// 标识替换
// 原请求地址为 /api/getData 将'/api'替换''时,
// 代理后的请求地址为: http://xxx.xxx.xxx/getData
// 若替换为'/other',则代理后的请求地址为 http://xxx.xxx.xxx/other/getData
// rewrite: (path) => path.replace(/^\/api/, ''),
pathRewrite: {
//重写接口 后台接口指向不统一 所以指向所有''
'^/api': ''
}
},
},
},

环境变量配置

.env.development

1
2
3
4
5
6
7
# just a flag
ENV = 'development'

VUE_APP_BASE_API = '/api'
VUE_APP_BASE_FILE_API = 'http://192.168.1.103:9999/'


axios 请求 配置
src\utils\request.js

1
2
3
4
5
6

const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
// withCredentials: true, // send cookies when cross-domain requests
timeout: 5000 // request timeout
})

图片地址代理

src\utils\request.js

1
2
3
4
5
6
7
8
// create an axios instance
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
// baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
// withCredentials: true, // send cookies when cross-domain requests
timeout: 5000 // request timeout
})

process.env.VUE_APP_BASE_API
本地.env.development没有的时候是空

vue.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
proxy: {
// 如果地址以 /api开头 就会请求到目标 ip
"/pc": {
// 目标代理服务器地址
target: process.env.VUE_APP_BASE_API2,//https://huzhou-safecode-nx.spacecig.com:8443
// 开启代理,本地创建一个虚拟服务器 允许跨域
changeOrigin: true,
// 如果要代理 websockets,配置这个参数
ws: true,
// 如果是https接口,需要配置这个参数
secure: true,
// 标识替换
// 原请求地址为 /api/getData 将'/api'替换''时,
// 代理后的请求地址为: http://xxx.xxx.xxx/getData
// 若替换为'/other',则代理后的请求地址为 http://xxx.xxx.xxx/other/getData
// 接口本身有api就注释掉
pathRewrite: {
//重写接口 后台接口指向不统一 所以指向所有''
'^/pc': '/pc'
}
},
"/mini": {
// 目标代理服务器地址
target: process.env.VUE_APP_BASE_API2,//https://huzhou-safecode-nx.spacecig.com:8443
// 开启代理,本地创建一个虚拟服务器 允许跨域
changeOrigin: true,
// 如果要代理 websockets,配置这个参数
ws: true,
// 如果是https接口,需要配置这个参数
secure: true,
// 标识替换
// 原请求地址为 /api/getData 将'/api'替换''时,
// 代理后的请求地址为: http://xxx.xxx.xxx/getData
// 若替换为'/other',则代理后的请求地址为 http://xxx.xxx.xxx/other/getData
// 接口本身有api就注释掉
pathRewrite: {
//重写接口 后台接口指向不统一 所以指向所有''
'^/mini': ''
}
},
}

.env.production

1
2
3
4
5
6
7
# just a flag
ENV = 'production'

# base api
# VUE_APP_BASE_API = '/prod-api'
VUE_APP_BASE_API = '/mini'
VUE_APP_BASE_API2 = 'https://wsq.tjxwyun.com/mini'

.env.development

1
2
3
4
5
6
7
8
9
10
11

# just a flag
ENV = 'development'

# base api
# VUE_APP_BASE_API = '/dev-api'
# VUE_APP_BASE_API = '/mini'
VUE_APP_BASE_API2 = 'https://wsq.tjxwyun.com/mini'
# VUE_APP_BASE_API2 = 'http://192.168.1.39:9095/mini'
# VUE_APP_BASE_API2 = 'http://192.168.1.22:9095/mini'

vue文件 `/mini

1
<img :src="`/mini${item.cusHead}`" alt="">

知识点vue.config.js 只代理本地地址生效,线上地址不生效(需要后端代理

每个请求设置token

config.headers[‘Token’] = getToken()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
src\utils\request.js



service.interceptors.request.use(
config => {
// do something before request is sent

if (store.getters.token) {
// let each request carry token
// ['X-Token'] is a custom headers key
// please modify it according to the actual situation
// config.headers['X-Token'] = getToken()
config.headers['Token'] = getToken()
}
return config
},
error => {
// do something with request error
console.log(error) // for debug
return Promise.reject(error)
}
)

git post请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import request from '@/utils/request'


// 登陆
export function login(data) {
return request({
url: 'zljc-auth/login',
method: 'post',
data
})
}
// 查询系统路由权限
export function getuser(data) {
return request({
url: '/zljc-system/menu/user',
method: 'get',
params: data
})
}

路由meta 操作

1
this.$route.meta

菜单三级子集路由嵌套

1
2
3
4
5
6
7
要再第二级  加   index.vue


<template>
<router-view />
</template>

修改hmlt页面标题和图标

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
src\settings.js

module.exports = {
title: '微社区后台管理系统',
// title: 'Vue Element Admin',



图标
public\favicon.ico

把图片放这里 public 文件夹下



public\index.html


修改图片名称
<link rel="icon" href="<%= BASE_URL %>favicon.ico">

el-input

input 记忆连锁导致背景色bug

1
2
3
4
5
6
7
8
9
10
::v-deep .el-input input:-webkit-autofill{
webkit-box-shadow:none;
box-shadow:none !important;
//文字颜色
-webkit-text-fill-color:#000 !important;
//背景色
-webkit-box-shadow: 0 0 0px 1000px #fff inset !important;
background-color: #fff !important;

}

只能输入数字并限制输入范围

1
2
3
<el-input onkeyup="value=value.replace(/[^\d||/.]/g,'')"
oninput="if(value){value=value.replace(/[^\d]/g,'')} if(value<=0){value= ''} if(value>60){value=60}"
v-model="input" type="number" placeholder="请输入内容"></el-input>

vue-element-admin遇到的问题和解决记录
http://www.dwyblog.cn/2024/01/10/vue-element-admin遇到的问题和解决记录/
作者
幸福来敲门
发布于
2024年1月10日
许可协议