初始版本提交
This commit is contained in:
355
src/views/system/role/components/AppAuthModal.vue
Normal file
355
src/views/system/role/components/AppAuthModal.vue
Normal file
@ -0,0 +1,355 @@
|
||||
<template>
|
||||
<BasicModal
|
||||
wrapClassName="autherizeDialog"
|
||||
v-bind="$attrs"
|
||||
@register="registerRoleAuthModal"
|
||||
:title="t('APP功能授权')"
|
||||
destroy-on-close
|
||||
@ok="handleSubmit"
|
||||
width="90%"
|
||||
>
|
||||
<a-row :gutter="[16, 16]" class="h-full">
|
||||
<a-col :span="6">
|
||||
<div class="text-base border-l-6 border-[#5e95ff] pl-3 h-5 leading-5 mb-3 ml-2">{{
|
||||
t('系统功能')
|
||||
}}</div>
|
||||
<div class="treebox">
|
||||
<BasicTree
|
||||
:treeData="treeData"
|
||||
checkable
|
||||
ref="treeRef"
|
||||
@check="handleTreeSelect"
|
||||
:fieldNames="{ title: 'name', key: 'id' }"
|
||||
/>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<div class="text-base border-l-6 border-[#5e95ff] pl-3 h-5 leading-5 mb-3 ml-2">{{
|
||||
t('按钮权限')
|
||||
}}</div>
|
||||
<div class="treebox">
|
||||
<BasicTree
|
||||
:treeData="buttonSelectData"
|
||||
checkable
|
||||
ref="ButtonRef"
|
||||
@check="handleButtonSelect"
|
||||
:fieldNames="{ title: 'name', key: 'id' }"
|
||||
/>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<div class="text-base border-l-6 border-[#5e95ff] pl-3 h-5 leading-5 mb-3 ml-2">{{
|
||||
t('字段权限')
|
||||
}}</div>
|
||||
<div class="treebox">
|
||||
<BasicTree
|
||||
:treeData="columnSelectData"
|
||||
checkable
|
||||
ref="ColumnRef"
|
||||
@check="handleColumnSelect"
|
||||
:fieldNames="{ title: 'name', key: 'id' }"
|
||||
/>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<div class="text-base border-l-6 border-[#5e95ff] pl-3 h-5 leading-5 mb-3 ml-2">{{
|
||||
t('表单权限')
|
||||
}}</div>
|
||||
<div class="treebox">
|
||||
<BasicTree
|
||||
:treeData="fieldSelectData"
|
||||
checkable
|
||||
ref="FieldRef"
|
||||
@check="handleFieldSelect"
|
||||
:fieldNames="{ title: 'name', key: 'id' }"
|
||||
/>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</BasicModal>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, unref, nextTick } from 'vue';
|
||||
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import { TreeItem, BasicTree, TreeActionType } from '/@/components/Tree';
|
||||
import { RoleSetAppAuth, getAppMenuAuth, getAppMenu } from '/@/api/system/role';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
|
||||
import {
|
||||
getAppMenuButtonList,
|
||||
getAppMenuColumnList,
|
||||
getAppMenuFieldList,
|
||||
} from '/@/api/system/menuButton';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SelectUserModal',
|
||||
components: { BasicModal, BasicTree },
|
||||
emits: ['success', 'register'],
|
||||
setup(_, { emit }) {
|
||||
const { notification } = useMessage();
|
||||
const { t } = useI18n();
|
||||
const treeRef = ref<Nullable<TreeActionType>>(null);
|
||||
const ButtonRef = ref<Nullable<TreeActionType>>(null);
|
||||
const ColumnRef = ref<Nullable<TreeActionType>>(null);
|
||||
const FieldRef = ref<Nullable<TreeActionType>>(null);
|
||||
const treeData = ref<TreeItem[]>([]);
|
||||
const buttonData = ref<TreeItem[]>([]);
|
||||
const columnData = ref<TreeItem[]>([]);
|
||||
const fieldData = ref<TreeItem[]>([]);
|
||||
|
||||
const buttonSelectData = ref<TreeItem[]>([]);
|
||||
const columnSelectData = ref<TreeItem[]>([]);
|
||||
const fieldSelectData = ref<TreeItem[]>([]);
|
||||
const btnKeys = ref<string[]>([]);
|
||||
const colKeys = ref<string[]>([]);
|
||||
const menuKeys = ref<string[]>([]);
|
||||
const fieldKeys = ref<string[]>([]);
|
||||
|
||||
const btnFilterKeys = ref<string[]>([]);
|
||||
const colFilterKeys = ref<string[]>([]);
|
||||
const fieldFilterKeys = ref<string[]>([]);
|
||||
|
||||
const rowId = ref('');
|
||||
|
||||
function getTree(tree) {
|
||||
if (!tree) {
|
||||
return null;
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
const [registerRoleAuthModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
setModalProps({ confirmLoading: false });
|
||||
rowId.value = data.id;
|
||||
treeData.value = await getAppMenu();
|
||||
|
||||
buttonData.value = await getAppMenuButtonList();
|
||||
columnData.value = await getAppMenuColumnList();
|
||||
fieldData.value = await getAppMenuFieldList();
|
||||
|
||||
const authList = await getAppMenuAuth(rowId.value);
|
||||
menuKeys.value = authList.menuIds || [];
|
||||
btnKeys.value = authList.buttonIds || [];
|
||||
colKeys.value = authList.columnIds || [];
|
||||
fieldKeys.value = authList.formIds || [];
|
||||
let menuCheckedKey = [];
|
||||
let btnCheckedKey = [];
|
||||
let colCheckedKey = [];
|
||||
let fieldCheckedKey = [];
|
||||
menuKeys.value.forEach((o) => {
|
||||
getParentKeys(menuCheckedKey, treeData.value, o);
|
||||
});
|
||||
menuKeys.value = menuCheckedKey;
|
||||
getTree(unref(treeRef)).setCheckedKeys(authList.menuIds);
|
||||
initTree(menuCheckedKey);
|
||||
|
||||
btnKeys.value.forEach((o) => {
|
||||
getParentKeys(btnCheckedKey, buttonSelectData.value, o);
|
||||
});
|
||||
btnKeys.value = btnCheckedKey;
|
||||
colKeys.value.forEach((o) => {
|
||||
getParentKeys(colCheckedKey, columnSelectData.value, o);
|
||||
});
|
||||
colKeys.value = colCheckedKey;
|
||||
|
||||
fieldKeys.value.forEach((o) => {
|
||||
getParentKeys(fieldCheckedKey, fieldSelectData.value, o);
|
||||
});
|
||||
fieldKeys.value = fieldCheckedKey;
|
||||
|
||||
nextTick(() => {
|
||||
getTree(unref(ButtonRef))?.setCheckedKeys(authList.buttonIds);
|
||||
getTree(unref(ColumnRef))?.setCheckedKeys(authList.columnIds);
|
||||
getTree(unref(FieldRef))?.setCheckedKeys(authList.formIds);
|
||||
getTree(unref(ButtonRef)).expandAll(true);
|
||||
getTree(unref(ColumnRef)).expandAll(true);
|
||||
getTree(unref(FieldRef)).expandAll(true);
|
||||
});
|
||||
|
||||
getTree(unref(treeRef)).expandAll(true);
|
||||
});
|
||||
|
||||
async function handleSubmit() {
|
||||
try {
|
||||
setModalProps({ confirmLoading: true });
|
||||
|
||||
await RoleSetAppAuth({
|
||||
id: rowId.value,
|
||||
menuIds: menuKeys.value,
|
||||
buttonIds: btnKeys.value,
|
||||
columnIds: colKeys.value,
|
||||
formIds: fieldKeys.value,
|
||||
});
|
||||
notification.success({
|
||||
message: t('提示'),
|
||||
description: t('功能授权更新成功'),
|
||||
}); //提示消息
|
||||
closeModal();
|
||||
emit('success');
|
||||
} catch (error) {
|
||||
setModalProps({ confirmLoading: false });
|
||||
}
|
||||
}
|
||||
function handleButtonSelect(keys, e) {
|
||||
btnKeys.value = [...e.halfCheckedKeys, ...keys];
|
||||
}
|
||||
function handleColumnSelect(keys, e) {
|
||||
colKeys.value = [...e.halfCheckedKeys, ...keys];
|
||||
}
|
||||
function handleFieldSelect(keys, e) {
|
||||
fieldKeys.value = [...e.halfCheckedKeys, ...keys];
|
||||
}
|
||||
function handleTreeSelect(keys, e) {
|
||||
//keys 所有全选中的key
|
||||
//e.halfCheckedKeys 所有半选中的
|
||||
|
||||
//如果没有半选 就证明全部全选 直接使用keys
|
||||
//如果有半选需要 使用keys + e.halfCheckedKeys
|
||||
|
||||
const menuSelect: string[] = [...e.halfCheckedKeys, ...keys];
|
||||
|
||||
initTree(menuSelect);
|
||||
|
||||
menuKeys.value = menuSelect;
|
||||
}
|
||||
function initTree(menuSelect) {
|
||||
buttonSelectData.value = [];
|
||||
columnSelectData.value = [];
|
||||
fieldSelectData.value = [];
|
||||
|
||||
btnFilterKeys.value = [];
|
||||
colFilterKeys.value = [];
|
||||
fieldFilterKeys.value = [];
|
||||
|
||||
findMenuTree(buttonSelectData.value, treeData.value, menuSelect, 'button');
|
||||
findMenuTree(columnSelectData.value, treeData.value, menuSelect, 'column');
|
||||
findMenuTree(fieldSelectData.value, treeData.value, menuSelect, 'field');
|
||||
|
||||
getTree(unref(ButtonRef))?.setExpandedKeys(menuSelect);
|
||||
getTree(unref(ColumnRef))?.setExpandedKeys(menuSelect);
|
||||
getTree(unref(FieldRef))?.setExpandedKeys(menuSelect);
|
||||
}
|
||||
function getParentKeys(checkedKey, arr, keys) {
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
let o = arr[i];
|
||||
if (o.id == keys) {
|
||||
checkedKey.push(o.id);
|
||||
if (o.categoryId > 0 && !checkedKey.includes(o.categoryId)) {
|
||||
checkedKey.push(o.categoryId);
|
||||
}
|
||||
}
|
||||
if (o.children?.length > 0) {
|
||||
getParentKeys(checkedKey, o.children, keys);
|
||||
}
|
||||
}
|
||||
}
|
||||
function findMenuTree(menuSelectTree, treeData, keys, type) {
|
||||
for (let i = 0; i < treeData.length; i++) {
|
||||
let o = cloneDeep(treeData[i]);
|
||||
if (keys.includes(o.id)) {
|
||||
o.children = [];
|
||||
menuSelectTree.push(o);
|
||||
if (treeData[i].children?.length > 0) {
|
||||
findMenuTree(o.children, treeData[i].children, keys, type);
|
||||
} else {
|
||||
let list =
|
||||
type == 'button'
|
||||
? buttonData.value
|
||||
: type == 'column'
|
||||
? columnData.value
|
||||
: fieldData.value;
|
||||
o.children = getAuthData(list, o.id, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function getAuthData(list, id, type) {
|
||||
let arr: TreeItem[] = [];
|
||||
|
||||
arr = list.filter((o) => {
|
||||
return o.menuId == id;
|
||||
});
|
||||
|
||||
arr.forEach((o) => {
|
||||
o.categoryId = o.menuId;
|
||||
if (type == 'button') {
|
||||
btnFilterKeys.value.push(o.id);
|
||||
} else if (type == 'column') {
|
||||
colFilterKeys.value.push(o.id);
|
||||
} else {
|
||||
if (o.children && o.children.length > 0) {
|
||||
o.children?.forEach((k) => {
|
||||
fieldFilterKeys.value.push(k.id);
|
||||
});
|
||||
}
|
||||
fieldFilterKeys.value.push(o.id);
|
||||
}
|
||||
});
|
||||
return arr;
|
||||
}
|
||||
|
||||
return {
|
||||
registerRoleAuthModal,
|
||||
handleSubmit,
|
||||
handleTreeSelect,
|
||||
handleButtonSelect,
|
||||
handleColumnSelect,
|
||||
handleFieldSelect,
|
||||
menuKeys,
|
||||
treeData,
|
||||
treeRef,
|
||||
ButtonRef,
|
||||
FieldRef,
|
||||
ColumnRef,
|
||||
buttonSelectData,
|
||||
columnSelectData,
|
||||
fieldSelectData,
|
||||
t,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="less">
|
||||
.autherizeDialog {
|
||||
.ant-modal {
|
||||
top: 20px;
|
||||
height: calc(100% - 40px) !important;
|
||||
|
||||
.ant-modal-content {
|
||||
height: 100%;
|
||||
|
||||
.ant-modal-body {
|
||||
height: calc(100% - 120px) !important;
|
||||
|
||||
.scrollbar__view {
|
||||
height: 100%;
|
||||
|
||||
& > div {
|
||||
height: 100%;
|
||||
max-height: none !important;
|
||||
|
||||
.ant-col {
|
||||
height: 100%;
|
||||
|
||||
.treebox {
|
||||
height: calc(100% - 42px);
|
||||
overflow: auto;
|
||||
padding-right: 15px;
|
||||
margin-bottom: 10px;
|
||||
border-right: solid 1px #ccc;
|
||||
|
||||
.vben-tree {
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
162
src/views/system/role/components/HomeList.vue
Normal file
162
src/views/system/role/components/HomeList.vue
Normal file
@ -0,0 +1,162 @@
|
||||
<template>
|
||||
<PageLayout
|
||||
:hasOperationSlot="false"
|
||||
:searchConfig="searchConfig"
|
||||
@search="search"
|
||||
@scroll-height="scrollHeight"
|
||||
>
|
||||
<template #search> </template>
|
||||
<template #right>
|
||||
<div v-if="data.dataSource.length > 0">
|
||||
<a-row
|
||||
:gutter="16"
|
||||
class="list-box"
|
||||
:style="{ overflowY: 'auto', maxHeight: tableOptions.scrollHeight + 70 + 'px' }"
|
||||
:key="data.renderKey"
|
||||
>
|
||||
<a-col :span="6" class="item" v-for="(item, index) in data.dataSource" :key="index">
|
||||
<div class="image"><img :src="item.backgroundUrl" /></div>
|
||||
|
||||
<div class="main">
|
||||
<a-checkbox v-model:checked="item.checked" @change="handleCheck(item)">{{
|
||||
item.name
|
||||
}}</a-checkbox>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<div class="page-box">
|
||||
<a-pagination
|
||||
v-model:current="data.pagination.current"
|
||||
:pageSize="data.pagination.pageSize"
|
||||
:total="data.pagination.total"
|
||||
show-less-items
|
||||
@change="getList"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<EmptyBox />
|
||||
</div>
|
||||
</template>
|
||||
</PageLayout>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, reactive, watch } from 'vue';
|
||||
|
||||
import { DesktopAuthPage } from '/@/api/desktop/model';
|
||||
import { PageLayout, EmptyBox } from '/@/components/ModalPanel';
|
||||
import userTableScrollHeight from '/@/hooks/setting/userTableScrollHeight';
|
||||
|
||||
import { getRolePageList } from '/@/api/desktop';
|
||||
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
const props = defineProps({
|
||||
checkedIds: { type: Array as PropType<String[]> },
|
||||
});
|
||||
const { t } = useI18n();
|
||||
const emit = defineEmits(['checked']);
|
||||
watch(
|
||||
() => props.checkedIds,
|
||||
() => {
|
||||
checkItems();
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
const searchConfig = [
|
||||
{
|
||||
field: 'keyword',
|
||||
label: t('关键字'),
|
||||
type: 'input',
|
||||
},
|
||||
];
|
||||
const { tableOptions, scrollHeight } = userTableScrollHeight();
|
||||
let data: {
|
||||
dataSource: Array<DesktopAuthPage>;
|
||||
renderKey: number;
|
||||
keyword: string;
|
||||
pagination: {
|
||||
current: number;
|
||||
total: number;
|
||||
pageSize: number;
|
||||
};
|
||||
} = reactive({
|
||||
dataSource: [],
|
||||
renderKey: 0,
|
||||
pagination: { current: 1, total: 0, pageSize: 8 },
|
||||
keyword: '',
|
||||
});
|
||||
onMounted(() => {
|
||||
data.pagination.current = 1;
|
||||
data.dataSource = [];
|
||||
getList();
|
||||
});
|
||||
async function getList() {
|
||||
let params = {
|
||||
limit: data.pagination.current,
|
||||
size: data.pagination.pageSize,
|
||||
keyword: data.keyword,
|
||||
};
|
||||
let res = await getRolePageList(params);
|
||||
data.dataSource = res.list;
|
||||
data.pagination.total = res.total;
|
||||
data.renderKey++;
|
||||
checkItems();
|
||||
}
|
||||
function checkItems() {
|
||||
data.dataSource.forEach((o) => {
|
||||
o.checked = false;
|
||||
if (props.checkedIds?.includes(o.id)) {
|
||||
o.checked = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
function search(params?: any) {
|
||||
data.keyword = params.keyword;
|
||||
data.pagination.current = 1;
|
||||
data.dataSource = [];
|
||||
getList();
|
||||
}
|
||||
function handleCheck(item) {
|
||||
emit('checked', item);
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.list-box {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: 10px -8px;
|
||||
|
||||
.ant-row {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.item {
|
||||
position: relative;
|
||||
margin-bottom: 16px;
|
||||
overflow: hidden;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.image {
|
||||
width: 100%;
|
||||
height: 140px;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.main {
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.page-box {
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
}
|
||||
</style>
|
||||
174
src/views/system/role/components/HomeModal.vue
Normal file
174
src/views/system/role/components/HomeModal.vue
Normal file
@ -0,0 +1,174 @@
|
||||
<template>
|
||||
<BasicModal
|
||||
v-bind="$attrs"
|
||||
destroy-on-close
|
||||
@register="registerModal"
|
||||
:title="t('首页授权')"
|
||||
width="1100px"
|
||||
@ok="handleSubmit"
|
||||
>
|
||||
<a-tabs v-model:activeKey="activeKey">
|
||||
<a-tab-pane key="1" :tab="t('首页列表')">
|
||||
<div class="-mx-8px -mt-10px" v-if="activeKey == '1'"
|
||||
><HomeList @checked="handleChange" :checkedIds="checkedIds"
|
||||
/></div>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2" :tab="t('已选择')">
|
||||
<div class="-mx-8px -mt-16px">
|
||||
<PageLayout
|
||||
:hasOperationSlot="false"
|
||||
:hasSearchSlot="false"
|
||||
@scroll-height="scrollHeight"
|
||||
>
|
||||
<template #right>
|
||||
<div v-if="dataSource.length > 0">
|
||||
<a-row
|
||||
:gutter="16"
|
||||
class="list-box"
|
||||
:style="{ overflowY: 'auto', maxHeight: tableOptions.scrollHeight + 70 + 'px' }"
|
||||
>
|
||||
<a-col :span="6" class="item" v-for="(item, index) in dataSource" :key="index">
|
||||
<div class="image"><img :src="item.backgroundUrl" /></div>
|
||||
|
||||
<div class="main">
|
||||
<a-checkbox v-model:checked="item.checked" @change="handleChecked(item)">{{
|
||||
item.name
|
||||
}}</a-checkbox>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
<div v-else>
|
||||
<EmptyBox />
|
||||
</div>
|
||||
</template>
|
||||
</PageLayout>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</BasicModal>
|
||||
</template>
|
||||
<script lang="tsx" setup>
|
||||
import { ref } from 'vue';
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import HomeList from './HomeList.vue';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { PageLayout, EmptyBox } from '/@/components/ModalPanel';
|
||||
import { addRoleHomeAuth, getRoleHomeAuth } from '/@/api/system/role';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import userTableScrollHeight from '/@/hooks/setting/userTableScrollHeight';
|
||||
|
||||
import { DesktopAuthPage } from '/@/api/desktop/model';
|
||||
|
||||
const { t } = useI18n();
|
||||
const activeKey = ref('1');
|
||||
const emit = defineEmits(['success', 'register']);
|
||||
const { tableOptions, scrollHeight } = userTableScrollHeight();
|
||||
|
||||
const dataSource = ref<DesktopAuthPage[]>([]);
|
||||
const { notification } = useMessage();
|
||||
const checkedIds = ref<string[]>([]);
|
||||
const rowId = ref();
|
||||
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
setModalProps({ confirmLoading: false });
|
||||
activeKey.value = '1';
|
||||
rowId.value = data.id;
|
||||
let res = await getRoleHomeAuth(data.id);
|
||||
dataSource.value = [];
|
||||
checkedIds.value = [];
|
||||
if (res) {
|
||||
res.forEach((o) => {
|
||||
o.checked = true;
|
||||
dataSource.value.push(o);
|
||||
checkedIds.value.push(o.id);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
async function handleSubmit() {
|
||||
try {
|
||||
setModalProps({ confirmLoading: true });
|
||||
let ids: string[] = [];
|
||||
dataSource.value.forEach((o) => {
|
||||
ids.push(o.id);
|
||||
});
|
||||
await addRoleHomeAuth(rowId.value, ids);
|
||||
notification.success({
|
||||
message: t('首页授权成功'),
|
||||
description: t('成功'),
|
||||
}); //提示消息
|
||||
|
||||
closeModal();
|
||||
emit('success');
|
||||
} finally {
|
||||
setModalProps({ confirmLoading: false });
|
||||
}
|
||||
}
|
||||
|
||||
function handleChange(v) {
|
||||
if (v.checked) {
|
||||
let obj = dataSource.value.find((o) => {
|
||||
return o.id == v.id;
|
||||
});
|
||||
if (!obj) {
|
||||
dataSource.value.push(v);
|
||||
}
|
||||
} else {
|
||||
let idx = dataSource.value.findIndex((o) => {
|
||||
return o.id == v.id;
|
||||
});
|
||||
if (idx >= 0) {
|
||||
dataSource.value.splice(idx, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
function handleChecked(v) {
|
||||
if (!v.checked) {
|
||||
let idx = dataSource.value.findIndex((o) => {
|
||||
return o.id == v.id;
|
||||
});
|
||||
if (idx >= 0) {
|
||||
dataSource.value.splice(idx, 1);
|
||||
}
|
||||
checkedIds.value = [];
|
||||
dataSource.value.forEach((o) => {
|
||||
checkedIds.value.push(o.id);
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.list-box {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: 10px -8px;
|
||||
|
||||
.ant-row {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.item {
|
||||
position: relative;
|
||||
margin-bottom: 16px;
|
||||
overflow: hidden;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.image {
|
||||
width: 100%;
|
||||
height: 140px;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.main {
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
419
src/views/system/role/components/RoleAuthModal.vue
Normal file
419
src/views/system/role/components/RoleAuthModal.vue
Normal file
@ -0,0 +1,419 @@
|
||||
<template>
|
||||
<BasicModal
|
||||
wrapClassName="autherizeDialog"
|
||||
v-bind="$attrs"
|
||||
@register="registerRoleAuthModal"
|
||||
:title="t('功能授权')"
|
||||
destroy-on-close
|
||||
@ok="handleSubmit"
|
||||
width="90%"
|
||||
>
|
||||
<a-row :gutter="[16, 16]" class="h-full">
|
||||
<a-col :span="6">
|
||||
<div class="text-base border-l-6 border-[#5e95ff] pl-3 h-5 leading-5 mb-3 ml-2">{{
|
||||
t('系统功能')
|
||||
}}</div>
|
||||
<div class="treebox">
|
||||
<BasicTree
|
||||
:treeData="treeData"
|
||||
checkable
|
||||
ref="treeRef"
|
||||
@check="handleTreeSelect"
|
||||
:fieldNames="{ title: 'title', key: 'id' }"
|
||||
>
|
||||
<template #title="{ title, systemName, parentId }">
|
||||
<div v-if="parentId == 0">{{ title }} 【{{ systemName }}】</div>
|
||||
<div v-else>{{ title }}</div>
|
||||
</template>
|
||||
</BasicTree>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<div class="text-base border-l-6 border-[#5e95ff] pl-3 h-5 leading-5 mb-3 ml-2">{{
|
||||
t('按钮权限')
|
||||
}}</div>
|
||||
<div class="treebox">
|
||||
<BasicTree
|
||||
:treeData="buttonSelectData"
|
||||
checkable
|
||||
ref="ButtonRef"
|
||||
@check="handleButtonSelect"
|
||||
:fieldNames="{ title: 'title', key: 'id' }"
|
||||
/>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<div class="text-base border-l-6 border-[#5e95ff] pl-3 h-5 leading-5 mb-3 ml-2">{{
|
||||
t('字段权限')
|
||||
}}</div>
|
||||
<div class="treebox">
|
||||
<BasicTree
|
||||
:treeData="columnSelectData"
|
||||
checkable
|
||||
ref="ColumnRef"
|
||||
@check="handleColumnSelect"
|
||||
:fieldNames="{ title: 'title', key: 'id' }"
|
||||
/>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<div class="text-base border-l-6 border-[#5e95ff] pl-3 h-5 leading-5 mb-3 ml-2">{{
|
||||
t('表单权限')
|
||||
}}</div>
|
||||
<div class="treebox">
|
||||
<BasicTree
|
||||
:treeData="fieldSelectData"
|
||||
checkable
|
||||
ref="FieldRef"
|
||||
@check="handleFieldSelect"
|
||||
:fieldNames="{ title: 'title', key: 'id' }"
|
||||
/>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</BasicModal>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, unref, nextTick } from 'vue';
|
||||
import { getMenuSimpleTree } from '/@/api/system/menu';
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import { TreeItem, BasicTree, TreeActionType } from '/@/components/Tree';
|
||||
import { getRoleAuth, RoleSetAuth } from '/@/api/system/role';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
|
||||
import { getMenuButtonList, getMenuColumnList, getMenuFieldList } from '/@/api/system/menuButton';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SelectUserModal',
|
||||
components: { BasicModal, BasicTree },
|
||||
emits: ['success', 'register'],
|
||||
setup(_, { emit }) {
|
||||
const { notification } = useMessage();
|
||||
const { t } = useI18n();
|
||||
const treeRef = ref<Nullable<TreeActionType>>(null);
|
||||
const ButtonRef = ref<Nullable<TreeActionType>>(null);
|
||||
const ColumnRef = ref<Nullable<TreeActionType>>(null);
|
||||
const FieldRef = ref<Nullable<TreeActionType>>(null);
|
||||
const treeData = ref<TreeItem[]>([]);
|
||||
const buttonData = ref<TreeItem[]>([]);
|
||||
const columnData = ref<TreeItem[]>([]);
|
||||
const fieldData = ref<TreeItem[]>([]);
|
||||
|
||||
const buttonSelectData = ref<TreeItem[]>([]);
|
||||
const columnSelectData = ref<TreeItem[]>([]);
|
||||
const fieldSelectData = ref<TreeItem[]>([]);
|
||||
const btnKeys = ref<string[]>([]);
|
||||
const colKeys = ref<string[]>([]);
|
||||
const menuKeys = ref<string[]>([]);
|
||||
const fieldKeys = ref<string[]>([]);
|
||||
|
||||
const btnFilterKeys = ref<string[]>([]);
|
||||
const colFilterKeys = ref<string[]>([]);
|
||||
const fieldFilterKeys = ref<string[]>([]);
|
||||
|
||||
const rowId = ref('');
|
||||
|
||||
function getTree(tree) {
|
||||
if (!tree) {
|
||||
return null;
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
const [registerRoleAuthModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
setModalProps({ confirmLoading: false });
|
||||
rowId.value = data.id;
|
||||
treeData.value = await getMenuSimpleTree();
|
||||
|
||||
buttonData.value = await getMenuButtonList();
|
||||
columnData.value = await getMenuColumnList();
|
||||
fieldData.value = await getMenuFieldList();
|
||||
|
||||
const authList = await getRoleAuth(rowId.value);
|
||||
menuKeys.value = authList.menuIds || [];
|
||||
btnKeys.value = authList.buttonIds || [];
|
||||
colKeys.value = authList.columnIds || [];
|
||||
fieldKeys.value = authList.formIds || [];
|
||||
let menuCheckedKey = [];
|
||||
let btnCheckedKey = [];
|
||||
let colCheckedKey = [];
|
||||
let fieldCheckedKey = [];
|
||||
menuKeys.value.forEach((o) => {
|
||||
getParentKeys(menuCheckedKey, treeData.value, o);
|
||||
});
|
||||
menuKeys.value = menuCheckedKey;
|
||||
getTree(unref(treeRef)).setCheckedKeys(authList.menuIds);
|
||||
initTree(menuCheckedKey);
|
||||
|
||||
btnKeys.value.forEach((o) => {
|
||||
getParentKeys(btnCheckedKey, buttonSelectData.value, o);
|
||||
});
|
||||
btnKeys.value = btnCheckedKey;
|
||||
colKeys.value.forEach((o) => {
|
||||
getParentKeys(colCheckedKey, columnSelectData.value, o);
|
||||
});
|
||||
colKeys.value = colCheckedKey;
|
||||
|
||||
fieldKeys.value.forEach((o) => {
|
||||
getParentKeys(fieldCheckedKey, fieldSelectData.value, o);
|
||||
});
|
||||
fieldKeys.value = fieldCheckedKey;
|
||||
|
||||
nextTick(() => {
|
||||
getTree(unref(ButtonRef))?.setCheckedKeys(authList.buttonIds);
|
||||
getTree(unref(ColumnRef))?.setCheckedKeys(authList.columnIds);
|
||||
getTree(unref(FieldRef))?.setCheckedKeys(authList.formIds);
|
||||
getTree(unref(ButtonRef)).expandAll(true);
|
||||
getTree(unref(ColumnRef)).expandAll(true);
|
||||
getTree(unref(FieldRef)).expandAll(true);
|
||||
});
|
||||
|
||||
getTree(unref(treeRef)).expandAll(true);
|
||||
});
|
||||
|
||||
async function handleSubmit() {
|
||||
try {
|
||||
setModalProps({ confirmLoading: true });
|
||||
|
||||
//由于树组件的原因,提交之前先过滤一遍,没有选中的不提交
|
||||
// btnKeys.value = getTree(unref(ButtonRef)).getCheckedKeys();
|
||||
// colKeys.value = getTree(unref(ColumnRef)).getCheckedKeys();
|
||||
// fieldKeys.value = getTree(unref(FieldRef)).getCheckedKeys();
|
||||
|
||||
// btnKeys.value = btnKeys.value.filter((o) => {
|
||||
// return btnFilterKeys.value.includes(o);
|
||||
// });
|
||||
// colKeys.value = colKeys.value.filter((o) => {
|
||||
// return colFilterKeys.value.includes(o);
|
||||
// });
|
||||
// fieldKeys.value = fieldKeys.value.filter((o) => {
|
||||
// return fieldFilterKeys.value.includes(o);
|
||||
// });
|
||||
|
||||
await RoleSetAuth({
|
||||
id: rowId.value,
|
||||
menuIds: menuKeys.value,
|
||||
buttonIds: btnKeys.value,
|
||||
columnIds: colKeys.value,
|
||||
formIds: fieldKeys.value,
|
||||
});
|
||||
notification.success({
|
||||
message: t('提示'),
|
||||
description: t('功能授权更新成功'),
|
||||
}); //提示消息
|
||||
closeModal();
|
||||
emit('success');
|
||||
} catch (error) {
|
||||
setModalProps({ confirmLoading: false });
|
||||
}
|
||||
}
|
||||
function handleButtonSelect(keys, e) {
|
||||
btnKeys.value = [...e.halfCheckedKeys, ...keys];
|
||||
}
|
||||
function handleColumnSelect(keys, e) {
|
||||
colKeys.value = [...e.halfCheckedKeys, ...keys];
|
||||
}
|
||||
function handleFieldSelect(keys, e) {
|
||||
fieldKeys.value = [...e.halfCheckedKeys, ...keys];
|
||||
}
|
||||
function handleTreeSelect(keys, e) {
|
||||
//keys 所有全选中的key
|
||||
//e.halfCheckedKeys 所有半选中的
|
||||
|
||||
//如果没有半选 就证明全部全选 直接使用keys
|
||||
//如果有半选需要 使用keys + e.halfCheckedKeys
|
||||
|
||||
const menuSelect: string[] = [...e.halfCheckedKeys, ...keys];
|
||||
|
||||
initTree(menuSelect);
|
||||
|
||||
menuKeys.value = menuSelect;
|
||||
}
|
||||
function initTree(menuSelect) {
|
||||
buttonSelectData.value = [];
|
||||
columnSelectData.value = [];
|
||||
fieldSelectData.value = [];
|
||||
|
||||
btnFilterKeys.value = [];
|
||||
colFilterKeys.value = [];
|
||||
fieldFilterKeys.value = [];
|
||||
|
||||
findMenuTree(buttonSelectData.value, treeData.value, menuSelect, 'button');
|
||||
findMenuTree(columnSelectData.value, treeData.value, menuSelect, 'column');
|
||||
findMenuTree(fieldSelectData.value, treeData.value, menuSelect, 'field');
|
||||
|
||||
getTree(unref(ButtonRef))?.setExpandedKeys(menuSelect);
|
||||
getTree(unref(ColumnRef))?.setExpandedKeys(menuSelect);
|
||||
getTree(unref(FieldRef))?.setExpandedKeys(menuSelect);
|
||||
}
|
||||
function getParentKeys(checkedKey, arr, keys) {
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
let o = arr[i];
|
||||
if (o.id == keys) {
|
||||
checkedKey.push(o.id);
|
||||
if (o.parentId > 0 && !checkedKey.includes(o.parentId)) {
|
||||
checkedKey.push(o.parentId);
|
||||
}
|
||||
}
|
||||
if (o.children?.length > 0) {
|
||||
getParentKeys(checkedKey, o.children, keys);
|
||||
}
|
||||
}
|
||||
}
|
||||
function findMenuTree(menuSelectTree, treeData, keys, type) {
|
||||
for (let i = 0; i < treeData.length; i++) {
|
||||
let o = cloneDeep(treeData[i]);
|
||||
if (keys.includes(o.id)) {
|
||||
o.children = [];
|
||||
menuSelectTree.push(o);
|
||||
if (treeData[i].children?.length > 0) {
|
||||
findMenuTree(o.children, treeData[i].children, keys, type);
|
||||
} else {
|
||||
let list =
|
||||
type == 'button'
|
||||
? buttonData.value
|
||||
: type == 'column'
|
||||
? columnData.value
|
||||
: fieldData.value;
|
||||
o.children = getAuthData(list, o.id, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function getAuthData(list, id, type) {
|
||||
let arr: TreeItem[] = [];
|
||||
|
||||
arr = list.filter((o) => {
|
||||
return o.menuId == id;
|
||||
});
|
||||
|
||||
arr.forEach((o) => {
|
||||
o.parentId = o.menuId;
|
||||
if (type == 'button') {
|
||||
btnFilterKeys.value.push(o.id);
|
||||
} else if (type == 'column') {
|
||||
colFilterKeys.value.push(o.id);
|
||||
} else {
|
||||
if (o.children && o.children.length > 0) {
|
||||
o.children?.forEach((k) => {
|
||||
fieldFilterKeys.value.push(k.id);
|
||||
});
|
||||
}
|
||||
fieldFilterKeys.value.push(o.id);
|
||||
}
|
||||
});
|
||||
return arr;
|
||||
}
|
||||
// function findMenuTree(menuTree, menuSelectTree, keys) {
|
||||
// let selected: any = {};
|
||||
// menuTree.forEach((key) => {
|
||||
// //找到node对象
|
||||
|
||||
// if (keys.includes(key.id)) {
|
||||
// console.log(key, 'kkkkkkkkkk');
|
||||
|
||||
// selected = cloneDeep(key);
|
||||
// if (key.children?.length > 0) {
|
||||
// selected.children = [];
|
||||
// findMenuTree(key.children, selected.children, keys);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// // let obj = menuSelectTree.find((o) => {
|
||||
// // return o.id == selected.id;
|
||||
// // });
|
||||
// // if (!obj) {
|
||||
// // menuSelectTree.push(selected);
|
||||
// // } else {
|
||||
// // obj.children = obj.children.concat(selected.children);
|
||||
// // }
|
||||
// checkChild(menuSelectTree, selected);
|
||||
// }
|
||||
// function checkChild(menuTree, selected) {
|
||||
// menuTree.forEach((o) => {
|
||||
// if (o.id == selected.parentId) {
|
||||
// o.children = o.children.concat(selected.children);
|
||||
// checkChild(o.children, selected);
|
||||
// } else {
|
||||
// menuTree.push(selected);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//将按钮塞入到菜单树
|
||||
// function menuInsertButton(menuTree, buttonList) {
|
||||
// menuTree.forEach((menu) => {
|
||||
// const thisMenuButton = buttonList.filter((btn) => btn.menuId === menu.id);
|
||||
// if (menu.children && menu.children.length > 0) {
|
||||
// menuInsertButton(menu.children, buttonList);
|
||||
// }
|
||||
|
||||
// // console.log('thisMenuButton', thisMenuButton);
|
||||
|
||||
// menu.children = menu.children?.concat(thisMenuButton);
|
||||
// });
|
||||
// }
|
||||
|
||||
return {
|
||||
registerRoleAuthModal,
|
||||
handleSubmit,
|
||||
handleTreeSelect,
|
||||
handleButtonSelect,
|
||||
handleColumnSelect,
|
||||
handleFieldSelect,
|
||||
menuKeys,
|
||||
treeData,
|
||||
treeRef,
|
||||
ButtonRef,
|
||||
FieldRef,
|
||||
ColumnRef,
|
||||
buttonSelectData,
|
||||
columnSelectData,
|
||||
fieldSelectData,
|
||||
t,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="less">
|
||||
.autherizeDialog {
|
||||
.ant-modal {
|
||||
top: 20px;
|
||||
height: calc(100% - 40px) !important;
|
||||
|
||||
.ant-modal-content {
|
||||
height: 100%;
|
||||
|
||||
.ant-modal-body {
|
||||
height: calc(100% - 120px) !important;
|
||||
|
||||
.scrollbar__view {
|
||||
height: 100%;
|
||||
|
||||
& > div {
|
||||
height: 100%;
|
||||
max-height: none !important;
|
||||
|
||||
.ant-col {
|
||||
height: 100%;
|
||||
|
||||
.treebox {
|
||||
height: calc(100% - 42px);
|
||||
overflow: auto;
|
||||
padding-right: 15px;
|
||||
margin-bottom: 10px;
|
||||
border-right: solid 1px #ccc;
|
||||
|
||||
.vben-tree {
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
117
src/views/system/role/components/RoleModal.vue
Normal file
117
src/views/system/role/components/RoleModal.vue
Normal file
@ -0,0 +1,117 @@
|
||||
<template>
|
||||
<BasicModal v-bind="$attrs" @register="registerModal" :title="getTitle" @ok="handleSubmit">
|
||||
<BasicForm @register="registerForm" :style="{ 'margin-right': '10px' }" />
|
||||
</BasicModal>
|
||||
</template>
|
||||
<script lang="tsx" setup>
|
||||
import { ref, computed, unref } from 'vue';
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import { BasicForm, useForm } from '/@/components/Form/index';
|
||||
import { FormSchema } from '/@/components/Table';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
|
||||
import { addRole, updateRole } from '/@/api/system/role';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
const { t } = useI18n();
|
||||
const formSchema: FormSchema[] = [
|
||||
{
|
||||
field: 'name',
|
||||
label: t('角色名称'),
|
||||
required: true,
|
||||
component: 'Input',
|
||||
colProps: { span: 24 },
|
||||
},
|
||||
{
|
||||
field: 'code',
|
||||
label: t('角色编码'),
|
||||
required: true,
|
||||
component: 'Input',
|
||||
colProps: { span: 24 },
|
||||
},
|
||||
{
|
||||
field: 'enabledMark',
|
||||
label: t('状态'),
|
||||
component: 'RadioButtonGroup',
|
||||
defaultValue: 1,
|
||||
componentProps: {
|
||||
options: [
|
||||
{ label: t('启用'), value: 1 },
|
||||
{ label: t('停用'), value: 0 },
|
||||
],
|
||||
},
|
||||
colProps: { span: 24 },
|
||||
},
|
||||
{
|
||||
label: t('备注'),
|
||||
field: 'remark',
|
||||
component: 'InputTextArea',
|
||||
colProps: { span: 24 },
|
||||
},
|
||||
{
|
||||
label: ' ',
|
||||
field: 'authList',
|
||||
slot: 'menu',
|
||||
component: 'Input',
|
||||
colProps: { span: 24 },
|
||||
},
|
||||
];
|
||||
|
||||
const emit = defineEmits(['success', 'register']);
|
||||
|
||||
const { notification } = useMessage();
|
||||
const isUpdate = ref(true);
|
||||
const rowId = ref('');
|
||||
|
||||
const [registerForm, { setFieldsValue, resetFields, validate }] = useForm({
|
||||
labelWidth: 100,
|
||||
schemas: formSchema,
|
||||
showActionButtonGroup: false,
|
||||
actionColOptions: {
|
||||
span: 23,
|
||||
},
|
||||
});
|
||||
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
resetFields();
|
||||
setModalProps({ confirmLoading: false });
|
||||
|
||||
isUpdate.value = !!data?.isUpdate;
|
||||
|
||||
if (unref(isUpdate)) {
|
||||
rowId.value = data.record.id;
|
||||
setFieldsValue({
|
||||
...data.record,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const getTitle = computed(() => (!unref(isUpdate) ? t('新增角色') : t('编辑角色')));
|
||||
|
||||
async function handleSubmit() {
|
||||
try {
|
||||
const values = await validate();
|
||||
|
||||
setModalProps({ confirmLoading: true });
|
||||
// TODO custom api
|
||||
if (!unref(isUpdate)) {
|
||||
//false 新增
|
||||
await addRole(values);
|
||||
notification.success({
|
||||
message: t('新增角色'),
|
||||
description: t('成功'),
|
||||
}); //提示消息
|
||||
} else {
|
||||
values.id = rowId.value;
|
||||
await updateRole(values);
|
||||
notification.success({
|
||||
message: t('编辑角色'),
|
||||
description: t('成功'),
|
||||
}); //提示消息
|
||||
}
|
||||
closeModal();
|
||||
emit('success');
|
||||
} finally {
|
||||
setModalProps({ confirmLoading: false });
|
||||
}
|
||||
}
|
||||
</script>
|
||||
104
src/views/system/role/components/SelectInterfaceModal.vue
Normal file
104
src/views/system/role/components/SelectInterfaceModal.vue
Normal file
@ -0,0 +1,104 @@
|
||||
<template>
|
||||
<BasicModal v-bind="$attrs" @register="registerSelectUserModal" @ok="handleSubmit" width="1000px">
|
||||
<BasicTable @register="registerTable" />
|
||||
</BasicModal>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
// import { getUserPageList } from '/@/api/system/user';
|
||||
import { useTable, FormSchema, BasicColumn, BasicTable } from '/@/components/Table';
|
||||
|
||||
import { getRoleInterfaceList } from '/@/api/system/role';
|
||||
import { getAllInterface } from '/@/api/system/interface';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
const { t } = useI18n();
|
||||
export const searchFormSchema: FormSchema[] = [
|
||||
{
|
||||
field: 'keyword',
|
||||
label: t('关键字'),
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: t('输入接口名称或接口地址搜索'),
|
||||
},
|
||||
colProps: { span: 8 },
|
||||
},
|
||||
];
|
||||
|
||||
export const columns: BasicColumn[] = [
|
||||
{
|
||||
title: t('名称'),
|
||||
dataIndex: 'name',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: t('接口地址'),
|
||||
dataIndex: 'path',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: t('请求类型'),
|
||||
dataIndex: 'method',
|
||||
width: 120,
|
||||
},
|
||||
];
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SelectInterfaceModal',
|
||||
components: { BasicModal, BasicTable },
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
emits: ['success', 'register'],
|
||||
setup(_, { emit }) {
|
||||
const roleId = ref<string>();
|
||||
const selectIds = ref<string[]>([]);
|
||||
const [registerTable, { setSelectedRowKeys, getSelectRowKeys }] = useTable({
|
||||
api: getAllInterface,
|
||||
rowKey: 'id',
|
||||
columns,
|
||||
formConfig: {
|
||||
rowProps: {
|
||||
gutter: 16,
|
||||
},
|
||||
schemas: searchFormSchema,
|
||||
},
|
||||
rowSelection: {
|
||||
type: 'checkbox',
|
||||
checkStrictly: false,
|
||||
},
|
||||
pagination: false,
|
||||
useSearchForm: true,
|
||||
showTableSetting: true,
|
||||
bordered: true,
|
||||
showIndexColumn: false,
|
||||
});
|
||||
|
||||
const [registerSelectUserModal, { setModalProps, closeModal }] = useModalInner(
|
||||
async (data) => {
|
||||
roleId.value = data.id;
|
||||
setModalProps({ confirmLoading: false, title: data.title });
|
||||
selectIds.value = await getRoleInterfaceList({ roleId: data.id });
|
||||
|
||||
setSelectedRowKeys(selectIds.value || []);
|
||||
},
|
||||
);
|
||||
|
||||
async function handleSubmit() {
|
||||
try {
|
||||
setModalProps({ confirmLoading: true });
|
||||
const selectRows = getSelectRowKeys();
|
||||
closeModal();
|
||||
emit('success', selectRows);
|
||||
} catch (error) {
|
||||
setModalProps({ confirmLoading: false });
|
||||
}
|
||||
}
|
||||
|
||||
return { registerSelectUserModal, registerTable, handleSubmit, t };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
404
src/views/system/role/index.vue
Normal file
404
src/views/system/role/index.vue
Normal file
@ -0,0 +1,404 @@
|
||||
<template>
|
||||
<PageWrapper dense fixedHeight contentFullHeight>
|
||||
<BasicTable @register="registerTable">
|
||||
<template #toolbar>
|
||||
<a-button type="primary" v-auth="'role:add'" @click="handleCreate">
|
||||
{{ t('新增角色') }}
|
||||
</a-button>
|
||||
|
||||
<a-button type="primary" v-auth="'role:addMember'" @click="handleAddUser">
|
||||
{{ t('添加成员') }}
|
||||
</a-button>
|
||||
|
||||
<a-button type="primary" v-auth="'role:view'" @click="handleViewUser">
|
||||
{{ t('查看成员') }}
|
||||
</a-button>
|
||||
<a-button type="primary" v-auth="'role:functionalAuth'" @click="handleAuth">
|
||||
{{ t('功能授权') }}
|
||||
</a-button>
|
||||
<a-button type="primary" v-auth="'role:functionalAuth'" @click="handleAppAuth">
|
||||
{{ t('移动端功能授权') }}
|
||||
</a-button>
|
||||
<a-button type="primary" v-auth="'role:interfaceAuth'" @click="handleInterfaceAuth">
|
||||
{{ t('接口授权') }}
|
||||
</a-button>
|
||||
<a-button type="primary" v-auth="'role:homeAuth'" @click="handleHomeAuth">
|
||||
{{ t('首页授权') }}
|
||||
</a-button>
|
||||
</template>
|
||||
<template #action="{ record }">
|
||||
<TableAction
|
||||
:actions="[
|
||||
{
|
||||
icon: 'clarity:note-edit-line',
|
||||
auth: 'role:edit',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
},
|
||||
{
|
||||
icon: 'ant-design:delete-outlined',
|
||||
auth: 'role:delete',
|
||||
color: 'error',
|
||||
popConfirm: {
|
||||
title: t('是否确认删除'),
|
||||
confirm: handleDelete.bind(null, record),
|
||||
},
|
||||
},
|
||||
]"
|
||||
/>
|
||||
</template>
|
||||
</BasicTable>
|
||||
<RoleModal @register="registerRoleModal" @success="handleSuccess" />
|
||||
<SelectInterfaceModal
|
||||
@register="registerInterfaceModal"
|
||||
@success="handleInterfaceSuccess"
|
||||
:minHeight="500"
|
||||
/>
|
||||
<RoleAuthModal
|
||||
@register="registerRoleAuthModal"
|
||||
@success="handleRoleAuthSuccess"
|
||||
:minHeight="500"
|
||||
/>
|
||||
<AppAuthModal @register="registerAppAuthModal" :minHeight="500" />
|
||||
<SelectDepartment
|
||||
v-if="visible"
|
||||
:visible="visible"
|
||||
:multiple="true"
|
||||
:selectedIds="selectedUserId"
|
||||
@close="
|
||||
() => {
|
||||
visible = false;
|
||||
}
|
||||
"
|
||||
@change="handleSelectUserSuccess"
|
||||
/>
|
||||
<AuthModal @register="registerModal" />
|
||||
|
||||
<HomeModal @register="registerHomeModal" @success="handleRoleAuthSuccess" :minHeight="500" />
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, h, ref } from 'vue';
|
||||
|
||||
import { BasicTable, useTable, TableAction, FormSchema, BasicColumn } from '/@/components/Table';
|
||||
import {
|
||||
getRolePageList,
|
||||
updateRoleStatus,
|
||||
deleteRole,
|
||||
addRoleUser,
|
||||
getRoleUser,
|
||||
addRoleInterface,
|
||||
} from '/@/api/system/role';
|
||||
import AuthModal from '../dataAuthority/components/AuthModal.vue';
|
||||
import HomeModal from './components/HomeModal.vue';
|
||||
import RoleModal from './components/RoleModal.vue';
|
||||
import SelectInterfaceModal from './components/SelectInterfaceModal.vue';
|
||||
import RoleAuthModal from './components/RoleAuthModal.vue';
|
||||
import AppAuthModal from './components/AppAuthModal.vue';
|
||||
import { SelectDepartment } from '/@/components/SelectOrganizational/index';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { Switch } from 'ant-design-vue';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
const { t } = useI18n();
|
||||
export const columns: BasicColumn[] = [
|
||||
{
|
||||
title: t('角色名称'),
|
||||
dataIndex: 'name',
|
||||
sorter: true,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('角色编码'),
|
||||
dataIndex: 'code',
|
||||
sorter: true,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('状态'),
|
||||
dataIndex: 'enabledMark',
|
||||
sorter: true,
|
||||
align: 'left',
|
||||
customRender: ({ record }) => {
|
||||
if (!Reflect.has(record, 'pendingStatus')) {
|
||||
record.pendingStatus = false;
|
||||
}
|
||||
return h(Switch, {
|
||||
checked: record.enabledMark === 1,
|
||||
checkedChildren: t('已启用'),
|
||||
unCheckedChildren: t('已禁用'),
|
||||
loading: record.pendingStatus,
|
||||
onChange(checked: boolean) {
|
||||
record.pendingStatus = true;
|
||||
const newStatus = checked ? 1 : 0;
|
||||
const { createMessage } = useMessage();
|
||||
updateRoleStatus(record.id, newStatus)
|
||||
.then(() => {
|
||||
record.enabledMark = newStatus;
|
||||
createMessage.success(t('已成功修改角色状态'));
|
||||
})
|
||||
.catch(() => {
|
||||
createMessage.error(t('修改角色状态失败'));
|
||||
})
|
||||
.finally(() => {
|
||||
record.pendingStatus = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('备注'),
|
||||
dataIndex: 'remark',
|
||||
sorter: true,
|
||||
align: 'left',
|
||||
},
|
||||
];
|
||||
|
||||
export const searchFormSchema: FormSchema[] = [
|
||||
{
|
||||
field: 'name',
|
||||
label: t('角色名称'),
|
||||
component: 'Input',
|
||||
colProps: { lg: 8, md: 12, sm: 12 },
|
||||
},
|
||||
{
|
||||
field: 'code',
|
||||
label: t('角色编码'),
|
||||
component: 'Input',
|
||||
colProps: { lg: 8, md: 12, sm: 12 },
|
||||
},
|
||||
{
|
||||
field: 'enabledMark',
|
||||
label: t('状态'),
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
options: [
|
||||
{ label: t('启用'), value: 1 },
|
||||
{ label: t('停用'), value: 0 },
|
||||
],
|
||||
},
|
||||
colProps: { lg: 8, md: 12, sm: 12 },
|
||||
},
|
||||
];
|
||||
|
||||
export default defineComponent({
|
||||
name: 'RoleManagement',
|
||||
components: {
|
||||
BasicTable,
|
||||
RoleModal,
|
||||
TableAction,
|
||||
RoleAuthModal,
|
||||
AuthModal,
|
||||
SelectDepartment,
|
||||
SelectInterfaceModal,
|
||||
PageWrapper,
|
||||
HomeModal,
|
||||
AppAuthModal,
|
||||
},
|
||||
setup() {
|
||||
const { notification } = useMessage();
|
||||
const visible = ref<boolean>(false);
|
||||
const selectedUserId = ref<string[]>([]);
|
||||
const [registerRoleAuthModal, { openModal: openRoleUserModal }] = useModal();
|
||||
const [registerAppAuthModal, { openModal: openAppAuthModal }] = useModal();
|
||||
const [registerInterfaceModal, { openModal: openInterfaceModal }] = useModal();
|
||||
const [registerModal, { openModal, setModalProps }] = useModal();
|
||||
const [registerRoleModal, { openModal: openRoleModal }] = useModal();
|
||||
const [registerHomeModal, { openModal: openHomeModal }] = useModal();
|
||||
const [registerTable, { reload, getSelectRows }] = useTable({
|
||||
title: t('角色列表'),
|
||||
api: getRolePageList,
|
||||
columns,
|
||||
formConfig: {
|
||||
rowProps: {
|
||||
gutter: 16,
|
||||
},
|
||||
schemas: searchFormSchema,
|
||||
actionColOptions: { span: 16 },
|
||||
showResetButton: false,
|
||||
},
|
||||
// clickToRowSelect:true,
|
||||
rowSelection: {
|
||||
type: 'radio',
|
||||
},
|
||||
useSearchForm: true,
|
||||
showTableSetting: true,
|
||||
striped: false,
|
||||
showIndexColumn: false,
|
||||
actionColumn: {
|
||||
width: 80,
|
||||
title: t('操作'),
|
||||
dataIndex: 'action',
|
||||
slots: { customRender: 'action' },
|
||||
fixed: undefined,
|
||||
},
|
||||
tableSetting: {
|
||||
size: false,
|
||||
setting: false,
|
||||
},
|
||||
});
|
||||
|
||||
function handleCreate() {
|
||||
openRoleModal(true, {
|
||||
isUpdate: false,
|
||||
});
|
||||
}
|
||||
function handleInterfaceAuth() {
|
||||
let res = warning(true);
|
||||
if (!res) {
|
||||
return;
|
||||
}
|
||||
openInterfaceModal(true, {
|
||||
isUpdate: false,
|
||||
title: t('接口授权') + ' - ' + res.name,
|
||||
id: res.id,
|
||||
});
|
||||
}
|
||||
function handleAuth() {
|
||||
let res = warning(true);
|
||||
if (!res) {
|
||||
return;
|
||||
}
|
||||
|
||||
openRoleUserModal(true, {
|
||||
id: res.id,
|
||||
});
|
||||
}
|
||||
function handleAppAuth() {
|
||||
let res = warning(true);
|
||||
if (!res) {
|
||||
return;
|
||||
}
|
||||
|
||||
openAppAuthModal(true, {
|
||||
id: res.id,
|
||||
});
|
||||
}
|
||||
function handleAddUser() {
|
||||
let rows = warning();
|
||||
if (!rows) {
|
||||
return;
|
||||
}
|
||||
getRoleUser(rows.id).then((res) => {
|
||||
selectedUserId.value = res.map((item) => {
|
||||
return item.id;
|
||||
});
|
||||
console.log(selectedUserId.value);
|
||||
visible.value = true;
|
||||
});
|
||||
}
|
||||
function warning(isAdminCantUse = false) {
|
||||
const selectRows = getSelectRows();
|
||||
if (selectRows.length === 0) {
|
||||
notification.warning({
|
||||
message: t('警告'),
|
||||
description: t('必须选中一行!'),
|
||||
}); //提示消息
|
||||
return false;
|
||||
} else if (isAdminCantUse && selectRows[0].id === '1') {
|
||||
notification.warning({
|
||||
message: t('警告'),
|
||||
description: t('超级管理员不允许授权'),
|
||||
});
|
||||
return false;
|
||||
} else {
|
||||
return selectRows[0];
|
||||
}
|
||||
}
|
||||
function handleSelectUserSuccess(rows, type) {
|
||||
const selectRows = getSelectRows();
|
||||
let paramas;
|
||||
if (type === 0) {
|
||||
paramas = { type, id: selectRows[0].id, userIds: rows };
|
||||
} else {
|
||||
paramas = { type, id: selectRows[0].id, departmentIds: rows };
|
||||
}
|
||||
|
||||
addRoleUser(paramas).then((_) => {
|
||||
notification.info({
|
||||
message: t('添加人员'),
|
||||
description: t('成功'),
|
||||
}); //提示消息
|
||||
});
|
||||
}
|
||||
function handleInterfaceSuccess(rows) {
|
||||
const selectRows = getSelectRows();
|
||||
|
||||
addRoleInterface(selectRows[0].id, rows).then((_) => {
|
||||
notification.info({
|
||||
message: t('接口授权成功'),
|
||||
description: t('成功'),
|
||||
}); //提示消息
|
||||
});
|
||||
}
|
||||
function handleViewUser() {
|
||||
let rows = warning();
|
||||
if (!rows) {
|
||||
return;
|
||||
}
|
||||
getRoleUser(rows.id).then((res) => {
|
||||
openModal(true, res);
|
||||
setModalProps({ title: t('查看成员') });
|
||||
});
|
||||
}
|
||||
function handleRoleAuthSuccess() {}
|
||||
|
||||
function handleEdit(record: Recordable) {
|
||||
openRoleModal(true, {
|
||||
record,
|
||||
isUpdate: true,
|
||||
});
|
||||
}
|
||||
|
||||
function handleDelete(record: Recordable) {
|
||||
deleteRole([record.id]).then((_) => {
|
||||
reload();
|
||||
notification.success({
|
||||
message: t('删除角色'),
|
||||
description: t('成功'),
|
||||
}); //提示消息
|
||||
});
|
||||
}
|
||||
|
||||
function handleSuccess() {
|
||||
reload();
|
||||
}
|
||||
function handleHomeAuth() {
|
||||
let res = warning();
|
||||
if (!res) {
|
||||
return;
|
||||
}
|
||||
|
||||
openHomeModal(true, {
|
||||
id: res.id,
|
||||
});
|
||||
}
|
||||
return {
|
||||
registerTable,
|
||||
registerRoleModal,
|
||||
handleCreate,
|
||||
handleEdit,
|
||||
handleDelete,
|
||||
handleSuccess,
|
||||
handleAuth,
|
||||
handleAddUser,
|
||||
handleViewUser,
|
||||
handleSelectUserSuccess,
|
||||
handleInterfaceSuccess,
|
||||
registerRoleAuthModal,
|
||||
handleRoleAuthSuccess,
|
||||
registerModal,
|
||||
visible,
|
||||
selectedUserId,
|
||||
registerInterfaceModal,
|
||||
handleInterfaceAuth,
|
||||
registerHomeModal,
|
||||
handleHomeAuth,
|
||||
t,
|
||||
registerAppAuthModal,
|
||||
handleAppAuth,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user