添加菜单权限

This commit is contained in:
熊丽君
2021-08-12 11:39:59 +08:00
parent 34356963db
commit e75d93de68
29 changed files with 2379 additions and 119 deletions

View File

@ -28,4 +28,57 @@ export function logout() {
url: '/admin/logout',
method: 'post'
})
}
}
export function fetchList(params) {
return request({
url: '/admin/list',
method: 'get',
params: params
});
}
export function createAdmin(data) {
return request({
url: '/admin/register',
method: 'post',
data: data
});
}
export function updateAdmin(id, data) {
return request({
url: '/admin/update/' + id,
method: 'post',
data: data
});
}
export function updateStatus(id, params) {
return request({
url: '/admin/updateStatus/' + id,
method: 'post',
params: params
});
}
export function deleteAdmin(id) {
return request({
url: '/admin/delete/' + id,
method: 'post'
});
}
export function getRoleByAdmin(id) {
return request({
url: '/admin/role/' + id,
method: 'get'
});
}
export function allocRole(params) {
return request({
url: '/admin/role/update',
method: 'post',
params
});
}

View File

@ -6,4 +6,56 @@ export const getRouters = () => {
url: '/getRouters',
method: 'get'
})
}
}
export function fetchList(parentId, params) {
return request({
url: '/menu/list/' + parentId,
method: 'get',
params: params
});
}
export function deleteMenu(id) {
return request({
url: '/menu/delete/' + id,
method: 'post'
});
}
export function createMenu(data) {
return request({
url: '/menu/create',
method: 'post',
data: data
});
}
export function updateMenu(id, data) {
return request({
url: '/menu/update/' + id,
method: 'post',
data: data
});
}
export function getMenu(id) {
return request({
url: '/menu/' + id,
method: 'get'
});
}
export function updateHidden(id, params) {
return request({
url: '/menu/updateHidden/' + id,
method: 'post',
params: params
});
}
export function fetchTreeList() {
return request({
url: '/menu/treeList',
method: 'get'
});
}

39
src/api/resource.js Normal file
View File

@ -0,0 +1,39 @@
import request from '@/utils/request'
export function fetchList(params) {
return request({
url: '/resource/list',
method: 'get',
params: params
})
}
export function createResource(data) {
return request({
url: '/resource/create',
method: 'post',
data: data
})
}
export function updateResource(id, data) {
return request({
url: '/resource/update/' + id,
method: 'post',
data: data
})
}
export function deleteResource(id) {
return request({
url: '/resource/delete/' + id,
method: 'post'
})
}
export function fetchAllResourceList() {
return request({
url: '/resource/listAll',
method: 'get'
})
}

View File

@ -0,0 +1,31 @@
import request from '@/utils/request'
export function listAllCate() {
return request({
url: '/resourceCategory/listAll',
method: 'get'
})
}
export function createResourceCategory(data) {
return request({
url: '/resourceCategory/create',
method: 'post',
data: data
})
}
export function updateResourceCategory(id, data) {
return request({
url: '/resourceCategory/update/' + id,
method: 'post',
data: data
})
}
export function deleteResourceCategory(id) {
return request({
url: '/resourceCategory/delete/' + id,
method: 'post'
})
}

81
src/api/role.js Normal file
View File

@ -0,0 +1,81 @@
import request from '@/utils/request';
export function fetchList(params) {
return request({
url: '/role/list',
method: 'get',
params: params
});
}
export function createRole(data) {
return request({
url: '/role/create',
method: 'post',
data: data
});
}
export function updateRole(id, data) {
return request({
url: '/role/update/' + id,
method: 'post',
data: data
});
}
export function updateStatus(id, params) {
return request({
url: '/role/updateStatus/' + id,
method: 'post',
params: params
});
}
export function deleteRole(params) {
return request({
url: '/role/delete',
method: 'post',
// data:
params
});
}
export function fetchAllRoleList() {
return request({
url: '/role/listAll',
method: 'get'
});
}
export function listMenuByRole(roleId) {
return request({
url: '/role/listMenu/' + roleId,
method: 'get'
});
}
export function listResourceByRole(roleId) {
return request({
url: '/role/listResource/' + roleId,
method: 'get'
});
}
export function allocMenu(params) {
return request({
url: '/role/allocMenu',
method: 'post',
// data:data
params
});
}
export function allocResource(params) {
return request({
url: '/role/allocResource',
method: 'post',
// data: data,
params
});
}

View File

@ -1,65 +1,52 @@
import router from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { getToken } from '@/utils/auth'
NProgress.configure({ showSpinner: false })
const whiteList = ['/login', '/auth-redirect', '/bind', '/register']
import router from './router';
import store from './store';
import NProgress from 'nprogress'; // Progress 进度条
import 'nprogress/nprogress.css'; // Progress 进度条样式
import { Message } from 'element-ui';
import { getToken } from '@/utils/auth'; // 验权
NProgress.configure({ showSpinner: false });
const whiteList = ['/login', '/auth-redirect', '/bind', '/register'];
router.beforeEach((to, from, next) => {
NProgress.start()
NProgress.start();
if (getToken()) {
/* has token*/
if (to.path === '/login') {
next({ path: '/' })
NProgress.done()
next({ path: '/' });
NProgress.done(); // if current page is dashboard will not trigger afterEach hook, so manually handle it
} else {
if (store.getters.roles.length === 0) {
// 判断当前用户是否已拉取完user_info信息
store.dispatch('GetInfo').then(res => {
// 拉取user_info
// console.log(res.roles);
const roles = res.roles
store.dispatch('GenerateRoutes', { roles }).then(accessRoutes => {
// 测试 默认静态页面
// store.dispatch('permission/generateRoutes', { roles }).then(accessRoutes => {
// 根据roles权限生成可访问路由表
router.addRoutes(accessRoutes) // 动态添加可访问路由表
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
store
.dispatch('GetInfo')
.then(res => {
// 拉取用户信息
let menus = res.data.menus;
let username = res.data.username;
store.dispatch('GenerateRoutes', { menus, username }).then(() => {
// 生成可访问的路由表
router.addRoutes(store.getters.addRoutes); // 动态添加可访问路由表
next({ ...to, replace: true });
});
})
})
.catch(err => {
store.dispatch('FedLogOut').then(() => {
Message.error(err)
next({ path: '/' })
})
})
Message.error(err || 'Verification failed, please login again');
next({ path: '/' });
});
});
} else {
next()
// 没有动态改变权限的需求可直接next() 删除下方权限判断 ↓
// if (hasPermission(store.getters.roles, to.meta.roles)) {
// next()
// } else {
// next({ path: '/401', replace: true, query: { noGoBack: true }})
// }
// 可删 ↑
next();
}
}
} else {
// 没有token
if (whiteList.indexOf(to.path) !== -1) {
// 在免登录白名单,直接进入
next()
next();
} else {
next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
NProgress.done()
next('/login');
NProgress.done();
}
}
})
});
router.afterEach(() => {
NProgress.done()
})
NProgress.done(); // 结束Progress
});

View File

