Commit f01c34f6 authored by 何远江's avatar 何远江

添加权限

parent 09a0b6f6
<template>
<vxe-modal
v-model="showModal"
@hide="onHide"
title="用户选择"
width="900px"
show-maximize
show-footer
esc-closable
>
<el-form inline :model="searchParam">
<el-row :gutter="12">
<el-col :span="8">
<el-form-item class="w-full" label="用户名称:" prop="username">
<el-input v-model="searchParam.username" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item class="w-full" label="昵称:" prop="nickName">
<el-input v-model="searchParam.nickName" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item class="w-full" label="状态:" prop="status">
<el-select v-model="searchParam.status">
<el-option label="启用" value="enable" />
<el-option label="禁用" value="disable" />
</el-select>
</el-form-item>
</el-col>
<el-col>
<el-form-item>
<el-button type="primary" :icon="Search" @click="search"> 搜索 </el-button>
<el-button :icon="Delete" @click="reset"> 重置 </el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
<vxe-table ref="xTable" :data="tableData" :loading="loading">
<vxe-column type="checkbox" width="50" />
<vxe-column field="username" title="用户账号" minWidth="120" />
<vxe-column field="nickName" title="昵称" minWidth="120" />
<vxe-column field="phone" title="手机号" width="140" />
<vxe-column field="status" title="状态" width="120">
<template #default="{ row }">
<el-tag :type="row.status == 'enable' ? 'primary' : 'danger'">{{
row.status == 'enable' ? '启用' : '禁用'
}}</el-tag>
</template>
</vxe-column>
</vxe-table>
<Pagination
:pageable="pageable"
:handleSizeChange="handleSizeChange"
:handleCurrentChange="handleCurrentChange"
/>
<template #footer>
<el-button type="default" @click="showModal = false">取消</el-button>
<el-button type="primary" @click="handleConfirm">确认</el-button>
</template>
</vxe-modal>
</template>
<script setup name="UserModal">
import { ref, onMounted } from 'vue';
import { ElMessage } from 'element-plus';
import { getUserPage } from '@/api/user';
import { Search, Delete } from '@element-plus/icons-vue';
import Pagination from '@/components/Pagination/index.vue';
import { useProTable } from '@/hooks/useProTable';
const emits = defineEmits(['confirm']);
const showModal = ref(false);
const xTable = ref(null);
const {
pageable,
tableData,
search,
searchParam,
reset,
loading,
handleSizeChange,
handleCurrentChange,
} = useProTable(getUserPage, {}, true);
const handleConfirm = async () => {
const checkedList = xTable.value.getCheckboxRecords();
if (!checkedList.length) {
return ElMessage({
type: 'warning',
message: '请选择有效数据!',
plain: true,
});
}
emits('confirm', checkedList);
showModal.value = false;
};
const onHide = () => {};
const openModal = () => {
showModal.value = true;
};
onMounted(() => {
search();
});
defineExpose({
openModal,
});
</script>
...@@ -96,6 +96,7 @@ ...@@ -96,6 +96,7 @@
reset, reset,
handleSizeChange, handleSizeChange,
handleCurrentChange, handleCurrentChange,
totalParam,
} = useProTable( } = useProTable(
props?.api, props?.api,
props.initParam, props.initParam,
...@@ -156,7 +157,7 @@ ...@@ -156,7 +157,7 @@
const _search = () => { const _search = () => {
search(); search();
emit('search'); emit('search', totalParam.value);
}; };
const _reset = () => { const _reset = () => {
......
...@@ -45,7 +45,6 @@ ...@@ -45,7 +45,6 @@
const route = useRoute(); const route = useRoute();
const authStore = useAuthStore(); const authStore = useAuthStore();
const globalStore = useGlobalStore(); const globalStore = useGlobalStore();
authStore.getAuthMenuList();
const accordion = computed(() => globalStore.accordion); const accordion = computed(() => globalStore.accordion);
const isCollapse = computed(() => globalStore.isCollapse); const isCollapse = computed(() => globalStore.isCollapse);
......
...@@ -68,6 +68,7 @@ export function setupVxeTabele(app) { ...@@ -68,6 +68,7 @@ export function setupVxeTabele(app) {
border: true, border: true,
stripe: true, stripe: true,
round: true, round: true,
size: 'small',
resizableConfig: { resizableConfig: {
dragMode: 'auto', dragMode: 'auto',
showDragTip: true, showDragTip: true,
...@@ -91,7 +92,9 @@ export function setupVxeTabele(app) { ...@@ -91,7 +92,9 @@ export function setupVxeTabele(app) {
keyField: '_ROW_KEY', keyField: '_ROW_KEY',
}, },
}, },
grid: {}, grid: {
size: 'small'
},
}); });
lazyVxeUI(app); lazyVxeUI(app);
lazyVxeTable(app); lazyVxeTable(app);
......
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { getShowMenuList, getFlatMenuList, getAllBreadcrumbList } from '@/utils/menu'; import { getShowMenuList, getFlatMenuList, getAllBreadcrumbList, filterMenu } from '@/utils/menu';
import authMenuList from '@/assets/json/authMenuList.json'; import authMenuList from '@/assets/json/authMenuList.json';
import { getMenuTree } from '@/api/menu';
import { useUserStore } from './user';
export const useAuthStore = defineStore({ export const useAuthStore = defineStore({
id: 'admin-auth', id: 'admin-auth',
state: () => ({ state: () => ({
...@@ -27,12 +29,24 @@ export const useAuthStore = defineStore({ ...@@ -27,12 +29,24 @@ export const useAuthStore = defineStore({
// Get AuthButtonList // Get AuthButtonList
async getAuthButtonList() { async getAuthButtonList() {
// const { data } = await getAuthButtonListApi(); // const { data } = await getAuthButtonListApi();
const { userInfo } = useUserStore();
this.authButtonList = userInfo.permissions;
// this.authButtonList = data; // this.authButtonList = data;
}, },
// Get AuthMenuList // Get AuthMenuList
async getAuthMenuList() { async getAuthMenuList() {
// const { data } = await getAuthMenuListApi(); // const { data } = await getAuthMenuListApi();
this.authMenuList = authMenuList; const { userInfo } = useUserStore();
if (userInfo?.menus.length) {
// 除了按钮的所有菜单
const userMenus = userInfo.menus.filter((v) => v.type !== '2');
// 1、获取所有菜单
const { result } = await getMenuTree();
// 2、递归菜单
this.authMenuList = filterMenu(result, userMenus);
} else {
this.authMenuList = [];
}
}, },
// Set RouteName // Set RouteName
async setRouteName(name) { async setRouteName(name) {
......
...@@ -39,3 +39,39 @@ export const getAllBreadcrumbList = (menuList, parent = [], result = {}) => { ...@@ -39,3 +39,39 @@ export const getAllBreadcrumbList = (menuList, parent = [], result = {}) => {
} }
return result; return result;
}; };
/**
* 通过全部菜单匹配用户的扁平菜单
* @param {*} menus 菜单列表
* @param {*} userMenus 用户菜单
* @param {*} menu 处理后的菜单
* @returns
*/
export function filterMenu(menus, userMenus, menu = []) {
if (!menus?.length) return menu;
menus.forEach((m) => {
if (userMenus.find((v) => v.id === m.id)) {
const target = {
path: m.path,
name: m.name,
redirect: m.redirect,
component: m.component,
meta: {
icon: m.icon,
title: m.title,
isLink: m.link,
isHide: m.hide === 'Y',
isFull: m.full === 'Y',
isAffix: m.affix === 'Y',
isKeepAlive: m.keepAlive == 'Y',
activeMenu: m.activeMenu,
},
};
menu.push(target);
if (m.children?.length) {
target.children = filterMenu(m.children, userMenus, []);
}
}
});
return menu;
}
...@@ -11,40 +11,61 @@ ...@@ -11,40 +11,61 @@
<el-form ref="formRef" :model="form" inline label-width="80px"> <el-form ref="formRef" :model="form" inline label-width="80px">
<el-row :gutter="10"> <el-row :gutter="10">
<el-col :span="24"> <el-col :span="24">
<el-form-item class="w-full" label="菜单类型" prop="type">
<el-radio-group v-model="form.type">
<el-radio-button label="一级菜单" value="0" />
<el-radio-button label="子菜单" value="1" />
<el-radio-button label="按钮" value="2" />
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24" v-show="form.type != '0'">
<el-form-item class="w-full" label="父级菜单" prop="parent"> <el-form-item class="w-full" label="父级菜单" prop="parent">
<el-tree-select <el-tree-select
clearable ref="treeSelectRef"
v-model="form.parent" v-model="form.parent"
:data="props.menuList" :data="props.menuList"
highlight-current
check-strictly check-strictly
node-key="name" :current-node-key="form.parent"
:props="{
label: 'title',
children: 'children',
}"
node-key="id"
:render-after-expand="false" :render-after-expand="false"
clearable
/> />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item class="w-full" label="菜单名称" prop="meta.title"> <el-form-item class="w-full" label="菜单名称" prop="title">
<el-input v-model="form.meta.title" placeholder="标题" /> <el-input v-model="form.title" placeholder="标题" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item class="w-full" label="图标" prop="meta.icon"> <el-form-item class="w-full" label="访问路径" prop="path">
<el-input v-model="form.meta.icon" placeholder="图标" /> <el-input v-model="form.path" placeholder="访问路径" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item class="w-full" label="访问路径" prop="path"> <el-form-item class="w-full" label="菜单图标" prop="icon">
<el-input v-model="form.path" placeholder="访问路径" /> <el-input v-model="form.icon" placeholder="菜单图标" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item class="w-full" label="重定向" prop="redirect">
<el-input v-model="form.redirect" placeholder="重定向路径" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item class="w-full" label="重定向" prop="path"> <el-form-item class="w-full" label="菜单Name" prop="name">
<el-input v-model="form.redirect" placeholder="重定向" /> <el-input v-model="form.name" placeholder="菜单Name" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item class="w-full" label="菜单name" prop="name"> <el-form-item class="w-full" label="权限编码" prop="code">
<el-input v-model="form.name" placeholder="菜单name" /> <el-input v-model="form.code" placeholder="权限编码" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
...@@ -52,35 +73,34 @@ ...@@ -52,35 +73,34 @@
<el-input v-model="form.component" placeholder="组件路径" /> <el-input v-model="form.component" placeholder="组件路径" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item class="w-full" label="外链地址" prop="isLink"> <el-form-item class="w-full" label="外链地址" prop="link">
<el-input v-model="form.isLink" placeholder="外链地址" /> <el-input v-model="form.link" placeholder="外链地址" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item class="w-full" label="显示菜单" prop="activeMenu"> <el-form-item class="w-full" label="显示菜单" prop="activeMenu">
<el-input v-model="form.meta.activeMenu" /> <el-input v-model="form.activeMenu" placeholder="显示菜单路径" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="是否隐藏" prop="isHide"> <el-form-item label="是否隐藏" prop="hide">
<el-checkbox v-model="form.meta.isHide" :true-value="1" :false-value="0" /> <el-checkbox v-model="form.hide" true-value="Y" false-value="N" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="是否全屏" prop="isFull"> <el-form-item label="是否全屏" prop="full">
<el-checkbox v-model="form.meta.isFull" :true-value="1" :false-value="0" /> <el-checkbox v-model="form.full" true-value="Y" false-value="N" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="是否固定" prop="isAffix"> <el-form-item label="是否固定" prop="affix">
<el-checkbox v-model="form.meta.isAffix" :true-value="1" :false-value="0" /> <el-checkbox v-model="form.affix" true-value="Y" false-value="N" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="是否缓存" prop="isKeepAlive"> <el-form-item label="是否缓存" prop="keepAlive">
<el-checkbox v-model="form.meta.isKeepAlive" :true-value="1" :false-value="0" /> <el-checkbox v-model="form.keepAlive" true-value="Y" false-value="N" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
...@@ -88,53 +108,98 @@ ...@@ -88,53 +108,98 @@
<template #footer> <template #footer>
<el-button type="default" @click="showModal = false">取消</el-button> <el-button type="default" @click="showModal = false">取消</el-button>
<el-button type="primary" @click="submitForm">提交</el-button> <el-button :loading="loading" type="primary" @click="submitForm">提交</el-button>
</template> </template>
</vxe-modal> </vxe-modal>
</template> </template>
<script setup name="menuFormModal"> <script setup name="menuFormModal">
import { ref, reactive, computed, unref } from 'vue'; import { ref, computed } from 'vue';
import { saveMenu } from '@/api/menu';
import { ElMessage } from 'element-plus';
const emits = defineEmits(['success']);
const props = defineProps({ const props = defineProps({
menuList: { menuList: {
type: Array, type: Array,
default: () => [], default: () => [],
}, },
}); });
const currentMenu = ref(null); const currentMenu = ref(null);
const showModal = ref(false); const showModal = ref(false);
const formRef = ref(null); const formRef = ref(null);
const treeSelectRef = ref(null);
const loading = ref(false);
const isEdit = computed(() => !!currentMenu.value); const isEdit = computed(() => !!currentMenu.value);
const modalTitle = computed(() => (isEdit.value ? '编辑菜单' : '新增菜单')); const modalTitle = computed(() => (isEdit.value ? '编辑菜单' : '新增菜单'));
const form = reactive({ const form = ref({
parent: '', type: '0',
parent: null,
path: '', // 访问路径 path: '', // 访问路径
name: '', // 组件 name name: '', // 组件 name
component: '', // 组件名称 component: '', // 组件路径
redirect: '', // 重定向 redirect: '', // 重定向
meta: { code: '', // 权限编码
icon: '', // icon icon: '', // icon
title: '', // 标题 title: '', // 标题
isLink: '', // 是否外链接 link: '', // 外链地址,
isHide: 0, // 是否隐藏 hide: 'N', // 是否隐藏
isFull: 0, // 是否全屏 full: 'N', // 是否全屏
isAffix: 1, // 是否固定 affix: 'N', // 是否固定
activeMenu: '', // 用于详情时,选中菜单路径 activeMenu: 'Y', // 选中菜单的地址
isKeepAlive: 1, // 是否缓存 keepAlive: 'Y', // 是否缓存
}, sortNo: 1,
}); });
const submitForm = () => {}; const submitForm = async () => {
// console.log(treeSelectRef.value.getCurrentNode(), '---');
// return
const params = {
...form.value,
parent: form.value.type == 'first' ? null : treeSelectRef.value.getCurrentNode(),
};
try {
await formRef.value.validate();
loading.value = true;
await saveMenu(params);
ElMessage({
type: 'success',
message: isEdit.value ? '修改成功!' : '新增成功!',
plain: true,
});
emits('success');
showModal.value = false;
} catch {}
loading.value = false;
};
const onHide = () => { const onHide = () => {
formRef.value.resetFields(); form.value = {
type: 'first',
parent: '',
path: '', // 访问路径
name: '', // 组件 name
component: '', // 组件路径
redirect: '', // 重定向
code: '', // 权限编码
icon: '', // icon
title: '', // 标题
link: '', // 外链地址,
hide: 'N', // 是否隐藏
full: 'N', // 是否全屏
affix: 'N', // 是否固定
activeMenu: 'Y', // 选中菜单的地址
keepAlive: 'Y', // 是否缓存
sortNo: 1,
};
formRef.value.clearValidate();
currentMenu.value = null; currentMenu.value = null;
}; };
const openModal = (menu) => { const openModal = (menu) => {
Object.assign(form, menu); menu && (form.value = menu);
currentMenu.value = menu; currentMenu.value = menu;
showModal.value = true; showModal.value = true;
}; };
......
<template> <template>
<div class="table-box"> <div class="table-box">
<ProTable ref="proTable" :config="config" :show-pagination="false" :data="menuData"> <ProTable
ref="proTable"
:config="config"
:show-pagination="false"
@search="handleSearch"
:data="tableData"
>
<!-- 表格 header 按钮 --> <!-- 表格 header 按钮 -->
<template #left_buttons> <template #left_buttons>
<el-button type="primary" :icon="CirclePlus" @click="menuFormModalRef?.openModal()" <el-button type="primary" :icon="CirclePlus" @click="menuFormModalRef?.openModal()"
...@@ -9,7 +15,7 @@ ...@@ -9,7 +15,7 @@
</template> </template>
</ProTable> </ProTable>
<MenuFormModal ref="menuFormModalRef" :menuList="authMenuList" /> <MenuFormModal ref="menuFormModalRef" :menuList="tableData" @success="onSuccess" />
</div> </div>
</template> </template>
...@@ -18,25 +24,27 @@ ...@@ -18,25 +24,27 @@
import { Delete, EditPen, CirclePlus } from '@element-plus/icons-vue'; import { Delete, EditPen, CirclePlus } from '@element-plus/icons-vue';
import authMenuList from '@/assets/json/authMenuList.json'; import authMenuList from '@/assets/json/authMenuList.json';
import ProTable from '@/components/ProTable/index.vue'; import ProTable from '@/components/ProTable/index.vue';
import { ElButton } from 'element-plus'; import { ElButton, ElMessage, ElMessageBox } from 'element-plus';
import MenuIcon from './components/MenuIcon.vue'; import MenuIcon from './components/MenuIcon.vue';
import MenuFormModal from './components/MenuFormModal.vue'; import MenuFormModal from './components/MenuFormModal.vue';
import { getMenuTree, deleteMenus } from '@/api/menu';
import { onMounted } from 'vue';
const proTable = ref(); const proTable = ref();
const menuFormModalRef = ref(); const menuFormModalRef = ref();
const menuData = ref(authMenuList); const menuData = ref(authMenuList);
const tableData = ref([]);
// 表格配置项 // 表格配置项
const config = { const config = {
height: 'auto',
stripe: false, // tree 不支持 stripe stripe: false, // tree 不支持 stripe
treeConfig: { treeConfig: {
rowField: 'name', rowField: 'id',
childrenField: 'children', childrenField: 'children',
}, },
columns: [ columns: [
{ {
field: 'meta.title', field: 'title',
title: '菜单名称', title: '菜单名称',
align: 'left', align: 'left',
minWidth: 240, minWidth: 240,
...@@ -44,12 +52,12 @@ ...@@ -44,12 +52,12 @@
treeNode: true, treeNode: true,
}, },
{ {
field: 'meta.icon', field: 'icon',
title: '菜单图标', title: '菜单图标',
minWidth: 120, minWidth: 120,
slots: { slots: {
default: ({ row }) => { default: ({ row }) => {
return <MenuIcon width={20} iconName={row.meta.icon} />; return row.icon && <MenuIcon width={20} iconName={row.icon} />;
}, },
}, },
}, },
...@@ -68,7 +76,7 @@ ...@@ -68,7 +76,7 @@
<ElButton type="primary" icon={EditPen} link onClick={() => handleEditClick(row)}> <ElButton type="primary" icon={EditPen} link onClick={() => handleEditClick(row)}>
编辑 编辑
</ElButton> </ElButton>
<ElButton type="primary" icon={Delete} link> <ElButton type="primary" icon={Delete} link onClick={() => handleDelete(row)}>
删除 删除
</ElButton> </ElButton>
</> </>
...@@ -79,7 +87,35 @@ ...@@ -79,7 +87,35 @@
], ],
}; };
const handleEditClick = (row) => { const onSuccess = () => {
handleSearch();
};
const handleSearch = async (params) => {
const { result } = await getMenuTree(params ?? {});
tableData.value = result;
};
const handleEditClick = (row) =>
menuFormModalRef.value.openModal(JSON.parse(JSON.stringify(row))); menuFormModalRef.value.openModal(JSON.parse(JSON.stringify(row)));
const handleDelete = async (row) => {
await ElMessageBox.confirm('是否确认删除该菜单?', '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
});
await deleteMenus(row.id);
ElMessage({
type: 'success',
message: '删除成功!',
plain: true,
});
handleSearch();
}; };
onMounted(() => {
handleSearch();
});
</script> </script>
<template>
<vxe-modal
v-model="showModal"
@hide="onHide"
title="菜单权限分配"
width="800px"
show-maximize
show-footer
esc-closable
>
<el-tree
ref="treeRef"
:data="menuData"
show-checkbox
node-key="id"
default-expand-all
:default-checked-keys="defaultCheckedKeys"
:props="defaultProps"
/>
<template #footer>
<el-button type="default" @click="showModal = false">取消</el-button>
<el-button :loading="loading" type="primary" @click="submitForm">提交</el-button>
</template>
</vxe-modal>
</template>
<script setup name="AllocationUserModal">
import { ref, onMounted, reactive, computed } from 'vue';
import { ElMessage } from 'element-plus';
import { getMenuTree } from '@/api/menu';
import { saveRole } from '@/api/role';
const defaultProps = {
children: 'children',
label: 'title',
};
const emits = defineEmits(['success']);
const currentRole = ref(null);
const showModal = ref(false);
const treeRef = ref(null);
const menuData = ref([]);
const defaultCheckedKeys = computed(() => currentRole.value?.menus.map((v) => v.id) || []);
const loading = ref(false);
const submitForm = async () => {
try {
// 获取全选中节点
const checkedNodes = treeRef.value.getCheckedNodes();
// 获取半选中节点
const halfCheckedNodes = treeRef.value.getHalfCheckedNodes();
if (!checkedNodes.length) {
return ElMessage.info('请选择要设置的权限!');
}
loading.value = true;
const params = {
...currentRole.value,
menus: checkedNodes.map((v) => ({ id: v.id })),
// menus: [...checkedNodes, ...halfCheckedNodes].map((v) => ({ id: v.id })),
};
await saveRole(params);
emits('success');
ElMessage({
type: 'success',
message: '设置成功!',
plain: true,
});
showModal.value = false;
} catch {}
loading.value = false;
};
const onHide = () => {
currentRole.value = null;
treeRef.value.setCheckedNodes([]);
};
const openModal = (role) => {
currentRole.value = role;
showModal.value = true;
};
const initTreeData = async () => {
const { result } = await getMenuTree();
menuData.value = result;
};
onMounted(() => {
initTreeData();
});
defineExpose({
openModal,
});
</script>
<template>
<vxe-modal
v-model="showModal"
@hide="onHide"
title="分配成员"
width="900px"
show-maximize
show-footer
esc-closable
>
<div class="mb-1">
<el-button type="primary" @click="userModalRef?.openModal">新增成员</el-button>
<el-button type="danger" @click="handleRemove">删除成员</el-button>
</div>
<vxe-table ref="xTable" :data="tableData">
<vxe-column type="checkbox" width="50" />
<vxe-column field="username" title="用户账号" minWidth="120" />
<vxe-column field="nickName" title="昵称" minWidth="120" />
<vxe-column field="status" title="状态" width="120">
<template #default="{ row }">
<el-tag :type="row.status == 'enable' ? 'primary' : 'danger'">{{
row.status == 'enable' ? '启用' : '禁用'
}}</el-tag>
</template>
</vxe-column>
</vxe-table>
<template #footer>
<el-button type="default" @click="showModal = false">取消</el-button>
<el-button :loading="loading" type="primary" @click="submitForm">提交</el-button>
</template>
</vxe-modal>
<UserModal ref="userModalRef" @confirm="hanldeConfirm" />
</template>
<script setup name="AllocationUserModal">
import { ref } from 'vue';
import { ElMessage } from 'element-plus';
import { saveRole } from '@/api/role';
import UserModal from '@/components/CommonModal/UserModal/index.vue';
const emits = defineEmits(['success']);
const xTable = ref(null);
const showModal = ref(false);
const userModalRef = ref(null);
const loading = ref(false);
const tableData = ref([]);
const currentRole = ref(null);
const submitForm = async () => {
try {
loading.value = true;
const params = {
...currentRole.value,
users: tableData.value.map((v) => ({ id: v.id })),
};
await saveRole(params);
emits('success');
ElMessage({
type: 'success',
message: '添加成功!',
plain: true,
});
showModal.value = false;
} catch {}
loading.value = false;
};
const onHide = () => {
currentRole.value = null;
tableData.value = [];
};
const openModal = (role) => {
currentRole.value = role;
tableData.value = role.users;
showModal.value = true;
};
const hanldeConfirm = (rows) => {
tableData.value.unshift(...rows.filter((row) => !tableData.value.find((v) => v.id == row.id)));
};
const handleRemove = () => {
const checkedList = xTable.value.getCheckboxRecords();
if (!checkedList.length) {
return ElMessage({
type: 'warning',
message: '请选择有效数据!',
plain: true,
});
}
tableData.value = tableData.value.filter((row) => !checkedList.find((v) => v.id == row.id));
};
defineExpose({
openModal,
});
</script>
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
</ProTable> </ProTable>
<RoleFormModal ref="roleModalRef" @success="query" /> <RoleFormModal ref="roleModalRef" @success="query" />
<AllocationMenuModal ref="allocationMenuModalRef" @success="query" />
<AllocationUserModal ref="allocationUserModalRef" />
</div> </div>
</template> </template>
...@@ -15,11 +17,15 @@ ...@@ -15,11 +17,15 @@
import { ref, reactive, onMounted } from 'vue'; import { ref, reactive, onMounted } from 'vue';
import { Plus, Delete, Edit, Setting } from '@element-plus/icons-vue'; import { Plus, Delete, Edit, Setting } from '@element-plus/icons-vue';
import { getRolePage, deleteRoles } from '@/api/role'; import { getRolePage, deleteRoles } from '@/api/role';
import RoleFormModal from './components/RoleFormModal.vue';
import { ElMessageBox, ElMessage, ElButton } from 'element-plus'; import { ElMessageBox, ElMessage, ElButton } from 'element-plus';
import RoleFormModal from './components/RoleFormModal.vue';
import AllocationMenuModal from './components/AllocationMenuModal.vue';
import AllocationUserModal from './components/AllocationUserModal.vue';
const proTable = ref(null); const proTable = ref(null);
const roleModalRef = ref(null); const roleModalRef = ref(null);
const allocationMenuModalRef = ref(null);
const allocationUserModalRef = ref(null);
const config = reactive({ const config = reactive({
columns: [ columns: [
{ type: 'checkbox', width: 50 }, { type: 'checkbox', width: 50 },
...@@ -35,10 +41,24 @@ ...@@ -35,10 +41,24 @@
<ElButton type="primary" link icon={Edit} onClick={() => handleEdit(row)}> <ElButton type="primary" link icon={Edit} onClick={() => handleEdit(row)}>
编辑 编辑
</ElButton> </ElButton>
<ElButton type="primary" link icon={Setting}> <ElButton
type="primary"
link
icon={Setting}
onClick={() =>
allocationMenuModalRef.value.openModal(JSON.parse(JSON.stringify(row)))
}
>
设置权限 设置权限
</ElButton> </ElButton>
<ElButton type="primary" link icon={Setting}> <ElButton
type="primary"
link
icon={Setting}
onClick={() =>
allocationUserModalRef.value.openModal(JSON.parse(JSON.stringify(row)))
}
>
设置成员 设置成员
</ElButton> </ElButton>
</> </>
......
<template>
<vxe-modal
v-model="showModal"
@hide="onHide"
title="分配成员"
width="900px"
show-maximize
show-footer
esc-closable
>
<div class="mb-1">
<el-button type="primary" @click="userModalRef?.openModal">新增成员</el-button>
<el-button type="danger" @click="handleRemove">删除成员</el-button>
</div>
<vxe-table ref="xTable" :data="tableData">
<vxe-column type="checkbox" width="50" />
<vxe-column field="username" title="用户账号" minWidth="120" />
<vxe-column field="nickName" title="昵称" minWidth="120" />
<vxe-column field="status" title="状态" width="120">
<template #default="{ row }">
<el-tag :type="row.status == 'enable' ? 'primary' : 'danger'">{{
row.status == 'enable' ? '启用' : '禁用'
}}</el-tag>
</template>
</vxe-column>
</vxe-table>
<template #footer>
<el-button type="default" @click="showModal = false">取消</el-button>
<el-button :loading="loading" type="primary" @click="submitForm">提交</el-button>
</template>
</vxe-modal>
<UserModal ref="userModalRef" @confirm="hanldeConfirm" />
</template>
<script setup name="AllocationUserModal">
import { ref } from 'vue';
import { ElMessage } from 'element-plus';
import { saveTenant } from '@/api/tenant';
import UserModal from '@/components/CommonModal/UserModal/index.vue';
const emits = defineEmits(['success']);
const xTable = ref(null);
const showModal = ref(false);
const userModalRef = ref(null);
const loading = ref(false);
const tableData = ref([]);
const currentRole = ref(null);
const submitForm = async () => {
try {
loading.value = true;
const params = {
...currentRole.value,
users: tableData.value.map((v) => ({ id: v.id })),
};
await saveTenant(params);
emits('success');
ElMessage({
type: 'success',
message: '设置成功!',
plain: true,
});
showModal.value = false;
} catch {}
loading.value = false;
};
const onHide = () => {
currentRole.value = null;
tableData.value = [];
};
const openModal = (role) => {
currentRole.value = role;
tableData.value = role.users;
showModal.value = true;
};
const hanldeConfirm = (rows) => {
tableData.value.unshift(...rows.filter((row) => !tableData.value.find((v) => v.id == row.id)));
};
const handleRemove = () => {
const checkedList = xTable.value.getCheckboxRecords();
if (!checkedList.length) {
return ElMessage({
type: 'warning',
message: '请选择有效数据!',
plain: true,
});
}
tableData.value = tableData.value.filter((row) => !checkedList.find((v) => v.id == row.id));
};
defineExpose({
openModal,
});
</script>
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
</ProTable> </ProTable>
<TenantFormModal ref="tenatModalRef" @success="query" /> <TenantFormModal ref="tenatModalRef" @success="query" />
<AllocationUserModal ref="allocationUserModalRef" @success="query" />
</div> </div>
</template> </template>
...@@ -16,10 +17,12 @@ ...@@ -16,10 +17,12 @@
import { Plus, Delete, Edit, Setting } from '@element-plus/icons-vue'; import { Plus, Delete, Edit, Setting } from '@element-plus/icons-vue';
import { getTenantPage, deleteTenants } from '@/api/tenant'; import { getTenantPage, deleteTenants } from '@/api/tenant';
import TenantFormModal from './components/TenantFormModal.vue'; import TenantFormModal from './components/TenantFormModal.vue';
import AllocationUserModal from './components/AllocationUserModal.vue';
import { ElMessageBox, ElMessage, ElButton, ElTag } from 'element-plus'; import { ElMessageBox, ElMessage, ElButton, ElTag } from 'element-plus';
const proTable = ref(null); const proTable = ref(null);
const tenatModalRef = ref(null); const tenatModalRef = ref(null);
const allocationUserModalRef = ref(null);
const config = reactive({ const config = reactive({
columns: [ columns: [
{ type: 'checkbox', width: 50 }, { type: 'checkbox', width: 50 },
...@@ -48,7 +51,14 @@ ...@@ -48,7 +51,14 @@
<ElButton type="primary" link icon={Edit} onClick={() => handleEdit(row)}> <ElButton type="primary" link icon={Edit} onClick={() => handleEdit(row)}>
编辑 编辑
</ElButton> </ElButton>
<ElButton type="primary" link icon={Setting}> <ElButton
type="primary"
link
icon={Setting}
onClick={() =>
allocationUserModalRef.value.openModal(JSON.parse(JSON.stringify(row)))
}
>
设置成员 设置成员
</ElButton> </ElButton>
</> </>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment