需求分析
完成权限(菜单,按钮(权限点),API接口)的基本操作
权限与菜单,菜单与按钮,菜单与API接口都是一对一关系。为了方便操作,在SAAS-HRM系统的表设计中,采用基于共享主键的形式实现一对一关系维护,并且数据库约束,一切的关系维护需要程序员在代码中实现。
import Vue from 'vue'
import 'normalize.css/normalize.css'// A modern alternative to CSS resets
import Element from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import '@/styles/index.scss' // global css
import App from './App'
import router from './router'
import store from './store'
import i18n from './lang' // Internationalization
import './icons' // icon
import './errorLog'// error log
import * as filters from './filters' // global filters
// font-awesome
import 'font-awesome/css/font-awesome.css'
import './mock' // simulation data
/*
* 注册 - 业务模块
*/
import dashboard from '@/module-dashboard/' // 面板
import demo from '@/module-demo/' // 面板
import saasClients from '@/module-saas-clients/' // 企业管理
import departments from '@/module-departments/' // 企业管理
import employees from '@/module-employees/' // 企业管理
import settings from '@/module-settings/'
import permissions from '@/module-permissions/'
import tools from './utils/common.js'
Vue.prototype.$tools = tools
Vue.use(tools)
Vue.use(dashboard, store)
Vue.use(demo, store)
Vue.use(saasClients,store)
Vue.use(departments,store)
Vue.use(employees,store)
Vue.use(settings,store)
Vue.use(permissions,store)
/*
* 注册 - 组件
*/
// 饿了么
Vue.use(Element, {
size: 'medium', // set element-ui default size
i18n: (key, value) => i18n.t(key, value)
})
// 过滤器
Object.keys(filters).forEach(key => {
Vue.filter(key, filters[key])
})
Vue.config.productionTip = false
/* eslint-disable */
new Vue({
el: '#app',
router,
store,
i18n,
template: '<App/>',
components: { App }
})
/*
* @Author: leon.sun
* @Description: 公司设置
* @Date: 2019-12-29 16:13:27
* @Last Modified by: leon.sun
* @Last Modified time: 2018-09-03 11:13:19
*/
import Layout from '@/module-dashboard/pages/layout'
const _import = require('@/router/import_' + process.env.NODE_ENV)
export default [
{
root: true,
path: '/settings',
component: Layout,
redirect: 'noredirect',
name: 'settings',
meta: {
title: '公司设置管理',
icon: 'set'
},
children: [
{
path: 'index',
component: _import('settings/pages/index'),
name: 'settings-index',
meta: {title: '公司设置', icon: 'set', noCache: true}
}
]
}
]
<template>
<div class="boxInfo">
<!-- 表单内容 -->
<div class="formInfo">
<div>
<!-- 头部信息 -->
<div class="userInfo">
<el-button type="primary" size="mini" icon="el-icon-plus" @click="handlerAdd">新增角色</el-button>
<el-table :data="dataList" border fit highlight-current-row style="width:100%; margin-top:10px;">
<el-table-column type="index" :index="1" label="序号" width="150"> </el-table-column>
<el-table-column sortable prop="name" label="角色名" width="150"></el-table-column>
<el-table-column sortable prop="description" label="描述"></el-table-column>
<el-table-column fixed="right" label="操作" align="center" width="250">
<template slot-scope="scope">
<el-button @click="handlerPerm(scope.row)" type="text" size="small">分配权限</el-button>
<el-button @click="handleUpdate(scope.row)" type="text" size="small">修改</el-button>
<el-button @click="handleDelete(scope.row)" type="text" size="small">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<PageTool :paginationPage="requestParameters.page" :paginationPagesize="requestParameters.pagesize" :total="counts" @pageChange="handleCurrentChange" @pageSizeChange="handleSizeChange">
</PageTool>
</div>
</div>
</div>
</div>
<el-dialog title="编辑角色" :visible.sync="dialogFormVisible" style="hight:100px;line-height:1px">
<el-form :model="formData" label-width="90px" style="margin-top:20px">
<el-form-item label="角色名称">
<el-input v-model="formData.name" autocomplete="off" style="width:90%"></el-input>
</el-form-item>
<el-form-item label="角色描述">
<el-input v-model="formData.description" autocomplete="off" style="width:90%"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="saveOrUpdate">确 定</el-button>
</div>
</el-dialog>
<el-dialog :title="'为【'+formData.name+'】分配权限'" :visible.sync="permFormVisible" style="hight:100px;line-height:1px">
<el-tree
:data="treeData"
default-expand-all
show-checkbox
node-key="id"
ref="tree"
:default-checked-keys="checkNodes"
:props="{label:'name'}">
</el-tree>
<div slot="footer" class="dialog-footer">
<el-button @click="permFormVisible = false">取 消</el-button>
<el-button type="primary" @click="assignPrem">确 定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {list,add,update,remove,detail,assignPrem} from "@/api/base/role"
import * as permApi from "@/api/base/permissions"
import commonApi from "@/utils/common"
import PageTool from './../../components/page/page-tool'
var _this = null
export default {
name: 'roleList',
components: {PageTool},
props: ['objId'],
data() {
return {
formData:{},
treeData:[],
checkNodes:[],
dialogFormVisible: false,
permFormVisible:false,
dataList:[],
counts:0,
requestParameters:{
page: 1,
pagesize: 10
}
}
},
methods: {
assignPrem() {
assignPrem({id:this.formData.id,permIds:this.$refs.tree.getCheckedKeys()}).then(res => {
this.$message({message:res.data.message,type:res.data.success?"success":"error"});
this.permFormVisible=false
})
},
handlerPerm(obj) {
detail({id:obj.id}).then(res=>{
this.formData = res.data.data;
this.checkNodes = res.data.data.permIds
permApi.list({type:0,pid:null,enVisible:1}).then(res => {
this.treeData = commonApi.transformTozTreeFormat(res.data.data)
this.permFormVisible=true
})
})
},
handlerAdd() {
this.formData={}
this.dialogFormVisible = true
},
handleDelete(obj) {
this.$confirm(
`本次操作将删除${obj.name},删除后角色将不可恢复,您确认删除吗?`
).then(() => {
remove({id: obj.id}).then(res => {
this.$message({message:res.data.message,type:res.data.success?"success":"error"});
this.doQuery()
})
})
},
handleUpdate(obj) {
detail({id:obj.id}).then(res=>{
this.formData = res.data.data;
this.formData.id = obj.id;
this.dialogFormVisible = true
})
},
saveOrUpdate() {
if(this.formData.id == null || this.formData.id == undefined) {
this.save()
}else{
this.update();
}
},
update(){
update(this.formData).then(res=>{
this.$message({message:res.data.message,type:res.data.success?"success":"error"});
if(res.data.success){
this.formData={};
this.dialogFormVisible=false;
this.doQuery();
}
})
},
save() {
add(this.formData).then(res=>{
this.$message({message:res.data.message,type:res.data.success?"success":"error"});
if(res.data.success){
this.formData={};
this.dialogFormVisible=false;
this.doQuery();
}
})
},
// 获取详情
doQuery() {
list(this.requestParameters).then(res => {
this.dataList = res.data.data.rows
this.counts = res.data.data.total
})
},
// 每页显示信息条数
handleSizeChange(pageSize) {
this.requestParameters.pagesize = pageSize
if (this.requestParameters.page === 1) {
_this.doQuery(this.requestParameters)
}
},
// 进入某一页
handleCurrentChange(val) {
this.requestParameters.page = val
_this.doQuery()
},
},
// 挂载结束
mounted: function() {},
// 创建完毕状态
created: function() {
_this = this
this.doQuery()
},
// 组件更新
updated: function() {}
}
</script>
<style rel="stylesheet/scss" lang="scss">
.el-collapse-item__arrow {
float: left;
}
.el-collapse-item {
position: relative;
// width: 80%;
// .el-collapse-item__header{width: 80%;}
.infoR {
position: absolute;
background: #fff;
display: inline-block;
width: 100px;
height: 35px;
line-height: 35px;
text-align: right;
right: -100px;
top: 0px;
}
}
// .el-input--medium {
// width: 80%;
// }
.linkage {
display: inline-block;
}
.textBotm {
vertical-align: text-bottom;
}
.navInfo {
height: auto;
font-size: 30px;
color: #333;
background-color: #e4e4e4;
text-align: center;
border-bottom: 1px solid #333;
}
.step {
position: fixed;
left: 220px;
top: 50%;
margin-top: -150px;
background: #fff;
z-index: 9;
}
</style>
<style rel="stylesheet/scss" lang="scss" scoped>
</style>
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')
// /company/xxx api/company
module.exports = merge(prodEnv, {
NODE_ENV: '"development"',
BASE_API: '"api"'
})
'use strict'
// Template version: 1.3.1
// see http://vuejs-templates.github.io/webpack for documentation.
const path = require('path')
module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '',
proxyTable: {
//企业信息请求的远程服务
'/api/company': {
target: 'http://localhost:9001/company/',
changeOrigin: true,
pathRewrite: {
'^/api/company': ''
}
},
//api/sys/ user
'/api/sys': {
target: 'http://localhost:9002/sys/',
changeOrigin: true,
pathRewrite: {
'^/api/sys': ''
}
}
},
// Various Dev Server settings
host: 'localhost', // can be overwritten by process.env.HOST
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
autoOpenBrowser: false,
errorOverlay: true,
notifyOnErrors: true,
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
// Use Eslint Loader?
// If true, your code will be linted during bundling and
// linting errors and warnings will be shown in the console.
useEslint: false,
// If true, eslint errors and warnings will also be shown in the error overlay
// in the browser.
showEslintErrorsInOverlay: false,
/**
* Source Maps
*/
// https://webpack.js.org/configuration/devtool/#development
devtool: 'cheap-module-eval-source-map',
// If you have problems debugging vue-files in devtools,
// set this to false - it *may* help
// https://vue-loader.vuejs.org/en/options.html#cachebusting
cacheBusting: true,
cssSourceMap: true
},
build: {
// Template for index.html
index: path.resolve(__dirname, '../dist/index.html'),
// Paths
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '',
/**
* Source Maps
*/
productionSourceMap: true,
// https://webpack.js.org/configuration/devtool/#production
devtool: '#source-map',
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report
}
}
import {createAPI} from '@/utils/request'
export const list = data => createAPI('/sys/user', 'get', data)
export const simple = data => createAPI('/sys/user/simple', 'get', data)
export const add = data => createAPI('/sys/user', 'post', data)
export const update = data => createAPI(`/sys/user/${data.id}`, 'put', data)
export const remove = data => createAPI(`/sys/user/${data.id}`, 'delete', data)
export const detail = data => createAPI(`/sys/user/${data.id}`, 'get', data)
export const assignRoles = data => createAPI(`/sys/user/assignRoles`, 'put', data)