@ -11,6 +11,7 @@ import customerManagement from './modules/customerManagement';
import accountManagement from './modules/accountManagement';
import customerService from './modules/customerService';
import feedback from './modules/feedback';
import settings from './modules/settings';
export const DynamicRoutes = [
// 政策管理
@ -26,7 +27,9 @@ export const DynamicRoutes = [
// 客服中心
customerService,
// 意见反馈
feedback
feedback,
// 系统设置
settings
];
export default DynamicRoutes;

View File

@ -23,6 +23,7 @@ import Layout from '@/layout'
breadcrumb: false // 如果设置为false则不会在breadcrumb面包屑中显示
}
*/
import DynamicRoutes from './dynamicRoutes'
// 公共路由
export const constantRoutes = [
@ -61,7 +62,7 @@ export const constantRoutes = [
path: 'index',
component: (resolve) => require(['@/views/index'], resolve),
name: '首页',
meta: { title: '首页', noCache: true, affix: true }
meta: { title: '首页', icon: 'dashboard', noCache: true, affix: true }
}
]
},
@ -119,6 +120,7 @@ export const constantRoutes = [
]
}
]
export const asyncRouterMap = DynamicRoutes
export default new Router({
mode: 'history', // 去掉url中的#

View File

@ -8,8 +8,8 @@ const nestedRouter = {
{
path: 'account',
component: resolve => require(['@/views/account/index'], resolve),
name: '账号管理',
meta: { title: '账号管理' }
name: 'account',
meta: { title: '账号管理', icon: 'user' }
}
]
};

View File

@ -6,14 +6,15 @@ const nestedRouter = {
path: '/front',
component: Layout,
redirect: 'noRedirect',
meta: { title: '前端配置' },
name:'front',
meta: { title: '前端配置', icon: 'swagger' },
children: [
{
path: 'unscramble',
component: resolve =>
require(['@/views/front/unscramble/index'], resolve),
name: 'unscramble',
meta: { title: '政策解读' }
meta: { title: '政策解读', icon: 'list' }
},
{
path: 'addUnscramble',
@ -27,7 +28,7 @@ const nestedRouter = {
component: resolve =>
require(['@/views/front/expressNews/index'], resolve),
name: 'expressNews',
meta: { title: '资讯快报' }
meta: { title: '资讯快报', icon: 'list' }
},
{
path: 'addExpressNews',

View File

@ -8,8 +8,8 @@ const nestedRouter = {
{
path: 'customer',
component: resolve => require(['@/views/customer/index'], resolve),
name: '客户管理',
meta: { title: '客户管理' }
name: 'customer',
meta: { title: '客户管理', icon: 'peoples' }
},
{
path: 'addCustomer',

View File

@ -8,8 +8,8 @@ const nestedRouter = {
{
path: 'service',
component: resolve => require(['@/views/service/index'], resolve),
name: '客服中心',
meta: { title: '客服中心' }
name: 'service',
meta: { title: '客服中心', icon:'people' }
}
]
};

View File

@ -9,7 +9,7 @@ const nestedRouter = {
path: 'feedback',
component: resolve => require(['@/views/feedback/index'], resolve),
name: 'feedback',
meta: { title: '意见反馈' }
meta: { title: '意见反馈', icon: 'message' }
}
]
};

View File

@ -6,13 +6,14 @@ const nestedRouter = {
path: '/policy',
component: Layout,
redirect: 'noRedirect',
meta: { title: '政策管理' },
name:'policy',
meta: { title: '政策管理', icon: 'row' },
children: [
{
path: 'library',
component: resolve => require(['@/views/policy/library/index'], resolve),
name: 'library',
meta: { title: '政策库' }
meta: { title: '政策库', icon: 'list' }
},
{
path: 'add',
@ -25,7 +26,7 @@ const nestedRouter = {
path: 'tag',
component: resolve => require(['@/views/policy/tag/index'], resolve),
name: 'tag',
meta: { title: '政策标签' }
meta: { title: '政策标签', icon: 'list' }
}
]
};

View File

@ -0,0 +1,72 @@
import Layout from '@/layout';
// 账号管理
const nestedRouter = {
path: '/ums',
component: Layout,
redirect: '/ums/admin',
name: 'ums',
meta: { title: '系统设置', icon: 'system' },
children: [
{
path: 'admin',
name: 'admin',
component: () => import('@/views/ums/admin/index'),
meta: { title: '用户列表', icon: 'list' }
},
{
path: 'role',
name: 'role',
component: () => import('@/views/ums/role/index'),
meta: { title: '角色列表', icon: 'list' }
},
{
path: 'allocMenu',
name: 'allocMenu',
component: () => import('@/views/ums/role/allocMenu'),
meta: { title: '分配菜单' },
hidden: true
},
{
path: 'allocResource',
name: 'allocResource',
component: () => import('@/views/ums/role/allocResource'),
meta: { title: '分配资源' },
hidden: true
},
{
path: 'menu',
name: 'menu',
component: () => import('@/views/ums/menu/index'),
meta: { title: '菜单列表', icon: 'list' }
},
{
path: 'addMenu',
name: 'addMenu',
component: () => import('@/views/ums/menu/add'),
meta: { title: '添加菜单' },
hidden: true
},
{
path: 'updateMenu',
name: 'updateMenu',
component: () => import('@/views/ums/menu/update'),
meta: { title: '修改菜单' },
hidden: true
},
{
path: 'resource',
name: 'resource',
component: () => import('@/views/ums/resource/index'),
meta: { title: '资源列表', icon: 'list' }
},
{
path: 'resourceCategory',
name: 'resourceCategory',
component: () => import('@/views/ums/resource/categoryList'),
meta: { title: '资源分类' },
hidden: true
}
]
}
export default nestedRouter;

View File

@ -6,14 +6,15 @@ const nestedRouter = {
path: '/technology',
component: Layout,
redirect: 'noRedirect',
meta: { title: '技术转移' },
name:'technology',
meta: { title: '技术转移', icon: 'clipboard'},
children: [
{
path: 'demand',
component: resolve =>
require(['@/views/technology/demand/index'], resolve),
name: 'demand',
meta: { title: '企业需求' }
meta: { title: '企业需求', icon: 'list' }
},
{
path: 'addDemand',
@ -27,7 +28,7 @@ const nestedRouter = {
component: resolve =>
require(['@/views/technology/achievement/index'], resolve),
name: 'achievement',
meta: { title: '科技成果' }
meta: { title: '科技成果', icon: 'list' }
},
{
path: 'addAchievement',

View File

@ -10,6 +10,7 @@ const getters = {
introduction: state => state.user.introduction,
roles: state => state.user.roles,
permissions: state => state.user.permissions,
permission_routes: state => state.permission.routes
}
export default getters
permission_routes: state => state.permission.routes,
addRoutes: state => state.permission.addRoutes
};
export default getters;

View File

@ -1,60 +1,109 @@
import { constantRoutes } from '@/router'
// import { getRouters } from '@/api/menu'
import Layout from '@/layout/index'
import DynamicRoutes from '@/router/dynamicRoutes'
import { asyncRouterMap, constantRoutes } from '@/router/index';
const permission = {
state: {
routes: [],
addRoutes: []
},
mutations: {
SET_ROUTES: (state, routes) => {
state.addRoutes = routes
state.routes = constantRoutes.concat(routes)
}
},
actions: {
// 生成路由
GenerateRoutes({ commit }) {
return new Promise(resolve => {
// console.log(DynamicRoutes);
const accessedRoutes = filterAsyncRouter(DynamicRoutes)
accessedRoutes.push({ path: '*', redirect: '/404', hidden: true })
commit('SET_ROUTES', accessedRoutes)
resolve(accessedRoutes)
// 向后端请求路由数据
// getRouters().then(res => {
// const accessedRoutes = filterAsyncRouter(res.data)
// accessedRoutes.push({ path: '*', redirect: '/404', hidden: true })
// commit('SET_ROUTES', accessedRoutes)
// resolve(accessedRoutes)
// })
})
//判断是否有权限访问该菜单
function hasPermission(menus, route) {
if (route.name) {
let currMenu = getMenu(route.name, menus);
if (currMenu != null) {
//设置菜单的标题、图标和可见性
if (currMenu.title != null && currMenu.title !== '') {
route.meta.title = currMenu.title;
}
if (currMenu.icon != null && currMenu.title !== '') {
route.meta.icon = currMenu.icon;
}
if (currMenu.hidden != null) {
route.hidden = currMenu.hidden !== 0;
}
if (currMenu.sort != null && currMenu.sort !== '') {
route.sort = currMenu.sort;
}
return true;
} else {
route.sort = 0;
if (route.hidden !== undefined && route.hidden === true) {
return true;
} else {
return false;
}
}
} else {
return true;
}
}
// 遍历后台传来的路由字符串,转换为组件对象
function filterAsyncRouter(asyncRouterMap) {
return asyncRouterMap.filter(route => {
// if (route.component) {
// // Layout组件特殊处理
// if (route.component === 'Layout') {
// route.component = Layout
// } else {
// route.component = loadView(route.component)
// }
// }
if (route.children != null && route.children && route.children.length) {
route.children = filterAsyncRouter(route.children)
//根据路由名称获取菜单
function getMenu(name, menus) {
for (let i = 0; i < menus.length; i++) {
let menu = menus[i];
if (name === menu.name) {
return menu;
}
return true
})
}
return null;
}
export const loadView = (view) => { // 路由懒加载
return (resolve) => require([`@/views/${view}`], resolve)
//对菜单进行排序
function sortRouters(accessedRouters) {
for (let i = 0; i < accessedRouters.length; i++) {
let router = accessedRouters[i];
if (router.children && router.children.length > 0) {
router.children.sort(compare('sort'));
}
}
accessedRouters.sort(compare('sort'));
}
export default permission
//降序比较函数
function compare(p) {
return function(m, n) {
let a = m[p];
let b = n[p];
return b - a;
};
}
const permission = {
state: {
routes: constantRoutes,
addRoutes: []
},
mutations: {
SET_ROUTERS: (state, routes) => {
state.addRoutes = routes;
state.routes = constantRoutes.concat(routes);
}
},
actions: {
GenerateRoutes({ commit }, data) {
return new Promise(resolve => {
const { menus } = data;
const { username } = data;
const accessedRouters = asyncRouterMap.filter(v => {
//admin帐号直接返回所有菜单
// if (username === 'admin') return true;
if (hasPermission(menus, v)) {
if (v.children && v.children.length > 0) {
v.children = v.children.filter(child => {
if (hasPermission(menus, child)) {
return child;
}
return false;
});
return v;
} else {
return v;
}
}
return false;
});
//对菜单进行排序
sortRouters(accessedRouters);
commit('SET_ROUTERS', accessedRouters);
resolve();
});
}
}
};
export default permission;

42
src/utils/date.js Normal file
View File

@ -0,0 +1,42 @@
// date.js
export function formatDate(date, fmt) {
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
}
let o = {
'M+': date.getMonth() + 1,
'd+': date.getDate(),
'h+': date.getHours(),
'm+': date.getMinutes(),
's+': date.getSeconds()
};
for (let k in o) {
if (new RegExp(`(${k})`).test(fmt)) {
let str = o[k] + '';
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : padLeftZero(str));
}
}
return fmt;
}
function padLeftZero(str) {
return ('00' + str).substr(str.length);
}
export function str2Date(dateStr, separator) {
if (!separator) {
separator = "-";
}
let dateArr = dateStr.split(separator);
let year = parseInt(dateArr[0]);
let month;
//处理月份为04这样的情况
if (dateArr[1].indexOf("0") == 0) {
month = parseInt(dateArr[1].substring(1));
} else {
month = parseInt(dateArr[1]);
}
let day = parseInt(dateArr[2]);
let date = new Date(year, month - 1, day);
return date;
}

View File

@ -0,0 +1,393 @@
<template>
<div class="app-container">
<el-card class="filter-container" shadow="never">
<div>
<i class="el-icon-search"></i>
<span>筛选搜索</span>
<el-button
style="float:right"
type="primary"
@click="handleSearchList()"
size="small"
>
查询
</el-button>
</div>
<div style="margin-top: 15px">
<el-form
:inline="true"
:model="listQuery"
size="small"
label-width="140px"
@submit.native.prevent
>
<el-form-item label="输入搜索:">
<el-input
v-model="listQuery.keyword"
class="input-width"
placeholder="帐号/姓名"
></el-input>
</el-form-item>
</el-form>
</div>
</el-card>
<el-card class="operate-container" shadow="never">
<i class="el-icon-tickets"></i>
<span>数据列表</span>
<el-button
size="mini"
class="btn-add"
@click="handleAdd()"
style="margin-left: 20px"
>添加</el-button
>
</el-card>
<div class="table-container">
<el-table
ref="adminTable"
:data="list"
style="width: 100%;"
v-loading="listLoading"
border
>
<el-table-column label="编号" width="100" align="center">
<template slot-scope="scope">{{ scope.row.id }}</template>
</el-table-column>
<el-table-column label="帐号" align="center">
<template slot-scope="scope">{{ scope.row.username }}</template>
</el-table-column>
<el-table-column label="姓名" align="center">
<template slot-scope="scope">{{ scope.row.nickName }}</template>
</el-table-column>
<el-table-column label="邮箱" align="center">
<template slot-scope="scope">{{ scope.row.email }}</template>
</el-table-column>
<el-table-column label="添加时间" width="160" align="center">
<template slot-scope="scope">{{
scope.row.createTime | formatDateTime
}}</template>
</el-table-column>
<el-table-column label="最后登录" width="160" align="center">
<template slot-scope="scope">{{
scope.row.loginTime | formatDateTime
}}</template>
</el-table-column>
<el-table-column label="是否启用" width="140" align="center">
<template slot-scope="scope">
<el-switch
@change="handleStatusChange(scope.$index, scope.row)"
:active-value="1"
:inactive-value="0"
v-model="scope.row.status"
>
</el-switch>
</template>
</el-table-column>
<el-table-column label="操作" width="180" align="center">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
@click="handleSelectRole(scope.$index, scope.row)"
>分配角色
</el-button>
<el-button
size="mini"
type="text"
@click="handleUpdate(scope.$index, scope.row)"
>
编辑
</el-button>
<el-button
size="mini"
type="text"
@click="handleDelete(scope.$index, scope.row)"
>删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="pagination-container">
<el-pagination
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
layout="total, sizes,prev, pager, next,jumper"
:current-page.sync="listQuery.pageNum"
:page-size="listQuery.pageSize"
:page-sizes="[10, 15, 20]"
:total="total"
>
</el-pagination>
</div>
<el-dialog
:title="isEdit ? '编辑用户' : '添加用户'"
:visible.sync="dialogVisible"
width="40%"
>
<el-form :model="admin" ref="adminForm" label-width="150px" size="small">
<el-form-item label="帐号:">
<el-input v-model="admin.username" style="width: 250px"></el-input>
</el-form-item>
<el-form-item label="姓名:">
<el-input v-model="admin.nickName" style="width: 250px"></el-input>
</el-form-item>
<el-form-item label="邮箱:">
<el-input v-model="admin.email" style="width: 250px"></el-input>
</el-form-item>
<el-form-item label="密码:">
<el-input
v-model="admin.password"
type="password"
style="width: 250px"
></el-input>
</el-form-item>
<el-form-item label="备注:">
<el-input
v-model="admin.note"
type="textarea"
:rows="5"
style="width: 250px"
></el-input>
</el-form-item>
<el-form-item label="是否启用:">
<el-radio-group v-model="admin.status">
<el-radio :label="1">是</el-radio>
<el-radio :label="0"></el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false" size="small"> </el-button>
<el-button type="primary" @click="handleDialogConfirm()" size="small"
> </el-button
>
</span>
</el-dialog>
<el-dialog title="分配角色" :visible.sync="allocDialogVisible" width="30%">
<el-select
v-model="allocRoleIds"
multiple
placeholder="请选择"
size="small"
style="width: 80%"
>
<el-option
v-for="item in allRoleList"
:key="item.id"
:label="item.name"
:value="item.id"
>
</el-option>
</el-select>
<span slot="footer" class="dialog-footer">
<el-button @click="allocDialogVisible = false" size="small"
> </el-button
>
<el-button
type="primary"
@click="handleAllocDialogConfirm()"
size="small"
> </el-button
>
</span>
</el-dialog>
</div>
</template>
<script>
import {
fetchList,
createAdmin,
updateAdmin,
updateStatus,
deleteAdmin,
getRoleByAdmin,
allocRole
} from '@/api/login';
import { fetchAllRoleList } from '@/api/role';
import { formatDate } from '@/utils/date';
const defaultListQuery = {
pageNum: 1,
pageSize: 10,
keyword: null
};
const defaultAdmin = {
id: null,
username: null,
password: null,
nickName: null,
email: null,
note: null,
status: 1
};
export default {
name: 'adminList',
data() {
return {
listQuery: Object.assign({}, defaultListQuery),
list: null,
total: null,
listLoading: false,
dialogVisible: false,
admin: Object.assign({}, defaultAdmin),
isEdit: false,
allocDialogVisible: false,
allocRoleIds: [],
allRoleList: [],
allocAdminId: null
};
},
created() {
this.getList();
this.getAllRoleList();
},
filters: {
formatDateTime(time) {
if (time == null || time === '') {
return 'N/A';
}
let date = new Date(time);
return formatDate(date, 'yyyy-MM-dd hh:mm:ss');
}
},
methods: {
handleSearchList() {
this.listQuery.pageNum = 1;
this.getList();
},
handleSizeChange(val) {
this.listQuery.pageNum = 1;
this.listQuery.pageSize = val;
this.getList();
},
handleCurrentChange(val) {
this.listQuery.pageNum = val;
this.getList();
},
handleAdd() {
this.dialogVisible = true;
this.isEdit = false;
this.admin = Object.assign({}, defaultAdmin);
},
handleStatusChange(index, row) {
this.$confirm('是否要修改该状态?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
updateStatus(row.id, { status: row.status }).then(response => {
this.$message({
type: 'success',
message: '修改成功!'
});
});
})
.catch(() => {
this.$message({
type: 'info',
message: '取消修改'
});
this.getList();
});
},
handleDelete(index, row) {
this.$confirm('是否要删除该用户?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
deleteAdmin(row.id).then(response => {
this.$message({
type: 'success',
message: '删除成功!'
});
this.getList();
});
});
},
handleUpdate(index, row) {
this.dialogVisible = true;
this.isEdit = true;
this.admin = Object.assign({}, row);
},
handleDialogConfirm() {
this.$confirm('是否要确认?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
if (this.isEdit) {
updateAdmin(this.admin.id, this.admin).then(response => {
this.$message({
message: '修改成功!',
type: 'success'
});
this.dialogVisible = false;
this.getList();
});
} else {
createAdmin(this.admin).then(response => {
this.$message({
message: '添加成功!',
type: 'success'
});
this.dialogVisible = false;
this.getList();
});
}
});
},
handleAllocDialogConfirm() {
this.$confirm('是否要确认?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
let params = new URLSearchParams();
params.append('adminId', this.allocAdminId);
params.append('roleIds', this.allocRoleIds);
allocRole(params).then(response => {
this.$message({
message: '分配成功!',
type: 'success'
});
this.allocDialogVisible = false;
});
});
},
handleSelectRole(index, row) {
this.allocAdminId = row.id;
this.allocDialogVisible = true;
this.getRoleListByAdmin(row.id);
},
getList() {
this.listLoading = true;
fetchList(this.listQuery).then(response => {
this.listLoading = false;
this.list = response.data.list;
this.total = response.data.total;
});
},
getAllRoleList() {
fetchAllRoleList().then(response => {
this.allRoleList = response.data;
});
},
getRoleListByAdmin(adminId) {
getRoleByAdmin(adminId).then(response => {
let allocRoleList = response.data;
this.allocRoleIds = [];
if (allocRoleList != null && allocRoleList.length > 0) {
for (let i = 0; i < allocRoleList.length; i++) {
this.allocRoleIds.push(allocRoleList[i].id);
}
}
});
}
}
};
</script>
<style></style>

View File

@ -0,0 +1,14 @@
<template> 
<menu-detail :is-edit='false'></menu-detail>
</template>
<script>
import MenuDetail from './components/MenuDetail'
export default {
name: 'addMenu',
components: { MenuDetail }
}
</script>
<style>
</style>

View File

@ -0,0 +1,164 @@
<template>
<el-card class="form-container" shadow="never">
<el-form :model="menu" :rules="rules" ref="menuFrom" label-width="150px">
<el-form-item label="菜单名称:" prop="title">
<el-input v-model="menu.title"></el-input>
</el-form-item>
<el-form-item label="上级菜单:">
<el-select v-model="menu.parentId" placeholder="请选择菜单">
<el-option
v-for="item in selectMenuList"
:key="item.id"
:label="item.title"
:value="item.id"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="前端名称:" prop="name">
<el-input v-model="menu.name"></el-input>
</el-form-item>
<el-form-item label="前端图标:" prop="icon">
<el-input v-model="menu.icon" style="width: 80%"></el-input>
<svg-icon style="margin-left: 8px" :icon-class="menu.icon"></svg-icon>
</el-form-item>
<el-form-item label="是否显示:">
<el-radio-group v-model="menu.hidden">
<el-radio :label="0">是</el-radio>
<el-radio :label="1"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="排序:">
<el-input v-model="menu.sort"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit('menuFrom')">提交</el-button>
<el-button v-if="!isEdit" @click="resetForm('menuFrom')"
>重置</el-button
>
</el-form-item>
</el-form>
</el-card>
</template>
<script>
import { fetchList, createMenu, updateMenu, getMenu } from '@/api/menu';
const defaultMenu = {
title: '',
parentId: '0',
name: '',
icon: '',
hidden: 0,
sort: 0
};
export default {
name: 'MenuDetail',
props: {
isEdit: {
type: Boolean,
default: false
}
},
data() {
return {
menu: Object.assign({}, defaultMenu),
selectMenuList: [],
rules: {
title: [
{ required: true, message: '请输入菜单名称', trigger: 'blur' },
{
min: 2,
max: 140,
message: '长度在 2 到 140 个字符',
trigger: 'blur'
}
],
name: [
{ required: true, message: '请输入前端名称', trigger: 'blur' },
{
min: 2,
max: 140,
message: '长度在 2 到 140 个字符',
trigger: 'blur'
}
],
icon: [
{ required: true, message: '请输入前端图标', trigger: 'blur' },
{
min: 2,
max: 140,
message: '长度在 2 到 140 个字符',
trigger: 'blur'
}
]
}
};
},
activated() {
if (this.isEdit) {
getMenu(this.$route.query.id).then(response => {
this.menu = response.data;
});
} else {
this.menu = Object.assign({}, defaultMenu);
}
this.getSelectMenuList();
},
methods: {
getSelectMenuList() {
fetchList(0, { pageSize: 100, pageNum: 1 }).then(response => {
this.selectMenuList = response.data.list;
this.selectMenuList.unshift({ id: '0', title: '无上级菜单' });
});
},
onSubmit(formName) {
this.$refs[formName].validate(valid => {
if (valid) {
this.$confirm('是否提交数据', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
if (this.isEdit) {
updateMenu(this.$route.query.id, this.menu).then(response => {
this.$message({
message: '修改成功',
type: 'success',
duration: 1000
});
this.$router.back();
});
} else {
createMenu(this.menu).then(response => {
this.$refs[formName].resetFields();
this.resetForm(formName);
this.$message({
message: '提交成功',
type: 'success',
duration: 1000
});
this.$router.back();
});
}
});
} else {
this.$message({
message: '验证失败',
type: 'error',
duration: 1000
});
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
this.menu = Object.assign({}, defaultMenu);
this.getSelectMenuList();
}
}
};
</script>
<style scoped></style>

View File

@ -0,0 +1,196 @@
<template>
<div class="app-container">
<el-card class="operate-container" shadow="never">
<i class="el-icon-tickets" style="margin-top: 5px"></i>
<span style="margin-top: 5px">数据列表</span>
<el-button
class="btn-add"
@click="handleAddMenu()"
size="mini">
添加
</el-button>
</el-card>
<div class="table-container">
<el-table ref="menuTable"
style="width: 100%"
:data="list"
v-loading="listLoading" border>
<el-table-column label="编号" width="100" align="center">
<template slot-scope="scope">{{scope.row.id}}</template>
</el-table-column>
<el-table-column label="菜单名称" align="center">
<template slot-scope="scope">{{scope.row.title}}</template>
</el-table-column>
<el-table-column label="菜单级数" width="100" align="center">
<template slot-scope="scope">{{scope.row.level | levelFilter}}</template>
</el-table-column>
<el-table-column label="前端名称" align="center">
<template slot-scope="scope">{{scope.row.name}}</template>
</el-table-column>
<el-table-column label="前端图标" width="100" align="center">
<template slot-scope="scope"><svg-icon :icon-class="scope.row.icon"></svg-icon></template>
</el-table-column>
<el-table-column label="是否显示" width="100" align="center">
<template slot-scope="scope">
<el-switch
@change="handleHiddenChange(scope.$index, scope.row)"
:active-value="0"
:inactive-value="1"
v-model="scope.row.hidden">
</el-switch>
</template>
</el-table-column>
<el-table-column label="排序" width="100" align="center">
<template slot-scope="scope">{{scope.row.sort }}</template>
</el-table-column>
<el-table-column label="设置" width="120" align="center">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
:disabled="scope.row.level | disableNextLevel"
@click="handleShowNextLevel(scope.$index, scope.row)">查看下级
</el-button>
</template>
</el-table-column>
<el-table-column label="操作" width="200" align="center">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
@click="handleUpdate(scope.$index, scope.row)">编辑
</el-button>
<el-button
size="mini"
type="text"
@click="handleDelete(scope.$index, scope.row)">删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="pagination-container">
<el-pagination
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
layout="total, sizes,prev, pager, next,jumper"
:page-size="listQuery.pageSize"
:page-sizes="[10,15,20]"
:current-page.sync="listQuery.pageNum"
:total="total">
</el-pagination>
</div>
</div>
</template>
<script>
import {fetchList,deleteMenu,updateMenu,updateHidden} from '@/api/menu'
export default {
name: "menuList",
data() {
return {
list: null,
total: null,
listLoading: true,
listQuery: {
pageNum: 1,
pageSize: 10
},
parentId: 0
}
},
created() {
this.resetParentId();
this.getList();
},
watch: {
$route(route) {
this.resetParentId();
this.getList();
}
},
methods: {
resetParentId(){
this.listQuery.pageNum = 1;
if (this.$route.query.parentId != null) {
this.parentId = this.$route.query.parentId;
} else {
this.parentId = 0;
}
},
handleAddMenu() {
this.$router.push('/ums/addMenu');
},
getList() {
this.listLoading = true;
fetchList(this.parentId, this.listQuery).then(response => {
this.listLoading = false;
this.list = response.data.list;
this.total = response.data.total;
});
},
handleSizeChange(val) {
this.listQuery.pageNum = 1;
this.listQuery.pageSize = val;
this.getList();
},
handleCurrentChange(val) {
this.listQuery.pageNum = val;
this.getList();
},
handleHiddenChange(index, row) {
updateHidden(row.id,{hidden:row.hidden}).then(response=>{
this.$message({
message: '修改成功',
type: 'success',
duration: 1000
});
});
},
handleShowNextLevel(index, row) {
this.$router.push({path: '/ums/menu', query: {parentId: row.id}})
},
handleUpdate(index, row) {
this.$router.push({path:'/ums/updateMenu',query:{id:row.id}});
},
handleDelete(index, row) {
this.$confirm('是否要删除该菜单', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
deleteMenu(row.id).then(response => {
this.$message({
message: '删除成功',
type: 'success',
duration: 1000
});
this.getList();
});
});
}
},
filters: {
levelFilter(value) {
if (value === 0) {
return '一级';
} else if (value === 1) {
return '二级';
}
},
disableNextLevel(value) {
if (value === 0) {
return false;
} else {
return true;
}
}
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,14 @@
<template> 
<menu-detail :is-edit='true'></menu-detail>
</template>
<script>
import MenuDetail from './components/MenuDetail'
export default {
name: 'updateMenu',
components: { MenuDetail }
}
</script>
<style>
</style>

View File

@ -0,0 +1,156 @@
<template> 
<div class="app-container">
<el-card shadow="never" class="operate-container">
<i class="el-icon-tickets"></i>
<span>数据列表</span>
<el-button size="mini" class="btn-add" @click="handleAdd()">添加</el-button>
</el-card>
<div class="table-container">
<el-table ref="resourceCategoryTable"
:data="list"
style="width: 100%;"
v-loading="listLoading" border>
<el-table-column label="编号" width="100" align="center">
<template slot-scope="scope">{{scope.row.id}}</template>
</el-table-column>
<el-table-column label="名称" align="center">
<template slot-scope="scope">{{scope.row.name}}</template>
</el-table-column>
<el-table-column label="创建时间" align="center">
<template slot-scope="scope">{{scope.row.createTime | formatDateTime}}</template>
</el-table-column>
<el-table-column label="排序" align="center">
<template slot-scope="scope">{{scope.row.sort}}</template>
</el-table-column>
<el-table-column label="操作" width="180" align="center">
<template slot-scope="scope">
<el-button size="mini"
type="text"
@click="handleUpdate(scope.$index, scope.row)">编辑
</el-button>
<el-button size="mini"
type="text"
@click="handleDelete(scope.$index, scope.row)">删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<el-dialog
title="添加分类"
:visible.sync="dialogVisible"
width="40%">
<el-form :model="resourceCategory"
ref="resourceCategoryForm"
label-width="150px" size="small">
<el-form-item label="名称:">
<el-input v-model="resourceCategory.name" style="width: 250px"></el-input>
</el-form-item>
<el-form-item label="排序:">
<el-input v-model="resourceCategory.sort" style="width: 250px"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false" size="small"> </el-button>
<el-button type="primary" @click="handleDialogConfirm()" size="small"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import {listAllCate,createResourceCategory,updateResourceCategory,deleteResourceCategory} from '@/api/resourceCategory';
import {formatDate} from '@/utils/date';
const defaultResourceCategory={
name:null,
sort:0
};
export default {
name: 'resourceCategoryList',
data() {
return {
list: null,
listLoading: false,
dialogVisible:false,
isEdit:false,
resourceCategory:Object.assign({},defaultResourceCategory)
}
},
created() {
this.getList();
},
filters:{
formatDateTime(time) {
if (time == null || time === '') {
return 'N/A';
}
let date = new Date(time);
return formatDate(date, 'yyyy-MM-dd hh:mm:ss')
}
},
methods: {
handleAdd() {
this.dialogVisible = true;
this.isEdit = false;
this.resourceCategory = Object.assign({},defaultResourceCategory);
},
handleUpdate(index,row){
this.dialogVisible = true;
this.isEdit = true;
this.resourceCategory = Object.assign({},row);
},
handleDelete(index,row){
this.$confirm('是否要删除该分类?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
deleteResourceCategory(row.id).then(response => {
this.$message({
type: 'success',
message: '删除成功!'
});
this.getList();
});
});
},
handleDialogConfirm() {
this.$confirm('是否要确认?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
if (this.isEdit) {
updateResourceCategory(this.resourceCategory.id,this.resourceCategory).then(response => {
this.$message({
message: '修改成功!',
type: 'success'
});
this.dialogVisible =false;
this.getList();
})
} else {
createResourceCategory(this.resourceCategory).then(response => {
this.$message({
message: '添加成功!',
type: 'success'
});
this.dialogVisible =false;
this.getList();
})
}
})
},
getList() {
this.listLoading = true;
listAllCate({}).then(response => {
this.listLoading = false;
this.list = response.data;
});
}
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,273 @@
<template> 
<div class="app-container">
<el-card class="filter-container" shadow="never">
<div>
<i class="el-icon-search"></i>
<span>筛选搜索</span>
<el-button
style="float:right"
type="primary"
@click="handleSearchList()"
size="small">
查询搜索
</el-button>
<el-button
style="float:right;margin-right: 15px"
@click="handleResetSearch()"
size="small">
重置
</el-button>
</div>
<div style="margin-top: 15px">
<el-form :inline="true" :model="listQuery" size="small" label-width="140px">
<el-form-item label="资源名称:">
<el-input v-model="listQuery.nameKeyword" class="input-width" placeholder="资源名称" clearable></el-input>
</el-form-item>
<el-form-item label="资源路径:">
<el-input v-model="listQuery.urlKeyword" class="input-width" placeholder="资源路径" clearable></el-input>
</el-form-item>
<el-form-item label="资源分类:">
<el-select v-model="listQuery.categoryId" placeholder="全部" clearable class="input-width">
<el-option v-for="item in categoryOptions"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
</el-form>
</div>
</el-card>
<el-card class="operate-container" shadow="never">
<i class="el-icon-tickets"></i>
<span>数据列表</span>
<el-button size="mini" class="btn-add" @click="handleAdd()" style="margin-left: 20px">添加</el-button>
<el-button size="mini" class="btn-add" @click="handleShowCategory()">资源分类</el-button>
</el-card>
<div class="table-container">
<el-table ref="resourceTable"
:data="list"
style="width: 100%;"
v-loading="listLoading" border>
<el-table-column label="编号" width="100" align="center">
<template slot-scope="scope">{{scope.row.id}}</template>
</el-table-column>
<el-table-column label="资源名称" align="center">
<template slot-scope="scope">{{scope.row.name}}</template>
</el-table-column>
<el-table-column label="资源路径" align="center">
<template slot-scope="scope">{{scope.row.url}}</template>
</el-table-column>
<el-table-column label="描述" align="center">
<template slot-scope="scope">{{scope.row.description}}</template>
</el-table-column>
<el-table-column label="添加时间" width="160" align="center">
<template slot-scope="scope">{{scope.row.createTime | formatDateTime}}</template>
</el-table-column>
<el-table-column label="操作" width="140" align="center">
<template slot-scope="scope">
<el-button size="mini"
type="text"
@click="handleUpdate(scope.$index, scope.row)">
编辑
</el-button>
<el-button size="mini"
type="text"
@click="handleDelete(scope.$index, scope.row)">删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="pagination-container">
<el-pagination
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
layout="total, sizes,prev, pager, next,jumper"
:current-page.sync="listQuery.pageNum"
:page-size="listQuery.pageSize"
:page-sizes="[10,15,20]"
:total="total">
</el-pagination>
</div>
<el-dialog
:title="isEdit?'编辑资源':'添加资源'"
:visible.sync="dialogVisible"
width="40%">
<el-form :model="resource"
ref="resourceForm"
label-width="150px" size="small">
<el-form-item label="资源名称:">
<el-input v-model="resource.name" style="width: 250px"></el-input>
</el-form-item>
<el-form-item label="资源路径:">
<el-input v-model="resource.url" style="width: 250px"></el-input>
</el-form-item>
<el-form-item label="资源分类:">
<el-select v-model="resource.categoryId" placeholder="全部" clearable style="width: 250px">
<el-option v-for="item in categoryOptions"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="描述:">
<el-input v-model="resource.description"
type="textarea"
:rows="5"
style="width: 250px"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false" size="small"> </el-button>
<el-button type="primary" @click="handleDialogConfirm()" size="small"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import {fetchList,createResource,updateResource,deleteResource} from '@/api/resource';
import {listAllCate} from '@/api/resourceCategory';
import {formatDate} from '@/utils/date';
const defaultListQuery = {
pageNum: 1,
pageSize: 10,
nameKeyword: null,
urlKeyword: null,
categoryId:null
};
const defaultResource = {
id: null,
name: null,
url: null,
categoryId: null,
description:''
};
export default {
name: 'resourceList',
data() {
return {
listQuery: Object.assign({}, defaultListQuery),
list: null,
total: null,
listLoading: false,
dialogVisible: false,
resource: Object.assign({}, defaultResource),
isEdit: false,
categoryOptions:[],
defaultCategoryId:null
}
},
created() {
this.getList();
this.getCateList();
},
filters: {
formatDateTime(time) {
if (time == null || time === '') {
return 'N/A';
}
let date = new Date(time);
return formatDate(date, 'yyyy-MM-dd hh:mm:ss')
}
},
methods: {
handleResetSearch() {
this.listQuery = Object.assign({}, defaultListQuery);
},
handleSearchList() {
this.listQuery.pageNum = 1;
this.getList();
},
handleSizeChange(val) {
this.listQuery.pageNum = 1;
this.listQuery.pageSize = val;
this.getList();
},
handleCurrentChange(val) {
this.listQuery.pageNum = val;
this.getList();
},
handleAdd() {
this.dialogVisible = true;
this.isEdit = false;
this.resource = Object.assign({},defaultResource);
this.resource.categoryId = this.defaultCategoryId;
},
handleDelete(index, row) {
this.$confirm('是否要删除该资源?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
deleteResource(row.id).then(response => {
this.$message({
type: 'success',
message: '删除成功!'
});
this.getList();
});
});
},
handleUpdate(index, row) {
this.dialogVisible = true;
this.isEdit = true;
this.resource = Object.assign({},row);
},
handleDialogConfirm() {
this.$confirm('是否要确认?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
if (this.isEdit) {
updateResource(this.resource.id,this.resource).then(response => {
this.$message({
message: '修改成功!',
type: 'success'
});
this.dialogVisible =false;
this.getList();
})
} else {
createResource(this.resource).then(response => {
this.$message({
message: '添加成功!',
type: 'success'
});
this.dialogVisible =false;
this.getList();
})
}
})
},
handleShowCategory(){
this.$router.push({path: '/ums/resourceCategory'})
},
getList() {
this.listLoading = true;
fetchList(this.listQuery).then(response => {
this.listLoading = false;
this.list = response.data.list;
this.total = response.data.total;
});
},
getCateList(){
listAllCate().then(response=>{
let cateList = response.data;
for(let i=0;i<cateList.length;i++){
let cate = cateList[i];
this.categoryOptions.push({label:cate.name,value:cate.id});
}
this.defaultCategoryId=cateList[0].id;
})
}
}
}
</script>
<style></style>

View File

@ -0,0 +1,100 @@
<template>
<el-card class="form-container" shadow="never">
<el-tree
:data="menuTreeList"
show-checkbox
default-expand-all
node-key="id"
ref="tree"
highlight-current
:props="defaultProps"
>
</el-tree>
<div style="margin-top: 20px" align="center">
<el-button type="primary" @click="handleSave()">保存</el-button>
<el-button @click="handleClear()">清空</el-button>
</div>
</el-card>
</template>
<script>
import { fetchTreeList } from '@/api/menu';
import { listMenuByRole, allocMenu } from '@/api/role';
export default {
name: 'allocMenu',
data() {
return {
menuTreeList: [],
defaultProps: {
children: 'children',
label: 'title'
},
roleId: null
};
},
created() {
this.roleId = this.$route.query.roleId;
this.treeList();
this.getRoleMenu(this.roleId);
},
methods: {
treeList() {
fetchTreeList().then(response => {
console.log(response.data);
this.menuTreeList = response.data;
});
},
getRoleMenu(roleId) {
listMenuByRole(roleId).then(response => {
let menuList = response.data;
let checkedMenuIds = [];
if (menuList != null && menuList.length > 0) {
for (let i = 0; i < menuList.length; i++) {
let menu = menuList[i];
if (menu.parentId !== 0) {
checkedMenuIds.push(menu.id);
}
}
}
this.$refs.tree.setCheckedKeys(checkedMenuIds);
});
},
handleSave() {
let checkedNodes = this.$refs.tree.getCheckedNodes();
let checkedMenuIds = new Set();
if (checkedNodes != null && checkedNodes.length > 0) {
for (let i = 0; i < checkedNodes.length; i++) {
let checkedNode = checkedNodes[i];
checkedMenuIds.add(checkedNode.id);
if (checkedNode.parentId !== 0) {
checkedMenuIds.add(checkedNode.parentId);
}
}
}
this.$confirm('是否分配菜单?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
let params = new URLSearchParams();
params.append('roleId', this.roleId);
params.append('menuIds', Array.from(checkedMenuIds));
allocMenu(params).then(response => {
this.$message({
message: '分配成功',
type: 'success',
duration: 1000
});
this.$router.back();
});
});
},
handleClear() {
this.$refs.tree.setCheckedKeys([]);
}
}
};
</script>
<style scoped></style>

View File

@ -0,0 +1,187 @@
<template>
<el-card class="form-container" shadow="never">
<div v-for="(cate,index) in allResourceCate" :class="index===0?'top-line':null" :key="'cate'+cate.id">
<el-row class="table-layout" style="background: #F2F6FC;">
<el-checkbox v-model="cate.checked"
:indeterminate="isIndeterminate(cate.id)"
@change="handleCheckAllChange(cate)">
{{cate.name}}
</el-checkbox>
</el-row>
<el-row class="table-layout">
<el-col :span="8" v-for="resource in getResourceByCate(cate.id)" :key="resource.id" style="padding: 4px 0">
<el-checkbox v-model="resource.checked" @change="handleCheckChange(resource)">
{{resource.name}}
</el-checkbox>
</el-col>
</el-row>
</div>
<div style="margin-top: 20px" align="center">
<el-button type="primary" @click="handleSave()">保存</el-button>
<el-button @click="handleClear()">清空</el-button>
</div>
</el-card>
</template>
<script>
import {fetchAllResourceList} from '@/api/resource';
import {listAllCate} from '@/api/resourceCategory';
import {allocResource,listResourceByRole} from '@/api/role';
export default {
name: "allocResource",
data() {
return {
roleId: null,
allResource: null,
allResourceCate: null
};
},
created() {
this.roleId = this.$route.query.roleId;
this.getAllResourceCateList();
},
methods: {
getAllResourceList() {
fetchAllResourceList().then(response => {
this.allResource = response.data;
for (let i = 0; i < this.allResource.length; i++) {
this.allResource[i].checked = false;
}
this.getResourceByRole(this.roleId);
});
},
getAllResourceCateList() {
listAllCate().then(response => {
this.allResourceCate = response.data;
for (let i = 0; i < this.allResourceCate.length; i++) {
this.allResourceCate[i].checked = false;
}
this.getAllResourceList();
});
},
getResourceByCate(categoryId) {
let cateResource = [];
if (this.allResource == null) return null;
for (let i = 0; i < this.allResource.length; i++) {
let resource = this.allResource[i];
if (resource.categoryId === categoryId) {
cateResource.push(resource);
}
}
return cateResource;
},
getResourceByRole(roleId){
listResourceByRole(roleId).then(response=>{
let allocResource = response.data;
this.allResource.forEach(item=>{
item.checked = this.getResourceChecked(item.id,allocResource);
});
this.allResourceCate.forEach(item=>{
item.checked = this.isAllChecked(item.id);
});
this.$forceUpdate();
});
},
getResourceChecked(resourceId,allocResource){
if(allocResource==null||allocResource.length===0) return false;
for(let i=0;i<allocResource.length;i++){
if(allocResource[i].id===resourceId){
return true;
}
}
return false;
},
isIndeterminate(categoryId) {
let cateResources = this.getResourceByCate(categoryId);
if (cateResources == null) return false;
let checkedCount = 0;
for (let i = 0; i < cateResources.length; i++) {
if (cateResources[i].checked === true) {
checkedCount++;
}
}
return !(checkedCount === 0 || checkedCount === cateResources.length);
},
isAllChecked(categoryId) {
let cateResources = this.getResourceByCate(categoryId);
if (cateResources == null) return false;
let checkedCount = 0;
for (let i = 0; i < cateResources.length; i++) {
if (cateResources[i].checked === true) {
checkedCount++;
}
}
if(checkedCount===0){
return false;
}
return checkedCount === cateResources.length;
},
handleSave() {
this.$confirm('是否分配资源', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
let checkedResourceIds = new Set();
if (this.allResource != null && this.allResource.length > 0) {
this.allResource.forEach(item => {
if (item.checked) {
checkedResourceIds.add(item.id);
}
});
}
let params = new URLSearchParams();
params.append("roleId", this.roleId);
params.append("resourceIds", Array.from(checkedResourceIds));
allocResource(params).then(response => {
this.$message({
message: '分配成功',
type: 'success',
duration: 1000
});
this.$router.back();
})
})
},
handleClear() {
this.allResourceCate.forEach(item => {
item.checked = false;
});
this.allResource.forEach(item => {
item.checked = false;
});
this.$forceUpdate();
},
handleCheckAllChange(cate) {
let cateResources = this.getResourceByCate(cate.id);
for (let i = 0; i < cateResources.length; i++) {
cateResources[i].checked = cate.checked;
}
this.$forceUpdate();
},
handleCheckChange(resource) {
this.allResourceCate.forEach(item=>{
if(item.id===resource.categoryId){
item.checked = this.isAllChecked(resource.categoryId);
}
});
this.$forceUpdate();
}
}
}
</script>
<style scoped>
.table-layout {
padding: 20px;
border-left: 1px solid #DCDFE6;
border-right: 1px solid #DCDFE6;
border-bottom: 1px solid #DCDFE6;
}
.top-line {
border-top: 1px solid #DCDFE6;
}
</style>

View File

@ -0,0 +1,348 @@
<template>
<div class="app-container">
<el-card class="filter-container" shadow="never">
<div>
<i class="el-icon-search"></i>
<span>筛选搜索</span>
<el-button
style="float:right"
type="primary"
@click="handleSearchList()"
size="small"
>
查询搜索
</el-button>
<el-button
style="float:right;margin-right: 15px"
@click="handleResetSearch()"
size="small"
>
重置
</el-button>
</div>
<div style="margin-top: 15px">
<el-form
:inline="true"
:model="listQuery"
size="small"
label-width="140px"
>
<el-form-item label="输入搜索:">
<el-input
v-model="listQuery.keyword"
class="input-width"
placeholder="角色名称"
clearable
></el-input>
</el-form-item>
</el-form>
</div>
</el-card>
<el-card class="operate-container" shadow="never">
<i class="el-icon-tickets"></i>
<span>数据列表</span>
<el-button
size="mini"
class="btn-add"
@click="handleAdd()"
style="margin-left: 20px"
>添加</el-button
>
</el-card>
<div class="table-container">
<el-table
ref="roleTable"
:data="list"
style="width: 100%;"
v-loading="listLoading"
border
>
<el-table-column label="编号" width="100" align="center">
<template slot-scope="scope">{{ scope.row.id }}</template>
</el-table-column>
<el-table-column label="角色名称" align="center">
<template slot-scope="scope">{{ scope.row.name }}</template>
</el-table-column>
<el-table-column label="描述" align="center">
<template slot-scope="scope">{{ scope.row.description }}</template>
</el-table-column>
<el-table-column label="添加时间" width="160" align="center">
<template slot-scope="scope">{{
scope.row.createTime | formatDateTime
}}</template>
</el-table-column>
<el-table-column label="是否启用" width="140" align="center">
<template slot-scope="scope">
<el-switch
@change="handleStatusChange(scope.$index, scope.row)"
:active-value="1"
:inactive-value="0"
v-model="scope.row.status"
:disabled="
scope.row.id === '1385165161056309248' ||
scope.row.id === '1418108522993946624'
"
>
</el-switch>
</template>
</el-table-column>
<el-table-column label="操作" width="160" align="center">
<template slot-scope="scope">
<el-row>
<el-button
size="mini"
type="text"
@click="handleSelectMenu(scope.$index, scope.row)"
:disabled="
scope.row.id === '1385165161056309248' ||
scope.row.id === '1418108522993946624'
"
>分配菜单
</el-button>
<el-button
size="mini"
type="text"
@click="handleSelectResource(scope.$index, scope.row)"
:disabled="
scope.row.id === '1385165161056309248' ||
scope.row.id === '1418108522993946624'
"
>分配资源
</el-button>
</el-row>
<el-row>
<el-button
size="mini"
type="text"
@click="handleUpdate(scope.$index, scope.row)"
:disabled="
scope.row.id === '1385165161056309248' ||
scope.row.id === '1418108522993946624'
"
>
编辑
</el-button>
<el-button
size="mini"
type="text"
@click="handleDelete(scope.$index, scope.row)"
:disabled="
scope.row.id === '1385165161056309248' ||
scope.row.id === '1418108522993946624'
"
>删除
</el-button>
</el-row>
</template>
</el-table-column>
</el-table>
</div>
<div class="pagination-container">
<el-pagination
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
layout="total, sizes,prev, pager, next,jumper"
:current-page.sync="listQuery.pageNum"
:page-size="listQuery.pageSize"
:page-sizes="[5, 10, 15]"
:total="total"
>
</el-pagination>
</div>
<el-dialog
:title="isEdit ? '编辑角色' : '添加角色'"
:visible.sync="dialogVisible"
width="40%"
>
<el-form :model="role" ref="roleForm" label-width="150px" size="small">
<el-form-item label="角色名称:">
<el-input v-model="role.name" style="width: 250px"></el-input>
</el-form-item>
<el-form-item label="描述:">
<el-input
v-model="role.description"
type="textarea"
:rows="5"
style="width: 250px"
></el-input>
</el-form-item>
<el-form-item label="是否启用:">
<el-radio-group v-model="role.status">
<el-radio :label="1">是</el-radio>
<el-radio :label="0"></el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false" size="small"> </el-button>
<el-button type="primary" @click="handleDialogConfirm()" size="small"
> </el-button
>
</span>
</el-dialog>
</div>
</template>
<script>
import {
fetchList,
createRole,
updateRole,
updateStatus,
deleteRole
} from '@/api/role';
import { formatDate } from '@/utils/date';
const defaultListQuery = {
pageNum: 1,
pageSize: 5,
keyword: null
};
const defaultRole = {
id: null,
name: null,
description: null,
adminCount: 0,
status: 1
};
export default {
name: 'roleList',
data() {
return {
listQuery: Object.assign({}, defaultListQuery),
list: null,
total: null,
listLoading: false,
dialogVisible: false,
role: Object.assign({}, defaultRole),
isEdit: false
};
},
created() {
this.getList();
},
filters: {
formatDateTime(time) {
if (time == null || time === '') {
return 'N/A';
}
let date = new Date(time);
return formatDate(date, 'yyyy-MM-dd hh:mm:ss');
}
},
methods: {
handleResetSearch() {
this.listQuery = Object.assign({}, defaultListQuery);
},
handleSearchList() {
this.listQuery.pageNum = 1;
this.getList();
},
handleSizeChange(val) {
this.listQuery.pageNum = 1;
this.listQuery.pageSize = val;
this.getList();
},
handleCurrentChange(val) {
this.listQuery.pageNum = val;
this.getList();
},
handleAdd() {
this.dialogVisible = true;
this.isEdit = false;
this.role = Object.assign({}, defaultRole);
},
handleStatusChange(index, row) {
this.$confirm('是否要修改该状态?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
updateStatus(row.id, { status: row.status }).then(response => {
this.$message({
type: 'success',
message: '修改成功!'
});
});
})
.catch(() => {
this.$message({
type: 'info',
message: '取消修改'
});
this.getList();
});
},
handleDelete(index, row) {
this.$confirm('是否要删除该角色?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
let ids = [];
ids.push(row.id);
let params = new URLSearchParams();
params.append('ids', ids);
deleteRole(params).then(response => {
this.$message({
type: 'success',
message: '删除成功!'
});
this.getList();
});
});
},
handleUpdate(index, row) {
this.dialogVisible = true;
this.isEdit = true;
this.role = Object.assign({}, row);
},
handleDialogConfirm() {
this.$confirm('是否要确认?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
if (this.isEdit) {
updateRole(this.role.id, this.role).then(response => {
this.$message({
message: '修改成功!',
type: 'success'
});
this.dialogVisible = false;
this.getList();
});
} else {
createRole(this.role).then(response => {
this.$message({
message: '添加成功!',
type: 'success'
});
this.dialogVisible = false;
this.getList();
});
}
});
},
handleSelectMenu(index, row) {
this.$router.push({ path: '/ums/allocMenu', query: { roleId: row.id } });
},
handleSelectResource(index, row) {
this.$router.push({
path: '/ums/allocResource',
query: { roleId: row.id }
});
},
getList() {
this.listLoading = true;
fetchList(this.listQuery).then(response => {
this.listLoading = false;
this.list = response.data.list;
this.total = response.data.total;
});
}
}
};
</script>
<style></style>