You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
412 lines
14 KiB
412 lines
14 KiB
<template>
|
|
<div class="app-container">
|
|
<div class="container-main" style="justify-content: flex-start;">
|
|
<!--侧边部门数据-->
|
|
<div class="elect-cont-right">
|
|
<!--工具栏-->
|
|
<div class="head-container">
|
|
<div v-if="crud.props.searchToggle" class="head-search">
|
|
<!-- 搜索 -->
|
|
<el-input v-model="query.blurry" size="small" clearable placeholder="输入部门名称搜索" prefix-icon="el-icon-search" style="width: 200px;" class="filter-item" @clear="crud.toQuery" @keyup.enter.native="crud.toQuery" />
|
|
<date-range-picker v-model="blurryTime" class="date-item" />
|
|
<rrOperation />
|
|
</div>
|
|
<crudOperation :permission="permission">
|
|
<template v-slot:right>
|
|
<el-button :loading="crud.downloadLoading" size="mini" :disabled="crud.selections.length === 0" @click="doExport(crud.selections)">
|
|
<i class="iconfont icon-daochu" />
|
|
导出
|
|
</el-button>
|
|
</template>
|
|
</crudOperation>
|
|
</div>
|
|
<div class="container-right">
|
|
<span class="right-top-line" />
|
|
<span class="left-bottom-line" />
|
|
<!-- 表单渲染 -->
|
|
<el-dialog append-to-body :close-on-click-modal="false" :before-close="crud.cancelCU" :visible.sync="crud.status.cu > 0" :title="crud.status.title" class="dialog-middle">
|
|
<span class="dialog-right-top" />
|
|
<span class="dialog-left-bottom" />
|
|
<div class="setting-dialog">
|
|
<el-form ref="form" :inline="true" :model="form" :rules="rules" size="small" label-width="85px">
|
|
<el-form-item label="角色名称" prop="name">
|
|
<el-input v-model="form.name" />
|
|
</el-form-item>
|
|
<el-form-item label="描述信息" prop="description">
|
|
<el-input v-model="form.description" rows="5" type="textarea" />
|
|
</el-form-item>
|
|
</el-form>
|
|
<div slot="footer" class="dialog-footer">
|
|
<el-button type="text" @click="crud.cancelCU">取消</el-button>
|
|
<el-button :loading="crud.status.cu === 2" type="primary" @click="crud.submitCU">确定</el-button>
|
|
</div>
|
|
</div>
|
|
</el-dialog>
|
|
<!-- table -->
|
|
<el-table ref="table" v-loading="crud.loading" highlight-current-row style="width: 100%;" :data="crud.data" @selection-change="crud.selectionChangeHandler" @current-change="handleCurrentChange">
|
|
<el-table-column type="selection" align="center" width="55" />
|
|
<el-table-column prop="name" label="角色名称" />
|
|
<!-- <el-table-column prop="dataScope" label="数据权限" /> -->
|
|
<!-- <el-table-column prop="level" label="角色级别" /> -->
|
|
<el-table-column :show-overflow-tooltip="true" prop="description" label="描述信息" />
|
|
<el-table-column prop="users" label="人数" algin="center">
|
|
<template slot-scope="scope">
|
|
<div>{{ scope.row.users.length }}</div>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column :show-overflow-tooltip="true" prop="createTime" label="创建日期">
|
|
<template slot-scope="scope">
|
|
<div>{{ scope.row.createTime | parseTime }}</div>
|
|
</template>
|
|
</el-table-column>
|
|
<!-- <el-table-column v-if="checkPer(['admin','roles:edit','roles:del'])" label="操作" width="130px" align="center" fixed="right">
|
|
<template slot-scope="scope">
|
|
<udOperation
|
|
v-if="scope.row.level >= level"
|
|
:data="scope.row"
|
|
:permission="permission"
|
|
/>
|
|
</template>
|
|
</el-table-column> -->
|
|
</el-table>
|
|
<!--分页组件-->
|
|
<pagination />
|
|
</div>
|
|
</div>
|
|
<div class="elect-cont-left role-cont-left" style="margin: 0 0 0 20px;">
|
|
<div class="container-left">
|
|
<span class="right-top-line" />
|
|
<span class="left-bottom-line" />
|
|
<div slot="header" class="tree-tab">
|
|
<el-tooltip class="item" effect="dark" content="选择指定角色分配菜单" placement="top">
|
|
<span :class="['role-span', {'role-tab-active': roleTabIndex == 0}]" @click="changeActiveTab(0)">菜单分配</span>
|
|
</el-tooltip>
|
|
<el-tooltip class="item" effect="dark" content="选择指定角色分配全宗范围" placement="top">
|
|
<span :class="['role-span', {'role-tab-active': roleTabIndex == 1}]" @click="changeActiveTab(1)">全宗范围</span>
|
|
</el-tooltip>
|
|
<el-button
|
|
v-permission="['admin','roles:edit']"
|
|
:disabled="!showButton"
|
|
:loading="treeLoading"
|
|
size="mini"
|
|
@click="saveMenu"
|
|
>保存</el-button>
|
|
</div>
|
|
<el-tree
|
|
v-show="roleTabIndex == 0"
|
|
ref="menu"
|
|
lazy
|
|
:data="menus"
|
|
:default-checked-keys="menuIds"
|
|
:load="getMenuDatas"
|
|
:props="defaultProps"
|
|
check-strictly
|
|
accordion
|
|
show-checkbox
|
|
node-key="id"
|
|
@check="menuChange"
|
|
/>
|
|
<el-tree
|
|
v-show="roleTabIndex == 1"
|
|
ref="fonds"
|
|
lazy
|
|
:data="fondDatas"
|
|
:default-checked-keys="fondIds"
|
|
:load="getFondsDatas"
|
|
:props="defaultFondsProps"
|
|
check-strictly
|
|
accordion
|
|
show-checkbox
|
|
node-key="id"
|
|
@check="fondsChange"
|
|
>
|
|
<template slot-scope="{ node }">
|
|
<el-tooltip :content="node.label" placement="top-end" effect="dark">
|
|
<span>{{ node.label }}</span>
|
|
</el-tooltip>
|
|
</template>
|
|
</el-tree>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import crudRoles from '@/api/system/role'
|
|
import { FetchFondsAll } from '@/api/system/fonds'
|
|
import { getMenusTree, getChild } from '@/api/system/menu'
|
|
import CRUD, { presenter, header, form, crud } from '@crud/crud'
|
|
import rrOperation from '@crud/RR.operation'
|
|
import crudOperation from '@crud/CRUD.operation'
|
|
import pagination from '@crud/Pagination'
|
|
import DateRangePicker from '@/components/DateRangePicker'
|
|
import { exportFile } from '@/utils/index'
|
|
import qs from 'qs'
|
|
import { mapGetters } from 'vuex'
|
|
|
|
const defaultForm = { id: null, name: null, description: null, dataScope: null }
|
|
export default {
|
|
name: 'Role',
|
|
components: { pagination, crudOperation, rrOperation, DateRangePicker },
|
|
cruds() {
|
|
return CRUD({ title: '角色', url: 'api/role/initRoleList', crudMethod: { ...crudRoles }, optShow: {
|
|
add: true,
|
|
edit: true,
|
|
del: true,
|
|
reset: true,
|
|
download: false,
|
|
group: false
|
|
}})
|
|
},
|
|
mixins: [presenter(), header(), form(defaultForm), crud()],
|
|
data() {
|
|
return {
|
|
defaultProps: { children: 'children', label: 'label', isLeaf: 'leaf' },
|
|
defaultFondsProps: { children: 'children', label: 'fondsName', isLeaf: 'leaf' },
|
|
// dateScopes: ['全部', '本级', '自定义'], level: 3,
|
|
currentId: 0, treeLoading: false, showButton: false,
|
|
menus: [], menuIds: [],
|
|
fondDatas: [], fondIds: [],
|
|
// depts: [], deptDatas: [], // 多选时使用
|
|
permission: {
|
|
add: ['admin', 'roles:add'],
|
|
edit: ['admin', 'roles:edit'],
|
|
del: ['admin', 'roles:del']
|
|
},
|
|
rules: {
|
|
name: [
|
|
{ required: true, message: '请输入名称', trigger: 'blur' }
|
|
],
|
|
permission: [
|
|
{ required: true, message: '请输入权限', trigger: 'blur' }
|
|
]
|
|
},
|
|
roleTabIndex: 0,
|
|
blurryTime: null,
|
|
fondsAllData: [],
|
|
getFondsChecked: []
|
|
}
|
|
},
|
|
computed: {
|
|
...mapGetters([
|
|
'baseApi'
|
|
])
|
|
},
|
|
created() {
|
|
},
|
|
mounted() {
|
|
FetchFondsAll().then(res => {
|
|
const resArr = []
|
|
res.forEach(item => {
|
|
resArr.push({
|
|
fondsName: item.fondsName,
|
|
id: item.id,
|
|
leaf: true
|
|
})
|
|
})
|
|
this.fondsAllData = resArr
|
|
})
|
|
},
|
|
methods: {
|
|
changeActiveTab(index) {
|
|
this.roleTabIndex = index
|
|
},
|
|
getMenuDatas(node, resolve) {
|
|
setTimeout(() => {
|
|
getMenusTree(node.data.id ? node.data.id : 0).then(res => {
|
|
resolve(res)
|
|
})
|
|
}, 100)
|
|
},
|
|
getFondsDatas(node, resolve) {
|
|
if (node.level === 0) {
|
|
return resolve([{ fondsName: '全宗选择', id: 0, isChecked: false }])
|
|
}
|
|
if (node.level > 1) return resolve([])
|
|
resolve(this.fondsAllData)
|
|
},
|
|
[CRUD.HOOK.beforeRefresh]() {
|
|
if (this.blurryTime) {
|
|
this.crud.query.startTime = this.blurryTime[0]
|
|
this.crud.query.endTime = this.blurryTime[1]
|
|
}
|
|
},
|
|
[CRUD.HOOK.afterRefresh]() {
|
|
this.$refs.menu.setCheckedKeys([])
|
|
this.$refs.fonds.setCheckedKeys([])
|
|
},
|
|
// 新增前初始化部门信息
|
|
[CRUD.HOOK.beforeToAdd](crud, form) {
|
|
form.menus = null
|
|
form.fondDatas = null
|
|
},
|
|
// 编辑前初始化自定义数据权限的部门信息
|
|
[CRUD.HOOK.beforeToEdit](crud, form) {
|
|
// 将角色的菜单清空,避免日志入库数据过长
|
|
form.menus = null
|
|
form.fondDatas = null
|
|
},
|
|
// 提交前做的操作
|
|
[CRUD.HOOK.afterValidateCU](crud) {
|
|
},
|
|
// 触发单选
|
|
handleCurrentChange(val) {
|
|
if (val) {
|
|
const _this = this
|
|
// 清空菜单的选中
|
|
this.$refs.menu.setCheckedKeys([])
|
|
this.$refs.fonds.setCheckedKeys([])
|
|
// 保存当前的角色id
|
|
this.currentId = val.id
|
|
// 初始化默认选中的key
|
|
this.menuIds = []
|
|
this.fondIds = []
|
|
val.menus.forEach(function(data) {
|
|
_this.menuIds.push(data.id)
|
|
})
|
|
|
|
if (val.fonds) {
|
|
if (this.fondsAllData.length === val.fonds.length) {
|
|
_this.fondIds.push(0)
|
|
}
|
|
val.fonds.forEach(function(data) {
|
|
_this.fondIds.push(data.id)
|
|
})
|
|
}
|
|
this.showButton = true
|
|
}
|
|
},
|
|
doExport(data) {
|
|
crud.downloadLoading = true
|
|
this.$confirm('此操作将导出所选数据' + '<span>你是否还要继续?</span>', '提示', {
|
|
confirmButtonText: '继续',
|
|
cancelButtonText: '取消',
|
|
type: 'warning',
|
|
dangerouslyUseHTMLString: true
|
|
}).then(() => {
|
|
const ids = []
|
|
data.forEach(val => {
|
|
ids.push(val.id)
|
|
})
|
|
const params = {
|
|
'roleIds': ids
|
|
}
|
|
exportFile(this.baseApi + '/api/role/exportRole?' + qs.stringify(params, { indices: false }))
|
|
}).catch(() => {
|
|
})
|
|
},
|
|
menuChange(menu) {
|
|
// 获取该节点的所有子节点,id 包含自身
|
|
getChild(menu.id).then(childIds => {
|
|
// 判断是否在 menuIds 中,如果存在则删除,否则添加
|
|
if (this.menuIds.indexOf(menu.id) !== -1) {
|
|
for (let i = 0; i < childIds.length; i++) {
|
|
const index = this.menuIds.indexOf(childIds[i])
|
|
if (index !== -1) {
|
|
this.menuIds.splice(index, 1)
|
|
}
|
|
}
|
|
} else {
|
|
for (let i = 0; i < childIds.length; i++) {
|
|
const index = this.menuIds.indexOf(childIds[i])
|
|
if (index === -1) {
|
|
this.menuIds.push(childIds[i])
|
|
}
|
|
}
|
|
}
|
|
this.$refs.menu.setCheckedKeys(this.menuIds)
|
|
})
|
|
},
|
|
fondsChange(fonds) {
|
|
if (fonds.id === 0) {
|
|
fonds.isChecked = !fonds.isChecked
|
|
this.fondIds.push(fonds.id)
|
|
this.fondsAllData.forEach(childIds => {
|
|
if (fonds.isChecked) {
|
|
const index = this.fondIds.indexOf(childIds.id)
|
|
if (index !== -1) {
|
|
this.fondIds.splice(index, 1)
|
|
}
|
|
this.fondIds.push(childIds.id)
|
|
} else {
|
|
this.fondIds = []
|
|
}
|
|
})
|
|
} else {
|
|
if (this.fondIds.indexOf(fonds.id) !== -1) {
|
|
const index = this.fondIds.indexOf(fonds.id)
|
|
if (index !== -1) {
|
|
this.fondIds.splice(index, 1)
|
|
}
|
|
} else {
|
|
const index = this.fondIds.indexOf(fonds.id)
|
|
if (index === -1) {
|
|
this.fondIds.push(fonds.id)
|
|
}
|
|
}
|
|
}
|
|
this.$refs.fonds.setCheckedKeys(this.fondIds)
|
|
},
|
|
// 保存菜单
|
|
saveMenu() {
|
|
this.treeLoading = true
|
|
if (this.roleTabIndex === 0) {
|
|
const role = { id: this.currentId, menus: [] }
|
|
// 得到已选中的 key 值
|
|
this.menuIds.forEach(function(id) {
|
|
const menu = { id: id }
|
|
role.menus.push(menu)
|
|
})
|
|
crudRoles.editMenu(role).then(() => {
|
|
this.crud.notify('保存成功', CRUD.NOTIFICATION_TYPE.SUCCESS)
|
|
this.treeLoading = false
|
|
this.update()
|
|
}).catch(err => {
|
|
this.treeLoading = false
|
|
console.log(err.response.data.message)
|
|
})
|
|
} else {
|
|
const params = { id: this.currentId, fonds: [] }
|
|
// 得到已选中的 key 值
|
|
this.fondIds.forEach(function(id, index) {
|
|
if (id !== 0) {
|
|
const fondsArray = { id: id }
|
|
params.fonds.push(fondsArray)
|
|
}
|
|
})
|
|
crudRoles.editFonds(params).then(() => {
|
|
this.crud.notify('保存成功', CRUD.NOTIFICATION_TYPE.SUCCESS)
|
|
this.treeLoading = false
|
|
}).catch(err => {
|
|
console.log(err.response.data.message)
|
|
this.treeLoading = false
|
|
})
|
|
}
|
|
},
|
|
// 改变数据
|
|
update() {
|
|
// 无刷新更新 表格数据
|
|
crudRoles.get(this.currentId).then(res => {
|
|
for (let i = 0; i < this.crud.data.length; i++) {
|
|
if (res.id === this.crud.data[i].id) {
|
|
this.crud.data[i] = res
|
|
break
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
::v-deep .el-tree .el-tree-node__children .el-tooltip{
|
|
width: 150px;
|
|
font-size: 14px;
|
|
color: #545b65;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
</style>
|