acl 样式升级

This commit is contained in:
wang-liang0615 2023-07-18 15:14:35 +08:00
parent 67d7062f39
commit 14c6d7178c
19 changed files with 1794 additions and 1653 deletions

View File

@ -1,35 +1,37 @@
<template>
<div>
<a-card title="应用管理" class="acl-app-wrapper" :style="{ '--ant-body-height': `${windowHeight - 150}px` }">
<a-row :guttr="24">
<a-col v-for="app in apps" :key="app.id" :span="8">
<div style="margin: 15px">
<a-card class="acl-app-single-card">
<a-card-meta :title="app.name">
<div slot="description" :title="app.description || ''">{{ app.description || '无' }}</div>
<a-avatar style="background-color: #5dc2f1" slot="avatar">{{ app.name[0].toUpperCase() }}</a-avatar>
</a-card-meta>
<template class="ant-card-actions" slot="actions">
<a-icon type="edit" @click="handleEditApp(app)" />
<a-icon type="delete" @click="handleDeleteApp(app)" />
</template>
</a-card>
</div>
</a-col>
<a-col :span="8">
<div class="acl-app-add" @click="handleCreateApp">
<span class="acl-app-add-icon" style="">+</span>
</div>
</a-col>
</a-row>
</a-card>
<div class="acl-apps">
<a-row :gutter="[24, 24]">
<a-col
v-for="app in apps"
:key="app.id"
:xxl="4"
:xl="6"
:md="8"
:sm="12"
:xs="24">
<a-card>
<a-card-meta :title="app.name">
<div slot="description" :title="app.description || ''">{{ app.description || '无' }}</div>
<a-avatar style="background-color: #5dc2f1" slot="avatar">{{ app.name[0].toUpperCase() }}</a-avatar>
</a-card-meta>
<template slot="actions">
<a-icon type="edit" @click="handleEditApp(app)" />
<a-icon type="delete" @click="handleDeleteApp(app)" />
</template>
</a-card>
</a-col>
<a-col :xxl="4" :xl="6" :md="8" :sm="12" :xs="24">
<div class="acl-apps-add" @click="handleCreateApp">
<span class="acl-apps-add-icon">+</span>
</div>
</a-col>
</a-row>
<app-form ref="appForm" @refresh="loadApps"></app-form>
</div>
</template>
<script>
/* eslint-disable */
import { mapState } from 'vuex'
import { searchApp, addApp, updateApp, deleteApp } from '@/modules/acl/api/app'
import { searchApp, deleteApp } from '@/modules/acl/api/app'
import AppForm from './module/appForm'
export default {
@ -81,32 +83,24 @@ export default {
},
}
</script>
<style lang="less">
.acl-app-wrapper {
> .ant-card-body {
overflow-y: auto;
height: var(--ant-body-height);
cursor: default;
.acl-apps {
.ant-card-meta-description > div {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.acl-app-single-card {
.ant-card-meta-description > div {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
&:hover {
box-shadow: 0 2px 8px #0000004d;
}
}
.acl-app-add {
.acl-apps-add {
width: 100%;
height: 141px;
margin: 15px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
border: 1px #e8e8e8 solid;
transition: all 0.3s;
&:hover {
box-shadow: 0 2px 8px #0000004d;
}
.acl-app-add-icon {
background-color: #fff;
.acl-apps-add-icon {
font-size: 70px;
display: block;
text-align: center;

View File

@ -1,72 +1,70 @@
<template>
<div>
<a-card :bordered="false">
<a-tabs default-active-key="1">
<a-tab-pane key="1" tab="权限变更">
<permisson-history-table
v-if="isloaded"
:allResourceTypes="allResourceTypes"
:allResources="allResources"
:allUsers="allUsers"
:allRoles="allRoles"
:allRolesMap="allRolesMap"
:allUsersMap="allUsersMap"
:allResourceTypesMap="allResourceTypesMap"
@loadMoreResources="loadMoreResources"
@reloadResources="reloadResources"
@fetchResources="fetchResources"
@resourceClear="resourceClear"
></permisson-history-table>
</a-tab-pane>
<a-tab-pane key="2" tab="角色变更">
<role-history-table
v-if="isloaded"
:allUsers="allUsers"
:allRoles="allRoles"
:allRolesMap="allRolesMap"
:allUsersMap="allUsersMap"
></role-history-table>
</a-tab-pane>
<a-tab-pane key="3" tab="资源变更">
<resource-history-table
v-if="isloaded"
:allResources="allResources"
:allUsers="allUsers"
:allRoles="allRoles"
:allRolesMap="allRolesMap"
:allUsersMap="allUsersMap"
:allResourcesMap="allResourcesMap"
@loadMoreResources="loadMoreResources"
@reloadResources="reloadResources"
@fetchResources="fetchResources"
@resourceClear="resourceClear"
></resource-history-table>
</a-tab-pane>
<a-tab-pane key="4" tab="资源类型变更">
<resource-type-history-table
v-if="isloaded"
:allResourceTypes="allResourceTypes"
:allUsers="allUsers"
:allRoles="allRoles"
:allRolesMap="allRolesMap"
:allUsersMap="allUsersMap"
:allResourceTypesMap="allResourceTypesMap"
></resource-type-history-table>
</a-tab-pane>
<a-tab-pane key="5" tab="触发器变更">
<trigger-history-table
v-if="isloaded"
:allTriggers="allTriggers"
:allUsers="allUsers"
:allRoles="allRoles"
:allRolesMap="allRolesMap"
:allUsersMap="allUsersMap"
:allTriggersMap="allTriggersMap"
:allResourceTypesMap="allResourceTypesMap"
></trigger-history-table>
</a-tab-pane>
</a-tabs>
</a-card>
<div class="acl-history">
<a-tabs default-active-key="1">
<a-tab-pane key="1" tab="权限变更">
<permisson-history-table
v-if="isloaded"
:allResourceTypes="allResourceTypes"
:allResources="allResources"
:allUsers="allUsers"
:allRoles="allRoles"
:allRolesMap="allRolesMap"
:allUsersMap="allUsersMap"
:allResourceTypesMap="allResourceTypesMap"
@loadMoreResources="loadMoreResources"
@reloadResources="reloadResources"
@fetchResources="fetchResources"
@resourceClear="resourceClear"
></permisson-history-table>
</a-tab-pane>
<a-tab-pane key="2" tab="角色变更">
<role-history-table
v-if="isloaded"
:allUsers="allUsers"
:allRoles="allRoles"
:allRolesMap="allRolesMap"
:allUsersMap="allUsersMap"
></role-history-table>
</a-tab-pane>
<a-tab-pane key="3" tab="资源变更">
<resource-history-table
v-if="isloaded"
:allResources="allResources"
:allUsers="allUsers"
:allRoles="allRoles"
:allRolesMap="allRolesMap"
:allUsersMap="allUsersMap"
:allResourcesMap="allResourcesMap"
@loadMoreResources="loadMoreResources"
@reloadResources="reloadResources"
@fetchResources="fetchResources"
@resourceClear="resourceClear"
></resource-history-table>
</a-tab-pane>
<a-tab-pane key="4" tab="资源类型变更">
<resource-type-history-table
v-if="isloaded"
:allResourceTypes="allResourceTypes"
:allUsers="allUsers"
:allRoles="allRoles"
:allRolesMap="allRolesMap"
:allUsersMap="allUsersMap"
:allResourceTypesMap="allResourceTypesMap"
></resource-type-history-table>
</a-tab-pane>
<a-tab-pane key="5" tab="触发器变更">
<trigger-history-table
v-if="isloaded"
:allTriggers="allTriggers"
:allUsers="allUsers"
:allRoles="allRoles"
:allRolesMap="allRolesMap"
:allUsersMap="allUsersMap"
:allTriggersMap="allTriggersMap"
:allResourceTypesMap="allResourceTypesMap"
></trigger-history-table>
</a-tab-pane>
</a-tabs>
</div>
</template>
@ -234,4 +232,12 @@ export default {
}
</script>
<style></style>
<style lang="less" scoped>
.acl-history {
border-radius: 15px;
height: calc(100vh - 64px);
margin-bottom: -24px;
padding: 24px;
background-color: #fff;
}
</style>

View File

@ -12,12 +12,13 @@
></search-form>
<vxe-table
ref="xTable"
border
stripe
class="ops-stripe-table"
resizable
size="small"
:data="tableData"
:loading="loading"
:max-height="`${windowHeight - windowHeightMinus}px`"
:height="`${windowHeight - windowHeightMinus}px`"
:scroll-y="{ enabled: false }"
>
<vxe-column field="created_at" width="144px" title="操作时间">
@ -71,6 +72,7 @@
:isLoading="loading"
@change="onChange"
@showSizeChange="onShowSizeChange"
:style="{ marginTop: '10px' }"
></pager>
</div>
</template>
@ -199,7 +201,7 @@ export default {
return this.$store.state.windowHeight
},
windowHeightMinus() {
return this.isExpand ? 396 : 331
return this.isExpand ? 374 : 310
},
tableDataLength() {
return this.tableData.length

View File

@ -14,12 +14,13 @@
></search-form>
<vxe-table
ref="xTable"
border
stripe
class="ops-stripe-table"
size="small"
:loading="loading"
:data="tableData"
resizable
:max-height="`${windowHeight - 331}px`"
:height="`${windowHeight - 310}px`"
>
<vxe-column field="created_at" width="144px" title="操作时间"></vxe-column>
<vxe-column field="operate_uid" width="130px" title="操作员"></vxe-column>
@ -54,6 +55,7 @@
:isLoading="loading"
@change="onChange"
@showSizeChange="onShowSizeChange"
:style="{ marginTop: '10px' }"
></pager>
</div>
</template>

View File

@ -8,12 +8,13 @@
></search-form>
<vxe-table
ref="xTable"
border
stripe
class="ops-stripe-table"
size="small"
:data="tableData"
resizable
:loading="loading"
:max-height="`${windowHeight - 331}px`"
:height="`${windowHeight - 310}px`"
>
<vxe-column field="created_at" width="144px" title="操作时间"></vxe-column>
<vxe-column field="operate_uid" width="130px" title="操作员"></vxe-column>
@ -43,11 +44,12 @@
<pager
:current-page.sync="queryParams.page"
:page-size.sync="queryParams.page_size"
:page-sizes="[50,100,200]"
:page-sizes="[50, 100, 200]"
:total="tableDataLength"
:isLoading="loading"
@change="onChange"
@showSizeChange="onShowSizeChange"
:style="{ marginTop: '10px' }"
></pager>
</div>
</template>
@ -58,207 +60,213 @@ import Pager from './pager.vue'
import SearchForm from './searchForm.vue'
import { searchResourceHistory } from '@/modules/acl/api/history'
export default {
components: { SearchForm, Pager },
props: {
allResourceTypes: {
type: Array,
required: true
},
allUsers: {
type: Array,
required: true
},
allRoles: {
type: Array,
required: true
},
allRolesMap: {
type: Map,
required: true
},
allUsersMap: {
type: Map,
required: true
},
allResourceTypesMap: {
type: Map,
required: true
},
components: { SearchForm, Pager },
props: {
allResourceTypes: {
type: Array,
required: true,
},
data() {
return {
loading: true,
checked: false,
tableData: [],
app_id: this.$route.name.split('_')[0],
resourceTableAttrList: [
{
alias: '日期',
is_choice: false,
name: 'datetime',
value_type: '3'
},
{
alias: '操作员',
is_choice: true,
name: 'operate_uid',
value_type: '2',
choice_value: this.allUsers
},
{
alias: '操作',
is_choice: true,
name: 'operate_type',
value_type: '2',
choice_value: [
{ '新建': 'create' },
{ '修改': 'update' },
{ '删除': 'delete' },
]
},
{
alias: '资源类型',
is_choice: true,
name: 'link_id',
value_type: '2',
choice_value: this.allResourceTypes
}
],
operateTypeMap: new Map([
['create', '新建'],
['update', '修改'],
['delete', '删除']
]),
colorMap: new Map([
['create', 'green'],
['update', 'orange'],
['delete', 'red']
]),
queryParams: {
page: 1,
page_size: 50,
app_id: this.$route.name.split('_')[0],
scope: 'resource_type',
start: '',
end: ''
},
}
allUsers: {
type: Array,
required: true,
},
async created() {
await this.getTable(this.queryParams)
allRoles: {
type: Array,
required: true,
},
updated() {
this.$refs.xTable.$el.querySelector('.vxe-table--body-wrapper').scrollTop = 0
allRolesMap: {
type: Map,
required: true,
},
watch: {
'$route.name': async function(oldName, newName) {
this.app_id = this.$route.name.split('_')[0]
await this.getTable(this.queryParams)
}
allUsersMap: {
type: Map,
required: true,
},
computed: {
windowHeight() {
return this.$store.state.windowHeight
},
tableDataLength() {
return this.tableData.length
}
allResourceTypesMap: {
type: Map,
required: true,
},
methods: {
async getTable(queryParams) {
try {
this.loading = true
const { data } = await searchResourceHistory(this.handleQueryParams(queryParams))
data.forEach(item => {
this.handleChangeDescription(item, item.operate_type)
item.operate_uid = this.allUsersMap.get(item.operate_uid)
})
this.tableData = data
} finally {
this.loading = false
}
},
data() {
return {
loading: true,
checked: false,
tableData: [],
app_id: this.$route.name.split('_')[0],
resourceTableAttrList: [
{
alias: '日期',
is_choice: false,
name: 'datetime',
value_type: '3',
},
// searchForm
handleSearch(queryParams) {
this.queryParams = { ...queryParams, app_id: this.app_id, scope: 'resource_type' }
this.getTable(this.queryParams)
{
alias: '操作员',
is_choice: true,
name: 'operate_uid',
value_type: '2',
choice_value: this.allUsers,
},
searchFormReset() {
this.$refs.child.checked = false
this.checked = false
this.queryParams = {
page: 1,
page_size: 50,
app_id: this.$route.name.split('_')[0],
scope: 'resource_type',
}
this.getTable(this.queryParams)
{
alias: '操作',
is_choice: true,
name: 'operate_type',
value_type: '2',
choice_value: [{ 新建: 'create' }, { 修改: 'update' }, { 删除: 'delete' }],
},
// pager
onShowSizeChange(size) {
this.queryParams.page_size = size
this.queryParams.page = 1
this.getTable(this.queryParams)
{
alias: '资源类型',
is_choice: true,
name: 'link_id',
value_type: '2',
choice_value: this.allResourceTypes,
},
onChange(pageNum) {
this.queryParams.page = pageNum
this.getTable(this.queryParams)
},
handleQueryParams(queryParams) {
let flag = false
let q = queryParams.q ? queryParams.q : ''
for (const key in queryParams) {
if (key !== 'page' && key !== 'page_size' && key !== 'app_id' && key !== 'q' && key !== 'start' && key !== 'end' && queryParams[key] !== undefined) {
flag = true
if (q) q += `,${key}:${queryParams[key]}`
else q += `${key}:${queryParams[key]}`
delete queryParams[key]
}
}
const newQueryParams = { ...queryParams, q }
return flag ? newQueryParams : queryParams
},
handleTagColor(operateType) {
return this.colorMap.get(operateType)
},
handleChangeDescription(item, operate_type) {
switch (operate_type) {
// create
case 'create': {
item.changeDescription = `新增资源类型:${item.current.name}\n描述${item.current.description}\n权限${item.extra.permission_ids.current}`
break
}
case 'update': {
item.changeDescription = ''
for (const key in item.origin) {
const newVal = item.current[key]
const oldVal = item.origin[key]
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
if (oldVal === null || oldVal === '') {
const str = `${key} : 改为 ${newVal}\n`
item.changeDescription += str
} else {
const str = `${key} : 由 ${oldVal} 改为 ${newVal}\n`
item.changeDescription += str
}
}
}
const currentPerms = item.extra.permission_ids.current
const originPerms = item.extra.permission_ids.origin
if (!_.isEqual(currentPerms, originPerms)) item.changeDescription += ` 【 permission_ids : 由 ${originPerms} 改为 ${currentPerms}`
if (!item.changeDescription) item.changeDescription = '没有修改'
break
}
case 'delete': {
item.changeDescription = `删除资源类型:${item.origin.name}\n描述${item.origin.description}\n权限${item.extra.permission_ids.origin}`
break
}
}
}
],
operateTypeMap: new Map([
['create', '新建'],
['update', '修改'],
['delete', '删除'],
]),
colorMap: new Map([
['create', 'green'],
['update', 'orange'],
['delete', 'red'],
]),
queryParams: {
page: 1,
page_size: 50,
app_id: this.$route.name.split('_')[0],
scope: 'resource_type',
start: '',
end: '',
},
}
},
async created() {
await this.getTable(this.queryParams)
},
updated() {
this.$refs.xTable.$el.querySelector('.vxe-table--body-wrapper').scrollTop = 0
},
watch: {
'$route.name': async function(oldName, newName) {
this.app_id = this.$route.name.split('_')[0]
await this.getTable(this.queryParams)
},
},
computed: {
windowHeight() {
return this.$store.state.windowHeight
},
tableDataLength() {
return this.tableData.length
},
},
methods: {
async getTable(queryParams) {
try {
this.loading = true
const { data } = await searchResourceHistory(this.handleQueryParams(queryParams))
data.forEach((item) => {
this.handleChangeDescription(item, item.operate_type)
item.operate_uid = this.allUsersMap.get(item.operate_uid)
})
this.tableData = data
} finally {
this.loading = false
}
},
// searchForm
handleSearch(queryParams) {
this.queryParams = { ...queryParams, app_id: this.app_id, scope: 'resource_type' }
this.getTable(this.queryParams)
},
searchFormReset() {
this.$refs.child.checked = false
this.checked = false
this.queryParams = {
page: 1,
page_size: 50,
app_id: this.$route.name.split('_')[0],
scope: 'resource_type',
}
this.getTable(this.queryParams)
},
// pager
onShowSizeChange(size) {
this.queryParams.page_size = size
this.queryParams.page = 1
this.getTable(this.queryParams)
},
onChange(pageNum) {
this.queryParams.page = pageNum
this.getTable(this.queryParams)
},
handleQueryParams(queryParams) {
let flag = false
let q = queryParams.q ? queryParams.q : ''
for (const key in queryParams) {
if (
key !== 'page' &&
key !== 'page_size' &&
key !== 'app_id' &&
key !== 'q' &&
key !== 'start' &&
key !== 'end' &&
queryParams[key] !== undefined
) {
flag = true
if (q) q += `,${key}:${queryParams[key]}`
else q += `${key}:${queryParams[key]}`
delete queryParams[key]
}
}
const newQueryParams = { ...queryParams, q }
return flag ? newQueryParams : queryParams
},
handleTagColor(operateType) {
return this.colorMap.get(operateType)
},
handleChangeDescription(item, operate_type) {
switch (operate_type) {
// create
case 'create': {
item.changeDescription = `新增资源类型:${item.current.name}\n描述${item.current.description}\n权限${item.extra.permission_ids.current}`
break
}
case 'update': {
item.changeDescription = ''
for (const key in item.origin) {
const newVal = item.current[key]
const oldVal = item.origin[key]
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
if (oldVal === null || oldVal === '') {
const str = `${key} : 改为 ${newVal}\n`
item.changeDescription += str
} else {
const str = `${key} : 由 ${oldVal} 改为 ${newVal}\n`
item.changeDescription += str
}
}
}
const currentPerms = item.extra.permission_ids.current
const originPerms = item.extra.permission_ids.origin
if (!_.isEqual(currentPerms, originPerms)) {
item.changeDescription += ` 【 permission_ids : 由 ${originPerms} 改为 ${currentPerms}`
}
if (!item.changeDescription) item.changeDescription = '没有修改'
break
}
case 'delete': {
item.changeDescription = `删除资源类型:${item.origin.name}\n描述${item.origin.description}\n权限${item.extra.permission_ids.origin}`
break
}
}
},
},
}
</script>
@ -269,7 +277,7 @@ export default {
.ant-tag {
max-width: 100%;
overflow: hidden;
text-overflow:ellipsis;
text-overflow: ellipsis;
}
p {
margin-bottom: 0;

View File

@ -11,12 +11,13 @@
></search-form>
<vxe-table
ref="xTable"
border
stripe
class="ops-stripe-table"
:data="tableData"
size="small"
:loading="loading"
resizable
:max-height="`${windowHeight - 331}px`"
:height="`${windowHeight - 310}px`"
>
<vxe-column field="created_at" width="144px" title="操作时间"></vxe-column>
<vxe-column field="operate_uid" title="操作员" width="130px"></vxe-column>
@ -33,17 +34,21 @@
<a-tag color="blue">{{ row.current.name || row.origin.name }}</a-tag>
</template>
<template v-else>
<a-tag v-for="(id,index) in row.extra.child_ids" :key="'child_ids_' + id + index" color="blue">{{ id }}</a-tag>
<a-tag v-for="(id, index) in row.extra.child_ids" :key="'child_ids_' + id + index" color="blue">{{
id
}}</a-tag>
</template>
</template>
</vxe-column>
<vxe-column :title="checked ? '继承自' : '管理员'" :width="checked ? '350px' : '80px'">
<template #default="{ row }">
<template v-if="!checked">
<a-icon type="check" v-if="row.current.is_app_admin"/>
<a-icon type="check" v-if="row.current.is_app_admin" />
</template>
<template v-else>
<a-tag v-for="(id,index) in row.extra.parent_ids" :key="'parent_ids_' + id + index" color="cyan">{{ id }}</a-tag>
<a-tag v-for="(id, index) in row.extra.parent_ids" :key="'parent_ids_' + id + index" color="cyan">{{
id
}}</a-tag>
</template>
</template>
</vxe-column>
@ -59,11 +64,12 @@
<pager
:current-page.sync="queryParams.page"
:page-size.sync="queryParams.page_size"
:page-sizes="[50,100,200]"
:page-sizes="[50, 100, 200]"
:total="tableDataLength"
:isLoading="loading"
@change="onChange"
@showSizeChange="onShowSizeChange"
:style="{ marginTop: '10px' }"
></pager>
</div>
</template>
@ -74,228 +80,246 @@ import Pager from './pager.vue'
import SearchForm from './searchForm.vue'
import { searchRoleHistory } from '@/modules/acl/api/history'
export default {
components: { SearchForm, Pager },
props: {
allUsers: {
type: Array,
required: true
},
allRoles: {
type: Array,
required: true
},
allRolesMap: {
type: Map,
required: true
},
allUsersMap: {
type: Map,
required: true
},
components: { SearchForm, Pager },
props: {
allUsers: {
type: Array,
required: true,
},
data() {
return {
loading: true,
checked: false,
tableData: [],
app_id: this.$route.name.split('_')[0],
operateTypeMap: new Map([
['create', '新建'],
['delete', '删除'],
['update', '修改'],
['role_relation_add', '添加角色关系'],
['role_relation_delete', '删除角色关系'],
]),
colorMap: new Map([
['create', 'green'],
['delete', 'red'],
['update', 'orange'],
['role_relation_add', 'green'],
['role_relation_delete', 'red']
]),
queryParams: {
page: 1,
page_size: 50,
app_id: this.$route.name.split('_')[0],
scope: 'role',
start: '',
end: ''
},
roleTableAttrList: [
{
alias: '日期',
is_choice: false,
name: 'datetime',
value_type: '3'
},
{
alias: '操作员',
is_choice: true,
name: 'operate_uid',
value_type: '2',
choice_value: this.allUsers
},
{
alias: '操作',
is_choice: true,
name: 'operate_type',
value_type: '2',
choice_value: [
{ '新建': 'create' },
{ '修改': 'update' },
{ '删除': 'delete' },
{ '添加角色关系': 'role_relation_add' },
{ '删除角色关系': 'role_relation_delete' },
]
}
]
}
allRoles: {
type: Array,
required: true,
},
computed: {
windowHeight() {
return this.$store.state.windowHeight
},
tableDataLength() {
return this.tableData.length
},
allRolesMap: {
type: Map,
required: true,
},
async created() {
await this.getTable(this.queryParams)
allUsersMap: {
type: Map,
required: true,
},
updated() {
this.$refs.xTable.$el.querySelector('.vxe-table--body-wrapper').scrollTop = 0
},
watch: {
'$route.name': async function(oldName, newName) {
this.app_id = this.$route.name.split('_')[0]
await this.getTable(this.queryParams)
}
},
methods: {
async getTable(queryParams) {
try {
this.loading = true
const { data, id2roles, id2perms, id2resources } = await searchRoleHistory(this.handleQueryParams(queryParams))
data.forEach(item => {
item.operate_uid = this.allUsersMap.get(item.operate_uid)
if (item.operate_type === 'role_relation_add' || item.operate_type === 'role_relation_delete') {
item.extra.child_ids.forEach((subItem, index) => { item.extra.child_ids[index] = id2roles[subItem].name })
item.extra.parent_ids.forEach((subItem, index) => { item.extra.parent_ids[index] = id2roles[subItem].name })
} else {
this.handleChangeDescription(item, item.operate_type, id2roles, id2perms, id2resources)
}
})
this.tableData = data
} finally {
this.loading = false
}
},
data() {
return {
loading: true,
checked: false,
tableData: [],
app_id: this.$route.name.split('_')[0],
operateTypeMap: new Map([
['create', '新建'],
['delete', '删除'],
['update', '修改'],
['role_relation_add', '添加角色关系'],
['role_relation_delete', '删除角色关系'],
]),
colorMap: new Map([
['create', 'green'],
['delete', 'red'],
['update', 'orange'],
['role_relation_add', 'green'],
['role_relation_delete', 'red'],
]),
queryParams: {
page: 1,
page_size: 50,
app_id: this.$route.name.split('_')[0],
scope: 'role',
start: '',
end: '',
},
roleTableAttrList: [
{
alias: '日期',
is_choice: false,
name: 'datetime',
value_type: '3',
},
// pager
onShowSizeChange(size) {
this.queryParams.page_size = size
this.queryParams.page = 1
this.getTable(this.queryParams)
{
alias: '操作员',
is_choice: true,
name: 'operate_uid',
value_type: '2',
choice_value: this.allUsers,
},
onChange(pageNum) {
this.queryParams.page = pageNum
this.getTable(this.queryParams)
},
// searchForm
onSwitchChange(checked) {
this.checked = checked
this.queryParams.scope = checked ? 'role_relation' : 'role'
this.queryParams.page = 1
this.getTable(this.queryParams)
},
handleSearch(queryParams) {
this.queryParams = { ...queryParams, app_id: this.app_id, scope: this.checked ? 'role_relation' : 'role' }
this.getTable(this.queryParams)
},
searchFormReset() {
this.$refs.child.checked = false
this.checked = false
this.queryParams = {
page: 1,
page_size: 50,
app_id: this.$route.name.split('_')[0],
scope: this.checked ? 'role_relation' : 'role'
}
this.getTable(this.queryParams)
},
//
handleQueryParams(queryParams) {
let flag = false
let q = queryParams.q ? queryParams.q : ''
for (const key in queryParams) {
if (key !== 'page' && key !== 'page_size' && key !== 'app_id' && key !== 'q' && key !== 'start' && key !== 'end' && queryParams[key] !== undefined) {
flag = true
if (q) q += `,${key}:${queryParams[key]}`
else q += `${key}:${queryParams[key]}`
delete queryParams[key]
}
}
const newQueryParams = { ...queryParams, q }
return flag ? newQueryParams : queryParams
},
// tag
handleTagColor(operateType) {
return this.colorMap.get(operateType)
},
handleChangeDescription(item, operate_type, id2roles, id2perms, id2resources) {
switch (operate_type) {
// create
case 'create': {
item.description = `新建角色:${item.current.name}`
break
}
case 'update': {
item.description = ''
for (const key in item.origin) {
const newVal = item.current[key]
const oldVal = item.origin[key]
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
if (oldVal === null) {
const str = `${key} : 改为 ${newVal}`
item.description += str
} else {
const str = `${key} : 由 ${oldVal} 改为 ${newVal}`
item.description += `${key} : 由 ${oldVal} 改为 ${newVal}`
}
}
}
if (!item.description) item.description = '没有修改'
break
}
case 'delete': {
const { extra: { child_ids, parent_ids, role_permissions } } = item
child_ids.forEach((subItem, index) => { child_ids[index] = id2roles[subItem].name })
parent_ids.forEach((subItem, index) => { parent_ids[index] = id2roles[subItem].name })
const resourceMap = new Map()
const permsArr = []
role_permissions.forEach(subItem => {
const resource_id = subItem.resource_id
const perm_id = subItem.perm_id
if (resourceMap.has(resource_id)) {
let resource_perms = resourceMap.get(resource_id)
resource_perms += `,${id2perms[perm_id].name}`
resourceMap.set(resource_id, resource_perms)
} else {
resourceMap.set(resource_id, String(id2perms[perm_id].name))
}
})
resourceMap.forEach((value, key) => {
permsArr.push(`${id2resources[key].name}${value}`)
})
item.description = `继承者:${child_ids}\n继承自${parent_ids}\n涉及资源及权限\n${permsArr.join(`\n`)}`
break
}
}
{
alias: '操作',
is_choice: true,
name: 'operate_type',
value_type: '2',
choice_value: [
{ 新建: 'create' },
{ 修改: 'update' },
{ 删除: 'delete' },
{ 添加角色关系: 'role_relation_add' },
{ 删除角色关系: 'role_relation_delete' },
],
},
],
}
},
computed: {
windowHeight() {
return this.$store.state.windowHeight
},
tableDataLength() {
return this.tableData.length
},
},
async created() {
await this.getTable(this.queryParams)
},
updated() {
this.$refs.xTable.$el.querySelector('.vxe-table--body-wrapper').scrollTop = 0
},
watch: {
'$route.name': async function(oldName, newName) {
this.app_id = this.$route.name.split('_')[0]
await this.getTable(this.queryParams)
},
},
methods: {
async getTable(queryParams) {
try {
this.loading = true
const { data, id2roles, id2perms, id2resources } = await searchRoleHistory(this.handleQueryParams(queryParams))
data.forEach((item) => {
item.operate_uid = this.allUsersMap.get(item.operate_uid)
if (item.operate_type === 'role_relation_add' || item.operate_type === 'role_relation_delete') {
item.extra.child_ids.forEach((subItem, index) => {
item.extra.child_ids[index] = id2roles[subItem].name
})
item.extra.parent_ids.forEach((subItem, index) => {
item.extra.parent_ids[index] = id2roles[subItem].name
})
} else {
this.handleChangeDescription(item, item.operate_type, id2roles, id2perms, id2resources)
}
})
this.tableData = data
} finally {
this.loading = false
}
},
// pager
onShowSizeChange(size) {
this.queryParams.page_size = size
this.queryParams.page = 1
this.getTable(this.queryParams)
},
onChange(pageNum) {
this.queryParams.page = pageNum
this.getTable(this.queryParams)
},
// searchForm
onSwitchChange(checked) {
this.checked = checked
this.queryParams.scope = checked ? 'role_relation' : 'role'
this.queryParams.page = 1
this.getTable(this.queryParams)
},
handleSearch(queryParams) {
this.queryParams = { ...queryParams, app_id: this.app_id, scope: this.checked ? 'role_relation' : 'role' }
this.getTable(this.queryParams)
},
searchFormReset() {
this.$refs.child.checked = false
this.checked = false
this.queryParams = {
page: 1,
page_size: 50,
app_id: this.$route.name.split('_')[0],
scope: this.checked ? 'role_relation' : 'role',
}
this.getTable(this.queryParams)
},
//
handleQueryParams(queryParams) {
let flag = false
let q = queryParams.q ? queryParams.q : ''
for (const key in queryParams) {
if (
key !== 'page' &&
key !== 'page_size' &&
key !== 'app_id' &&
key !== 'q' &&
key !== 'start' &&
key !== 'end' &&
queryParams[key] !== undefined
) {
flag = true
if (q) q += `,${key}:${queryParams[key]}`
else q += `${key}:${queryParams[key]}`
delete queryParams[key]
}
}
const newQueryParams = { ...queryParams, q }
return flag ? newQueryParams : queryParams
},
// tag
handleTagColor(operateType) {
return this.colorMap.get(operateType)
},
handleChangeDescription(item, operate_type, id2roles, id2perms, id2resources) {
switch (operate_type) {
// create
case 'create': {
item.description = `新建角色:${item.current.name}`
break
}
case 'update': {
item.description = ''
for (const key in item.origin) {
const newVal = item.current[key]
const oldVal = item.origin[key]
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
if (oldVal === null) {
const str = `${key} : 改为 ${newVal}`
item.description += str
} else {
const str = `${key} : 由 ${oldVal} 改为 ${newVal}`
item.description += `${key} : 由 ${oldVal} 改为 ${newVal}`
}
}
}
if (!item.description) item.description = '没有修改'
break
}
case 'delete': {
const {
extra: { child_ids, parent_ids, role_permissions },
} = item
child_ids.forEach((subItem, index) => {
child_ids[index] = id2roles[subItem].name
})
parent_ids.forEach((subItem, index) => {
parent_ids[index] = id2roles[subItem].name
})
const resourceMap = new Map()
const permsArr = []
role_permissions.forEach((subItem) => {
const resource_id = subItem.resource_id
const perm_id = subItem.perm_id
if (resourceMap.has(resource_id)) {
let resource_perms = resourceMap.get(resource_id)
resource_perms += `,${id2perms[perm_id].name}`
resourceMap.set(resource_id, resource_perms)
} else {
resourceMap.set(resource_id, String(id2perms[perm_id].name))
}
})
resourceMap.forEach((value, key) => {
permsArr.push(`${id2resources[key].name}${value}`)
})
item.description = `继承者:${child_ids}\n继承自${parent_ids}\n涉及资源及权限\n${permsArr.join(`\n`)}`
break
}
}
},
},
}
</script>
@ -306,7 +330,7 @@ export default {
.ant-tag {
max-width: 100%;
overflow: hidden;
text-overflow:ellipsis;
text-overflow: ellipsis;
}
p {
margin-bottom: 0;

View File

@ -8,12 +8,13 @@
></search-form>
<vxe-table
ref="xTable"
border
stripe
class="ops-stripe-table"
:data="tableData"
:loading="loading"
size="small"
resizable
:max-height="`${windowHeight - 331}px`"
:height="`${windowHeight - 310}px`"
>
<vxe-column field="created_at" width="144px" title="操作时间"></vxe-column>
<vxe-column field="operate_uid" width="130px" title="操作员"></vxe-column>
@ -42,11 +43,12 @@
<pager
:current-page.sync="queryParams.page"
:page-size.sync="queryParams.page_size"
:page-sizes="[50,100,200]"
:page-sizes="[50, 100, 200]"
:total="tableDataLength"
:isLoading="loading"
@change="onChange"
@showSizeChange="onShowSizeChange"
:style="{ marginTop: '10px' }"
></pager>
</div>
</template>
@ -57,229 +59,252 @@ import Pager from './pager.vue'
import SearchForm from './searchForm.vue'
import { searchTriggerHistory } from '@/modules/acl/api/history'
export default {
components: { SearchForm, Pager },
props: {
allUsers: {
type: Array,
required: true
},
allRoles: {
type: Array,
required: true
},
allTriggers: {
type: Array,
required: true
},
allRolesMap: {
type: Map,
required: true
},
allTriggersMap: {
type: Map,
required: true
},
allUsersMap: {
type: Map,
required: true
},
allResourceTypesMap: {
type: Map,
required: true
},
components: { SearchForm, Pager },
props: {
allUsers: {
type: Array,
required: true,
},
data() {
return {
app_id: this.$route.name.split('_')[0],
loading: true,
tableData: [],
operateTypeMap: new Map([
['create', '新建'],
['update', '修改'],
['delete', '删除'],
['trigger_apply', '应用'],
['trigger_cancel', '取消'],
]),
colorMap: new Map([
['create', 'green'],
['delete', 'red'],
['update', 'orange'],
['trigger_apply', 'green'],
['trigger_cancel', 'red'],
]),
triggerTableAttrList: [
{
alias: '日期',
is_choice: false,
name: 'datetime',
value_type: '3'
},
{
alias: '操作员',
is_choice: true,
name: 'operate_uid',
value_type: '2',
choice_value: this.allUsers
},
{
alias: '操作',
is_choice: true,
name: 'operate_type',
value_type: '2',
choice_value: [
{ '新建': 'create' },
{ '修改': 'update' },
{ '删除': 'delete' },
{ '应用': 'trigger_apply' },
{ '取消': 'trigger_cancel' },
]
},
{
alias: '触发器',
is_choice: true,
name: 'trigger_id',
value_type: '2',
choice_value: this.allTriggers
}
],
queryParams: {
page: 1,
page_size: 50,
app_id: this.$route.name.split('_')[0]
},
}
allRoles: {
type: Array,
required: true,
},
async created() {
await this.getTable(this.queryParams)
allTriggers: {
type: Array,
required: true,
},
updated() {
this.$refs.xTable.$el.querySelector('.vxe-table--body-wrapper').scrollTop = 0
allRolesMap: {
type: Map,
required: true,
},
watch: {
'$route.name': async function(oldName, newName) {
this.app_id = this.$route.name.split('_')[0]
await this.getTable(this.queryParams)
}
allTriggersMap: {
type: Map,
required: true,
},
computed: {
windowHeight() {
return this.$store.state.windowHeight
},
tableDataLength() {
return this.tableData.length
}
allUsersMap: {
type: Map,
required: true,
},
methods: {
async getTable(queryParams) {
try {
this.loading = true
const res = await searchTriggerHistory(this.handleQueryParams(queryParams))
res.data.forEach(item => {
this.handleChangeDescription(item, item.operate_type)
item.trigger_id = this.allTriggersMap.get(item.trigger_id)
item.operate_uid = this.allUsersMap.get(item.operate_uid)
})
this.tableData = res.data
} finally {
this.loading = false
}
allResourceTypesMap: {
type: Map,
required: true,
},
},
data() {
return {
app_id: this.$route.name.split('_')[0],
loading: true,
tableData: [],
operateTypeMap: new Map([
['create', '新建'],
['update', '修改'],
['delete', '删除'],
['trigger_apply', '应用'],
['trigger_cancel', '取消'],
]),
colorMap: new Map([
['create', 'green'],
['delete', 'red'],
['update', 'orange'],
['trigger_apply', 'green'],
['trigger_cancel', 'red'],
]),
triggerTableAttrList: [
{
alias: '日期',
is_choice: false,
name: 'datetime',
value_type: '3',
},
// pager
onShowSizeChange(size) {
this.queryParams.page_size = size
this.queryParams.page = 1
this.getTable(this.queryParams)
{
alias: '操作员',
is_choice: true,
name: 'operate_uid',
value_type: '2',
choice_value: this.allUsers,
},
onChange(pageNum) {
this.queryParams.page = pageNum
this.getTable(this.queryParams)
{
alias: '操作',
is_choice: true,
name: 'operate_type',
value_type: '2',
choice_value: [
{ 新建: 'create' },
{ 修改: 'update' },
{ 删除: 'delete' },
{ 应用: 'trigger_apply' },
{ 取消: 'trigger_cancel' },
],
},
// searchForm
handleSearch(queryParams) {
this.queryParams = queryParams
this.queryParams.app_id = this.app_id
this.getTable(this.queryParams)
{
alias: '触发器',
is_choice: true,
name: 'trigger_id',
value_type: '2',
choice_value: this.allTriggers,
},
searchFormReset() {
this.queryParams = {
page: 1,
page_size: 50,
app_id: this.$route.name.split('_')[0]
}
this.getTable(this.queryParams)
},
handleChangeDescription(item, operate_type) {
switch (operate_type) {
// create
case 'create': {
const str = item.current.roles
const newArr = str.slice(1, str.length - 1).split(', ')
const newStr = newArr.map(i => this.allRolesMap.get(Number(i))).join('')
item.changeDescription = `新增触发器:${item.current.name}\n资源类型${this.allResourceTypesMap.get(item.current.resource_type_id)},资源名:${item.current.wildcard},角色:[${newStr}]\n权限${item.current.permissions}\n状态${item.current.enabled}`
break
}
case 'update': {
item.changeDescription = ''
for (const key in item.origin) {
const newVal = item.current[key]
const oldVal = item.origin[key]
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
if (oldVal === null) {
const str = `${key} : 改为 ${newVal}`
item.changeDescription += str
} else {
const str = `${key} : 由 ${oldVal} 改为 ${newVal}`
item.changeDescription += `${key} : 由 ${oldVal} 改为 ${newVal}`
}
}
}
if (!item.changeDescription) item.changeDescription = '没有修改'
break
}
case 'delete': {
const str = item.origin.roles
const newArr = str.slice(1, str.length - 1).split(', ')
const newStr = newArr.map(i => this.allRolesMap.get(Number(i))).join('')
item.changeDescription = `删除触发器:${item.origin.name}\n资源类型${this.allResourceTypesMap.get(item.origin.resource_type_id)},资源名:${item.origin.wildcard},角色:[${newStr}]\n权限${item.origin.permissions}\n状态${item.origin.enabled}`
break
}
case 'trigger_apply': {
const str = item.current.roles
const newArr = str.slice(1, str.length - 1).split(', ')
const newStr = newArr.map(i => this.allRolesMap.get(Number(i))).join('')
item.changeDescription = `应用触发器:${item.current.name}\n资源类型${this.allResourceTypesMap.get(item.current.resource_type_id)},资源名:${item.current.wildcard},角色:[${newStr}]\n权限${item.current.permissions}\n状态${item.current.enabled}`
break
}
case 'trigger_cancel': {
const str = item.current.roles
const newArr = str.slice(1, str.length - 1).split(', ')
const newStr = newArr.map(i => this.allRolesMap.get(Number(i))).join('')
item.changeDescription = `取消触发器:${item.current.name}\n资源类型${this.allResourceTypesMap.get(item.current.resource_type_id)},资源名:${item.current.wildcard},角色:[${newStr}]\n权限${item.current.permissions}\n状态${item.current.enabled}`
break
}
}
},
handleQueryParams(queryParams) {
let q = ''
for (const key in queryParams) {
if (key !== 'page' && key !== 'page_size' && key !== 'app_id' && key !== 'start' && key !== 'end' && queryParams[key] !== undefined) {
if (q) {
q += `,${key}:${queryParams[key]}`
} else {
q += `${key}:${queryParams[key]}`
}
}
}
const newQueryParams = { ...queryParams, q }
return q ? newQueryParams : queryParams
},
handleTagColor(operateType) {
return this.colorMap.get(operateType)
}
],
queryParams: {
page: 1,
page_size: 50,
app_id: this.$route.name.split('_')[0],
},
}
},
async created() {
await this.getTable(this.queryParams)
},
updated() {
this.$refs.xTable.$el.querySelector('.vxe-table--body-wrapper').scrollTop = 0
},
watch: {
'$route.name': async function(oldName, newName) {
this.app_id = this.$route.name.split('_')[0]
await this.getTable(this.queryParams)
},
},
computed: {
windowHeight() {
return this.$store.state.windowHeight
},
tableDataLength() {
return this.tableData.length
},
},
methods: {
async getTable(queryParams) {
try {
this.loading = true
const res = await searchTriggerHistory(this.handleQueryParams(queryParams))
res.data.forEach((item) => {
this.handleChangeDescription(item, item.operate_type)
item.trigger_id = this.allTriggersMap.get(item.trigger_id)
item.operate_uid = this.allUsersMap.get(item.operate_uid)
})
this.tableData = res.data
} finally {
this.loading = false
}
},
// pager
onShowSizeChange(size) {
this.queryParams.page_size = size
this.queryParams.page = 1
this.getTable(this.queryParams)
},
onChange(pageNum) {
this.queryParams.page = pageNum
this.getTable(this.queryParams)
},
// searchForm
handleSearch(queryParams) {
this.queryParams = queryParams
this.queryParams.app_id = this.app_id
this.getTable(this.queryParams)
},
searchFormReset() {
this.queryParams = {
page: 1,
page_size: 50,
app_id: this.$route.name.split('_')[0],
}
this.getTable(this.queryParams)
},
handleChangeDescription(item, operate_type) {
switch (operate_type) {
// create
case 'create': {
const str = item.current.roles
const newArr = str.slice(1, str.length - 1).split(', ')
const newStr = newArr.map((i) => this.allRolesMap.get(Number(i))).join('')
item.changeDescription = `新增触发器:${item.current.name}\n资源类型${this.allResourceTypesMap.get(
item.current.resource_type_id
)}资源名${item.current.wildcard}角色[${newStr}]\n权限${item.current.permissions}\n状态${
item.current.enabled
}`
break
}
case 'update': {
item.changeDescription = ''
for (const key in item.origin) {
const newVal = item.current[key]
const oldVal = item.origin[key]
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
if (oldVal === null) {
const str = `${key} : 改为 ${newVal}`
item.changeDescription += str
} else {
const str = `${key} : 由 ${oldVal} 改为 ${newVal}`
item.changeDescription += `${key} : 由 ${oldVal} 改为 ${newVal}`
}
}
}
if (!item.changeDescription) item.changeDescription = '没有修改'
break
}
case 'delete': {
const str = item.origin.roles
const newArr = str.slice(1, str.length - 1).split(', ')
const newStr = newArr.map((i) => this.allRolesMap.get(Number(i))).join('')
item.changeDescription = `删除触发器:${item.origin.name}\n资源类型${this.allResourceTypesMap.get(
item.origin.resource_type_id
)}资源名${item.origin.wildcard}角色[${newStr}]\n权限${item.origin.permissions}\n状态${
item.origin.enabled
}`
break
}
case 'trigger_apply': {
const str = item.current.roles
const newArr = str.slice(1, str.length - 1).split(', ')
const newStr = newArr.map((i) => this.allRolesMap.get(Number(i))).join('')
item.changeDescription = `应用触发器:${item.current.name}\n资源类型${this.allResourceTypesMap.get(
item.current.resource_type_id
)}资源名${item.current.wildcard}角色[${newStr}]\n权限${item.current.permissions}\n状态${
item.current.enabled
}`
break
}
case 'trigger_cancel': {
const str = item.current.roles
const newArr = str.slice(1, str.length - 1).split(', ')
const newStr = newArr.map((i) => this.allRolesMap.get(Number(i))).join('')
item.changeDescription = `取消触发器:${item.current.name}\n资源类型${this.allResourceTypesMap.get(
item.current.resource_type_id
)}资源名${item.current.wildcard}角色[${newStr}]\n权限${item.current.permissions}\n状态${
item.current.enabled
}`
break
}
}
},
handleQueryParams(queryParams) {
let q = ''
for (const key in queryParams) {
if (
key !== 'page' &&
key !== 'page_size' &&
key !== 'app_id' &&
key !== 'start' &&
key !== 'end' &&
queryParams[key] !== undefined
) {
if (q) {
q += `,${key}:${queryParams[key]}`
} else {
q += `${key}:${queryParams[key]}`
}
}
}
const newQueryParams = { ...queryParams, q }
return q ? newQueryParams : queryParams
},
handleTagColor(operateType) {
return this.colorMap.get(operateType)
},
},
}
</script>
@ -290,6 +315,6 @@ p {
.ant-tag {
max-width: 100%;
overflow: hidden;
text-overflow:ellipsis;
text-overflow: ellipsis;
}
</style>

View File

@ -1,5 +1,5 @@
<template>
<div :style="{ backgroundColor: '#fff', padding: '24px' }">
<div class="acl-operation-history">
<a-tabs default-active-key="1">
<a-tab-pane key="1" tab="权限变更">
<permisson-table></permisson-table>
@ -31,4 +31,12 @@ export default {
}
</script>
<style></style>
<style lang="less" scoped>
.acl-operation-history {
border-radius: 15px;
height: calc(100vh - 64px);
margin-bottom: -24px;
padding: 24px;
background-color: #fff;
}
</style>

View File

@ -13,12 +13,13 @@
></search-form>
<vxe-table
ref="xTable"
border
stripe
class="ops-stripe-table"
resizable
size="small"
:data="tableData"
:loading="loading"
:max-height="`${windowHeight - windowHeightMinus}px`"
:height="`${windowHeight - windowHeightMinus}px`"
:scroll-y="{ enabled: false }"
>
<vxe-column field="created_at" width="144px" title="操作时间">
@ -72,6 +73,7 @@
:isLoading="loading"
@change="onChange"
@showSizeChange="onShowSizeChange"
:style="{ marginTop: '10px' }"
></pager>
</div>
</template>
@ -172,7 +174,7 @@ export default {
return this.$store.state.windowHeight
},
windowHeightMinus() {
return this.isExpand ? 396 : 331
return this.isExpand ? 374 : 310
},
tableDataLength() {
return this.tableData.length

View File

@ -15,13 +15,14 @@
@resourceClear="resourceClear"
></search-form>
<vxe-table
stripe
class="ops-stripe-table"
ref="xTable"
border
resizable
size="small"
:loading="loading"
:data="tableData"
:max-height="`${windowHeight - windowHeightMinus}px`"
:height="`${windowHeight - windowHeightMinus}px`"
>
<vxe-column field="created_at" width="144px" title="操作时间"></vxe-column>
<vxe-column field="operate_uid" width="130px" title="操作员"></vxe-column>
@ -56,6 +57,7 @@
:isLoading="loading"
@change="onChange"
@showSizeChange="onShowSizeChange"
:style="{ marginTop: '10px' }"
></pager>
</div>
</template>
@ -160,7 +162,7 @@ export default {
return this.$store.state.windowHeight
},
windowHeightMinus() {
return this.isExpand ? 396 : 331
return this.isExpand ? 374 : 310
},
tableDataLength() {
return this.tableData.length

View File

@ -10,12 +10,13 @@
></search-form>
<vxe-table
ref="xTable"
border
stripe
class="ops-stripe-table"
resizable
size="small"
:data="tableData"
:loading="loading"
:max-height="`${windowHeight - windowHeightMinus}px`"
:height="`${windowHeight - windowHeightMinus}px`"
>
<vxe-column field="created_at" width="144px" title="操作时间"></vxe-column>
<vxe-column field="operate_uid" width="130px" title="操作员"></vxe-column>
@ -45,11 +46,12 @@
<pager
:current-page.sync="queryParams.page"
:page-size.sync="queryParams.page_size"
:page-sizes="[50,100,200]"
:page-sizes="[50, 100, 200]"
:total="tableDataLength"
:isLoading="loading"
@change="onChange"
@showSizeChange="onShowSizeChange"
:style="{ marginTop: '10px' }"
></pager>
</div>
</template>
@ -63,249 +65,261 @@ import { searchUser } from '@/modules/acl/api/user'
import { searchResourceType } from '@/modules/acl/api/resource'
import { searchApp } from '@/modules/acl/api/app'
export default {
components: { SearchForm, Pager },
data() {
return {
loading: true,
checked: false,
isExpand: false,
app_id: undefined,
tableData: [],
allResourceTypes: [],
allUsers: [],
allApps: [],
allUsersMap: new Map(),
allResourcesMap: new Map(),
resourceTableAttrList: [
{
alias: '日期',
is_choice: false,
name: 'datetime',
value_type: '3'
},
{
alias: '应用',
is_choice: true,
name: 'app_id',
value_type: '2',
choice_value: []
},
{
alias: '操作员',
is_choice: true,
name: 'operate_uid',
value_type: '2',
choice_value: []
},
{
alias: '资源类型',
is_choice: true,
name: 'link_id',
value_type: '2',
choice_value: []
},
{
alias: '操作',
is_choice: true,
name: 'operate_type',
value_type: '2',
choice_value: [
{ '新建': 'create' },
{ '修改': 'update' },
{ '删除': 'delete' },
]
}
],
operateTypeMap: new Map([
['create', '新建'],
['update', '修改'],
['delete', '删除']
]),
colorMap: new Map([
['create', 'green'],
['update', 'orange'],
['delete', 'red']
]),
queryParams: {
page: 1,
page_size: 50,
scope: 'resource_type',
start: '',
end: ''
},
}
},
async created() {
this.$watch(
function () {
return this.resourceTableAttrList[3].choice_value
},
function () {
delete this.$refs.child.queryParams.link_id
}
)
await Promise.all([ this.getAllApps(), this.getAllUsers() ])
await this.getTable(this.queryParams)
},
updated() {
this.$refs.xTable.$el.querySelector('.vxe-table--body-wrapper').scrollTop = 0
},
computed: {
windowHeight() {
return this.$store.state.windowHeight
components: { SearchForm, Pager },
data() {
return {
loading: true,
checked: false,
isExpand: false,
app_id: undefined,
tableData: [],
allResourceTypes: [],
allUsers: [],
allApps: [],
allUsersMap: new Map(),
allResourcesMap: new Map(),
resourceTableAttrList: [
{
alias: '日期',
is_choice: false,
name: 'datetime',
value_type: '3',
},
windowHeightMinus() {
return this.isExpand ? 396 : 331
{
alias: '应用',
is_choice: true,
name: 'app_id',
value_type: '2',
choice_value: [],
},
tableDataLength() {
return this.tableData.length
}
},
methods: {
async getTable(queryParams) {
try {
this.loading = true
const { data } = await searchResourceHistory(this.handleQueryParams(queryParams))
data.forEach(item => {
this.handleChangeDescription(item, item.operate_type)
item.operate_uid = this.allUsersMap.get(item.operate_uid)
})
this.tableData = data
} finally {
this.loading = false
}
{
alias: '操作员',
is_choice: true,
name: 'operate_uid',
value_type: '2',
choice_value: [],
},
async getAllApps() {
const { apps } = await searchApp()
const allApps = []
apps.forEach(item => { allApps.push({ [item.name]: item.id }) })
this.allApps = allApps
this.resourceTableAttrList[1].choice_value = this.allApps
{
alias: '资源类型',
is_choice: true,
name: 'link_id',
value_type: '2',
choice_value: [],
},
async getAllUsers() {
const { users } = await searchUser({ page_size: 10000, app_id: 'acl' })
const allUsers = []
const allUsersMap = new Map()
users.forEach(item => {
allUsers.push({ [item.nickname]: item.uid })
allUsersMap.set(item.uid, item.nickname)
})
this.allUsers = allUsers
this.allUsersMap = allUsersMap
this.resourceTableAttrList[2].choice_value = this.allUsers
{
alias: '操作',
is_choice: true,
name: 'operate_type',
value_type: '2',
choice_value: [{ 新建: 'create' }, { 修改: 'update' }, { 删除: 'delete' }],
},
async getAllResourceTypes(app_id) {
if (!app_id) {
this.resourceTableAttrList[3].choice_value = []
return
}
const { groups } = await searchResourceType({
page: 1,
page_size: 9999,
app_id: app_id
})
const allResourceTypes = []
groups.forEach(item => { allResourceTypes.push({ [item.name]: item.id }) })
this.allResourceTypes = allResourceTypes
this.resourceTableAttrList[3].choice_value = this.allResourceTypes
},
// searchForm
handleExpandChange(expand) {
this.isExpand = expand
},
handleSearch(queryParams) {
this.queryParams = { ...queryParams, scope: 'resource_type' }
this.getTable(this.queryParams)
},
searchFormReset() {
this.$refs.child.checked = false
this.checked = false
this.queryParams = {
page: 1,
page_size: 50,
scope: 'resource_type',
}
this.getTable(this.queryParams)
},
async searchFormChange(queryParams) {
if (this.app_id !== queryParams.app_id) {
this.app_id = queryParams.app_id
await this.getAllResourceTypes(this.app_id)
}
if (queryParams.app_id === undefined) {
this.app_id = undefined
this.$refs.child.queryParams.link_id = undefined
}
},
// pager
onShowSizeChange(size) {
this.queryParams.page_size = size
this.queryParams.page = 1
this.getTable(this.queryParams)
},
onChange(pageNum) {
this.queryParams.page = pageNum
this.getTable(this.queryParams)
},
handleQueryParams(queryParams) {
let flag = false
let q = queryParams.q ? queryParams.q : ''
for (const key in queryParams) {
if (key !== 'page' && key !== 'page_size' && key !== 'app_id' && key !== 'q' && key !== 'start' && key !== 'end' && queryParams[key] !== undefined) {
flag = true
if (q) q += `,${key}:${queryParams[key]}`
else q += `${key}:${queryParams[key]}`
delete queryParams[key]
}
}
const newQueryParams = { ...queryParams, q }
return flag ? newQueryParams : queryParams
},
handleTagColor(operateType) {
return this.colorMap.get(operateType)
},
handleChangeDescription(item, operate_type) {
switch (operate_type) {
// create
case 'create': {
const description = item.current?.description === undefined ? '无' : item.current?.description
const permission = item.extra.permission_ids?.current === undefined ? '无' : item.extra.permission_ids?.current
item.changeDescription = `新增资源类型:${item.current.name}\n描述${description}\n权限${permission}`
break
}
case 'update': {
item.changeDescription = ''
for (const key in item.origin) {
const newVal = item.current[key]
const oldVal = item.origin[key]
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
if (oldVal === null || oldVal === '') {
const str = `${key} : 改为 ${newVal}\n`
item.changeDescription += str
} else {
const str = `${key} : 由 ${oldVal} 改为 ${newVal}\n`
item.changeDescription += str
}
}
}
const currentPerms = item.extra.permission_ids?.current === undefined ? '无' : item.extra.permission_ids?.current
const originPerms = item.extra.permission_ids?.origin === undefined ? '无' : item.extra.permission_ids?.origin
if (!_.isEqual(currentPerms, originPerms)) item.changeDescription += ` 【 permission_ids : 由 ${originPerms} 改为 ${currentPerms}`
if (!item.changeDescription) item.changeDescription = '没有修改'
break
}
case 'delete': {
const description = item.origin?.description === undefined ? '无' : item.origin?.description
const permission = item.extra.permission_ids?.origin === undefined ? '无' : item.extra.permission_ids?.origin
item.changeDescription = `删除资源类型:${item.origin.name}\n描述${description}\n权限${permission}`
break
}
}
}
],
operateTypeMap: new Map([
['create', '新建'],
['update', '修改'],
['delete', '删除'],
]),
colorMap: new Map([
['create', 'green'],
['update', 'orange'],
['delete', 'red'],
]),
queryParams: {
page: 1,
page_size: 50,
scope: 'resource_type',
start: '',
end: '',
},
}
},
async created() {
this.$watch(
function() {
return this.resourceTableAttrList[3].choice_value
},
function() {
delete this.$refs.child.queryParams.link_id
}
)
await Promise.all([this.getAllApps(), this.getAllUsers()])
await this.getTable(this.queryParams)
},
updated() {
this.$refs.xTable.$el.querySelector('.vxe-table--body-wrapper').scrollTop = 0
},
computed: {
windowHeight() {
return this.$store.state.windowHeight
},
windowHeightMinus() {
return this.isExpand ? 374 : 310
},
tableDataLength() {
return this.tableData.length
},
},
methods: {
async getTable(queryParams) {
try {
this.loading = true
const { data } = await searchResourceHistory(this.handleQueryParams(queryParams))
data.forEach((item) => {
this.handleChangeDescription(item, item.operate_type)
item.operate_uid = this.allUsersMap.get(item.operate_uid)
})
this.tableData = data
} finally {
this.loading = false
}
},
async getAllApps() {
const { apps } = await searchApp()
const allApps = []
apps.forEach((item) => {
allApps.push({ [item.name]: item.id })
})
this.allApps = allApps
this.resourceTableAttrList[1].choice_value = this.allApps
},
async getAllUsers() {
const { users } = await searchUser({ page_size: 10000, app_id: 'acl' })
const allUsers = []
const allUsersMap = new Map()
users.forEach((item) => {
allUsers.push({ [item.nickname]: item.uid })
allUsersMap.set(item.uid, item.nickname)
})
this.allUsers = allUsers
this.allUsersMap = allUsersMap
this.resourceTableAttrList[2].choice_value = this.allUsers
},
async getAllResourceTypes(app_id) {
if (!app_id) {
this.resourceTableAttrList[3].choice_value = []
return
}
const { groups } = await searchResourceType({
page: 1,
page_size: 9999,
app_id: app_id,
})
const allResourceTypes = []
groups.forEach((item) => {
allResourceTypes.push({ [item.name]: item.id })
})
this.allResourceTypes = allResourceTypes
this.resourceTableAttrList[3].choice_value = this.allResourceTypes
},
// searchForm
handleExpandChange(expand) {
this.isExpand = expand
},
handleSearch(queryParams) {
this.queryParams = { ...queryParams, scope: 'resource_type' }
this.getTable(this.queryParams)
},
searchFormReset() {
this.$refs.child.checked = false
this.checked = false
this.queryParams = {
page: 1,
page_size: 50,
scope: 'resource_type',
}
this.getTable(this.queryParams)
},
async searchFormChange(queryParams) {
if (this.app_id !== queryParams.app_id) {
this.app_id = queryParams.app_id
await this.getAllResourceTypes(this.app_id)
}
if (queryParams.app_id === undefined) {
this.app_id = undefined
this.$refs.child.queryParams.link_id = undefined
}
},
// pager
onShowSizeChange(size) {
this.queryParams.page_size = size
this.queryParams.page = 1
this.getTable(this.queryParams)
},
onChange(pageNum) {
this.queryParams.page = pageNum
this.getTable(this.queryParams)
},
handleQueryParams(queryParams) {
let flag = false
let q = queryParams.q ? queryParams.q : ''
for (const key in queryParams) {
if (
key !== 'page' &&
key !== 'page_size' &&
key !== 'app_id' &&
key !== 'q' &&
key !== 'start' &&
key !== 'end' &&
queryParams[key] !== undefined
) {
flag = true
if (q) q += `,${key}:${queryParams[key]}`
else q += `${key}:${queryParams[key]}`
delete queryParams[key]
}
}
const newQueryParams = { ...queryParams, q }
return flag ? newQueryParams : queryParams
},
handleTagColor(operateType) {
return this.colorMap.get(operateType)
},
handleChangeDescription(item, operate_type) {
switch (operate_type) {
// create
case 'create': {
const description = item.current?.description === undefined ? '无' : item.current?.description
const permission =
item.extra.permission_ids?.current === undefined ? '无' : item.extra.permission_ids?.current
item.changeDescription = `新增资源类型:${item.current.name}\n描述${description}\n权限${permission}`
break
}
case 'update': {
item.changeDescription = ''
for (const key in item.origin) {
const newVal = item.current[key]
const oldVal = item.origin[key]
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
if (oldVal === null || oldVal === '') {
const str = `${key} : 改为 ${newVal}\n`
item.changeDescription += str
} else {
const str = `${key} : 由 ${oldVal} 改为 ${newVal}\n`
item.changeDescription += str
}
}
}
const currentPerms =
item.extra.permission_ids?.current === undefined ? '无' : item.extra.permission_ids?.current
const originPerms = item.extra.permission_ids?.origin === undefined ? '无' : item.extra.permission_ids?.origin
if (!_.isEqual(currentPerms, originPerms)) {
item.changeDescription += ` 【 permission_ids : 由 ${originPerms} 改为 ${currentPerms}`
}
if (!item.changeDescription) item.changeDescription = '没有修改'
break
}
case 'delete': {
const description = item.origin?.description === undefined ? '无' : item.origin?.description
const permission = item.extra.permission_ids?.origin === undefined ? '无' : item.extra.permission_ids?.origin
item.changeDescription = `删除资源类型:${item.origin.name}\n描述${description}\n权限${permission}`
break
}
}
},
},
}
</script>
@ -316,7 +330,7 @@ export default {
.ant-tag {
max-width: 100%;
overflow: hidden;
text-overflow:ellipsis;
text-overflow: ellipsis;
}
p {
margin-bottom: 0;

View File

@ -10,13 +10,14 @@
@searchFormReset="searchFormReset"
></search-form>
<vxe-table
stripe
class="ops-stripe-table"
ref="xTable"
border
resizable
size="small"
:data="tableData"
:loading="loading"
:max-height="`${windowHeight - 331}px`"
:height="`${windowHeight - 310}px`"
>
<vxe-column field="created_at" width="144px" title="操作时间"></vxe-column>
<vxe-column field="operate_uid" width="130px" title="操作员"></vxe-column>
@ -33,17 +34,21 @@
<a-tag color="blue">{{ row.current.name || row.origin.name }}</a-tag>
</template>
<template v-else>
<a-tag v-for="(id,index) in row.extra.child_ids" :key="'child_ids_' + id + index" color="blue">{{ id }}</a-tag>
<a-tag v-for="(id, index) in row.extra.child_ids" :key="'child_ids_' + id + index" color="blue">{{
id
}}</a-tag>
</template>
</template>
</vxe-column>
<vxe-column :title="checked ? '继承自' : '管理员'" :width="checked ? '350px' : '80px'">
<template #default="{ row }">
<template v-if="!checked">
<a-icon type="check" v-if="row.current.is_app_admin"/>
<a-icon type="check" v-if="row.current.is_app_admin" />
</template>
<template v-else>
<a-tag v-for="(id,index) in row.extra.parent_ids" :key="'parent_ids_' + id + index" color="cyan">{{ id }}</a-tag>
<a-tag v-for="(id, index) in row.extra.parent_ids" :key="'parent_ids_' + id + index" color="cyan">{{
id
}}</a-tag>
</template>
</template>
</vxe-column>
@ -59,11 +64,12 @@
<pager
:current-page.sync="queryParams.page"
:page-size.sync="queryParams.page_size"
:page-sizes="[50,100,200]"
:page-sizes="[50, 100, 200]"
:total="tableDataLength"
:isLoading="loading"
@change="onChange"
@showSizeChange="onShowSizeChange"
:style="{ marginTop: '10px' }"
></pager>
</div>
</template>
@ -76,234 +82,254 @@ import { searchRoleHistory } from '@/modules/acl/api/history'
import { searchApp } from '@/modules/acl/api/app'
import { searchUser } from '@/modules/acl/api/user'
export default {
components: { SearchForm, Pager },
data() {
return {
loading: true,
checked: false,
app_id: undefined,
tableData: [],
allApps: [],
allUsers: [],
allRoles: [],
allRolesMap: new Map(),
allUsersMap: new Map(),
operateTypeMap: new Map([
['create', '新建'],
['delete', '删除'],
['update', '修改'],
['role_relation_add', '添加角色关系'],
['role_relation_delete', '删除角色关系'],
]),
colorMap: new Map([
['create', 'green'],
['delete', 'red'],
['update', 'orange'],
['role_relation_add', 'green'],
['role_relation_delete', 'red']
]),
queryParams: {
page: 1,
page_size: 50,
scope: 'role',
start: '',
end: ''
},
roleTableAttrList: [
{
alias: '日期',
is_choice: false,
name: 'datetime',
value_type: '3'
},
{
alias: '应用',
is_choice: true,
name: 'app_id',
value_type: '2',
choice_value: []
},
{
alias: '操作员',
is_choice: true,
name: 'operate_uid',
value_type: '2',
choice_value: []
},
{
alias: '操作',
is_choice: true,
name: 'operate_type',
value_type: '2',
choice_value: [
{ '新建': 'create' },
{ '修改': 'update' },
{ '删除': 'delete' },
{ '添加角色关系': 'role_relation_add' },
{ '删除角色关系': 'role_relation_delete' },
]
}
]
}
},
computed: {
windowHeight() {
return this.$store.state.windowHeight
components: { SearchForm, Pager },
data() {
return {
loading: true,
checked: false,
app_id: undefined,
tableData: [],
allApps: [],
allUsers: [],
allRoles: [],
allRolesMap: new Map(),
allUsersMap: new Map(),
operateTypeMap: new Map([
['create', '新建'],
['delete', '删除'],
['update', '修改'],
['role_relation_add', '添加角色关系'],
['role_relation_delete', '删除角色关系'],
]),
colorMap: new Map([
['create', 'green'],
['delete', 'red'],
['update', 'orange'],
['role_relation_add', 'green'],
['role_relation_delete', 'red'],
]),
queryParams: {
page: 1,
page_size: 50,
scope: 'role',
start: '',
end: '',
},
roleTableAttrList: [
{
alias: '日期',
is_choice: false,
name: 'datetime',
value_type: '3',
},
tableDataLength() {
return this.tableData.length
}
},
async created() {
await Promise.all([ this.getAllApps(), this.getAllUsers() ])
await this.getTable(this.queryParams)
},
updated() {
this.$refs.xTable.$el.querySelector('.vxe-table--body-wrapper').scrollTop = 0
},
methods: {
async getTable(queryParams) {
try {
this.loading = true
const { data, id2roles, id2perms, id2resources } = await searchRoleHistory(this.handleQueryParams(queryParams))
data.forEach(item => {
item.operate_uid = this.allUsersMap.get(item.operate_uid)
if (item.operate_type === 'role_relation_add' || item.operate_type === 'role_relation_delete') {
item.extra.child_ids.forEach((subItem, index) => { item.extra.child_ids[index] = id2roles[subItem].name })
item.extra.parent_ids.forEach((subItem, index) => { item.extra.parent_ids[index] = id2roles[subItem].name })
} else {
this.handleChangeDescription(item, item.operate_type, id2roles, id2perms, id2resources)
}
})
this.tableData = data
} finally {
this.loading = false
}
{
alias: '应用',
is_choice: true,
name: 'app_id',
value_type: '2',
choice_value: [],
},
async getAllApps() {
const { apps } = await searchApp()
const allApps = []
apps.forEach(item => { allApps.push({ [item.name]: item.id }) })
this.allApps = allApps
this.roleTableAttrList[1].choice_value = this.allApps
{
alias: '操作员',
is_choice: true,
name: 'operate_uid',
value_type: '2',
choice_value: [],
},
async getAllUsers() {
const { users } = await searchUser({ page_size: 10000, app_id: 'acl' })
const allUsers = []
const allUsersMap = new Map()
users.forEach(item => {
allUsers.push({ [item.nickname]: item.uid })
allUsersMap.set(item.uid, item.nickname)
})
this.allUsers = allUsers
this.allUsersMap = allUsersMap
this.roleTableAttrList[2].choice_value = this.allUsers
},
// pager
onShowSizeChange(size) {
this.queryParams.page_size = size
this.queryParams.page = 1
this.getTable(this.queryParams)
},
onChange(pageNum) {
this.queryParams.page = pageNum
this.getTable(this.queryParams)
},
// searchForm
onSwitchChange(checked) {
this.checked = checked
this.queryParams.scope = checked ? 'role_relation' : 'role'
this.queryParams.page = 1
this.getTable(this.queryParams)
},
handleSearch(queryParams) {
this.queryParams = { ...queryParams, scope: this.checked ? 'role_relation' : 'role' }
this.getTable(this.queryParams)
},
searchFormReset() {
this.$refs.child.checked = false
this.checked = false
this.queryParams = {
page: 1,
page_size: 50,
scope: this.checked ? 'role_relation' : 'role'
}
this.getTable(this.queryParams)
},
//
handleQueryParams(queryParams) {
let flag = false
let q = queryParams.q ? queryParams.q : ''
for (const key in queryParams) {
if (key !== 'page' && key !== 'page_size' && key !== 'app_id' && key !== 'q' && key !== 'start' && key !== 'end' && queryParams[key] !== undefined) {
flag = true
if (q) q += `,${key}:${queryParams[key]}`
else q += `${key}:${queryParams[key]}`
delete queryParams[key]
}
}
const newQueryParams = { ...queryParams, q }
return flag ? newQueryParams : queryParams
},
// tag
handleTagColor(operateType) {
return this.colorMap.get(operateType)
},
handleChangeDescription(item, operate_type, id2roles, id2perms, id2resources) {
switch (operate_type) {
// create
case 'create': {
item.description = `新建角色:${item.current.name}`
break
}
case 'update': {
item.description = ''
for (const key in item.origin) {
const newVal = item.current[key]
const oldVal = item.origin[key]
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
if (oldVal === null) {
const str = `${key} : 改为 ${newVal}`
item.description += str
} else {
const str = `${key} : 由 ${oldVal} 改为 ${newVal}`
item.description += str
}
}
}
if (!item.description) item.description = '没有修改'
break
}
case 'delete': {
const { extra: { child_ids, parent_ids, role_permissions } } = item
child_ids.forEach((subItem, index) => { child_ids[index] = id2roles[subItem].name })
parent_ids.forEach((subItem, index) => { parent_ids[index] = id2roles[subItem].name })
const resourceMap = new Map()
const permsArr = []
role_permissions.forEach(subItem => {
const resource_id = subItem.resource_id
const perm_id = subItem.perm_id
if (resourceMap.has(resource_id)) {
let resource_perms = resourceMap.get(resource_id)
resource_perms += `,${id2perms[perm_id].name}`
resourceMap.set(resource_id, resource_perms)
} else {
resourceMap.set(resource_id, String(id2perms[perm_id].name))
}
})
resourceMap.forEach((value, key) => {
permsArr.push(`${id2resources[key].name}${value}`)
})
item.description = `继承者:${child_ids}\n继承自${parent_ids}\n涉及资源及权限\n${permsArr.join(`\n`)}`
break
}
}
{
alias: '操作',
is_choice: true,
name: 'operate_type',
value_type: '2',
choice_value: [
{ 新建: 'create' },
{ 修改: 'update' },
{ 删除: 'delete' },
{ 添加角色关系: 'role_relation_add' },
{ 删除角色关系: 'role_relation_delete' },
],
},
],
}
},
computed: {
windowHeight() {
return this.$store.state.windowHeight
},
tableDataLength() {
return this.tableData.length
},
},
async created() {
await Promise.all([this.getAllApps(), this.getAllUsers()])
await this.getTable(this.queryParams)
},
updated() {
this.$refs.xTable.$el.querySelector('.vxe-table--body-wrapper').scrollTop = 0
},
methods: {
async getTable(queryParams) {
try {
this.loading = true
const { data, id2roles, id2perms, id2resources } = await searchRoleHistory(this.handleQueryParams(queryParams))
data.forEach((item) => {
item.operate_uid = this.allUsersMap.get(item.operate_uid)
if (item.operate_type === 'role_relation_add' || item.operate_type === 'role_relation_delete') {
item.extra.child_ids.forEach((subItem, index) => {
item.extra.child_ids[index] = id2roles[subItem].name
})
item.extra.parent_ids.forEach((subItem, index) => {
item.extra.parent_ids[index] = id2roles[subItem].name
})
} else {
this.handleChangeDescription(item, item.operate_type, id2roles, id2perms, id2resources)
}
})
this.tableData = data
} finally {
this.loading = false
}
},
async getAllApps() {
const { apps } = await searchApp()
const allApps = []
apps.forEach((item) => {
allApps.push({ [item.name]: item.id })
})
this.allApps = allApps
this.roleTableAttrList[1].choice_value = this.allApps
},
async getAllUsers() {
const { users } = await searchUser({ page_size: 10000, app_id: 'acl' })
const allUsers = []
const allUsersMap = new Map()
users.forEach((item) => {
allUsers.push({ [item.nickname]: item.uid })
allUsersMap.set(item.uid, item.nickname)
})
this.allUsers = allUsers
this.allUsersMap = allUsersMap
this.roleTableAttrList[2].choice_value = this.allUsers
},
// pager
onShowSizeChange(size) {
this.queryParams.page_size = size
this.queryParams.page = 1
this.getTable(this.queryParams)
},
onChange(pageNum) {
this.queryParams.page = pageNum
this.getTable(this.queryParams)
},
// searchForm
onSwitchChange(checked) {
this.checked = checked
this.queryParams.scope = checked ? 'role_relation' : 'role'
this.queryParams.page = 1
this.getTable(this.queryParams)
},
handleSearch(queryParams) {
this.queryParams = { ...queryParams, scope: this.checked ? 'role_relation' : 'role' }
this.getTable(this.queryParams)
},
searchFormReset() {
this.$refs.child.checked = false
this.checked = false
this.queryParams = {
page: 1,
page_size: 50,
scope: this.checked ? 'role_relation' : 'role',
}
this.getTable(this.queryParams)
},
//
handleQueryParams(queryParams) {
let flag = false
let q = queryParams.q ? queryParams.q : ''
for (const key in queryParams) {
if (
key !== 'page' &&
key !== 'page_size' &&
key !== 'app_id' &&
key !== 'q' &&
key !== 'start' &&
key !== 'end' &&
queryParams[key] !== undefined
) {
flag = true
if (q) q += `,${key}:${queryParams[key]}`
else q += `${key}:${queryParams[key]}`
delete queryParams[key]
}
}
const newQueryParams = { ...queryParams, q }
return flag ? newQueryParams : queryParams
},
// tag
handleTagColor(operateType) {
return this.colorMap.get(operateType)
},
handleChangeDescription(item, operate_type, id2roles, id2perms, id2resources) {
switch (operate_type) {
// create
case 'create': {
item.description = `新建角色:${item.current.name}`
break
}
case 'update': {
item.description = ''
for (const key in item.origin) {
const newVal = item.current[key]
const oldVal = item.origin[key]
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
if (oldVal === null) {
const str = `${key} : 改为 ${newVal}`
item.description += str
} else {
const str = `${key} : 由 ${oldVal} 改为 ${newVal}`
item.description += str
}
}
}
if (!item.description) item.description = '没有修改'
break
}
case 'delete': {
const {
extra: { child_ids, parent_ids, role_permissions },
} = item
child_ids.forEach((subItem, index) => {
child_ids[index] = id2roles[subItem].name
})
parent_ids.forEach((subItem, index) => {
parent_ids[index] = id2roles[subItem].name
})
const resourceMap = new Map()
const permsArr = []
role_permissions.forEach((subItem) => {
const resource_id = subItem.resource_id
const perm_id = subItem.perm_id
if (resourceMap.has(resource_id)) {
let resource_perms = resourceMap.get(resource_id)
resource_perms += `,${id2perms[perm_id].name}`
resourceMap.set(resource_id, resource_perms)
} else {
resourceMap.set(resource_id, String(id2perms[perm_id].name))
}
})
resourceMap.forEach((value, key) => {
permsArr.push(`${id2resources[key].name}${value}`)
})
item.description = `继承者:${child_ids}\n继承自${parent_ids}\n涉及资源及权限\n${permsArr.join(`\n`)}`
break
}
}
},
},
}
</script>
@ -314,7 +340,7 @@ export default {
.ant-tag {
max-width: 100%;
overflow: hidden;
text-overflow:ellipsis;
text-overflow: ellipsis;
}
p {
margin-bottom: 0;

View File

@ -10,12 +10,13 @@
></search-form>
<vxe-table
ref="xTable"
border
stripe
class="ops-stripe-table"
resizable
size="small"
:data="tableData"
:loading="loading"
:max-height="`${windowHeight - windowHeightMinus}px`"
:height="`${windowHeight - windowHeightMinus}px`"
>
<vxe-column field="created_at" width="144px" title="操作时间"></vxe-column>
<vxe-column field="operate_uid" width="130px" title="操作员"></vxe-column>
@ -44,11 +45,12 @@
<pager
:current-page.sync="queryParams.page"
:page-size.sync="queryParams.page_size"
:page-sizes="[50,100,200]"
:page-sizes="[50, 100, 200]"
:total="tableDataLength"
:isLoading="loading"
@change="onChange"
@showSizeChange="onShowSizeChange"
:style="{ marginTop: '10px' }"
></pager>
</div>
</template>
@ -62,275 +64,292 @@ import { getTriggers } from '@/modules/acl/api/trigger'
import { searchUser } from '@/modules/acl/api/user'
import { searchApp } from '@/modules/acl/api/app'
export default {
components: { SearchForm, Pager },
data() {
return {
app_id: undefined,
loading: true,
isExpand: false,
tableData: [],
allResourceTypes: [],
allResources: [],
allUsers: [],
allRoles: [],
allTriggers: [],
allApps: [],
allRolesMap: new Map(),
allUsersMap: new Map(),
allResourceTypesMap: new Map(),
allResourcesMap: new Map(),
allTriggersMap: new Map(),
operateTypeMap: new Map([
['create', '新建'],
['update', '修改'],
['delete', '删除'],
['trigger_apply', '应用'],
['trigger_cancel', '取消'],
]),
colorMap: new Map([
['create', 'green'],
['delete', 'red'],
['update', 'orange'],
['trigger_apply', 'green'],
['trigger_cancel', 'red'],
]),
triggerTableAttrList: [
{
alias: '日期',
is_choice: false,
name: 'datetime',
value_type: '3'
},
{
alias: '应用',
is_choice: true,
name: 'app_id',
value_type: '2',
choice_value: []
},
{
alias: '操作员',
is_choice: true,
name: 'operate_uid',
value_type: '2',
choice_value: []
},
{
alias: '触发器',
is_choice: true,
name: 'trigger_id',
value_type: '2',
choice_value: []
},
{
alias: '操作',
is_choice: true,
name: 'operate_type',
value_type: '2',
choice_value: [
{ '新建': 'create' },
{ '修改': 'update' },
{ '删除': 'delete' },
{ '应用': 'trigger_apply' },
{ '取消': 'trigger_cancel' },
]
},
],
queryParams: {
page: 1,
page_size: 50,
start: '',
end: ''
},
}
},
async created() {
this.$watch(
function () {
return this.triggerTableAttrList[3].choice_value
},
function () {
delete this.$refs.child.queryParams.trigger_id
}
)
await Promise.all([ this.getAllApps(), this.getAllUsers() ])
await this.getTable(this.queryParams)
},
updated() {
this.$refs.xTable.$el.querySelector('.vxe-table--body-wrapper').scrollTop = 0
},
computed: {
windowHeight() {
return this.$store.state.windowHeight
components: { SearchForm, Pager },
data() {
return {
app_id: undefined,
loading: true,
isExpand: false,
tableData: [],
allResourceTypes: [],
allResources: [],
allUsers: [],
allRoles: [],
allTriggers: [],
allApps: [],
allRolesMap: new Map(),
allUsersMap: new Map(),
allResourceTypesMap: new Map(),
allResourcesMap: new Map(),
allTriggersMap: new Map(),
operateTypeMap: new Map([
['create', '新建'],
['update', '修改'],
['delete', '删除'],
['trigger_apply', '应用'],
['trigger_cancel', '取消'],
]),
colorMap: new Map([
['create', 'green'],
['delete', 'red'],
['update', 'orange'],
['trigger_apply', 'green'],
['trigger_cancel', 'red'],
]),
triggerTableAttrList: [
{
alias: '日期',
is_choice: false,
name: 'datetime',
value_type: '3',
},
windowHeightMinus() {
return this.isExpand ? 396 : 331
{
alias: '应用',
is_choice: true,
name: 'app_id',
value_type: '2',
choice_value: [],
},
tableDataLength() {
return this.tableData.length
}
},
methods: {
async getTable(queryParams) {
try {
this.loading = true
const { data, id2resource_types, id2roles } = await searchTriggerHistory(this.handleQueryParams(queryParams))
data.forEach(item => {
this.handleChangeDescription(item, item.operate_type, id2resource_types, id2roles)
item.trigger_id = this.allTriggersMap.get(item.trigger_id)
item.operate_uid = this.allUsersMap.get(item.operate_uid)
})
this.tableData = data
} finally {
this.loading = false
}
{
alias: '操作员',
is_choice: true,
name: 'operate_uid',
value_type: '2',
choice_value: [],
},
async getAllApps() {
const { apps } = await searchApp()
const allApps = []
apps.forEach(item => { allApps.push({ [item.name]: item.id }) })
this.allApps = allApps
this.triggerTableAttrList[1].choice_value = this.allApps
{
alias: '触发器',
is_choice: true,
name: 'trigger_id',
value_type: '2',
choice_value: [],
},
async getAllUsers() {
const { users } = await searchUser({ page_size: 10000, app_id: 'acl' })
const allUsers = []
const allUsersMap = new Map()
users.forEach(item => {
allUsers.push({ [item.nickname]: item.uid })
allUsersMap.set(item.uid, item.nickname)
})
this.allUsers = allUsers
this.allUsersMap = allUsersMap
this.triggerTableAttrList[2].choice_value = this.allUsers
{
alias: '操作',
is_choice: true,
name: 'operate_type',
value_type: '2',
choice_value: [
{ 新建: 'create' },
{ 修改: 'update' },
{ 删除: 'delete' },
{ 应用: 'trigger_apply' },
{ 取消: 'trigger_cancel' },
],
},
async getTriggers(app_id) {
if (!app_id) {
this.triggerTableAttrList[3].choice_value = []
return
}
const res = await getTriggers({ app_id: app_id })
const allTriggers = []
const allTriggersMap = new Map()
res.forEach(item => {
allTriggers.push({ [item.name]: item.id })
allTriggersMap.set(item.id, item.name)
})
this.allTriggers = allTriggers
this.allTriggersMap = allTriggersMap
this.triggerTableAttrList[3].choice_value = this.allTriggers
},
// pager
onShowSizeChange(size) {
this.queryParams.page_size = size
this.queryParams.page = 1
this.getTable(this.queryParams)
},
onChange(pageNum) {
this.queryParams.page = pageNum
this.getTable(this.queryParams)
},
// searchForm
handleExpandChange(expand) {
this.isExpand = expand
},
handleSearch(queryParams) {
this.queryParams = queryParams
this.getTable(this.queryParams)
},
searchFormReset() {
this.queryParams = {
page: 1,
page_size: 50,
}
this.getTable(this.queryParams)
},
async searchFormChange(queryParams) {
if (this.app_id !== queryParams.app_id) {
this.app_id = queryParams.app_id
await this.getTriggers(this.app_id)
}
if (queryParams.app_id === undefined) {
this.app_id = undefined
this.$refs.child.queryParams.trigger_id = undefined
}
},
handleChangeDescription(item, operate_type, id2resource_types, id2roles) {
switch (operate_type) {
// create
case 'create': {
const str = item.current.roles
const newArr = str.slice(1, str.length - 1).split(', ')
const newStr = newArr.map(i => id2roles[i].name).join('')
const { name, resource_type_id, wildcard, permissions, enabled } = item.current
item.changeDescription = `新增触发器:${name}\n资源类型${id2resource_types[resource_type_id].name},资源名:${wildcard || ''},角色:[${newStr}]\n权限${permissions}\n状态${enabled}`
break
}
case 'update': {
item.changeDescription = ''
for (const key in item.origin) {
const newVal = item.current[key]
const oldVal = item.origin[key]
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
if (oldVal === null) {
const str = `${key} : 改为 ${newVal}`
item.changeDescription += str
} else {
const str = `${key} : 由 ${oldVal} 改为 ${newVal}`
item.changeDescription += `${key} : 由 ${oldVal} 改为 ${newVal}`
}
}
}
if (!item.changeDescription) item.changeDescription = '没有修改'
break
}
case 'delete': {
const str = item.origin.roles
const newArr = str.slice(1, str.length - 1).split(', ')
const newStr = newArr.map(i => id2roles[i].name).join('')
const { name, resource_type_id, wildcard, permissions, enabled } = item.origin
item.changeDescription = `删除触发器:${name}\n资源类型${id2resource_types[resource_type_id].name},资源名:${wildcard || ''},角色:[${newStr}]\n权限${permissions}\n状态${enabled}`
break
}
case 'trigger_apply': {
const str = item.current.roles
const newArr = str.slice(1, str.length - 1).split(', ')
const newStr = newArr.map(i => id2roles[i].name).join('')
const { name, resource_type_id, wildcard, permissions, enabled } = item.current
item.changeDescription = `应用触发器:${name}\n资源类型${id2resource_types[resource_type_id].name},资源名:${wildcard || ''},角色:[${newStr}]\n权限${permissions}\n状态${enabled}`
break
}
case 'trigger_cancel': {
const str = item.current.roles
const newArr = str.slice(1, str.length - 1).split(', ')
const newStr = newArr.map(i => id2roles[i].name).join('')
const { name, resource_type_id, wildcard, permissions, enabled } = item.current
item.changeDescription = `取消触发器:${name}\n资源类型${id2resource_types[resource_type_id].name},资源名:${wildcard || ''},角色:[${newStr}]\n权限${permissions}\n状态${enabled}`
break
}
}
},
handleQueryParams(queryParams) {
let q = ''
for (const key in queryParams) {
if (key !== 'page' && key !== 'page_size' && key !== 'app_id' && key !== 'start' && key !== 'end' && queryParams[key] !== undefined) {
if (q) {
q += `,${key}:${queryParams[key]}`
} else {
q += `${key}:${queryParams[key]}`
}
}
}
const newQueryParams = { ...queryParams, q }
return q ? newQueryParams : queryParams
},
handleTagColor(operateType) {
return this.colorMap.get(operateType)
}
],
queryParams: {
page: 1,
page_size: 50,
start: '',
end: '',
},
}
},
async created() {
this.$watch(
function() {
return this.triggerTableAttrList[3].choice_value
},
function() {
delete this.$refs.child.queryParams.trigger_id
}
)
await Promise.all([this.getAllApps(), this.getAllUsers()])
await this.getTable(this.queryParams)
},
updated() {
this.$refs.xTable.$el.querySelector('.vxe-table--body-wrapper').scrollTop = 0
},
computed: {
windowHeight() {
return this.$store.state.windowHeight
},
windowHeightMinus() {
return this.isExpand ? 374 : 310
},
tableDataLength() {
return this.tableData.length
},
},
methods: {
async getTable(queryParams) {
try {
this.loading = true
const { data, id2resource_types, id2roles } = await searchTriggerHistory(this.handleQueryParams(queryParams))
data.forEach((item) => {
this.handleChangeDescription(item, item.operate_type, id2resource_types, id2roles)
item.trigger_id = this.allTriggersMap.get(item.trigger_id)
item.operate_uid = this.allUsersMap.get(item.operate_uid)
})
this.tableData = data
} finally {
this.loading = false
}
},
async getAllApps() {
const { apps } = await searchApp()
const allApps = []
apps.forEach((item) => {
allApps.push({ [item.name]: item.id })
})
this.allApps = allApps
this.triggerTableAttrList[1].choice_value = this.allApps
},
async getAllUsers() {
const { users } = await searchUser({ page_size: 10000, app_id: 'acl' })
const allUsers = []
const allUsersMap = new Map()
users.forEach((item) => {
allUsers.push({ [item.nickname]: item.uid })
allUsersMap.set(item.uid, item.nickname)
})
this.allUsers = allUsers
this.allUsersMap = allUsersMap
this.triggerTableAttrList[2].choice_value = this.allUsers
},
async getTriggers(app_id) {
if (!app_id) {
this.triggerTableAttrList[3].choice_value = []
return
}
const res = await getTriggers({ app_id: app_id })
const allTriggers = []
const allTriggersMap = new Map()
res.forEach((item) => {
allTriggers.push({ [item.name]: item.id })
allTriggersMap.set(item.id, item.name)
})
this.allTriggers = allTriggers
this.allTriggersMap = allTriggersMap
this.triggerTableAttrList[3].choice_value = this.allTriggers
},
// pager
onShowSizeChange(size) {
this.queryParams.page_size = size
this.queryParams.page = 1
this.getTable(this.queryParams)
},
onChange(pageNum) {
this.queryParams.page = pageNum
this.getTable(this.queryParams)
},
// searchForm
handleExpandChange(expand) {
this.isExpand = expand
},
handleSearch(queryParams) {
this.queryParams = queryParams
this.getTable(this.queryParams)
},
searchFormReset() {
this.queryParams = {
page: 1,
page_size: 50,
}
this.getTable(this.queryParams)
},
async searchFormChange(queryParams) {
if (this.app_id !== queryParams.app_id) {
this.app_id = queryParams.app_id
await this.getTriggers(this.app_id)
}
if (queryParams.app_id === undefined) {
this.app_id = undefined
this.$refs.child.queryParams.trigger_id = undefined
}
},
handleChangeDescription(item, operate_type, id2resource_types, id2roles) {
switch (operate_type) {
// create
case 'create': {
const str = item.current.roles
const newArr = str.slice(1, str.length - 1).split(', ')
const newStr = newArr.map((i) => id2roles[i].name).join('')
const { name, resource_type_id, wildcard, permissions, enabled } = item.current
item.changeDescription = `新增触发器:${name}\n资源类型${
id2resource_types[resource_type_id].name
}资源名${wildcard || ''}角色[${newStr}]\n权限${permissions}\n状态${enabled}`
break
}
case 'update': {
item.changeDescription = ''
for (const key in item.origin) {
const newVal = item.current[key]
const oldVal = item.origin[key]
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
if (oldVal === null) {
const str = `${key} : 改为 ${newVal}`
item.changeDescription += str
} else {
const str = `${key} : 由 ${oldVal} 改为 ${newVal}`
item.changeDescription += `${key} : 由 ${oldVal} 改为 ${newVal}`
}
}
}
if (!item.changeDescription) item.changeDescription = '没有修改'
break
}
case 'delete': {
const str = item.origin.roles
const newArr = str.slice(1, str.length - 1).split(', ')
const newStr = newArr.map((i) => id2roles[i].name).join('')
const { name, resource_type_id, wildcard, permissions, enabled } = item.origin
item.changeDescription = `删除触发器:${name}\n资源类型${
id2resource_types[resource_type_id].name
}资源名${wildcard || ''}角色[${newStr}]\n权限${permissions}\n状态${enabled}`
break
}
case 'trigger_apply': {
const str = item.current.roles
const newArr = str.slice(1, str.length - 1).split(', ')
const newStr = newArr.map((i) => id2roles[i].name).join('')
const { name, resource_type_id, wildcard, permissions, enabled } = item.current
item.changeDescription = `应用触发器:${name}\n资源类型${
id2resource_types[resource_type_id].name
}资源名${wildcard || ''}角色[${newStr}]\n权限${permissions}\n状态${enabled}`
break
}
case 'trigger_cancel': {
const str = item.current.roles
const newArr = str.slice(1, str.length - 1).split(', ')
const newStr = newArr.map((i) => id2roles[i].name).join('')
const { name, resource_type_id, wildcard, permissions, enabled } = item.current
item.changeDescription = `取消触发器:${name}\n资源类型${
id2resource_types[resource_type_id].name
}资源名${wildcard || ''}角色[${newStr}]\n权限${permissions}\n状态${enabled}`
break
}
}
},
handleQueryParams(queryParams) {
let q = ''
for (const key in queryParams) {
if (
key !== 'page' &&
key !== 'page_size' &&
key !== 'app_id' &&
key !== 'start' &&
key !== 'end' &&
queryParams[key] !== undefined
) {
if (q) {
q += `,${key}:${queryParams[key]}`
} else {
q += `${key}:${queryParams[key]}`
}
}
}
const newQueryParams = { ...queryParams, q }
return q ? newQueryParams : queryParams
},
handleTagColor(operateType) {
return this.colorMap.get(operateType)
},
},
}
</script>
@ -341,6 +360,6 @@ p {
.ant-tag {
max-width: 100%;
overflow: hidden;
text-overflow:ellipsis;
text-overflow: ellipsis;
}
</style>

View File

@ -1,6 +1,6 @@
<template>
<div :style="{ backgroundColor: '#fff', padding: '24px' }">
<div class="resource-types-action-btn">
<div class="acl-resource-types">
<div class="acl-resource-types-header">
<a-button @click="handleCreate" type="primary" style="margin-right: 0.3rem">{{ btnName }}</a-button>
<a-input-search
class="ops-input"
@ -17,12 +17,12 @@
></a-input-search>
</div>
<a-spin :spinning="loading">
<vxe-table
<ops-table
stripe
size="mini"
size="small"
class="ops-stripe-table"
:data="groups"
:max-height="`${windowHeight - 185}px`"
:height="`${windowHeight - 200}px`"
highlight-hover-row
>
<!-- 1 -->
@ -45,28 +45,25 @@
</vxe-table-column>
<!-- 4 -->
<vxe-table-column field="action" title="操作" :min-width="175" fixed="right">
<vxe-table-column field="action" title="操作" :width="100" fixed="right">
<template #default="{ row }">
<a @click="handleEdit(row)"><a-icon type="edit" /></a>
<a @click="handleEdit(row)"><a-icon type="edit"/></a>
<a-divider type="vertical" />
<a-popconfirm title="确认删除?" @confirm="handleDelete(row)" okText="是" cancelText="否">
<a style="color: red"><a-icon type="delete" /></a>
<a style="color: red"><a-icon type="delete"/></a>
</a-popconfirm>
</template>
</vxe-table-column>
<template slot="empty">
<img :src="require(`@/assets/data_empty.png`)" />
<p style="font-size: 14px; line-height: 17px; color: rgba(0, 0, 0, 0.6)">暂无数据</p>
</template>
</vxe-table>
</ops-table>
<vxe-pager
size="mini"
size="small"
:layouts="['Total', 'PrevPage', 'JumpNumber', 'NextPage', 'Sizes']"
:current-page.sync="tablePage.currentPage"
:page-size.sync="tablePage.pageSize"
:total="tablePage.total"
:page-sizes="pageSizeOptions"
@page-change="handlePageChange"
:style="{ marginTop: '10px' }"
>
</vxe-pager>
</a-spin>
@ -140,7 +137,7 @@ export default {
}),
},
watch: {
'$route.name': function (newName, oldName) {
'$route.name': function(newName, oldName) {
this.tablePage = {
total: 0,
currentPage: 1,
@ -222,10 +219,17 @@ export default {
</script>
<style lang="less" scoped>
.resource-types-action-btn {
width: 100%;
display: inline-flex;
margin-bottom: 15px;
align-items: center;
.acl-resource-types {
border-radius: 15px;
background-color: #fff;
height: calc(100vh - 64px);
margin-bottom: -24px;
padding: 24px;
.acl-resource-types-header {
width: 100%;
display: inline-flex;
margin-bottom: 15px;
align-items: center;
}
}
</style>

View File

@ -1,10 +1,10 @@
<template>
<div :style="{ backgroundColor: '#fff', padding: '24px' }">
<div v-if="allResourceTypes.length > 0">
<div class="acl-resources">
<div v-if="allResourceTypes.length">
<a-tabs default-active-key="1" @change="loadCurrentType">
<a-tab-pane v-for="rtype in allResourceTypes" :key="rtype.id" :tab="rtype.name"> </a-tab-pane>
</a-tabs>
<div class="resources-action-btn">
<div class="acl-resources-header">
<a-space>
<a-button @click="handleCreate" type="primary">{{ btnName }}</a-button>
<a-input-search
@ -18,25 +18,13 @@
}
"
></a-input-search>
<a-dropdown v-if="selectedRows && selectedRows.length">
<a-button type="primary" ghost>
批量操作
</a-button>
<a-menu slot="overlay">
<a-menu-item @click="handleBatchPerm">
<a href="javascript:;">授权</a>
</a-menu-item>
<a-menu-item @click="handleBatchRevoke">
<a href="javascript:;">权限回收</a>
</a-menu-item>
</a-menu>
</a-dropdown>
<span
v-if="selectedRows && selectedRows.length"
>已选择<strong>{{ selectedRows.length }}</strong
></span
>
<div v-if="!!selectedRows.length" class="ops-list-batch-action">
<span @click="handleBatchPerm">授权</span>
<a-divider type="vertical" />
<span @click="handleBatchRevoke">权限回收</span>
<span>选取: {{ selectedRows.length }} </span>
</div>
</a-space>
<a-space>
@ -67,13 +55,13 @@
</a-space>
</div>
<a-spin :spinning="loading">
<vxe-table
size="mini"
<ops-table
size="small"
stripe
class="ops-stripe-table"
:data="tableData"
highlight-hover-row
:height="`${windowHeight - 280}px`"
:height="`${windowHeight - 250}px`"
:checkbox-config="{ reserve: true }"
@checkbox-change="changeCheckbox"
@checkbox-all="changeCheckbox"
@ -132,24 +120,21 @@
</a-popconfirm>
</template>
</vxe-table-column>
<template slot="empty">
<img :src="require(`@/assets/data_empty.png`)" />
<p style="font-size: 14px; line-height: 17px; color: rgba(0, 0, 0, 0.6)">暂无数据</p>
</template>
</vxe-table>
</ops-table>
<vxe-pager
size="mini"
size="small"
:layouts="['Total', 'PrevPage', 'JumpNumber', 'NextPage', 'Sizes']"
:current-page.sync="tablePage.currentPage"
:page-size.sync="tablePage.pageSize"
:total="tablePage.total"
:page-sizes="pageSizeOptions"
@page-change="handlePageChange"
:style="{ marginTop: '10px' }"
>
</vxe-pager>
</a-spin>
</div>
<div v-else style="text-align: center">
<div v-else style="text-align: center;margin-top:20%">
<a-icon style="font-size:50px; margin-bottom: 20px; color: orange" type="info-circle" />
<h3>暂无类型信息请先添加资源类型</h3>
</div>
@ -398,14 +383,21 @@ export default {
</script>
<style lang="less" scoped>
.resources-action-btn {
width: 100%;
display: inline-flex;
margin-bottom: 15px;
align-items: center;
justify-content: space-between;
.ant-switch {
margin-left: auto;
.acl-resources {
border-radius: 15px;
background-color: #fff;
height: calc(100vh - 64px);
margin-bottom: -24px;
padding: 12px 24px 24px 24px;
.acl-resources-header {
width: 100%;
display: inline-flex;
margin-bottom: 15px;
align-items: center;
justify-content: space-between;
.ant-switch {
margin-left: auto;
}
}
}
</style>

View File

@ -1,6 +1,6 @@
<template>
<div class="acl-role">
<div class="roles-action-btn">
<div class="acl-roles">
<div class="acl-roles-header">
<a-button @click="handleCreate" type="primary">{{ btnName }}</a-button>
<a-input-search
class="ops-input"
@ -18,19 +18,17 @@
<a-checkbox :checked="is_all" @click="handleClickBoxChange">所有角色</a-checkbox>
</div>
<a-spin :spinning="loading">
<vxe-table
<ops-table
stripe
class="ops-stripe-table"
size="mini"
size="small"
resizable
:data="tableData"
:max-height="`${windowHeight - 185}px`"
:height="`${windowHeight - 200}px`"
highlight-hover-row
min-height="300px"
:filter-config="{ remote: true }"
@filter-change="filterTableMethod"
>
<vxe-table-column
field="name"
title="角色名"
@ -57,65 +55,57 @@
<vxe-table-column
field="uid"
title="虚拟角色"
:min-width="100"
:width="100"
align="center"
:filters="[
{ label: '是', value: 1 },
{ label: '否', value: 0 },
]"
:filterMultiple="false"
:filter-method="({ value, row }) => {
return value === !row.uid
}">
:filter-method="
({ value, row }) => {
return value === !row.uid
}
"
>
<template #default="{row}">
{{ row.uid ? '否' : '是' }}
</template>
</vxe-table-column>
<vxe-table-column field="action" title="操作" :min-width="150" fixed="right">
<vxe-table-column field="action" title="操作" :width="120" fixed="right">
<template #default="{row}">
<div style="width:300px">
<span>
<a-tooltip title="资源列表">
<a
v-if="$route.name !== 'acl_roles'"
@click="handleDisplayUserResource(row)"
><a-icon
type="file-search"
/></a>
</a-tooltip>
<a-divider type="vertical" />
<div v-if="!row.uid" style="display: inline-block">
<a-tooltip
title="用户列表"
><a @click="handleDisplayUserUnderRole(row)"><a-icon type="team"/></a
></a-tooltip>
<a-divider type="vertical" />
</div>
<a @click="handleEdit(row)"><a-icon type="edit"/></a>
<a-divider type="vertical" />
<a-popconfirm title="确认删除?" @confirm="handleDelete(row)" @cancel="cancel" okText="是" cancelText="否">
<a style="color: red"><a-icon type="delete"/></a>
</a-popconfirm>
</span>
</div>
<a-space>
<a-tooltip title="资源列表">
<a
v-if="$route.name !== 'acl_roles'"
@click="handleDisplayUserResource(row)"
><a-icon
type="file-search"
/></a>
</a-tooltip>
<a-tooltip
title="用户列表"
v-if="!row.uid"
><a @click="handleDisplayUserUnderRole(row)"><a-icon type="team"/></a
></a-tooltip>
<a @click="handleEdit(row)"><a-icon type="edit"/></a>
<a-popconfirm title="确认删除?" @confirm="handleDelete(row)" @cancel="cancel" okText="是" cancelText="否">
<a style="color: red"><a-icon type="delete"/></a>
</a-popconfirm>
</a-space>
</template>
</vxe-table-column>
<template slot="empty">
<img :src="require(`@/assets/data_empty.png`)" />
<p style="font-size: 14px; line-height: 17px; color: rgba(0, 0, 0, 0.6)">暂无数据</p>
</template>
</vxe-table>
</ops-table>
<vxe-pager
size="mini"
size="small"
:layouts="['Total', 'PrevPage', 'JumpNumber', 'NextPage', 'Sizes']"
:current-page.sync="tablePage.currentPage"
:page-size.sync="tablePage.pageSize"
:total="tablePage.total"
:page-sizes="pageSizeOptions"
@page-change="handlePageChange"
:style="{ marginTop: '10px' }"
>
</vxe-pager>
</a-spin>
@ -336,10 +326,13 @@ export default {
</script>
<style lang="less">
.acl-role {
.acl-roles {
border-radius: 15px;
background-color: #fff;
height: calc(100vh - 64px);
margin-bottom: -24px;
padding: 24px;
.roles-action-btn {
.acl-roles-header {
width: 100%;
display: inline-flex;
margin-bottom: 15px;

View File

@ -91,6 +91,8 @@ export default {
.acl-secret-key {
background-color: #fff;
padding: 24px;
border-radius: 15px;
height: calc(100% + 24px);
.ant-input[disabled] {
color: rgba(0, 0, 0, 0.5);
}

View File

@ -1,6 +1,6 @@
<template>
<div :style="{ backgroundColor: '#fff', padding: '24px' }">
<div class="trigger-action-btn">
<div class="acl-trigger">
<div class="acl-trigger-header">
<a-button type="primary" @click="handleCreateTrigger">新增触发器</a-button>
<a-input-search
class="ops-input"
@ -14,7 +14,7 @@
<vxe-grid
stripe
size="mini"
size="small"
class="ops-stripe-table"
:columns="tableColumns"
:data="filterTriggers"
@ -65,8 +65,10 @@
</a-space>
</template>
<template slot="empty">
<img :src="require(`@/assets/data_empty.png`)" />
<p style="font-size: 14px; line-height: 17px; color: rgba(0, 0, 0, 0.6)">暂无数据</p>
<div>
<img :style="{ width: '100px' }" :src="require('@/assets/data_empty.png')" />
<div>暂无数据</div>
</div>
</template>
</vxe-grid>
<trigger-form
@ -188,7 +190,7 @@ export default {
{
title: '操作',
field: 'action',
minWidth: '200px',
width: '120px',
fixed: 'right',
slots: {
default: 'action_default',
@ -317,10 +319,17 @@ export default {
}
</script>
<style lang="less" scoped>
.trigger-action-btn {
width: 100%;
display: inline-flex;
margin-bottom: 15px;
align-items: center;
.acl-trigger {
border-radius: 15px;
background-color: #fff;
height: calc(100vh - 64px);
margin-bottom: -24px;
padding: 24px;
.acl-trigger-header {
width: 100%;
display: inline-flex;
margin-bottom: 15px;
align-items: center;
}
}
</style>

View File

@ -1,8 +1,9 @@
<template>
<a-card :bordered="false">
<div class="user-action-btn">
<div class="acl-users">
<div class="acl-users-header">
<a-button v-if="isAclAdmin" @click="handleCreate" type="primary">{{ btnName }}</a-button>
<a-input-search
class="ops-input"
allowClear
:style="{ display: 'inline', marginLeft: '10px' }"
placeholder="搜索 | 用户名、中文名"
@ -10,7 +11,15 @@
></a-input-search>
</div>
<a-spin :spinning="loading">
<vxe-grid :columns="tableColumns" :data="tableData" highlight-hover-row :max-height="`${windowHeight - 185}px`">
<vxe-grid
stripe
class="ops-stripe-table"
:columns="tableColumns"
:data="tableData"
highlight-hover-row
:height="`${windowHeight - 165}px`"
size="small"
>
<template #block_default="{row}">
<a-icon type="lock" v-if="row.block" />
</template>
@ -29,7 +38,7 @@
</a-spin>
<userForm ref="userForm" :handleOk="handleOk"> </userForm>
<perm-collect-form ref="permCollectForm"></perm-collect-form>
</a-card>
</div>
</template>
<script>
@ -95,30 +104,46 @@ export default {
},
async beforeMount() {
this.loading = true
await getOnDutyUser().then(res => {
this.onDutuUids = res.map(i => i.uid)
await getOnDutyUser().then((res) => {
this.onDutuUids = res.map((i) => i.uid)
this.search()
})
},
computed: {
...mapState({
windowHeight: state => state.windowHeight,
windowHeight: (state) => state.windowHeight,
}),
isAclAdmin: function() {
if (this.$store.state.user.roles.permissions.filter(item => item === 'acl_admin').length > 0) {
if (this.$store.state.user.roles.permissions.filter((item) => item === 'acl_admin').length > 0) {
return true
} else {
return false
}
},
},
watch: {
searchName: {
immediate: true,
handler(newVal, oldVal) {
if (newVal) {
this.tableData = this.allUsers.filter(
(item) =>
item.username.toLowerCase().includes(newVal.toLowerCase()) ||
item.nickname.toLowerCase().includes(newVal.toLowerCase())
)
} else {
this.tableData = this.allUsers
}
},
},
},
mounted() {},
inject: ['reload'],
methods: {
search() {
searchUser({ page_size: 10000 }).then(res => {
const ret = res.users.filter(u => this.onDutuUids.includes(u.uid))
searchUser({ page_size: 10000 }).then((res) => {
const ret = res.users.filter((u) => this.onDutuUids.includes(u.uid))
this.allUsers = ret
this.tableData = ret
this.loading = false
@ -137,45 +162,29 @@ export default {
this.searchName = ''
this.search()
},
handleCreate() {
this.$refs.userForm.handleCreate()
},
deleteUser(attrId) {
deleteUserById(attrId).then(res => {
deleteUserById(attrId).then((res) => {
this.$message.success(`删除成功`)
this.handleOk()
})
// .catch(err => this.requestFailed(err))
},
// requestFailed(err) {
// const msg = ((err.response || {}).data || {}).message || ''
// this.$message.error(`${msg}`)
// },
},
watch: {
searchName: {
immediate: true,
handler(newVal, oldVal) {
if (newVal) {
this.tableData = this.allUsers.filter(
item =>
item.username.toLowerCase().includes(newVal.toLowerCase()) ||
item.nickname.toLowerCase().includes(newVal.toLowerCase())
)
} else {
this.tableData = this.allUsers
}
},
},
},
}
</script>
<style lang="less" scoped>
.user-action-btn {
display: inline-flex;
margin-bottom: 15px;
.acl-users {
border-radius: 15px;
background-color: #fff;
height: calc(100vh - 64px);
margin-bottom: -24px;
padding: 24px;
.acl-users-header {
display: inline-flex;
margin-bottom: 15px;
}
}
</style>