Commit 61317410 authored by dupengyu's avatar dupengyu

Squashed commit of the following:

commit b1aba8b5
Author: wuxth <wuxth@foxmail.com>
Date:   Thu Jan 16 19:22:49 2025 +0800

    路由 角色 权限 模块对接完成 整体流程未测试

commit 3bbb3783
Author: wuxth <wuxth@foxmail.com>
Date:   Thu Jan 16 11:27:04 2025 +0800

    路由角色权限等调试

# Conflicts:
#	src/api/menu.js
parent 8e9af031
File deleted
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
"echarts": "^5.3.1", "echarts": "^5.3.1",
"element-ui": "2.13.2", "element-ui": "2.13.2",
"events": "^3.3.0", "events": "^3.3.0",
"file-saver": "^2.0.5",
"inquirer": "^8.2.0", "inquirer": "^8.2.0",
"js-cookie": "2.2.0", "js-cookie": "2.2.0",
"moment": "^2.29.1", "moment": "^2.29.1",
......
...@@ -4,6 +4,6 @@ import request from '@/utils/request' ...@@ -4,6 +4,6 @@ import request from '@/utils/request'
export const getRouters = () => { export const getRouters = () => {
return request({ return request({
url: '/api/user/getRouters', url: '/api/user/getRouters',
method: 'get' method: 'post'
}) })
} }
\ No newline at end of file
<template >
<router-view />
</template>
...@@ -10,7 +10,6 @@ export default { ...@@ -10,7 +10,6 @@ export default {
const { value } = binding const { value } = binding
const all_permission = "*:*:*"; const all_permission = "*:*:*";
const permissions = store.getters && store.getters.permissions const permissions = store.getters && store.getters.permissions
console.log(permissions)
if (value && value instanceof Array && value.length > 0) { if (value && value instanceof Array && value.length > 0) {
const permissionFlag = value const permissionFlag = value
......
<template>
<div
:style="'height:' + height"
v-loading="loading"
element-loading-text="正在加载页面,请稍候!"
>
<iframe
:id="iframeId"
style="width: 100%; height: 100%"
:src="src"
frameborder="no"
></iframe>
</div>
</template>
<script>
export default {
props: {
src: {
type: String,
default: "/",
},
iframeId: {
type: String,
},
},
data() {
return {
loading: false,
height: document.documentElement.clientHeight - 94.5 + "px;",
};
},
mounted() {
var _this = this;
const iframeId = ("#" + this.iframeId).replace(/\//g, "\\/");
const iframe = document.querySelector(iframeId);
// iframe页面loading控制
if (iframe.attachEvent) {
this.loading = true;
iframe.attachEvent("onload", function () {
_this.loading = false;
});
} else {
this.loading = true;
iframe.onload = function () {
_this.loading = false;
};
}
},
};
</script>
...@@ -17,25 +17,17 @@ export default { ...@@ -17,25 +17,17 @@ export default {
const vnodes = [] const vnodes = []
if (icon) { if (icon) {
if (icon.includes('el-icon')) { vnodes.push(<svg-icon icon-class={icon}/>)
vnodes.push(<i class={[icon, 'sub-el-icon']} />)
} else {
vnodes.push(<svg-icon icon-class={icon}/>)
}
} }
if (title) { if (title) {
vnodes.push(<span slot='title'>{(title)}</span>) if (title.length > 5) {
vnodes.push(<span slot='title' title={(title)}>{(title)}</span>)
} else {
vnodes.push(<span slot='title'>{(title)}</span>)
}
} }
return vnodes return vnodes
} }
} }
</script> </script>
<style scoped>
.sub-el-icon {
color: currentColor;
width: 1em;
height: 1em;
}
</style>
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
!item.alwaysShow !item.alwaysShow
" "
> >
<app-link <app-link
v-if="onlyOneChild.meta" v-if="onlyOneChild.meta"
:to=" :to="
...@@ -29,12 +30,13 @@ ...@@ -29,12 +30,13 @@
</template> </template>
<template v-else> <template v-else>
<el-submenu id="subid" ref="subMenu" :index="resolvePath(item.path)"> <el-submenu id="subid" ref="subMenu" :index="resolvePath(item.path)">
<template slot="title"> <template slot="title">
<icon-item <icon-item
v-if="item.meta" v-if="item.meta"
:icon="item.meta && item.meta.icon" :icon="item.meta && item.meta.icon"
:title="item.meta.title" :title="item.meta.title||item.menuName"
/> />
</template> </template>
<sidebar-item <sidebar-item
......
...@@ -34,11 +34,13 @@ export default { ...@@ -34,11 +34,13 @@ export default {
'sidebar' 'sidebar'
]), ]),
routes() { routes() {
console.log('routes',this.$store.state.permission.routes)
return this.$store.state.permission.routes return this.$store.state.permission.routes
}, },
activeMenu() { activeMenu() {
const route = this.$route; const route = this.$route;
const { meta, path } = route; const { meta, path } = route;
// if set path, the sidebar will highlight the path you set // if set path, the sidebar will highlight the path you set
if (meta.activeMenu) { if (meta.activeMenu) {
return meta.activeMenu; return meta.activeMenu;
......
...@@ -10,6 +10,7 @@ import router from './router' ...@@ -10,6 +10,7 @@ import router from './router'
import '@/icons' // icon import '@/icons' // icon
import '@/permission' // permission control import '@/permission' // permission control
import performLoader from '@/utils/global_main_loader.js' import performLoader from '@/utils/global_main_loader.js'
import plugins from './plugins' // plugins
import WS from '@/utils/websocket' import WS from '@/utils/websocket'
import { getDicts } from "@/api/system/dict/data"; import { getDicts } from "@/api/system/dict/data";
import directive from './directive' // directive import directive from './directive' // directive
...@@ -31,6 +32,7 @@ Vue.prototype.resetForm = resetForm ...@@ -31,6 +32,7 @@ Vue.prototype.resetForm = resetForm
Vue.prototype.addDateRange = addDateRange Vue.prototype.addDateRange = addDateRange
Vue.prototype.selectDictLabel = selectDictLabel Vue.prototype.selectDictLabel = selectDictLabel
Vue.prototype.selectDictLabels = selectDictLabels Vue.prototype.selectDictLabels = selectDictLabels
Vue.use(plugins)
Vue.component('RightToolbar', RightToolbar) Vue.component('RightToolbar', RightToolbar)
Vue.component('DictTag', DictTag) Vue.component('DictTag', DictTag)
Vue.use(directive) Vue.use(directive)
......
import router from './router' import router from './router'
import store from './store' import store from './store'
import { Message } from 'element-ui' import { Message } from 'element-ui'
import NProgress from 'nprogress' // progress bar import NProgress from 'nprogress'
import 'nprogress/nprogress.css' // progress bar style import 'nprogress/nprogress.css'
import { getToken } from '@/utils/auth' // get token from cookie import { getToken } from '@/utils/auth'
import getPageTitle from '@/utils/get-page-title' import { isRelogin } from '@/utils/request'
NProgress.configure({ showSpinner: false }) // NProgress Configuration NProgress.configure({ showSpinner: false })
const whiteList = ['/login'] const whiteList = ['/login', '/register']
router.beforeEach(async (to, from, next) => { router.beforeEach((to, from, next) => {
console.log('console.log(to)',to)
NProgress.start() NProgress.start()
if (getToken()) {
document.title = getPageTitle(to.meta.title) to.meta.title && store.dispatch('settings/setTitle', to.meta.title)
/* has token*/
const hasToken = getToken()
if (hasToken) {
if (to.path === '/login') { if (to.path === '/login') {
next({ path: '/' }) next({ path: '/' })
NProgress.done() NProgress.done()
} else if (whiteList.indexOf(to.path) !== -1) {
next()
} else { } else {
const hasRoles = store.state.user && store.state.user.roles.length > 0 if (store.getters.roles.length === 0) {
if (hasRoles) { console.log('console.log(store.getters.roles.length)',store.getters.roles)
next() isRelogin.show = true
// 判断当前用户是否已拉取完user_info信息
store.dispatch('user/getInfo').then(() => {
isRelogin.show = false
store.dispatch('GenerateRoutes').then(accessRoutes => {
console.log('accessRoutes',accessRoutes)
// 根据roles权限生成可访问的路由表
router.addRoutes(accessRoutes) // 动态添加可访问路由表
if (to.path == '/') {
var path = accessRoutes[0].path == '/' ? '' : accessRoutes[0].path + '/' + accessRoutes[0].children[0].path
next({ path: path })
} else {
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
}
})
}).catch(err => {
store.dispatch('LogOut').then(() => {
Message.error(err)
next({ path: '/' })
})
})
} else { } else {
try { next()
const { isAdmin } = await store.dispatch('user/getInfo')
const roles = isAdmin == 1 ? ['admin'] : ['editor']
const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
router.addRoutes(accessRoutes)
next({ ...to, replace: true })
} catch (error) {
await store.dispatch('user/resetToken')
Message.error(error || 'Has Error')
next(`/login?redirect=${to.path}`)
NProgress.done()
}
} }
} }
} else { } else {
/* has no token*/ // 没有token
if (whiteList.indexOf(to.path) !== -1) { if (whiteList.indexOf(to.path) !== -1) {
// 在免登录白名单,直接进入
next() next()
} else { } else {
next(`/login?redirect=${to.path}`) next(`/login?redirect=${encodeURIComponent(to.fullPath)}`) // 否则全部重定向到登录页
NProgress.done() NProgress.done()
} }
} }
......
import store from '@/store'
function authPermission(permission) {
const all_permission = "*:*:*";
const permissions = store.getters && store.getters.permissions
if (permission && permission.length > 0) {
return permissions.some(v => {
return all_permission === v || v === permission
})
} else {
return false
}
}
function authRole(role) {
const super_admin = "admin";
const roles = store.getters && store.getters.roles
if (role && role.length > 0) {
return roles.some(v => {
return super_admin === v || v === role
})
} else {
return false
}
}
export default {
// 验证用户是否具备某权限
hasPermi(permission) {
return authPermission(permission);
},
// 验证用户是否含有指定权限,只需包含其中一个
hasPermiOr(permissions) {
return permissions.some(item => {
return authPermission(item)
})
},
// 验证用户是否含有指定权限,必须全部拥有
hasPermiAnd(permissions) {
return permissions.every(item => {
return authPermission(item)
})
},
// 验证用户是否具备某角色
hasRole(role) {
return authRole(role);
},
// 验证用户是否含有指定角色,只需包含其中一个
hasRoleOr(roles) {
return roles.some(item => {
return authRole(item)
})
},
// 验证用户是否含有指定角色,必须全部拥有
hasRoleAnd(roles) {
return roles.every(item => {
return authRole(item)
})
}
}
const sessionCache = {
set (key, value) {
if (!sessionStorage) {
return
}
if (key != null && value != null) {
sessionStorage.setItem(key, value)
}
},
get (key) {
if (!sessionStorage) {
return null
}
if (key == null) {
return null
}
return sessionStorage.getItem(key)
},
setJSON (key, jsonValue) {
if (jsonValue != null) {
this.set(key, JSON.stringify(jsonValue))
}
},
getJSON (key) {
const value = this.get(key)
if (value != null) {
return JSON.parse(value)
}
},
remove (key) {
sessionStorage.removeItem(key);
}
}
const localCache = {
set (key, value) {
if (!localStorage) {
return
}
if (key != null && value != null) {
localStorage.setItem(key, value)
}
},
get (key) {
if (!localStorage) {
return null
}
if (key == null) {
return null
}
return localStorage.getItem(key)
},
setJSON (key, jsonValue) {
if (jsonValue != null) {
this.set(key, JSON.stringify(jsonValue))
}
},
getJSON (key) {
const value = this.get(key)
if (value != null) {
return JSON.parse(value)
}
},
remove (key) {
localStorage.removeItem(key);
}
}
export default {
/**
* 会话级缓存
*/
session: sessionCache,
/**
* 本地缓存
*/
local: localCache
}
import axios from 'axios'
import {Loading, Message} from 'element-ui'
import { saveAs } from 'file-saver'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { blobValidate } from "@/utils/ruoyi";
const baseURL = process.env.VUE_APP_BASE_API
let downloadLoadingInstance;
export default {
name(name, isDelete = true) {
var url = baseURL + "/common/download?fileName=" + encodeURIComponent(name) + "&delete=" + isDelete
axios({
method: 'get',
url: url,
responseType: 'blob',
headers: { 'Authorization': 'Bearer ' + getToken() }
}).then((res) => {
const isBlob = blobValidate(res.data);
if (isBlob) {
const blob = new Blob([res.data])
this.saveAs(blob, decodeURIComponent(res.headers['download-filename']))
} else {
this.printErrMsg(res.data);
}
})
},
resource(resource) {
var url = baseURL + "/common/download/resource?resource=" + encodeURIComponent(resource);
axios({
method: 'get',
url: url,
responseType: 'blob',
headers: { 'Authorization': 'Bearer ' + getToken() }
}).then((res) => {
const isBlob = blobValidate(res.data);
if (isBlob) {
const blob = new Blob([res.data])
this.saveAs(blob, decodeURIComponent(res.headers['download-filename']))
} else {
this.printErrMsg(res.data);
}
})
},
zip(url, name) {
var url = baseURL + url
downloadLoadingInstance = Loading.service({ text: "正在下载数据,请稍候", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", })
axios({
method: 'get',
url: url,
responseType: 'blob',
headers: { 'Authorization': 'Bearer ' + getToken() }
}).then((res) => {
const isBlob = blobValidate(res.data);
if (isBlob) {
const blob = new Blob([res.data], { type: 'application/zip' })
this.saveAs(blob, name)
} else {
this.printErrMsg(res.data);
}
downloadLoadingInstance.close();
}).catch((r) => {
console.error(r)
Message.error('下载文件出现错误,请联系管理员!')
downloadLoadingInstance.close();
})
},
saveAs(text, name, opts) {
saveAs(text, name, opts);
},
async printErrMsg(data) {
const resText = await data.text();
const rspObj = JSON.parse(resText);
const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
Message.error(errMsg);
}
}
import tab from './tab'
import auth from './auth'
import cache from './cache'
import modal from './modal'
import download from './download'
export default {
install(Vue) {
// 页签操作
Vue.prototype.$tab = tab
// 认证对象
Vue.prototype.$auth = auth
// 缓存对象
Vue.prototype.$cache = cache
// 模态框对象
Vue.prototype.$modal = modal
// 下载文件
Vue.prototype.$download = download
}
}
import { Message, MessageBox, Notification, Loading } from 'element-ui'
let loadingInstance;
export default {
// 消息提示
msg(content) {
Message.info(content)
},
// 错误消息
msgError(content) {
Message.error(content)
},
// 成功消息
msgSuccess(content) {
Message.success(content)
},
// 警告消息
msgWarning(content) {
Message.warning(content)
},
// 弹出提示
alert(content) {
MessageBox.alert(content, "系统提示")
},
// 错误提示
alertError(content) {
MessageBox.alert(content, "系统提示", { type: 'error' })
},
// 成功提示
alertSuccess(content) {
MessageBox.alert(content, "系统提示", { type: 'success' })
},
// 警告提示
alertWarning(content) {
MessageBox.alert(content, "系统提示", { type: 'warning' })
},
// 通知提示
notify(content) {
Notification.info(content)
},
// 错误通知
notifyError(content) {
Notification.error(content);
},
// 成功通知
notifySuccess(content) {
Notification.success(content)
},
// 警告通知
notifyWarning(content) {
Notification.warning(content)
},
// 确认窗体
confirm(content) {
return MessageBox.confirm(content, "系统提示", {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: "warning",
})
},
// 提交内容
prompt(content) {
return MessageBox.prompt(content, "系统提示", {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: "warning",
})
},
// 打开遮罩层
loading(content) {
loadingInstance = Loading.service({
lock: true,
text: content,
spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.7)",
})
},
// 关闭遮罩层
closeLoading() {
loadingInstance.close();
}
}
import store from '@/store'
import router from '@/router';
export default {
// 刷新当前tab页签
refreshPage(obj) {
const { path, query, matched } = router.currentRoute;
if (obj === undefined) {
matched.forEach((m) => {
if (m.components && m.components.default && m.components.default.name) {
if (!['Layout', 'ParentView'].includes(m.components.default.name)) {
obj = { name: m.components.default.name, path: path, query: query };
}
}
});
}
return store.dispatch('tagsView/delCachedView', obj).then(() => {
const { path, query } = obj
router.replace({
path: '/redirect' + path,
query: query
})
})
},
// 关闭当前tab页签,打开新页签
closeOpenPage(obj) {
store.dispatch("tagsView/delView", router.currentRoute);
if (obj !== undefined) {
return router.push(obj);
}
},
// 关闭指定tab页签
closePage(obj) {
if (obj === undefined) {
return store.dispatch('tagsView/delView', router.currentRoute).then(({ visitedViews }) => {
const latestView = visitedViews.slice(-1)[0]
if (latestView) {
return router.push(latestView.fullPath)
}
return router.push('/');
});
}
return store.dispatch('tagsView/delView', obj);
},
// 关闭所有tab页签
closeAllPage() {
return store.dispatch('tagsView/delAllViews');
},
// 关闭左侧tab页签
closeLeftPage(obj) {
return store.dispatch('tagsView/delLeftTags', obj || router.currentRoute);
},
// 关闭右侧tab页签
closeRightPage(obj) {
return store.dispatch('tagsView/delRightTags', obj || router.currentRoute);
},
// 关闭其他tab页签
closeOtherPage(obj) {
return store.dispatch('tagsView/delOthersViews', obj || router.currentRoute);
},
// 添加tab页签
openPage(title, url, params) {
const obj = { path: url, meta: { title: title } }
store.dispatch('tagsView/addView', obj);
return router.push({ path: url, query: params });
},
// 修改tab页签
updatePage(obj) {
return store.dispatch('tagsView/updateVisitedView', obj);
}
}
...@@ -11,51 +11,38 @@ import Layout from '@/layout' ...@@ -11,51 +11,38 @@ import Layout from '@/layout'
* all roles can be accessed * all roles can be accessed
*/ */
export const constantRoutes = [ export const constantRoutes = [
{
path: '/404',
component: () => import('@/views/error/404'),
hidden: true
},
{ {
path: '/login', path: '/login',
component: () => import('@/views/login/index'), component: () => import('@/views/login/index'),
meta: { title: "登录" }, meta: { title: "登录" },
hidden: true hidden: true
}, },
// {
{ // path: '/alarm',
path: '/', // component: Layout,
component: Layout, // redirect: '/dashboard',
redirect: '/dashboard', // name: 'alarm',
children: [{ // meta: { title: '告警管理', icon: 'alarm' },
path: 'dashboard', // children: [
name: 'Dashboard', // {
component: () => import('@/views/dashboard/index'), // path: 'cableTime',
meta: { title: '首页', icon: 'homePage' } // name: 'cableTime',
}] // component: () => import('@/views/alarm/cableTime/index'),
}, // meta: { title: '漏缆监测告警' }
{ // },
path: '/alarm', // {
component: Layout, // path: 'statistics',
redirect: '/dashboard', // name: 'statistics',
name: 'alarm', // component: () => import('@/views/alarm/statistics/index'),
meta: { title: '告警管理', icon: 'alarm' }, // meta: { title: '告警信息统计' }
children: [ // }
{ // ]
path: 'cableTime', // },
name: 'cableTime',
component: () => import('@/views/alarm/cableTime/index'),
meta: { title: '漏缆监测告警' }
},
// {
// path: 'device',
// name: 'device',
// component: () => import('@/views/alarm/device/index'),
// meta: { title: '设备连接告警' }
// },
{
path: 'statistics',
name: 'statistics',
component: () => import('@/views/alarm/statistics/index'),
meta: { title: '告警信息统计' }
}
]
},
{ {
path: '/setting', path: '/setting',
component: Layout, component: Layout,
...@@ -247,7 +234,29 @@ export const constantRoutes = [ ...@@ -247,7 +234,29 @@ export const constantRoutes = [
name: '角色管理', name: '角色管理',
component: () => import('@/views/system/role/index'), component: () => import('@/views/system/role/index'),
meta: { title: '角色管理' } meta: { title: '角色管理' }
},
{
path: 'updateUser',
name: 'UpdateUser',
component: () => import('@/views/system/user/updateUser'),
meta: { title: '个人信息管理', },
},
{
path: 'userList',
name: 'UserList',
component: () => import('@/views/system/user/userList'),
meta: { title: '用户信息列表', },
},
{
path: 'userLog',
name: 'UserLog',
component: () => import('@/views/system/user/userLog'),
meta: { title: '用户操作日志', },
} }
] ]
}, },
] ]
...@@ -282,9 +291,44 @@ export const asyncRoutes = [ ...@@ -282,9 +291,44 @@ export const asyncRoutes = [
}] }]
}, },
// 404 page must be placed at the end !!! // 404 page must be placed at the end !!!
{ path: '*', redirect: '/404', hidden: true } { path: '*', redirect: '/404', hidden: true },
] {
path: '/404',
component: () => import('@/views/error/404'),
hidden: true
},
]
export const dynamicRoutes = [
{
path: '/system/user-auth',
component: Layout,
hidden: true,
permissions: ['system:user:edit'],
children: [
{
path: 'role/:userId(\\d+)',
component: () => import('@/views/system/user/authRole'),
name: 'AuthRole',
meta: { title: '分配角色', activeMenu: '/system/user' }
}
]
},
{
path: '/system/role-auth',
component: Layout,
hidden: true,
permissions: ['system:role:edit'],
children: [
{
path: 'user/:roleId(\\d+)',
component: () => import('@/views/system/role/authUser'),
name: 'AuthUser',
meta: { title: '分配用户', activeMenu: '/system/role' }
}
]
},
]
const createRouter = () => new Router({ const createRouter = () => new Router({
// mode: 'history', // require service support // mode: 'history', // require service support
scrollBehavior: () => ({ y: 0 }), scrollBehavior: () => ({ y: 0 }),
......
...@@ -3,5 +3,7 @@ const getters = { ...@@ -3,5 +3,7 @@ const getters = {
device: state => state.app.device, device: state => state.app.device,
token: state => state.user.token, token: state => state.user.token,
dict: state => state.dict.dict, dict: state => state.dict.dict,
roles: state => state.user.roles,
permissions: state => state.user.permissions,
} }
export default getters export default getters
import { asyncRoutes, constantRoutes } from '@/router' import auth from '@/plugins/auth'
import router, { constantRoutes, dynamicRoutes } from '@/router'
import { getRouters } from '@/api/menu'
import Layout from '@/layout/index'
import ParentView from '@/components/ParentView'
import InnerLink from '@/layout/components/InnerLink'
/** const permission = {
* Use meta.role to determine if the current user has permission state: {
* @param roles routes: [],
* @param route addRoutes: [],
*/ defaultRoutes: [],
function hasPermission(roles, route) { topbarRouters: [],
if (route.meta && route.meta.roles) { sidebarRouters: []
return roles.some(role => route.meta.roles.includes(role)) },
} else { mutations: {
return true SET_ROUTES: (state, routes) => {
state.addRoutes = routes
state.routes = constantRoutes.concat(routes)
},
SET_DEFAULT_ROUTES: (state, routes) => {
state.defaultRoutes = constantRoutes.concat(routes)
},
SET_TOPBAR_ROUTES: (state, routes) => {
state.topbarRouters = routes
},
SET_SIDEBAR_ROUTERS: (state, routes) => {
state.sidebarRouters = routes
},
},
actions: {
// 生成路由
GenerateRoutes({ commit }) {
return new Promise(resolve => {
// 向后端请求路由数据
getRouters().then(res => {
console.log(res)
const sdata = JSON.parse(JSON.stringify(res))
const rdata = JSON.parse(JSON.stringify(res))
const sidebarRoutes = filterAsyncRouter(sdata)
const rewriteRoutes = filterAsyncRouter(rdata, false, true)
console.log(rewriteRoutes)
const asyncRoutes = filterDynamicRoutes(dynamicRoutes);
rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true })
router.addRoutes(asyncRoutes);
commit('SET_ROUTES', rewriteRoutes)
commit('SET_SIDEBAR_ROUTERS', constantRoutes.concat(sidebarRoutes))
commit('SET_DEFAULT_ROUTES', sidebarRoutes)
commit('SET_TOPBAR_ROUTES', sidebarRoutes)
resolve(rewriteRoutes)
})
})
}
} }
} }
/** // 遍历后台传来的路由字符串,转换为组件对象
* Filter asynchronous routing tables by recursion function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) {
* @param routes asyncRoutes return asyncRouterMap.filter(route => {
* @param roles if (type && route.children) {
*/ route.children = filterChildren(route.children)
export function filterAsyncRoutes(routes, roles) { }
const res = [] if (route.component) {
// Layout ParentView 组件特殊处理
routes.forEach(route => { if (route.component === 'Layout') {
const tmp = { ...route } route.component = Layout
if (hasPermission(roles, tmp)) { }
if (tmp.children) { else if (route.component === 'ParentView') {
tmp.children = filterAsyncRoutes(tmp.children, roles) route.component = ParentView
} else if (route.component === 'InnerLink') {
route.component = InnerLink
} }
res.push(tmp) else {
route.component = loadView(route.component)
}
}
if (route.children != null && route.children && route.children.length) {
route.children = filterAsyncRouter(route.children, route, type)
} else {
delete route['children']
delete route['redirect']
} }
return true
}) })
return res
}
const state = {
routes: constantRoutes,
addRoutes: []
} }
const mutations = { function filterChildren(childrenMap, lastRouter = false) {
SET_ROUTES: (state, routes) => { var children = []
state.addRoutes = routes childrenMap.forEach((el, index) => {
state.routes = constantRoutes.concat(routes) if (el.children && el.children.length) {
} if (el.component === 'ParentView' && !lastRouter) {
el.children.forEach(c => {
c.path = el.path + '/' + c.path
if (c.children && c.children.length) {
children = children.concat(filterChildren(c.children, c))
return
}
children.push(c)
})
return
}
}
if (lastRouter) {
el.path = lastRouter.path + '/' + el.path
if (el.children && el.children.length) {
children = children.concat(filterChildren(el.children, el))
return
}
}
children = children.concat(el)
})
return children
} }
const actions = { // 动态路由遍历,验证是否具备权限
generateRoutes({ commit }, roles) { export function filterDynamicRoutes(routes) {
return new Promise(resolve => { const res = []
let accessedRoutes routes.forEach(route => {
if (roles.includes('admin')) { if (route.permissions) {
accessedRoutes = asyncRoutes || [] if (auth.hasPermiOr(route.permissions)) {
} else { res.push(route)
accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
} }
commit('SET_ROUTES', accessedRoutes) } else if (route.roles) {
resolve(accessedRoutes) if (auth.hasRoleOr(route.roles)) {
}) res.push(route)
} }
}
})
return res
} }
export default { export const loadView = (view) => {
namespaced: true, if (process.env.NODE_ENV === 'development') {
state, return (resolve) => require([`@/views/${view}`], resolve)
mutations, } else {
actions, // 使用 import 实现生产环境的路由懒加载
return () => import(`@/views/${view}`)
}
} }
export default permission
import defaultSettings from '@/settings' import defaultSettings from '@/settings'
const { showSettings, fixedHeader, sidebarLogo } = defaultSettings const { sideTheme, showSettings, topNav, tagsView, fixedHeader, sidebarLogo, dynamicTitle } = defaultSettings
const storageSetting = JSON.parse(localStorage.getItem('layout-setting')) || ''
const state = { const state = {
title: '',
theme: storageSetting.theme || '#409EFF',
sideTheme: storageSetting.sideTheme || sideTheme,
showSettings: showSettings, showSettings: showSettings,
fixedHeader: fixedHeader, topNav: storageSetting.topNav === undefined ? topNav : storageSetting.topNav,
sidebarLogo: sidebarLogo tagsView: storageSetting.tagsView === undefined ? tagsView : storageSetting.tagsView,
fixedHeader: storageSetting.fixedHeader === undefined ? fixedHeader : storageSetting.fixedHeader,
sidebarLogo: storageSetting.sidebarLogo === undefined ? sidebarLogo : storageSetting.sidebarLogo,
dynamicTitle: storageSetting.dynamicTitle === undefined ? dynamicTitle : storageSetting.dynamicTitle
} }
const mutations = { const mutations = {
CHANGE_SETTING: (state, { key, value }) => { CHANGE_SETTING: (state, { key, value }) => {
// eslint-disable-next-line no-prototype-builtins
if (state.hasOwnProperty(key)) { if (state.hasOwnProperty(key)) {
state[key] = value state[key] = value
} }
...@@ -18,8 +23,13 @@ const mutations = { ...@@ -18,8 +23,13 @@ const mutations = {
} }
const actions = { const actions = {
// 修改布局设置
changeSetting({ commit }, data) { changeSetting({ commit }, data) {
commit('CHANGE_SETTING', data) commit('CHANGE_SETTING', data)
},
// 设置网页标题
setTitle({ commit }, title) {
state.title = title
} }
} }
......
...@@ -7,7 +7,8 @@ const getDefaultState = () => { ...@@ -7,7 +7,8 @@ const getDefaultState = () => {
token: getToken(), token: getToken(),
userBaseInfo: {}, userBaseInfo: {},
userId: '', userId: '',
roles: [] roles: [],
permissions: []
} }
} }
...@@ -27,7 +28,12 @@ const mutations = { ...@@ -27,7 +28,12 @@ const mutations = {
state.userId = data state.userId = data
}, },
SET_ROLES: (state, data) => { SET_ROLES: (state, data) => {
state.roles = handleRoles(data) console.log('console.log(res.roleNames)')
console.log(data)
state.roles = data
},
SET_PERMISSIONS: (state, permissions) => {
state.permissions = permissions
} }
} }
...@@ -70,14 +76,20 @@ const actions = { ...@@ -70,14 +76,20 @@ const actions = {
reject('Verification failed, please Login again.') reject('Verification failed, please Login again.')
} }
const { isAdmin } = res if (res.roleNames && res.roleNames.length > 0) { // 验证返回的roles是否是一个非空数组
let roles = isAdmin==1 ? ['admin'] : ['editor'] commit('SET_ROLES', res.roleNames)
// roles must be a non-empty array commit('SET_PERMISSIONS', res.permissions)
if (!roles || roles.length <= 0) { } else {
reject('getInfo: roles must be a non-null array!') commit('SET_ROLES', ['ROLE_DEFAULT'])
} }
// const { isAdmin } = res
// let roles = isAdmin==1 ? ['admin'] : ['editor']
// roles must be a non-empty array
// if (!roleNames || roles.length <= 0) {
// reject('getInfo: roles must be a non-null array!')
// }
commit('SET_ROLES', roles) // commit('SET_ROLES', roles)
commit('SET_BASEINFO', res) commit('SET_BASEINFO', res)
resolve(res) resolve(res)
}).catch(error => { }).catch(error => {
...@@ -91,7 +103,7 @@ const actions = { ...@@ -91,7 +103,7 @@ const actions = {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
removeToken() // must remove token first removeToken() // must remove token first
removeUserName() removeUserName()
removeUserId() removeUserId()
resetRouter() resetRouter()
commit('SET_TOKEN', '') commit('SET_TOKEN', '')
commit('SET_BASEINFO', {}) commit('SET_BASEINFO', {})
...@@ -119,21 +131,11 @@ const getters = { ...@@ -119,21 +131,11 @@ const getters = {
}, },
userBaseInfo(state) { userBaseInfo(state) {
return state.userBaseInfo return state.userBaseInfo
}, },
roles(state) { roles(state) {
return state.roles return state.roles
} }
} }
function handleRoles(data) {
if (!data) return
if(data.isAdmin == 1) {
return ['admin']
} else {
return ['editor']
}
}
export default { export default {
namespaced: true, namespaced: true,
state, state,
......
...@@ -215,7 +215,7 @@ ...@@ -215,7 +215,7 @@
>.el-menu--popup { >.el-menu--popup {
max-height: 20vh; max-height: 20vh;
min-width: 80px; min-width: 80px;
overflow-y: auto; // overflow-y: auto;
&::-webkit-scrollbar-track-piece { &::-webkit-scrollbar-track-piece {
background: #d3dce6; background: #d3dce6;
......
export default {
'401': '认证失败,无法访问系统资源',
'403': '当前操作没有权限',
'404': '访问资源不存在',
'default': '系统未知错误,请反馈给管理员'
}
...@@ -145,4 +145,447 @@ export function changeToLatDFM(du) { ...@@ -145,4 +145,447 @@ export function changeToLatDFM(du) {
const m = tp.toFixed(2);//保留两位小数 const m = tp.toFixed(2);//保留两位小数
const dfm = '北纬N' + d + "°" + f + "'" + m + "\""; const dfm = '北纬N' + d + "°" + f + "'" + m + "\"";
return dfm; return dfm;
} }
\ No newline at end of file // import { parseTime } from './ruoyi'
/**
* 表格时间格式化
*/
export function formatDate(cellValue) {
if (cellValue == null || cellValue == "") return "";
var date = new Date(cellValue)
var year = date.getFullYear()
var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1
var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours()
var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()
var seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds
}
/**
* @param {number} time
* @param {string} option
* @returns {string}
*/
// export function formatTime(time, option) {
// if (('' + time).length === 10) {
// time = parseInt(time) * 1000
// } else {
// time = +time
// }
// const d = new Date(time)
// const now = Date.now()
// const diff = (now - d) / 1000
// if (diff < 30) {
// return '刚刚'
// } else if (diff < 3600) {
// // less 1 hour
// return Math.ceil(diff / 60) + '分钟前'
// } else if (diff < 3600 * 24) {
// return Math.ceil(diff / 3600) + '小时前'
// } else if (diff < 3600 * 24 * 2) {
// return '1天前'
// }
// if (option) {
// return parseTime(time, option)
// } else {
// return (
// d.getMonth() +
// 1 +
// '月' +
// d.getDate() +
// '日' +
// d.getHours() +
// '时' +
// d.getMinutes() +
// '分'
// )
// }
// }
/**
* @param {string} url
* @returns {Object}
*/
export function getQueryObject(url) {
url = url == null ? window.location.href : url
const search = url.substring(url.lastIndexOf('?') + 1)
const obj = {}
const reg = /([^?&=]+)=([^?&=]*)/g
search.replace(reg, (rs, $1, $2) => {
const name = decodeURIComponent($1)
let val = decodeURIComponent($2)
val = String(val)
obj[name] = val
return rs
})
return obj
}
/**
* @param {string} input value
* @returns {number} output value
*/
export function byteLength(str) {
// returns the byte length of an utf8 string
let s = str.length
for (var i = str.length - 1; i >= 0; i--) {
const code = str.charCodeAt(i)
if (code > 0x7f && code <= 0x7ff) s++
else if (code > 0x7ff && code <= 0xffff) s += 2
if (code >= 0xDC00 && code <= 0xDFFF) i--
}
return s
}
/**
* @param {Array} actual
* @returns {Array}
*/
export function cleanArray(actual) {
const newArray = []
for (let i = 0; i < actual.length; i++) {
if (actual[i]) {
newArray.push(actual[i])
}
}
return newArray
}
/**
* @param {Object} json
* @returns {Array}
*/
export function param(json) {
if (!json) return ''
return cleanArray(
Object.keys(json).map(key => {
if (json[key] === undefined) return ''
return encodeURIComponent(key) + '=' + encodeURIComponent(json[key])
})
).join('&')
}
/**
* @param {string} url
* @returns {Object}
*/
// export function param2Obj(url) {
// const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
// if (!search) {
// return {}
// }
// const obj = {}
// const searchArr = search.split('&')
// searchArr.forEach(v => {
// const index = v.indexOf('=')
// if (index !== -1) {
// const name = v.substring(0, index)
// const val = v.substring(index + 1, v.length)
// obj[name] = val
// }
// })
// return obj
// }
/**
* @param {string} val
* @returns {string}
*/
export function html2Text(val) {
const div = document.createElement('div')
div.innerHTML = val
return div.textContent || div.innerText
}
/**
* Merges two objects, giving the last one precedence
* @param {Object} target
* @param {(Object|Array)} source
* @returns {Object}
*/
export function objectMerge(target, source) {
if (typeof target !== 'object') {
target = {}
}
if (Array.isArray(source)) {
return source.slice()
}
Object.keys(source).forEach(property => {
const sourceProperty = source[property]
if (typeof sourceProperty === 'object') {
target[property] = objectMerge(target[property], sourceProperty)
} else {
target[property] = sourceProperty
}
})
return target
}
/**
* @param {HTMLElement} element
* @param {string} className
*/
export function toggleClass(element, className) {
if (!element || !className) {
return
}
let classString = element.className
const nameIndex = classString.indexOf(className)
if (nameIndex === -1) {
classString += '' + className
} else {
classString =
classString.substr(0, nameIndex) +
classString.substr(nameIndex + className.length)
}
element.className = classString
}
/**
* @param {string} type
* @returns {Date}
*/
export function getTime(type) {
if (type === 'start') {
return new Date().getTime() - 3600 * 1000 * 24 * 90
} else {
return new Date(new Date().toDateString())
}
}
/**
* @param {Function} func
* @param {number} wait
* @param {boolean} immediate
* @return {*}
*/
export function debounce(func, wait, immediate) {
let timeout, args, context, timestamp, result
const later = function() {
// 据上一次触发时间间隔
const last = +new Date() - timestamp
// 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
if (last < wait && last > 0) {
timeout = setTimeout(later, wait - last)
} else {
timeout = null
// 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
if (!immediate) {
result = func.apply(context, args)
if (!timeout) context = args = null
}
}
}
return function(...args) {
context = this
timestamp = +new Date()
const callNow = immediate && !timeout
// 如果延时不存在,重新设定延时
if (!timeout) timeout = setTimeout(later, wait)
if (callNow) {
result = func.apply(context, args)
context = args = null
}
return result
}
}
/**
* This is just a simple version of deep copy
* Has a lot of edge cases bug
* If you want to use a perfect deep copy, use lodash's _.cloneDeep
* @param {Object} source
* @returns {Object}
*/
export function deepClone(source) {
if (!source && typeof source !== 'object') {
throw new Error('error arguments', 'deepClone')
}
const targetObj = source.constructor === Array ? [] : {}
Object.keys(source).forEach(keys => {
if (source[keys] && typeof source[keys] === 'object') {
targetObj[keys] = deepClone(source[keys])
} else {
targetObj[keys] = source[keys]
}
})
return targetObj
}
/**
* @param {Array} arr
* @returns {Array}
*/
export function uniqueArr(arr) {
return Array.from(new Set(arr))
}
/**
* @returns {string}
*/
export function createUniqueString() {
const timestamp = +new Date() + ''
const randomNum = parseInt((1 + Math.random()) * 65536) + ''
return (+(randomNum + timestamp)).toString(32)
}
/**
* Check if an element has a class
* @param {HTMLElement} elm
* @param {string} cls
* @returns {boolean}
*/
export function hasClass(ele, cls) {
return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'))
}
/**
* Add class to element
* @param {HTMLElement} elm
* @param {string} cls
*/
export function addClass(ele, cls) {
if (!hasClass(ele, cls)) ele.className += ' ' + cls
}
/**
* Remove class from element
* @param {HTMLElement} elm
* @param {string} cls
*/
export function removeClass(ele, cls) {
if (hasClass(ele, cls)) {
const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)')
ele.className = ele.className.replace(reg, ' ')
}
}
export function makeMap(str, expectsLowerCase) {
const map = Object.create(null)
const list = str.split(',')
for (let i = 0; i < list.length; i++) {
map[list[i]] = true
}
return expectsLowerCase
? val => map[val.toLowerCase()]
: val => map[val]
}
export const exportDefault = 'export default '
export const beautifierConf = {
html: {
indent_size: '2',
indent_char: ' ',
max_preserve_newlines: '-1',
preserve_newlines: false,
keep_array_indentation: false,
break_chained_methods: false,
indent_scripts: 'separate',
brace_style: 'end-expand',
space_before_conditional: true,
unescape_strings: false,
jslint_happy: false,
end_with_newline: true,
wrap_line_length: '110',
indent_inner_html: true,
comma_first: false,
e4x: true,
indent_empty_lines: true
},
js: {
indent_size: '2',
indent_char: ' ',
max_preserve_newlines: '-1',
preserve_newlines: false,
keep_array_indentation: false,
break_chained_methods: false,
indent_scripts: 'normal',
brace_style: 'end-expand',
space_before_conditional: true,
unescape_strings: false,
jslint_happy: true,
end_with_newline: true,
wrap_line_length: '110',
indent_inner_html: true,
comma_first: false,
e4x: true,
indent_empty_lines: true
}
}
// 首字母大小
export function titleCase(str) {
return str.replace(/( |^)[a-z]/g, L => L.toUpperCase())
}
// 下划转驼峰
export function camelCase(str) {
return str.replace(/_[a-z]/g, str1 => str1.substr(-1).toUpperCase())
}
export function isNumberStr(str) {
return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str)
}
// 文件流下载
export function downloadByFilestream(stream, filename) {
const blob = new Blob([stream])
// 创建一个 URL 对象
const url = window.URL.createObjectURL(blob)
// 创建一个 <a> 标签
const link = document.createElement('a')
// 设置 <a> 标签的属性
link.href = url
link.setAttribute('download', filename) // 设置要下载的文件名
// 触发点击事件
link.click()
// 释放 URL 对象
window.URL.revokeObjectURL(url)
}
export function chineseDigits(n) {
var num = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
var word = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十']
return num.indexOf(n) !== -1 ? word[num.indexOf(n)] : n
}
export function chineseCircles(n) {
var num = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
var word = ['①', '②', '③', '④', '⑤', '⑥', '⑦', '⑧', '⑨', '⑩']
return num.indexOf(n) !== -1 ? word[num.indexOf(n)] : n
}
// 颜色随机
export function dictColor(val) {
return `hsl(${(Number(val)) * 200}, 100%, 50%)`
}
// 删除空字段
export function removeEmpty(obj) {
for (const i in obj) {
if (obj[i] === '' || obj[i] === null) {
delete obj[i]
}
}
return obj
}
export function formatFileSize(value) {
if (value === 0) return '0 Bytes'
const units = ['Bytes', 'KB', 'MB', 'GB', 'TB']
const digitGroups = Math.floor(Math.log10(value) / Math.log10(1024))
return parseFloat((value / Math.pow(1024, digitGroups)).toFixed(2)) + ' ' + units[digitGroups]
}
export function getWeek(date) {
const week = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
return week[new Date(date).getDay()]
}
...@@ -12,6 +12,8 @@ const service = axios.create({ ...@@ -12,6 +12,8 @@ const service = axios.create({
timeout: 5000 // request timeout timeout: 5000 // request timeout
}) })
export let isRelogin = { show: false };
let loading = {} let loading = {}
function startLoading(el) { function startLoading(el) {
if (!el) return if (!el) return
...@@ -55,20 +57,25 @@ let errorShowing = false ...@@ -55,20 +57,25 @@ let errorShowing = false
service.interceptors.response.use( service.interceptors.response.use(
response => { response => {
console.log(response) console.log(response)
let res = response.data.data ? response.data.data : response.data
let res = response.data.data ? response.data.data : response.data
if (response.data.msg == "操作成功") { if (response.data.msg == "操作成功") {
res = response.data res = response.data
} }
// if (response.data.success) {
// res = response.data
// }
if (response.data.recordsTotal) { if (response.data.recordsTotal) {
res = { res = {
recordsTotal: response.data.recordsTotal, recordsTotal: response.data.recordsTotal,
data: res data: res
} }
} }
if (!response.data) {
res = response
}
// if (response.data.success) {
// res = response.data
// }
let config = response.config let config = response.config
endLoading(config.el) endLoading(config.el)
let resFinal = res.rsp || res || {} let resFinal = res.rsp || res || {}
...@@ -80,6 +87,19 @@ service.interceptors.response.use( ...@@ -80,6 +87,19 @@ service.interceptors.response.use(
EventBus.$emit('cancelWS') EventBus.$emit('cancelWS')
return return
} }
if (code === 401) {
if (!isRelogin.show) {
isRelogin.show = true;
MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
isRelogin.show = false;
store.dispatch('LogOut').then(() => {
location.href = '/web';
})
}).catch(() => {
isRelogin.show = false;
});
}
}
if (code === 501) { if (code === 501) {
// !config.silence && !errorShowing && Message.error(message) // !config.silence && !errorShowing && Message.error(message)
errorShowing = true errorShowing = true
......
<template>
<div class="errPage-container">
<el-button icon="arrow-left" class="pan-back-btn" @click="back">
返回
</el-button>
<el-row>
<el-col :span="12">
<h1 class="text-jumbo text-ginormous">
401错误!
</h1>
<h2>您没有访问权限!</h2>
<h6>对不起,您没有访问权限,请不要进行非法操作!您可以返回主页面</h6>
<ul class="list-unstyled">
<li class="link-type">
<router-link to="/">
回首页
</router-link>
</li>
</ul>
</el-col>
<el-col :span="12">
<img :src="errGif" width="313" height="428" alt="Girl has dropped her ice cream.">
</el-col>
</el-row>
</div>
</template>
<script>
import errGif from '@/assets/401_images/401.gif'
export default {
name: 'Page401',
data() {
return {
errGif: errGif + '?' + +new Date()
}
},
methods: {
back() {
if (this.$route.query.noGoBack) {
this.$router.push({ path: '/' })
} else {
this.$router.go(-1)
}
}
}
}
</script>
<style lang="scss" scoped>
.errPage-container {
width: 800px;
max-width: 100%;
margin: 100px auto;
.pan-back-btn {
background: #008489;
color: #fff;
border: none!important;
}
.pan-gif {
margin: 0 auto;
display: block;
}
.pan-img {
display: block;
margin: 0 auto;
width: 100%;
}
.text-jumbo {
font-size: 60px;
font-weight: 700;
color: #484848;
}
.list-unstyled {
font-size: 14px;
li {
padding-bottom: 5px;
}
a {
color: #008489;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
}
}
</style>
<template>
<div class="wscn-http404-container">
<div class="wscn-http404">
<div class="pic-404">
<img class="pic-404__parent" src="@/assets/404_images/404.png" alt="404">
<img class="pic-404__child left" src="@/assets/404_images/404_cloud.png" alt="404">
<img class="pic-404__child mid" src="@/assets/404_images/404_cloud.png" alt="404">
<img class="pic-404__child right" src="@/assets/404_images/404_cloud.png" alt="404">
</div>
<div class="bullshit">
<div class="bullshit__oops">
404错误!
</div>
<div class="bullshit__headline">
{{ message }}
</div>
<div class="bullshit__info">
对不起,您正在寻找的页面不存在。尝试检查URL的错误,然后按浏览器上的刷新按钮或尝试在我们的应用程序中找到其他内容。
</div>
<router-link to="/" class="bullshit__return-home">
返回首页
</router-link>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Page404',
computed: {
message() {
return '找不到网页!'
}
}
}
</script>
<style lang="scss" scoped>
.wscn-http404-container{
transform: translate(-50%,-50%);
position: absolute;
top: 40%;
left: 50%;
}
.wscn-http404 {
position: relative;
width: 1200px;
padding: 0 50px;
overflow: hidden;
.pic-404 {
position: relative;
float: left;
width: 600px;
overflow: hidden;
&__parent {
width: 100%;
}
&__child {
position: absolute;
&.left {
width: 80px;
top: 17px;
left: 220px;
opacity: 0;
animation-name: cloudLeft;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-delay: 1s;
}
&.mid {
width: 46px;
top: 10px;
left: 420px;
opacity: 0;
animation-name: cloudMid;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-delay: 1.2s;
}
&.right {
width: 62px;
top: 100px;
left: 500px;
opacity: 0;
animation-name: cloudRight;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-delay: 1s;
}
@keyframes cloudLeft {
0% {
top: 17px;
left: 220px;
opacity: 0;
}
20% {
top: 33px;
left: 188px;
opacity: 1;
}
80% {
top: 81px;
left: 92px;
opacity: 1;
}
100% {
top: 97px;
left: 60px;
opacity: 0;
}
}
@keyframes cloudMid {
0% {
top: 10px;
left: 420px;
opacity: 0;
}
20% {
top: 40px;
left: 360px;
opacity: 1;
}
70% {
top: 130px;
left: 180px;
opacity: 1;
}
100% {
top: 160px;
left: 120px;
opacity: 0;
}
}
@keyframes cloudRight {
0% {
top: 100px;
left: 500px;
opacity: 0;
}
20% {
top: 120px;
left: 460px;
opacity: 1;
}
80% {
top: 180px;
left: 340px;
opacity: 1;
}
100% {
top: 200px;
left: 300px;
opacity: 0;
}
}
}
}
.bullshit {
position: relative;
float: left;
width: 300px;
padding: 30px 0;
overflow: hidden;
&__oops {
font-size: 32px;
font-weight: bold;
line-height: 40px;
color: #1482f0;
opacity: 0;
margin-bottom: 20px;
animation-name: slideUp;
animation-duration: 0.5s;
animation-fill-mode: forwards;
}
&__headline {
font-size: 20px;
line-height: 24px;
color: #222;
font-weight: bold;
opacity: 0;
margin-bottom: 10px;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.1s;
animation-fill-mode: forwards;
}
&__info {
font-size: 13px;
line-height: 21px;
color: grey;
opacity: 0;
margin-bottom: 30px;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.2s;
animation-fill-mode: forwards;
}
&__return-home {
display: block;
float: left;
width: 110px;
height: 36px;
background: #1482f0;
border-radius: 100px;
text-align: center;
color: #ffffff;
opacity: 0;
font-size: 14px;
line-height: 36px;
cursor: pointer;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.3s;
animation-fill-mode: forwards;
}
@keyframes slideUp {
0% {
transform: translateY(60px);
opacity: 0;
}
100% {
transform: translateY(0);
opacity: 1;
}
}
}
}
</style>
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch"> <el-form
:model="queryParams"
ref="queryForm"
size="small"
:inline="true"
v-show="showSearch"
>
<el-form-item label="菜单名称" prop="menuName"> <el-form-item label="菜单名称" prop="menuName">
<el-input <el-input
v-model="queryParams.menuName" v-model="queryParams.menuName"
...@@ -10,7 +16,11 @@ ...@@ -10,7 +16,11 @@
/> />
</el-form-item> </el-form-item>
<el-form-item label="状态" prop="status"> <el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="菜单状态" clearable> <el-select
v-model="queryParams.status"
placeholder="菜单状态"
clearable
>
<el-option <el-option
v-for="dict in dict.type.sys_normal_disable" v-for="dict in dict.type.sys_normal_disable"
:key="dict.value" :key="dict.value"
...@@ -20,8 +30,16 @@ ...@@ -20,8 +30,16 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <el-button
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> type="primary"
icon="el-icon-search"
size="mini"
@click="handleQuery"
>搜索</el-button
>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
>重置</el-button
>
</el-form-item> </el-form-item>
</el-form> </el-form>
...@@ -34,8 +52,10 @@ ...@@ -34,8 +52,10 @@
size="mini" size="mini"
@click="handleAdd" @click="handleAdd"
v-hasPermi="['system:menu:add']" v-hasPermi="['system:menu:add']"
>新增</el-button> >新增</el-button
>
</el-col> </el-col>
<!-- v-hasPermi="['system:menu:add']" -->
<el-col :span="1.5"> <el-col :span="1.5">
<el-button <el-button
type="info" type="info"
...@@ -43,9 +63,15 @@ ...@@ -43,9 +63,15 @@
icon="el-icon-sort" icon="el-icon-sort"
size="mini" size="mini"
@click="toggleExpandAll" @click="toggleExpandAll"
>展开/折叠</el-button> >展开/折叠</el-button
>
</el-col>
<el-col :span="7">
<right-toolbar
:showSearch.sync="showSearch"
@queryTable="getList"
></right-toolbar>
</el-col> </el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row> </el-row>
<el-table <el-table
...@@ -54,20 +80,40 @@ ...@@ -54,20 +80,40 @@
:data="menuList" :data="menuList"
row-key="menuId" row-key="menuId"
:default-expand-all="isExpandAll" :default-expand-all="isExpandAll"
:tree-props="{children: 'children', hasChildren: 'hasChildren'}" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
> >
<el-table-column prop="menuName" label="菜单名称" :show-overflow-tooltip="true" width="160"></el-table-column> <el-table-column
prop="menuName"
label="菜单名称"
:show-overflow-tooltip="true"
width="160"
></el-table-column>
<el-table-column prop="icon" label="图标" align="center" width="100"> <el-table-column prop="icon" label="图标" align="center" width="100">
<template slot-scope="scope"> <template slot-scope="scope">
<svg-icon :icon-class="scope.row.icon" /> <svg-icon :icon-class="scope.row.icon" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="orderNum" label="排序" width="60"></el-table-column> <el-table-column
<el-table-column prop="perms" label="权限标识" :show-overflow-tooltip="true"></el-table-column> prop="orderNum"
<el-table-column prop="component" label="组件路径" :show-overflow-tooltip="true"></el-table-column> label="排序"
width="60"
></el-table-column>
<el-table-column
prop="perms"
label="权限标识"
:show-overflow-tooltip="true"
></el-table-column>
<el-table-column
prop="component"
label="组件路径"
:show-overflow-tooltip="true"
></el-table-column>
<el-table-column prop="status" label="状态" width="80"> <el-table-column prop="status" label="状态" width="80">
<template slot-scope="scope"> <template slot-scope="scope">
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/> <dict-tag
:options="dict.type.sys_normal_disable"
:value="scope.row.status"
/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime"> <el-table-column label="创建时间" align="center" prop="createTime">
...@@ -75,7 +121,11 @@ ...@@ -75,7 +121,11 @@
<span>{{ parseTime(scope.row.createTime) }}</span> <span>{{ parseTime(scope.row.createTime) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <el-table-column
label="操作"
align="center"
class-name="small-padding fixed-width"
>
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
size="mini" size="mini"
...@@ -83,21 +133,24 @@ ...@@ -83,21 +133,24 @@
icon="el-icon-edit" icon="el-icon-edit"
@click="handleUpdate(scope.row)" @click="handleUpdate(scope.row)"
v-hasPermi="['system:menu:edit']" v-hasPermi="['system:menu:edit']"
>修改</el-button> >修改</el-button
>
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
icon="el-icon-plus" icon="el-icon-plus"
@click="handleAdd(scope.row)" @click="handleAdd(scope.row)"
v-hasPermi="['system:menu:add']" v-hasPermi="['system:menu:add']"
>新增</el-button> >新增</el-button
>
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
icon="el-icon-delete" icon="el-icon-delete"
@click="handleDelete(scope.row)" @click="handleDelete(scope.row)"
v-hasPermi="['system:menu:remove']" v-hasPermi="['system:menu:remove']"
>删除</el-button> >删除</el-button
>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
...@@ -134,15 +187,28 @@ ...@@ -134,15 +187,28 @@
trigger="click" trigger="click"
@show="$refs['iconSelect'].reset()" @show="$refs['iconSelect'].reset()"
> >
<IconSelect ref="iconSelect" @selected="selected" :active-icon="form.icon" /> <IconSelect
<el-input slot="reference" v-model="form.icon" placeholder="点击选择图标" readonly> ref="iconSelect"
@selected="selected"
:active-icon="form.icon"
/>
<el-input
slot="reference"
v-model="form.icon"
placeholder="点击选择图标"
readonly
>
<svg-icon <svg-icon
v-if="form.icon" v-if="form.icon"
slot="prefix" slot="prefix"
:icon-class="form.icon" :icon-class="form.icon"
style="width: 25px;" style="width: 25px"
/>
<i
v-else
slot="prefix"
class="el-icon-search el-input__icon"
/> />
<i v-else slot="prefix" class="el-icon-search el-input__icon" />
</el-input> </el-input>
</el-popover> </el-popover>
</el-form-item> </el-form-item>
...@@ -154,14 +220,21 @@ ...@@ -154,14 +220,21 @@
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="显示排序" prop="orderNum"> <el-form-item label="显示排序" prop="orderNum">
<el-input-number v-model="form.orderNum" controls-position="right" :min="0" /> <el-input-number
v-model="form.orderNum"
controls-position="right"
:min="0"
/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12" v-if="form.menuType != 'F'"> <el-col :span="12" v-if="form.menuType != 'F'">
<el-form-item prop="isFrame"> <el-form-item prop="isFrame">
<span slot="label"> <span slot="label">
<el-tooltip content="选择是外链则路由地址需要以`http(s)://`开头" placement="top"> <el-tooltip
<i class="el-icon-question"></i> content="选择是外链则路由地址需要以`http(s)://`开头"
placement="top"
>
<i class="el-icon-question"></i>
</el-tooltip> </el-tooltip>
是否外链 是否外链
</span> </span>
...@@ -174,8 +247,11 @@ ...@@ -174,8 +247,11 @@
<el-col :span="12" v-if="form.menuType != 'F'"> <el-col :span="12" v-if="form.menuType != 'F'">
<el-form-item prop="path"> <el-form-item prop="path">
<span slot="label"> <span slot="label">
<el-tooltip content="访问的路由地址,如:`user`,如外网地址需内链访问则以`http(s)://`开头" placement="top"> <el-tooltip
<i class="el-icon-question"></i> content="访问的路由地址,如:`user`,如外网地址需内链访问则以`http(s)://`开头"
placement="top"
>
<i class="el-icon-question"></i>
</el-tooltip> </el-tooltip>
路由地址 路由地址
</span> </span>
...@@ -185,8 +261,11 @@ ...@@ -185,8 +261,11 @@
<el-col :span="12" v-if="form.menuType == 'C'"> <el-col :span="12" v-if="form.menuType == 'C'">
<el-form-item prop="component"> <el-form-item prop="component">
<span slot="label"> <span slot="label">
<el-tooltip content="访问的组件路径,如:`system/user/index`,默认在`views`目录下" placement="top"> <el-tooltip
<i class="el-icon-question"></i> content="访问的组件路径,如:`system/user/index`,默认在`views`目录下"
placement="top"
>
<i class="el-icon-question"></i>
</el-tooltip> </el-tooltip>
组件路径 组件路径
</span> </span>
...@@ -195,10 +274,17 @@ ...@@ -195,10 +274,17 @@
</el-col> </el-col>
<el-col :span="12" v-if="form.menuType != 'M'"> <el-col :span="12" v-if="form.menuType != 'M'">
<el-form-item prop="perms"> <el-form-item prop="perms">
<el-input v-model="form.perms" placeholder="请输入权限标识" maxlength="100" /> <el-input
v-model="form.perms"
placeholder="请输入权限标识"
maxlength="100"
/>
<span slot="label"> <span slot="label">
<el-tooltip content="控制器中定义的权限字符,如:@PreAuthorize(`@ss.hasPermi('system:user:list')`)" placement="top"> <el-tooltip
<i class="el-icon-question"></i> content="控制器中定义的权限字符,如:@PreAuthorize(`@ss.hasPermi('system:user:list')`)"
placement="top"
>
<i class="el-icon-question"></i>
</el-tooltip> </el-tooltip>
权限字符 权限字符
</span> </span>
...@@ -206,10 +292,17 @@ ...@@ -206,10 +292,17 @@
</el-col> </el-col>
<el-col :span="12" v-if="form.menuType == 'C'"> <el-col :span="12" v-if="form.menuType == 'C'">
<el-form-item prop="query"> <el-form-item prop="query">
<el-input v-model="form.query" placeholder="请输入路由参数" maxlength="255" /> <el-input
v-model="form.query"
placeholder="请输入路由参数"
maxlength="255"
/>
<span slot="label"> <span slot="label">
<el-tooltip content='访问路由的默认传递参数,如:`{"id": 1, "name": "ry"}`' placement="top"> <el-tooltip
<i class="el-icon-question"></i> content='访问路由的默认传递参数,如:`{"id": 1, "name": "ry"}`'
placement="top"
>
<i class="el-icon-question"></i>
</el-tooltip> </el-tooltip>
路由参数 路由参数
</span> </span>
...@@ -218,8 +311,11 @@ ...@@ -218,8 +311,11 @@
<el-col :span="12" v-if="form.menuType == 'C'"> <el-col :span="12" v-if="form.menuType == 'C'">
<el-form-item prop="isCache"> <el-form-item prop="isCache">
<span slot="label"> <span slot="label">
<el-tooltip content="选择是则会被`keep-alive`缓存,需要匹配组件的`name`和地址保持一致" placement="top"> <el-tooltip
<i class="el-icon-question"></i> content="选择是则会被`keep-alive`缓存,需要匹配组件的`name`和地址保持一致"
placement="top"
>
<i class="el-icon-question"></i>
</el-tooltip> </el-tooltip>
是否缓存 是否缓存
</span> </span>
...@@ -232,8 +328,11 @@ ...@@ -232,8 +328,11 @@
<el-col :span="12" v-if="form.menuType != 'F'"> <el-col :span="12" v-if="form.menuType != 'F'">
<el-form-item prop="visible"> <el-form-item prop="visible">
<span slot="label"> <span slot="label">
<el-tooltip content="选择隐藏则路由将不会出现在侧边栏,但仍然可以访问" placement="top"> <el-tooltip
<i class="el-icon-question"></i> content="选择隐藏则路由将不会出现在侧边栏,但仍然可以访问"
placement="top"
>
<i class="el-icon-question"></i>
</el-tooltip> </el-tooltip>
显示状态 显示状态
</span> </span>
...@@ -242,15 +341,19 @@ ...@@ -242,15 +341,19 @@
v-for="dict in dict.type.sys_show_hide" v-for="dict in dict.type.sys_show_hide"
:key="dict.value" :key="dict.value"
:label="dict.value" :label="dict.value"
>{{dict.label}}</el-radio> >{{ dict.label }}</el-radio
>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item prop="status"> <el-form-item prop="status">
<span slot="label"> <span slot="label">
<el-tooltip content="选择停用则路由将不会出现在侧边栏,也不能被访问" placement="top"> <el-tooltip
<i class="el-icon-question"></i> content="选择停用则路由将不会出现在侧边栏,也不能被访问"
placement="top"
>
<i class="el-icon-question"></i>
</el-tooltip> </el-tooltip>
菜单状态 菜单状态
</span> </span>
...@@ -259,7 +362,8 @@ ...@@ -259,7 +362,8 @@
v-for="dict in dict.type.sys_normal_disable" v-for="dict in dict.type.sys_normal_disable"
:key="dict.value" :key="dict.value"
:label="dict.value" :label="dict.value"
>{{dict.label}}</el-radio> >{{ dict.label }}</el-radio
>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </el-col>
...@@ -274,14 +378,20 @@ ...@@ -274,14 +378,20 @@
</template> </template>
<script> <script>
import { listMenu, getMenu, delMenu, addMenu, updateMenu } from "@/api/system/menu"; import {
listMenu,
getMenu,
delMenu,
addMenu,
updateMenu,
} from "@/api/system/menu";
import Treeselect from "@riophae/vue-treeselect"; import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css"; import "@riophae/vue-treeselect/dist/vue-treeselect.css";
import IconSelect from "@/components/IconSelect"; import IconSelect from "@/components/IconSelect";
export default { export default {
name: "Menu", name: "Menu",
dicts: ['sys_show_hide', 'sys_normal_disable'], dicts: ["sys_show_hide", "sys_normal_disable"],
components: { Treeselect, IconSelect }, components: { Treeselect, IconSelect },
data() { data() {
return { return {
...@@ -304,24 +414,24 @@ export default { ...@@ -304,24 +414,24 @@ export default {
// 查询参数 // 查询参数
queryParams: { queryParams: {
menuName: undefined, menuName: undefined,
visible: undefined visible: undefined,
}, },
// 表单参数 // 表单参数
form: { form: {
parentId:'' parentId: "",
}, },
// 表单校验 // 表单校验
rules: { rules: {
menuName: [ menuName: [
{ required: true, message: "菜单名称不能为空", trigger: "blur" } { required: true, message: "菜单名称不能为空", trigger: "blur" },
], ],
orderNum: [ orderNum: [
{ required: true, message: "菜单顺序不能为空", trigger: "blur" } { required: true, message: "菜单顺序不能为空", trigger: "blur" },
], ],
path: [ path: [
{ required: true, message: "路由地址不能为空", trigger: "blur" } { required: true, message: "路由地址不能为空", trigger: "blur" },
] ],
} },
}; };
}, },
created() { created() {
...@@ -335,7 +445,7 @@ export default { ...@@ -335,7 +445,7 @@ export default {
/** 查询菜单列表 */ /** 查询菜单列表 */
getList() { getList() {
this.loading = true; this.loading = true;
listMenu(this.queryParams).then(response => { listMenu(this.queryParams).then((response) => {
console.log(response); console.log(response);
this.menuList = this.handleTree(response.data, "menuId"); this.menuList = this.handleTree(response.data, "menuId");
this.loading = false; this.loading = false;
...@@ -349,14 +459,14 @@ export default { ...@@ -349,14 +459,14 @@ export default {
return { return {
id: node.menuId, id: node.menuId,
label: node.menuName, label: node.menuName,
children: node.children children: node.children,
}; };
}, },
/** 查询菜单下拉树结构 */ /** 查询菜单下拉树结构 */
getTreeselect() { getTreeselect() {
listMenu().then(response => { listMenu().then((response) => {
this.menuOptions = []; this.menuOptions = [];
const menu = { menuId: 0, menuName: '主类目', children: [] }; const menu = { menuId: 0, menuName: "主类目", children: [] };
menu.children = this.handleTree(response.data, "menuId"); menu.children = this.handleTree(response.data, "menuId");
this.menuOptions.push(menu); this.menuOptions.push(menu);
}); });
...@@ -378,7 +488,7 @@ export default { ...@@ -378,7 +488,7 @@ export default {
isFrame: "1", isFrame: "1",
isCache: "0", isCache: "0",
visible: "0", visible: "0",
status: "0" status: "0",
}; };
this.resetForm("form"); this.resetForm("form");
}, },
...@@ -416,24 +526,24 @@ export default { ...@@ -416,24 +526,24 @@ export default {
handleUpdate(row) { handleUpdate(row) {
this.reset(); this.reset();
this.getTreeselect(); this.getTreeselect();
getMenu(row.menuId).then(response => { getMenu(row.menuId).then((response) => {
this.form = response.data; this.form = response.data;
this.open = true; this.open = true;
this.title = "修改菜单"; this.title = "修改菜单";
}); });
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm: function() { submitForm: function () {
this.$refs["form"].validate(valid => { this.$refs["form"].validate((valid) => {
if (valid) { if (valid) {
if (this.form.menuId != undefined) { if (this.form.menuId != undefined) {
updateMenu(this.form).then(response => { updateMenu(this.form).then((response) => {
this.$modal.msgSuccess("修改成功"); this.$modal.msgSuccess("修改成功");
this.open = false; this.open = false;
this.getList(); this.getList();
}); });
} else { } else {
addMenu(this.form).then(response => { addMenu(this.form).then((response) => {
this.$modal.msgSuccess("新增成功"); this.$modal.msgSuccess("新增成功");
this.open = false; this.open = false;
this.getList(); this.getList();
...@@ -444,13 +554,17 @@ export default { ...@@ -444,13 +554,17 @@ export default {
}, },
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
this.$modal.confirm('是否确认删除名称为"' + row.menuName + '"的数据项?').then(function() { this.$modal
return delMenu(row.menuId); .confirm('是否确认删除名称为"' + row.menuName + '"的数据项?')
}).then(() => { .then(function () {
this.getList(); return delMenu(row.menuId);
this.$modal.msgSuccess("删除成功"); })
}).catch(() => {}); .then(() => {
} this.getList();
} this.$modal.msgSuccess("删除成功");
})
.catch(() => {});
},
},
}; };
</script> </script>
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch"> <el-form
:model="queryParams"
ref="queryForm"
size="small"
:inline="true"
v-show="showSearch"
>
<el-form-item label="用户名称" prop="userName"> <el-form-item label="用户名称" prop="userName">
<el-input <el-input
v-model="queryParams.userName" v-model="queryParams.userName"
...@@ -10,9 +16,9 @@ ...@@ -10,9 +16,9 @@
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="手机号码" prop="phonenumber"> <el-form-item label="手机号码" prop="phone">
<el-input <el-input
v-model="queryParams.phonenumber" v-model="queryParams.phone"
placeholder="请输入手机号码" placeholder="请输入手机号码"
clearable clearable
style="width: 240px" style="width: 240px"
...@@ -20,8 +26,16 @@ ...@@ -20,8 +26,16 @@
/> />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <el-button
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> type="primary"
icon="el-icon-search"
size="mini"
@click="handleQuery"
>搜索</el-button
>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
>重置</el-button
>
</el-form-item> </el-form-item>
</el-form> </el-form>
...@@ -34,7 +48,8 @@ ...@@ -34,7 +48,8 @@
size="mini" size="mini"
@click="openSelectUser" @click="openSelectUser"
v-hasPermi="['system:role:add']" v-hasPermi="['system:role:add']"
>添加用户</el-button> >添加用户</el-button
>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
<el-button <el-button
...@@ -45,7 +60,8 @@ ...@@ -45,7 +60,8 @@
:disabled="multiple" :disabled="multiple"
@click="cancelAuthUserAll" @click="cancelAuthUserAll"
v-hasPermi="['system:role:remove']" v-hasPermi="['system:role:remove']"
>批量取消授权</el-button> >批量取消授权</el-button
>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
<el-button <el-button
...@@ -54,28 +70,56 @@ ...@@ -54,28 +70,56 @@
icon="el-icon-close" icon="el-icon-close"
size="mini" size="mini"
@click="handleClose" @click="handleClose"
>关闭</el-button> >关闭</el-button
>
</el-col>
<el-col :span="1.5">
<right-toolbar
:showSearch.sync="showSearch"
@queryTable="getList"
></right-toolbar>
</el-col> </el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row> </el-row>
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange"> <el-table
v-loading="loading"
:data="userList"
width="800px"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column label="用户名称" prop="userName" :show-overflow-tooltip="true" /> <el-table-column
<el-table-column label="用户昵称" prop="nickName" :show-overflow-tooltip="true" /> label="用户名称"
<el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" /> prop="userName"
<el-table-column label="手机" prop="phonenumber" :show-overflow-tooltip="true" /> :show-overflow-tooltip="true"
<el-table-column label="状态" align="center" prop="status"> />
<!-- <el-table-column label="用户昵称" prop="nickName" :show-overflow-tooltip="true" /> -->
<!-- <el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" /> -->
<el-table-column
label="手机"
prop="phone"
:show-overflow-tooltip="true"
/>
<!-- <el-table-column label="状态" align="center" prop="status">
<template slot-scope="scope"> <template slot-scope="scope">
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/> <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
</template> </template>
</el-table-column> </el-table-column> -->
<el-table-column label="创建时间" align="center" prop="createTime" width="180"> <el-table-column
label="创建时间"
align="center"
prop="creationTime"
width="180"
>
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span> <span>{{ parseTime(scope.row.creationTime) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <el-table-column
label="操作"
align="center"
class-name="small-padding fixed-width"
>
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
size="mini" size="mini"
...@@ -83,16 +127,17 @@ ...@@ -83,16 +127,17 @@
icon="el-icon-circle-close" icon="el-icon-circle-close"
@click="cancelAuthUser(scope.row)" @click="cancelAuthUser(scope.row)"
v-hasPermi="['system:role:remove']" v-hasPermi="['system:role:remove']"
>取消授权</el-button> >取消授权</el-button
>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<pagination <pagination
v-show="total>0" v-show="total > 0"
:total="total" :total="total"
:page.sync="queryParams.pageNum" :page.sync="queryParams.current"
:limit.sync="queryParams.pageSize" :limit.sync="queryParams.size"
@pagination="getList" @pagination="getList"
/> />
<select-user ref="select" :roleId="queryParams.roleId" @ok="handleQuery" /> <select-user ref="select" :roleId="queryParams.roleId" @ok="handleQuery" />
...@@ -100,12 +145,16 @@ ...@@ -100,12 +145,16 @@
</template> </template>
<script> <script>
import { allocatedUserList, authUserCancel, authUserCancelAll } from "@/api/system/role"; import {
allocatedUserList,
authUserCancel,
authUserCancelAll,
} from "@/api/system/role";
import selectUser from "./selectUser"; import selectUser from "./selectUser";
export default { export default {
name: "AuthUser", name: "AuthUser",
dicts: ['sys_normal_disable'], dicts: ["sys_normal_disable"],
components: { selectUser }, components: { selectUser },
data() { data() {
return { return {
...@@ -123,12 +172,12 @@ export default { ...@@ -123,12 +172,12 @@ export default {
userList: [], userList: [],
// 查询参数 // 查询参数
queryParams: { queryParams: {
pageNum: 1, current: 1,
pageSize: 10, size: 10,
roleId: undefined, roleId: undefined,
userName: undefined, userName: undefined,
phonenumber: undefined phonenumber: undefined,
} },
}; };
}, },
created() { created() {
...@@ -142,12 +191,11 @@ export default { ...@@ -142,12 +191,11 @@ export default {
/** 查询授权用户列表 */ /** 查询授权用户列表 */
getList() { getList() {
this.loading = true; this.loading = true;
allocatedUserList(this.queryParams).then(response => { allocatedUserList(this.queryParams).then((response) => {
this.userList = response.rows; this.userList = response.data.records;
this.total = response.total; this.total = response.data.total;
this.loading = false; this.loading = false;
} });
);
}, },
// 返回按钮 // 返回按钮
handleClose() { handleClose() {
...@@ -166,8 +214,8 @@ export default { ...@@ -166,8 +214,8 @@ export default {
}, },
// 多选框选中数据 // 多选框选中数据
handleSelectionChange(selection) { handleSelectionChange(selection) {
this.userIds = selection.map(item => item.userId) this.userIds = selection.map((item) => item.id);
this.multiple = !selection.length this.multiple = !selection.length;
}, },
/** 打开授权用户表弹窗 */ /** 打开授权用户表弹窗 */
openSelectUser() { openSelectUser() {
...@@ -176,24 +224,32 @@ export default { ...@@ -176,24 +224,32 @@ export default {
/** 取消授权按钮操作 */ /** 取消授权按钮操作 */
cancelAuthUser(row) { cancelAuthUser(row) {
const roleId = this.queryParams.roleId; const roleId = this.queryParams.roleId;
this.$modal.confirm('确认要取消该用户"' + row.userName + '"角色吗?').then(function() { this.$modal
return authUserCancel({ userId: row.userId, roleId: roleId }); .confirm('确认要取消该用户"' + row.userName + '"角色吗?')
}).then(() => { .then(function () {
this.getList(); return authUserCancel({ userId: row.id, roleId: roleId });
this.$modal.msgSuccess("取消授权成功"); })
}).catch(() => {}); .then(() => {
this.getList();
this.$modal.msgSuccess("取消授权成功");
})
.catch(() => {});
}, },
/** 批量取消授权按钮操作 */ /** 批量取消授权按钮操作 */
cancelAuthUserAll(row) { cancelAuthUserAll(row) {
const roleId = this.queryParams.roleId; const roleId = this.queryParams.roleId;
const userIds = this.userIds.join(","); const userIds = this.userIds.join(",");
this.$modal.confirm('是否取消选中用户授权数据项?').then(function() { this.$modal
return authUserCancelAll({ roleId: roleId, userIds: userIds }); .confirm("是否取消选中用户授权数据项?")
}).then(() => { .then(function () {
this.getList(); return authUserCancelAll({ roleId: roleId, userIds: userIds });
this.$modal.msgSuccess("取消授权成功"); })
}).catch(() => {}); .then(() => {
} this.getList();
} this.$modal.msgSuccess("取消授权成功");
})
.catch(() => {});
},
},
}; };
</script> </script>
\ No newline at end of file
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch"> <el-form
:model="queryParams"
ref="queryForm"
size="small"
:inline="true"
v-show="showSearch"
>
<el-form-item label="角色名称" prop="roleName"> <el-form-item label="角色名称" prop="roleName">
<el-input <el-input
v-model="queryParams.roleName" v-model="queryParams.roleName"
...@@ -46,8 +52,16 @@ ...@@ -46,8 +52,16 @@
></el-date-picker> ></el-date-picker>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <el-button
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> type="primary"
icon="el-icon-search"
size="mini"
@click="handleQuery"
>搜索</el-button
>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
>重置</el-button
>
</el-form-item> </el-form-item>
</el-form> </el-form>
...@@ -60,7 +74,8 @@ ...@@ -60,7 +74,8 @@
size="mini" size="mini"
@click="handleAdd" @click="handleAdd"
v-hasPermi="['system:role:add']" v-hasPermi="['system:role:add']"
>新增</el-button> >新增</el-button
>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
<el-button <el-button
...@@ -71,7 +86,8 @@ ...@@ -71,7 +86,8 @@
:disabled="single" :disabled="single"
@click="handleUpdate" @click="handleUpdate"
v-hasPermi="['system:role:edit']" v-hasPermi="['system:role:edit']"
>修改</el-button> >修改</el-button
>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
<el-button <el-button
...@@ -82,26 +98,36 @@ ...@@ -82,26 +98,36 @@
:disabled="multiple" :disabled="multiple"
@click="handleDelete" @click="handleDelete"
v-hasPermi="['system:role:remove']" v-hasPermi="['system:role:remove']"
>删除</el-button> >删除</el-button
>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
<el-button <right-toolbar
type="warning" :showSearch.sync="showSearch"
plain @queryTable="getList"
icon="el-icon-download" ></right-toolbar>
size="mini"
@click="handleExport"
v-hasPermi="['system:role:export']"
>导出</el-button>
</el-col> </el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row> </el-row>
<el-table v-loading="loading" :data="roleList" @selection-change="handleSelectionChange"> <el-table
v-loading="loading"
:data="roleList"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column label="角色编号" prop="roleId" width="120" /> <el-table-column label="角色编号" prop="roleId" width="120" />
<el-table-column label="角色名称" prop="roleName" :show-overflow-tooltip="true" width="150" /> <el-table-column
<el-table-column label="权限字符" prop="roleKey" :show-overflow-tooltip="true" width="150" /> label="角色名称"
prop="roleName"
:show-overflow-tooltip="true"
width="150"
/>
<el-table-column
label="权限字符"
prop="roleKey"
:show-overflow-tooltip="true"
width="150"
/>
<el-table-column label="显示顺序" prop="roleSort" width="100" /> <el-table-column label="显示顺序" prop="roleSort" width="100" />
<el-table-column label="状态" align="center" width="100"> <el-table-column label="状态" align="center" width="100">
<template slot-scope="scope"> <template slot-scope="scope">
...@@ -113,12 +139,21 @@ ...@@ -113,12 +139,21 @@
></el-switch> ></el-switch>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180"> <el-table-column
label="创建时间"
align="center"
prop="createTime"
width="180"
>
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span> <span>{{ parseTime(scope.row.createTime) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <el-table-column
label="操作"
align="center"
class-name="small-padding fixed-width"
>
<template slot-scope="scope" v-if="scope.row.roleId !== 1"> <template slot-scope="scope" v-if="scope.row.roleId !== 1">
<el-button <el-button
size="mini" size="mini"
...@@ -126,21 +161,33 @@ ...@@ -126,21 +161,33 @@
icon="el-icon-edit" icon="el-icon-edit"
@click="handleUpdate(scope.row)" @click="handleUpdate(scope.row)"
v-hasPermi="['system:role:edit']" v-hasPermi="['system:role:edit']"
>修改</el-button> >修改</el-button
>
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
icon="el-icon-delete" icon="el-icon-delete"
@click="handleDelete(scope.row)" @click="handleDelete(scope.row)"
v-hasPermi="['system:role:remove']" v-hasPermi="['system:role:remove']"
>删除</el-button> >删除</el-button
<el-dropdown size="mini" @command="(command) => handleCommand(command, scope.row)" v-hasPermi="['system:role:edit']"> >
<el-button size="mini" type="text" icon="el-icon-d-arrow-right">更多</el-button> <el-dropdown
size="mini"
@command="(command) => handleCommand(command, scope.row)"
v-hasPermi="['system:role:edit']"
>
<el-button size="mini" type="text" icon="el-icon-d-arrow-right"
>更多</el-button
>
<el-dropdown-menu slot="dropdown"> <el-dropdown-menu slot="dropdown">
<el-dropdown-item command="handleDataScope" icon="el-icon-circle-check" <!-- <el-dropdown-item command="handleDataScope" icon="el-icon-circle-check"
v-hasPermi="['system:role:edit']">数据权限</el-dropdown-item> v-hasPermi="['system:role:edit']">数据权限</el-dropdown-item> -->
<el-dropdown-item command="handleAuthUser" icon="el-icon-user" <el-dropdown-item
v-hasPermi="['system:role:edit']">分配用户</el-dropdown-item> command="handleAuthUser"
icon="el-icon-user"
v-hasPermi="['system:role:edit']"
>分配用户</el-dropdown-item
>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
</template> </template>
...@@ -148,7 +195,7 @@ ...@@ -148,7 +195,7 @@
</el-table> </el-table>
<pagination <pagination
v-show="total>0" v-show="total > 0"
:total="total" :total="total"
:page.sync="queryParams.current" :page.sync="queryParams.current"
:limit.sync="queryParams.size" :limit.sync="queryParams.size"
...@@ -156,14 +203,17 @@ ...@@ -156,14 +203,17 @@
/> />
<!-- 添加或修改角色配置对话框 --> <!-- 添加或修改角色配置对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="100px"> <el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-form-item label="角色名称" prop="roleName"> <el-form-item label="角色名称" prop="roleName">
<el-input v-model="form.roleName" placeholder="请输入角色名称" /> <el-input v-model="form.roleName" placeholder="请输入角色名称" />
</el-form-item> </el-form-item>
<el-form-item prop="roleKey"> <el-form-item prop="roleKey">
<span slot="label"> <span slot="label">
<el-tooltip content="控制器中定义的权限字符,如:@PreAuthorize(`@ss.hasRole('admin')`)" placement="top"> <el-tooltip
content="控制器中定义的权限字符,如:@PreAuthorize(`@ss.hasRole('admin')`)"
placement="top"
>
<i class="el-icon-question"></i> <i class="el-icon-question"></i>
</el-tooltip> </el-tooltip>
权限字符 权限字符
...@@ -171,7 +221,11 @@ ...@@ -171,7 +221,11 @@
<el-input v-model="form.roleKey" placeholder="请输入权限字符" /> <el-input v-model="form.roleKey" placeholder="请输入权限字符" />
</el-form-item> </el-form-item>
<el-form-item label="角色顺序" prop="roleSort"> <el-form-item label="角色顺序" prop="roleSort">
<el-input-number v-model="form.roleSort" controls-position="right" :min="0" /> <el-input-number
v-model="form.roleSort"
controls-position="right"
:min="0"
/>
</el-form-item> </el-form-item>
<el-form-item label="状态"> <el-form-item label="状态">
<el-radio-group v-model="form.status"> <el-radio-group v-model="form.status">
...@@ -179,13 +233,26 @@ ...@@ -179,13 +233,26 @@
v-for="dict in dict.type.sys_normal_disable" v-for="dict in dict.type.sys_normal_disable"
:key="dict.value" :key="dict.value"
:label="dict.value" :label="dict.value"
>{{dict.label}}</el-radio> >{{ dict.label }}</el-radio
>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="菜单权限"> <el-form-item label="菜单权限">
<el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox> <el-checkbox
<el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">全选/全不选</el-checkbox> v-model="menuExpand"
<el-checkbox v-model="form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">父子联动</el-checkbox> @change="handleCheckedTreeExpand($event, 'menu')"
>展开/折叠</el-checkbox
>
<el-checkbox
v-model="menuNodeAll"
@change="handleCheckedTreeNodeAll($event, 'menu')"
>全选/全不选</el-checkbox
>
<el-checkbox
v-model="form.menuCheckStrictly"
@change="handleCheckedTreeConnect($event, 'menu')"
>父子联动</el-checkbox
>
<el-tree <el-tree
class="tree-border" class="tree-border"
:data="menuOptions" :data="menuOptions"
...@@ -198,7 +265,11 @@ ...@@ -198,7 +265,11 @@
></el-tree> ></el-tree>
</el-form-item> </el-form-item>
<el-form-item label="备注"> <el-form-item label="备注">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input> <el-input
v-model="form.remark"
type="textarea"
placeholder="请输入内容"
></el-input>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
...@@ -208,7 +279,12 @@ ...@@ -208,7 +279,12 @@
</el-dialog> </el-dialog>
<!-- 分配角色数据权限对话框 --> <!-- 分配角色数据权限对话框 -->
<el-dialog :title="title" :visible.sync="openDataScope" width="500px" append-to-body> <el-dialog
:title="title"
:visible.sync="openDataScope"
width="500px"
append-to-body
>
<el-form :model="form" label-width="80px"> <el-form :model="form" label-width="80px">
<el-form-item label="角色名称"> <el-form-item label="角色名称">
<el-input v-model="form.roleName" :disabled="true" /> <el-input v-model="form.roleName" :disabled="true" />
...@@ -227,9 +303,21 @@ ...@@ -227,9 +303,21 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="数据权限" v-show="form.dataScope == 2"> <el-form-item label="数据权限" v-show="form.dataScope == 2">
<el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">展开/折叠</el-checkbox> <el-checkbox
<el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">全选/全不选</el-checkbox> v-model="deptExpand"
<el-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')">父子联动</el-checkbox> @change="handleCheckedTreeExpand($event, 'dept')"
>展开/折叠</el-checkbox
>
<el-checkbox
v-model="deptNodeAll"
@change="handleCheckedTreeNodeAll($event, 'dept')"
>全选/全不选</el-checkbox
>
<el-checkbox
v-model="form.deptCheckStrictly"
@change="handleCheckedTreeConnect($event, 'dept')"
>父子联动</el-checkbox
>
<el-tree <el-tree
class="tree-border" class="tree-border"
:data="deptOptions" :data="deptOptions"
...@@ -252,12 +340,24 @@ ...@@ -252,12 +340,24 @@
</template> </template>
<script> <script>
import { listRole, getRole, delRole, addRole, updateRole, dataScope, changeRoleStatus, deptTreeSelect } from "@/api/system/role"; import {
import { treeselect as menuTreeselect, roleMenuTreeselect } from "@/api/system/menu"; listRole,
getRole,
delRole,
addRole,
updateRole,
dataScope,
changeRoleStatus,
deptTreeSelect,
} from "@/api/system/role";
import {
treeselect as menuTreeselect,
roleMenuTreeselect,
} from "@/api/system/menu";
export default { export default {
name: "Role", name: "Role",
dicts: ['sys_normal_disable'], dicts: ["sys_normal_disable"],
data() { data() {
return { return {
// 遮罩层 // 遮罩层
...@@ -290,24 +390,24 @@ export default { ...@@ -290,24 +390,24 @@ export default {
dataScopeOptions: [ dataScopeOptions: [
{ {
value: "1", value: "1",
label: "全部数据权限" label: "全部数据权限",
}, },
{ {
value: "2", value: "2",
label: "自定数据权限" label: "自定数据权限",
}, },
{ {
value: "3", value: "3",
label: "本部门数据权限" label: "本部门数据权限",
}, },
{ {
value: "4", value: "4",
label: "本部门及以下数据权限" label: "本部门及以下数据权限",
}, },
{ {
value: "5", value: "5",
label: "仅本人数据权限" label: "仅本人数据权限",
} },
], ],
// 菜单列表 // 菜单列表
menuOptions: [], menuOptions: [],
...@@ -319,26 +419,26 @@ export default { ...@@ -319,26 +419,26 @@ export default {
size: 10, size: 10,
roleName: undefined, roleName: undefined,
roleKey: undefined, roleKey: undefined,
status: undefined status: undefined,
}, },
// 表单参数 // 表单参数
form: {}, form: {},
defaultProps: { defaultProps: {
children: "children", children: "children",
label: "label" label: "label",
}, },
// 表单校验 // 表单校验
rules: { rules: {
roleName: [ roleName: [
{ required: true, message: "角色名称不能为空", trigger: "blur" } { required: true, message: "角色名称不能为空", trigger: "blur" },
], ],
roleKey: [ roleKey: [
{ required: true, message: "权限字符不能为空", trigger: "blur" } { required: true, message: "权限字符不能为空", trigger: "blur" },
], ],
roleSort: [ roleSort: [
{ required: true, message: "角色顺序不能为空", trigger: "blur" } { required: true, message: "角色顺序不能为空", trigger: "blur" },
] ],
} },
}; };
}, },
created() { created() {
...@@ -348,17 +448,16 @@ export default { ...@@ -348,17 +448,16 @@ export default {
/** 查询角色列表 */ /** 查询角色列表 */
getList() { getList() {
this.loading = true; this.loading = true;
let data = { ...this.queryParams ,...this.dateRange}; let data = { ...this.queryParams, ...this.dateRange };
listRole(data).then(response => { listRole(data).then((response) => {
this.roleList = response.records; this.roleList = response.records;
this.total = response.total; this.total = response.total;
this.loading = false; this.loading = false;
} });
);
}, },
/** 查询菜单树结构 */ /** 查询菜单树结构 */
getMenuTreeselect() { getMenuTreeselect() {
menuTreeselect().then(response => { menuTreeselect().then((response) => {
this.menuOptions = response.data; this.menuOptions = response.data;
}); });
}, },
...@@ -382,14 +481,14 @@ export default { ...@@ -382,14 +481,14 @@ export default {
}, },
/** 根据角色ID查询菜单树结构 */ /** 根据角色ID查询菜单树结构 */
getRoleMenuTreeselect(roleId) { getRoleMenuTreeselect(roleId) {
return roleMenuTreeselect(roleId).then(response => { return roleMenuTreeselect(roleId).then((response) => {
this.menuOptions = response.menus; this.menuOptions = response.menus;
return response; return response;
}); });
}, },
/** 根据角色ID查询部门树结构 */ /** 根据角色ID查询部门树结构 */
getDeptTree(roleId) { getDeptTree(roleId) {
return deptTreeSelect(roleId).then(response => { return deptTreeSelect(roleId).then((response) => {
this.deptOptions = response.depts; this.deptOptions = response.depts;
return response; return response;
}); });
...@@ -397,13 +496,17 @@ export default { ...@@ -397,13 +496,17 @@ export default {
// 角色状态修改 // 角色状态修改
handleStatusChange(row) { handleStatusChange(row) {
let text = row.status === "0" ? "启用" : "停用"; let text = row.status === "0" ? "启用" : "停用";
this.$modal.confirm('确认要"' + text + '""' + row.roleName + '"角色吗?').then(function() { this.$modal
return changeRoleStatus(row.roleId, row.status); .confirm('确认要"' + text + '""' + row.roleName + '"角色吗?')
}).then(() => { .then(function () {
this.$modal.msgSuccess(text + "成功"); return changeRoleStatus(row.roleId, row.status);
}).catch(function() { })
row.status = row.status === "0" ? "1" : "0"; .then(() => {
}); this.$modal.msgSuccess(text + "成功");
})
.catch(function () {
row.status = row.status === "0" ? "1" : "0";
});
}, },
// 取消按钮 // 取消按钮
cancel() { cancel() {
...@@ -420,22 +523,22 @@ export default { ...@@ -420,22 +523,22 @@ export default {
if (this.$refs.menu != undefined) { if (this.$refs.menu != undefined) {
this.$refs.menu.setCheckedKeys([]); this.$refs.menu.setCheckedKeys([]);
} }
this.menuExpand = false, (this.menuExpand = false),
this.menuNodeAll = false, (this.menuNodeAll = false),
this.deptExpand = true, (this.deptExpand = true),
this.deptNodeAll = false, (this.deptNodeAll = false),
this.form = { (this.form = {
roleId: undefined, roleId: undefined,
roleName: undefined, roleName: undefined,
roleKey: undefined, roleKey: undefined,
roleSort: 0, roleSort: 0,
status: "0", status: "0",
menuIds: [], menuIds: [],
deptIds: [], deptIds: [],
menuCheckStrictly: true, menuCheckStrictly: true,
deptCheckStrictly: true, deptCheckStrictly: true,
remark: undefined remark: undefined,
}; });
this.resetForm("form"); this.resetForm("form");
}, },
/** 搜索按钮操作 */ /** 搜索按钮操作 */
...@@ -451,9 +554,9 @@ export default { ...@@ -451,9 +554,9 @@ export default {
}, },
// 多选框选中数据 // 多选框选中数据
handleSelectionChange(selection) { handleSelectionChange(selection) {
this.ids = selection.map(item => item.roleId) this.ids = selection.map((item) => item.roleId);
this.single = selection.length!=1 this.single = selection.length != 1;
this.multiple = !selection.length this.multiple = !selection.length;
}, },
// 更多操作触发 // 更多操作触发
handleCommand(command, row) { handleCommand(command, row) {
...@@ -470,12 +573,12 @@ export default { ...@@ -470,12 +573,12 @@ export default {
}, },
// 树权限(展开/折叠) // 树权限(展开/折叠)
handleCheckedTreeExpand(value, type) { handleCheckedTreeExpand(value, type) {
if (type == 'menu') { if (type == "menu") {
let treeList = this.menuOptions; let treeList = this.menuOptions;
for (let i = 0; i < treeList.length; i++) { for (let i = 0; i < treeList.length; i++) {
this.$refs.menu.store.nodesMap[treeList[i].id].expanded = value; this.$refs.menu.store.nodesMap[treeList[i].id].expanded = value;
} }
} else if (type == 'dept') { } else if (type == "dept") {
let treeList = this.deptOptions; let treeList = this.deptOptions;
for (let i = 0; i < treeList.length; i++) { for (let i = 0; i < treeList.length; i++) {
this.$refs.dept.store.nodesMap[treeList[i].id].expanded = value; this.$refs.dept.store.nodesMap[treeList[i].id].expanded = value;
...@@ -484,18 +587,18 @@ export default { ...@@ -484,18 +587,18 @@ export default {
}, },
// 树权限(全选/全不选) // 树权限(全选/全不选)
handleCheckedTreeNodeAll(value, type) { handleCheckedTreeNodeAll(value, type) {
if (type == 'menu') { if (type == "menu") {
this.$refs.menu.setCheckedNodes(value ? this.menuOptions: []); this.$refs.menu.setCheckedNodes(value ? this.menuOptions : []);
} else if (type == 'dept') { } else if (type == "dept") {
this.$refs.dept.setCheckedNodes(value ? this.deptOptions: []); this.$refs.dept.setCheckedNodes(value ? this.deptOptions : []);
} }
}, },
// 树权限(父子联动) // 树权限(父子联动)
handleCheckedTreeConnect(value, type) { handleCheckedTreeConnect(value, type) {
if (type == 'menu') { if (type == "menu") {
this.form.menuCheckStrictly = value ? true: false; this.form.menuCheckStrictly = value ? true : false;
} else if (type == 'dept') { } else if (type == "dept") {
this.form.deptCheckStrictly = value ? true: false; this.form.deptCheckStrictly = value ? true : false;
} }
}, },
/** 新增按钮操作 */ /** 新增按钮操作 */
...@@ -508,19 +611,19 @@ export default { ...@@ -508,19 +611,19 @@ export default {
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { handleUpdate(row) {
this.reset(); this.reset();
const roleId = row.roleId || this.ids const roleId = row.roleId || this.ids;
const roleMenu = this.getRoleMenuTreeselect(roleId); const roleMenu = this.getRoleMenuTreeselect(roleId);
getRole(roleId).then(response => { getRole(roleId).then((response) => {
this.form = response.data; this.form = response;
this.open = true; this.open = true;
this.$nextTick(() => { this.$nextTick(() => {
roleMenu.then(res => { roleMenu.then((res) => {
let checkedKeys = res.checkedKeys let checkedKeys = res.checkedKeys;
checkedKeys.forEach((v) => { checkedKeys.forEach((v) => {
this.$nextTick(()=>{ this.$nextTick(() => {
this.$refs.menu.setChecked(v, true ,false); this.$refs.menu.setChecked(v, true, false);
}) });
}) });
}); });
}); });
this.title = "修改角色"; this.title = "修改角色";
...@@ -528,44 +631,42 @@ export default { ...@@ -528,44 +631,42 @@ export default {
}, },
/** 选择角色权限范围触发 */ /** 选择角色权限范围触发 */
dataScopeSelectChange(value) { dataScopeSelectChange(value) {
if(value !== '2') { if (value !== "2") {
this.$refs.dept.setCheckedKeys([]); this.$refs.dept.setCheckedKeys([]);
} }
}, },
/** 分配数据权限操作 */ /** 分配数据权限操作 */
handleDataScope(row) { handleDataScope(row) {
this.reset(); this.reset();
const deptTreeSelect = this.getDeptTree(row.roleId); // const deptTreeSelect = []
getRole(row.roleId).then(response => { getRole(row.roleId).then((response) => {
this.form = response.data; this.form = response;
this.openDataScope = true; this.openDataScope = true;
this.$nextTick(() => { // this.$nextTick(() => {
deptTreeSelect.then(res => { // this.$refs.dept.setCheckedKeys([]);
this.$refs.dept.setCheckedKeys(res.checkedKeys); // });
});
});
this.title = "分配数据权限"; this.title = "分配数据权限";
}); });
}, },
/** 分配用户操作 */ /** 分配用户操作 */
handleAuthUser: function(row) { handleAuthUser: function (row) {
const roleId = row.roleId; const roleId = row.roleId;
this.$router.push("/system/role-auth/user/" + roleId); this.$router.push("/system/role-auth/user/" + roleId);
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm: function() { submitForm: function () {
this.$refs["form"].validate(valid => { this.$refs["form"].validate((valid) => {
if (valid) { if (valid) {
if (this.form.roleId != undefined) { if (this.form.roleId != undefined) {
this.form.menuIds = this.getMenuAllCheckedKeys(); this.form.menuIds = this.getMenuAllCheckedKeys();
updateRole(this.form).then(response => { updateRole(this.form).then((response) => {
this.$modal.msgSuccess("修改成功"); this.$modal.msgSuccess("修改成功");
this.open = false; this.open = false;
this.getList(); this.getList();
}); });
} else { } else {
this.form.menuIds = this.getMenuAllCheckedKeys(); this.form.menuIds = this.getMenuAllCheckedKeys();
addRole(this.form).then(response => { addRole(this.form).then((response) => {
this.$modal.msgSuccess("新增成功"); this.$modal.msgSuccess("新增成功");
this.open = false; this.open = false;
this.getList(); this.getList();
...@@ -575,10 +676,10 @@ export default { ...@@ -575,10 +676,10 @@ export default {
}); });
}, },
/** 提交按钮(数据权限) */ /** 提交按钮(数据权限) */
submitDataScope: function() { submitDataScope: function () {
if (this.form.roleId != undefined) { if (this.form.roleId != undefined) {
this.form.deptIds = this.getDeptAllCheckedKeys(); this.form.deptIds = this.getDeptAllCheckedKeys();
dataScope(this.form).then(response => { dataScope(this.form).then((response) => {
this.$modal.msgSuccess("修改成功"); this.$modal.msgSuccess("修改成功");
this.openDataScope = false; this.openDataScope = false;
this.getList(); this.getList();
...@@ -588,19 +689,27 @@ export default { ...@@ -588,19 +689,27 @@ export default {
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
const roleIds = row.roleId || this.ids; const roleIds = row.roleId || this.ids;
this.$modal.confirm('是否确认删除角色编号为"' + roleIds + '"的数据项?').then(function() { this.$modal
return delRole(roleIds); .confirm('是否确认删除角色编号为"' + roleIds + '"的数据项?')
}).then(() => { .then(function () {
this.getList(); return delRole(roleIds);
this.$modal.msgSuccess("删除成功"); })
}).catch(() => {}); .then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
})
.catch(() => {});
}, },
/** 导出按钮操作 */ /** 导出按钮操作 */
handleExport() { handleExport() {
this.download('system/role/export', { this.download(
...this.queryParams "system/role/export",
}, `role_${new Date().getTime()}.xlsx`) {
} ...this.queryParams,
} },
`role_${new Date().getTime()}.xlsx`
);
},
},
}; };
</script> </script>
\ No newline at end of file
...@@ -29,23 +29,23 @@ ...@@ -29,23 +29,23 @@
<el-table-column label="用户名称" prop="userName" :show-overflow-tooltip="true" /> <el-table-column label="用户名称" prop="userName" :show-overflow-tooltip="true" />
<el-table-column label="用户昵称" prop="nickName" :show-overflow-tooltip="true" /> <el-table-column label="用户昵称" prop="nickName" :show-overflow-tooltip="true" />
<el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" /> <el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" />
<el-table-column label="手机" prop="phonenumber" :show-overflow-tooltip="true" /> <el-table-column label="手机" prop="phone" :show-overflow-tooltip="true" />
<el-table-column label="状态" align="center" prop="status"> <el-table-column label="状态" align="center" prop="status">
<template slot-scope="scope"> <template slot-scope="scope">
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/> <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180"> <el-table-column label="创建时间" align="center" prop="creationTime" width="180">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span> <span>{{ parseTime(scope.row.creationTime) }}</span>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<pagination <pagination
v-show="total>0" v-show="total>0"
:total="total" :total="total"
:page.sync="queryParams.pageNum" :page.sync="queryParams.current"
:limit.sync="queryParams.pageSize" :limit.sync="queryParams.size"
@pagination="getList" @pagination="getList"
/> />
</el-row> </el-row>
...@@ -78,8 +78,8 @@ export default { ...@@ -78,8 +78,8 @@ export default {
userList: [], userList: [],
// 查询参数 // 查询参数
queryParams: { queryParams: {
pageNum: 1, current: 1,
pageSize: 10, size: 10,
roleId: undefined, roleId: undefined,
userName: undefined, userName: undefined,
phonenumber: undefined phonenumber: undefined
...@@ -98,13 +98,14 @@ export default { ...@@ -98,13 +98,14 @@ export default {
}, },
// 多选框选中数据 // 多选框选中数据
handleSelectionChange(selection) { handleSelectionChange(selection) {
this.userIds = selection.map(item => item.userId); console.log(selection);
this.userIds = selection.map(item => item.id);
}, },
// 查询表数据 // 查询表数据
getList() { getList() {
unallocatedUserList(this.queryParams).then(res => { unallocatedUserList(this.queryParams).then(res => {
this.userList = res.rows; this.userList = res.data.records;
this.total = res.total; this.total = res.data.total;
}); });
}, },
/** 搜索按钮操作 */ /** 搜索按钮操作 */
......
import request from '@/utils/request'
const path = {
list: 'api/user/selectUserPage',
create: 'api/user/saveUser',
updatePwd: 'api/user/updatePwd',
updateInfo: 'api/user/updateUserBaseInfo',
logList: 'api/sysLog/selectLogPage',
}
export function list() {
return request.post(path.list, ...arguments);
}
export function create() {
return request.post(path.create, ...arguments);
}
export function updatePwd() {
return request.post(path.updatePwd, ...arguments);
}
export function updateInfo() {
return request.post(path.updateInfo, ...arguments);
}
export function logList() {
return request.post(path.logList, ...arguments);
}
...@@ -10,34 +10,57 @@ ...@@ -10,34 +10,57 @@
</el-col> </el-col>
<el-col :span="8" :offset="2"> <el-col :span="8" :offset="2">
<el-form-item label="登录账号" prop="userName"> <el-form-item label="登录账号" prop="userName">
<el-input v-model="form.userName" disabled /> <el-input v-model="form.userName" disabled />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
</el-form> </el-form>
<h4 class="form-header h4">角色信息</h4> <h4 class="form-header h4">角色信息</h4>
<el-table v-loading="loading" :row-key="getRowKey" @row-click="clickRow" ref="table" @selection-change="handleSelectionChange" :data="roles.slice((pageNum-1)*pageSize,pageNum*pageSize)"> <el-table
v-loading="loading"
:row-key="getRowKey"
@row-click="clickRow"
ref="table"
@selection-change="handleSelectionChange"
:data="roles.slice((pageNum - 1) * pageSize, pageNum * pageSize)"
>
<el-table-column label="序号" type="index" align="center"> <el-table-column label="序号" type="index" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{(pageNum - 1) * pageSize + scope.$index + 1}}</span> <span>{{ (pageNum - 1) * pageSize + scope.$index + 1 }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column type="selection" :reserve-selection="true" width="55"></el-table-column> <el-table-column
type="selection"
:reserve-selection="true"
width="55"
></el-table-column>
<el-table-column label="角色编号" align="center" prop="roleId" /> <el-table-column label="角色编号" align="center" prop="roleId" />
<el-table-column label="角色名称" align="center" prop="roleName" /> <el-table-column label="角色名称" align="center" prop="roleName" />
<el-table-column label="权限字符" align="center" prop="roleKey" /> <el-table-column label="权限字符" align="center" prop="roleKey" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180"> <el-table-column
label="创建时间"
align="center"
prop="createTime"
width="180"
>
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span> <span>{{ parseTime(scope.row.createTime) }}</span>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<pagination v-show="total>0" :total="total" :page.sync="pageNum" :limit.sync="pageSize" /> <pagination
v-show="total > 0"
:total="total"
:page.sync="pageNum"
:limit.sync="pageSize"
/>
<el-form label-width="100px"> <el-form label-width="100px">
<el-form-item style="text-align: center;margin-left:-120px;margin-top:30px;"> <el-form-item
style="text-align: center; margin-left: -120px; margin-top: 30px"
>
<el-button type="primary" @click="submitForm()">提交</el-button> <el-button type="primary" @click="submitForm()">提交</el-button>
<el-button @click="close()">返回</el-button> <el-button @click="close()">返回</el-button>
</el-form-item> </el-form-item>
...@@ -52,18 +75,18 @@ export default { ...@@ -52,18 +75,18 @@ export default {
name: "AuthRole", name: "AuthRole",
data() { data() {
return { return {
// 遮罩层 // 遮罩层
loading: true, loading: true,
// 分页信息 // 分页信息
total: 0, total: 0,
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
// 选中角色编号 // 选中角色编号
roleIds:[], roleIds: [],
// 角色信息 // 角色信息
roles: [], roles: [],
// 用户信息 // 用户信息
form: {} form: {},
}; };
}, },
created() { created() {
......
export function formInit(data = {}) {
return {
originName: '',
realName: '',
userName: '',
deptId: '',
password: '123456',
phone: '',
email: '',
userId: '',
...data
}
}
export function formInitPwd(data = {}) {
return {
userName: '',
originPwd: '',
password: '',
sureNewPwd: '',
userId: '',
...data
}
}
export const rules = {
userName: { required: true, message: '请输入用户名', trigger: 'blur' },
deptId: { required: true, message: '请选择所在部门', trigger: 'blur' }
}
<template>
<div>
<div class="title">修改基本信息</div>
<el-form ref="form" :model="form" label-width="130px" :rules="rules">
<el-form-item label="用户名:" prop="userName">
<el-input v-model="form.userName" />
</el-form-item>
<el-form-item label="所在部门:" prop="deptId">
<el-select v-model="form.deptId" style="width:100%" placeholder="请选择">
<el-option
v-for="item in departList"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="电话号码:">
<el-input v-model="form.phone" />
</el-form-item>
<el-form-item label="邮箱:">
<el-input v-model="form.email" />
</el-form-item>
</el-form>
<div class="btn">
<el-button type="primary" @click="confirm">确认修改</el-button>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import { rules } from '../../const'
import { updateInfo } from '../../api'
export default {
data() {
let { deptId, email, phone, userId, userName } = this.$store.state.user.userBaseInfo
return {
form: {
deptId: deptId,
email: email,
phone: phone,
userId: userId,
userName: userName
},
rules
}
},
computed: {
...mapGetters('depart', ['departList']),
},
methods: {
confirm() {
this.$refs.form.validate((valid) => {
if (valid) {
updateInfo(this.form).then(res => {
this.$message.success('操作成功');
})
} else {
return false;
}
})
}
}
}
</script>
<style lang="scss" scoped>
.btn {
margin-top: 50px;
text-align: center;
}
.title {
width: 100%;
height: 60px;
background: rgba(226, 235, 255, 0.39);
line-height: 60px;
font-size: 18px;
color: #333;
font-weight: 500;
text-align: center;
margin-bottom: 30px;
}
.el-form {
width: 500px;
margin: 0 auto;
}
</style>
<template>
<div>
<div class="title">修改密码</div>
<el-form ref="form" :model="form" label-width="100px" :rules="rules">
<el-form-item label="用户名:" prop="userName">
<el-input v-model="form.userName" />
</el-form-item>
<el-form-item label="原密码:" prop="originPwd">
<el-input type="password" v-model="form.originPwd" />
</el-form-item>
<el-form-item label="新密码:" prop="password">
<el-input type="password" v-model="form.password" />
</el-form-item>
<el-form-item label="确认新密码:" prop="sureNewPwd">
<el-input type="password" v-model="form.sureNewPwd" />
</el-form-item>
</el-form>
<div class="btn">
<el-button type="primary" @click="confirm">确认修改</el-button>
</div>
</div>
</template>
<script>
import { updatePwd } from '../../api';
export default {
data() {
var validatePass2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入新密码'));
} else if (value !== this.form.password) {
callback(new Error('两次输入密码不一致!'));
} else {
callback();
}
}
let { userId, userName } = this.$store.state.user.userBaseInfo
return {
form: {
userName: userName,
originPwd: '',
password: '',
sureNewPwd: '',
userId: userId
},
rules: {
userName: { required: true, message: '请输入用户名', trigger: 'blur' },
originPwd: { required: true, message: '请输入原密码', trigger: 'blur' },
password: { required: true, message: '请输入新密码', trigger: 'blur' },
sureNewPwd: [{ required: true, validator: validatePass2, trigger: 'blur' }]
}
}
},
methods: {
confirm() {
this.$refs.form.validate((valid) => {
if (valid) {
updatePwd(this.form).then(res => {
this.$message.success('操作成功');
})
} else {
return false;
}
})
}
}
}
</script>
<style lang="scss" scoped>
.btn {
margin-top: 50px;
text-align: center;
}
.el-form {
width: 500px;
margin: 0 auto;
}
.title {
width: 100%;
height: 60px;
background: rgba(226, 235, 255, 0.39);
line-height: 60px;
font-size: 18px;
color: #333;
font-weight: 500;
text-align: center;
margin-bottom: 30px;
}
</style>
<template>
<div>
<div class="update-user-container">
<div class="header">
<div class="tab">
<div
v-for="(item, index) in options"
:key="item.id"
class="tab-item"
:class="tabIndex === index ? 'tab-active' : ''"
@click="radioChange(item.value, index)"
>
{{ item.name }}
</div>
</div>
</div>
<base-info v-if="tabIndex === 0" />
<password v-if="tabIndex === 1" />
</div>
</div>
</template>
<script>
import baseInfo from '../updateUser/components/baseInfo.vue';
import Password from '../updateUser/components/password.vue';
export default {
components: { baseInfo, Password },
data() {
return {
options: [{
name: '修改基本信息',
value: 1
},
{
name: '修改密码',
value: 2
}],
tabIndex: 0
}
},
methods: {
radioChange(val, index) {
this.tabIndex = index;
}
}
}
</script>
<style lang="scss" scoped>
.header {
display: flex;
justify-content: center;
margin-bottom: 30px;
.tab {
display: flex;
cursor: pointer;
.tab-item {
margin: 0 50px;
padding-bottom: 10px;
}
.tab-active {
color: #038ed7;
border-bottom: 1px solid #038ed7;
}
}
}
</style>
<template>
<el-dialog
:title="editText"
:visible.sync="visible"
@close="cancel"
width="700px"
:close-on-click-modal="false"
>
<el-form ref="form" :model="form" label-width="100px" :rules="rules">
<el-form-item label="用户名:" prop="userName">
<el-input v-model="form.userName" />
</el-form-item>
<el-form-item label="真实姓名:" prop="realName">
<el-input v-model="form.realName" />
</el-form-item>
<el-form-item label="所在部门:" prop="deptId">
<el-select
v-model="form.deptId"
style="width: 100%"
placeholder="请选择"
>
<el-option
v-for="item in departList"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="电话号码:">
<el-input v-model="form.phone" />
</el-form-item>
<el-form-item label="邮箱:">
<el-input v-model="form.email" />
</el-form-item>
<el-form-item label="是否为管理员:">
<el-switch
v-model="form.isAdmin"
active-color="#13ce66"
inactive-color="#ccc"
:active-value="1"
:inactive-value="0"
>
</el-switch>
</el-form-item>
<el-form-item v-if="flag==1">注:新用户初始密码为123456</el-form-item>
</el-form>
<span slot="footer">
<el-button @click="cancel">取消</el-button>
<el-button type="primary" @click="confrim">确定</el-button>
</span>
</el-dialog>
</template>
<script>
import { formInit, rules } from '../../const';
import { updateInfo, create } from '../../api';
import { mapGetters } from 'vuex';
export default {
name: 'edit',
data() {
return {
rules,
form: formInit(),
visible: false
}
},
props: {
flag: {
type: Number,
default: 1
},
curInfo: {
type: Object,
default: () => { }
}
},
watch: {
flag: {
immediate: true,
handler(newV) {
this.visible = !!newV;
this.form = formInit(this.curInfo);
},
},
},
computed: {
...mapGetters('depart', ['departList']),
editText() {
return `${this.flag === 1 ? '新增' : '编辑'}基本信息`;
}
},
methods: {
cancel() {
this.form = formInit();
this.$emit('reset');
},
confrim() {
let apiMap = {
1: create,
2: updateInfo,
}
let api = apiMap[this.flag];
this.$refs['form'].validate(valid => {
let params = {
...this.form
}
if (valid) {
api(params).then(() => {
this.$message.success('操作成功');
this.$emit('reset', true);
})
}
})
}
}
}
</script>
<template>
<el-dialog
title="修改密码"
:visible.sync="visible"
@close="cancel"
width="700px"
:close-on-click-modal="false"
>
<el-form ref="form" :model="form" label-width="100px" :rules="rules">
<el-form-item label="用户名:" prop="userName">
<el-input v-model="form.userName" />
</el-form-item>
<el-form-item label="原密码:" prop="originPwd">
<el-input type="password" v-model="form.originPwd" />
</el-form-item>
<el-form-item label="新密码:" prop="password">
<el-input type="password" v-model="form.password" />
</el-form-item>
<el-form-item label="确认新密码:" prop="sureNewPwd">
<el-input type="password" v-model="form.sureNewPwd" />
</el-form-item>
</el-form>
<span slot="footer">
<el-button @click="cancel">取消</el-button>
<el-button type="primary" @click="confrim">确定</el-button>
</span>
</el-dialog>
</template>
<script>
import { formInitPwd } from '../../const';
import { updatePwd } from '../../api';
export default {
name: 'editPwd',
data() {
var validatePass2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入新密码'));
} else if (value !== this.form.password) {
callback(new Error('两次输入密码不一致!'));
} else {
callback();
}
}
return {
rules: {
userName: { required: true, message: '请输入用户名', trigger: 'blur' },
originPwd: { required: true, message: '请输入原密码', trigger: 'blur' },
password: { required: true, message: '请输入新密码', trigger: 'blur' },
sureNewPwd: [{ required: true, validator: validatePass2, trigger: 'blur' }]
},
form: formInitPwd(),
visible: false
}
},
props: {
flag1: {
type: Number,
default: 0
},
curInfo: {
type: Object,
default: () => { }
}
},
watch: {
flag1: {
immediate: true,
handler(newV) {
this.visible = !!newV;
this.form = formInitPwd(this.curInfo);
},
},
},
methods: {
cancel() {
this.form = formInitPwd();
this.$emit('reset');
},
confrim() {
this.$refs['form'].validate(valid => {
let params = {
...this.form
}
if (valid) {
updatePwd(params).then(() => {
this.$message.success('操作成功');
this.$emit('reset', true);
})
}
})
}
}
}
</script>
<template>
<div class="leakage-cable">
<div class="leakage-top">
<div style="color: #666666"></div>
<div class="operate-btn">
<el-button type="primary" @click="addUser">添加新用户</el-button>
</div>
</div>
<el-table
v-loading="loading"
:data="tableData"
class="statistics-table"
style="width: 100%"
:row-class-name="tableRowClassName"
:header-cell-style="{
background: '#eaf1fe',
color: '#000',
fontWeight: 700,
height: '50px',
}"
>
<el-table-column
type="index"
label="用户编号"
align="center"
width="100"
/>
<el-table-column prop="userName" label="用户名" align="center" />
<el-table-column prop="realName" label="真实姓名" align="center" />
<el-table-column prop="deptName" label="用户部门" align="center" />
<el-table-column prop="phone" label="电话号码" align="center" />
<el-table-column prop="email" label="邮箱" align="center" />
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="text" @click="toEditPwd(scope.row)">修改密码</el-button>
<el-button type="text" @click="toEditInfo(scope.row)">修改基本信息</el-button>
</template>
</el-table-column>
</el-table>
<Pagination
:limit="params.pageSize"
:page="params.pageNum"
:total="total"
class="pagination"
@pagination="handlePageChange"
/>
<edit @reset="reset" :cur-info="curInfo" :flag="flag"></edit>
<ediPwd @reset="reset" :cur-info="curInfo" :flag1="flag1"></ediPwd>
</div>
</template>
<script>
import { list } from '../api';
import edit from './components/editInfo.vue';
import ediPwd from './components/editPwd.vue';
export default {
data() {
return {
params: {
pageNum: 1,
pageSize: 10
},
tableData: [],
total: 5,
loading: false,
curInfo: {},
flag: 0,
flag1: 0
}
},
components: {
edit,
ediPwd
},
methods: {
tableRowClassName({ row, rowIndex }) {
return rowIndex % 2 === 0 ? '' : 'single-row';
},
handlePageChange(pageData) {
this.params.pageSize = pageData.size;
this.params.pageNum = pageData.page;
this.getTableData();
},
getTableData() {
let params = {
current: this.params.pageNum,
size: this.params.pageSize
}
list(params).then(res => {
let list = res.records || [];
list.forEach(item => {
item.userId = item.id;
})
this.tableData = list;
this.total = res.total;
})
},
addUser() {
this.curInfo = {};
this.flag = 1;
},
toEditInfo(row) {
this.curInfo = row;
this.flag = 2;
},
toEditPwd(row) {
this.curInfo = row;
this.flag1 = 3;
},
reset(needRefresh) {
this.flag = 0;
this.flag1 = 0;
if(needRefresh) {
this.getTableData();
}
}
},
mounted() {
this.getTableData();
},
}
</script>
<style lang="scss" scoped>
.leakage-cable {
.leakage-top {
margin-bottom: 20px;
display: flex;
align-items: flex-end;
justify-content: space-between;
}
& ::v-deep .cell {
color: #333333;
}
& ::v-deep .stripe {
background-color: #eaf1fe;
}
& ::v-deep .red {
background-color: #f00;
}
& ::v-deep .green {
background-color: green;
}
.page {
display: flex;
align-items: center;
justify-content: center;
margin: 20px 0;
.pageNum {
margin: 0 20px;
}
}
}
</style>
<style lang="scss">
.statistics-table {
.single-row {
background: #f1f6ff;
}
td {
padding: 5px !important;
}
}
</style>
\ No newline at end of file
<template>
<div>
<el-form
class="search-form"
:model="form"
ref="form"
label-width="80px"
:inline="true"
size="mini"
>
<el-form-item label="操作对象">
<el-select
v-model="form.operateObj"
placeholder="请选择操作对象"
clearable
>
<el-option
v-for="item in operatObj"
:key="item.dictValue"
:label="item.dictValue"
:value="+item.dictValue1"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="操作内容">
<el-select
v-model="form.operateContent"
placeholder="请选择操作内容"
clearable
>
<el-option
v-for="item in operatContent"
:key="item.dictValue"
:label="item.dictValue"
:value="item.dictValue1"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="操作结果">
<el-select
v-model="form.operateResult"
placeholder="请选择操作结果"
clearable
>
<el-option
v-for="(val, key) in resultEnum"
:key="val"
:label="val"
:value="+key"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="success" @click="toSearch">查询</el-button>
<el-button type="primary" @click="reset">重置</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import { selectDictType } from '@/api/baseData';
export default {
name: 'search',
data() {
return {
operatContent: [],
operatObj: [],
resultEnum: {
0: '失败',
1: '成功',
},
form: formInit()
}
},
computed: {
},
mounted() {
this.getInit()
},
methods: {
toSearch() {
this.$emit('search', this.form);
},
reset() {
this.form = formInit();
this.$emit('search');
},
getInit() {
selectDictType({ dictType: '06' }).then(res => {
let list = res || [];
this.operatContent = list;
})
selectDictType({ dictType: '07' }).then(res => {
let list = res || [];
this.operatObj = list;
})
}
}
}
function formInit() {
return {
operateContent: '',
operateObj: null,
operateResult: null,
}
}
</script>
<style scoped lang="scss">
.w200 {
width: 200px;
}
.search-form {
padding: 10px;
background-color: #eaf1fe;
margin-bottom: 20px;
border-radius: 8px;
.el-form-item--mini.el-form-item,
.el-form-item--small.el-form-item {
margin-bottom: 0;
}
}
</style>
\ No newline at end of file
<template>
<!-- 用户操作日志 -->
<div class="leakage-cable">
<div class="leakage-top">
<div style="color: #666666"></div>
<div class="operate-btn">
<el-button type="primary" @click="refresh">刷新</el-button>
<el-button type="primary" @click="isQuery = !isQuery">查询</el-button>
<el-button type="primary" @click="exportLog">导出</el-button>
</div>
</div>
<div v-if="isQuery">
<search @search="search" ref="reset" />
</div>
<el-table
:data="tableData"
style="width: 100%"
class="statistics-table"
:row-class-name="tableRowClassName"
:row-style="{ height: '50px' }"
:header-cell-style="{ background: '#EAF1FE', color: '#666666' }"
>
<el-table-column prop="userName" label="用户名" align="center" />
<el-table-column prop="operateTypeName" label="操作类别" align="center" />
<el-table-column prop="operateObjName" label="操作对象" align="center" />
<el-table-column prop="objectName" label="对象名称" align="center" />
<el-table-column prop="operateContent" label="操作内容" align="center" />
<el-table-column
prop="operateResultName"
label="操作结果"
align="center"
/>
<el-table-column prop="creationTime" label="操作时间" align="center" />
</el-table>
<Pagination
:limit="params.size"
:page="params.current"
:total="total"
class="pagination"
@pagination="handlePageChange"
/>
</div>
</template>
<script>
import { logList } from "../api";
import search from "./components/search.vue";
import { exportLog } from "@/api/export";
import download from "@/utils/download";
import { successAlert, warningAlert } from "@/utils/alert";
export default {
data() {
return {
params: {
current: 1,
size: 10,
},
total: 10,
tableData: [],
isQuery: false,
istrue: 0,
searchOption: {},
exids: [],
};
},
components: {
search,
},
methods: {
handlePageChange(pageData) {
this.params.size = pageData.size;
this.params.current = pageData.page;
this.getTableData();
},
refresh() {
this.$refs.reset != undefined
? this.$refs.reset.reset()
: this.getTableData();
},
search(option) {
this.params.current = 1;
this.istrue = 1;
this.searchOption = option;
this.getTableData();
},
getTableData() {
let params = {
...this.params,
...this.searchOption,
};
logList(params).then((res) => {
let list = res.records || [];
this.tableData = list;
this.total = res.total;
this.exids = list.map((i) => i.id);
if (this.istrue == 1) {
if (this.tableData.length != 0) {
successAlert("操作成功");
} else {
warningAlert("查询结果为空");
}
this.istrue = 0;
}
});
},
tableRowClassName({ row, rowIndex }) {
return rowIndex % 2 === 0 ? "" : "single-row";
},
exportLog() {
if (this.exids.length == 0) {
this.$message.warning("暂无数据");
return false;
} else {
exportLog({ ids: this.exids }).then((res) => {
download(res, "vnd.ms-excel", `用户日志.xls`);
});
}
},
},
mounted() {
this.getTableData();
},
};
</script>
<style lang="scss" scoped>
.leakage-cable {
.leakage-top {
margin-bottom: 20px;
display: flex;
align-items: flex-end;
justify-content: space-between;
}
& ::v-deep .cell {
color: #333333;
}
.page {
display: flex;
align-items: center;
justify-content: center;
margin: 20px 0;
.current {
margin: 0 20px;
}
}
}
</style>
<style lang="scss">
.statistics-table {
.single-row {
background: #f1f6ff;
}
td {
padding: 5px !important;
}
}
</style>
\ No newline at end of file
<template>
<div class="app-container">
<h4 class="form-header h4">基本信息</h4>
<el-form ref="form" :model="form" label-width="80px">
<el-row>
<el-col :span="8" :offset="2">
<el-form-item label="用户昵称" prop="nickName">
<el-input v-model="form.nickName" disabled />
</el-form-item>
</el-col>
<el-col :span="8" :offset="2">
<el-form-item label="登录账号" prop="userName">
<el-input v-model="form.userName" disabled />
</el-form-item>
</el-col>
</el-row>
</el-form>
<h4 class="form-header h4">角色信息</h4>
<el-table v-loading="loading" :row-key="getRowKey" @row-click="clickRow" ref="table" @selection-change="handleSelectionChange" :data="roles.slice((pageNum-1)*pageSize,pageNum*pageSize)">
<el-table-column label="序号" type="index" align="center">
<template slot-scope="scope">
<span>{{(pageNum - 1) * pageSize + scope.$index + 1}}</span>
</template>
</el-table-column>
<el-table-column type="selection" :reserve-selection="true" width="55"></el-table-column>
<el-table-column label="角色编号" align="center" prop="roleId" />
<el-table-column label="角色名称" align="center" prop="roleName" />
<el-table-column label="权限字符" align="center" prop="roleKey" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
</el-table>
<pagination v-show="total>0" :total="total" :page.sync="pageNum" :limit.sync="pageSize" />
<el-form label-width="100px">
<el-form-item style="text-align: center;margin-left:-120px;margin-top:30px;">
<el-button type="primary" @click="submitForm()">提交</el-button>
<el-button @click="close()">返回</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import { getAuthRole, updateAuthRole } from "@/api/system/user";
export default {
name: "AuthRole",
data() {
return {
// 遮罩层
loading: true,
// 分页信息
total: 0,
pageNum: 1,
pageSize: 10,
// 选中角色编号
roleIds:[],
// 角色信息
roles: [],
// 用户信息
form: {}
};
},
created() {
const userId = this.$route.params && this.$route.params.userId;
if (userId) {
this.loading = true;
getAuthRole(userId).then((response) => {
this.form = response.user;
this.roles = response.roles;
this.total = this.roles.length;
this.$nextTick(() => {
this.roles.forEach((row) => {
if (row.flag) {
this.$refs.table.toggleRowSelection(row);
}
});
});
this.loading = false;
});
}
},
methods: {
/** 单击选中行数据 */
clickRow(row) {
this.$refs.table.toggleRowSelection(row);
},
// 多选框选中数据
handleSelectionChange(selection) {
this.roleIds = selection.map((item) => item.roleId);
},
// 保存选中的数据编号
getRowKey(row) {
return row.roleId;
},
/** 提交按钮 */
submitForm() {
const userId = this.form.userId;
const roleIds = this.roleIds.join(",");
updateAuthRole({ userId: userId, roleIds: roleIds }).then((response) => {
this.$modal.msgSuccess("授权成功");
this.close();
});
},
/** 关闭按钮 */
close() {
const obj = { path: "/system/user" };
this.$tab.closeOpenPage(obj);
},
},
};
</script>
\ No newline at end of file
...@@ -520,7 +520,7 @@ import { ...@@ -520,7 +520,7 @@ import {
changeUserStatus, changeUserStatus,
deptTreeSelect, deptTreeSelect,
} from "@/api/system/user"; } from "@/api/system/user";
import * as API_cmsParty from "@/api/cmsParty"; // import * as API_cmsParty from "@/api/cmsParty";
import { getToken } from "@/utils/auth"; import { getToken } from "@/utils/auth";
import Treeselect from "@riophae/vue-treeselect"; import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css"; import "@riophae/vue-treeselect/dist/vue-treeselect.css";
...@@ -653,22 +653,22 @@ export default { ...@@ -653,22 +653,22 @@ export default {
this.getConfigKey("sys.user.initPassword").then((response) => { this.getConfigKey("sys.user.initPassword").then((response) => {
this.initPassword = response.msg; this.initPassword = response.msg;
}); });
this.handleQueryOrganizationList(); // this.handleQueryOrganizationList();
}, },
methods: { methods: {
// 获取党组织列表 // 获取党组织列表
handleQueryOrganizationList() { // handleQueryOrganizationList() {
this.loading = true; // this.loading = true;
API_cmsParty.organizationList({}) // API_cmsParty.organizationList({})
.then((res) => { // .then((res) => {
if (res.code == 200) { // if (res.code == 200) {
this.organizeList = res.data; // this.organizeList = res.data;
} // }
}) // })
.finally(() => { // .finally(() => {
this.loading = false; // this.loading = false;
}); // });
}, // },
/** 查询用户列表 */ /** 查询用户列表 */
getList() { getList() {
this.loading = true; this.loading = true;
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body @opened="modalOpened" @close="closeDialog"> <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body @opened="modalOpened" @close="closeDialog">
<el-row> <el-row>
<el-col :xs="24" :md="12" :style="{height: '350px'}"> <el-col :xs="24" :md="12" :style="{height: '350px'}">
<vue-cropper <!-- <vue-cropper
ref="cropper" ref="cropper"
:img="options.img" :img="options.img"
:info="true" :info="true"
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
:outputType="options.outputType" :outputType="options.outputType"
@realTime="realTime" @realTime="realTime"
v-if="visible" v-if="visible"
/> /> -->
</el-col> </el-col>
<el-col :xs="24" :md="12" :style="{height: '350px'}"> <el-col :xs="24" :md="12" :style="{height: '350px'}">
<div class="avatar-upload-preview"> <div class="avatar-upload-preview">
...@@ -55,12 +55,12 @@ ...@@ -55,12 +55,12 @@
<script> <script>
import store from "@/store"; import store from "@/store";
import { VueCropper } from "vue-cropper"; // import { VueCropper } from "vue-cropper";
import { uploadAvatar } from "@/api/system/user"; import { uploadAvatar } from "@/api/system/user";
import { debounce } from '@/utils' import { debounce } from '@/utils'
export default { export default {
components: { VueCropper }, // components: { VueCropper },
data() { data() {
return { return {
// 是否显示弹出层 // 是否显示弹出层
......
...@@ -8,9 +8,9 @@ function resolve(dir) { ...@@ -8,9 +8,9 @@ function resolve(dir) {
const name = defaultSettings.title || '漏缆故障定位监测系统' // page title const name = defaultSettings.title || '漏缆故障定位监测系统' // page title
const port = process.env.port || process.env.npm_config_port || 8890 // dev port const port = process.env.port || process.env.npm_config_port || 8890 // dev port
const href = 'http://101.126.159.207' // const href = 'http://101.126.159.207'
// const href = 'http://127.0.0.1' // const href = 'http://127.0.0.1'
// const href = 'http://192.168.0.122' const href = 'http://192.168.0.122'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment