update: 角色管理组件更换、弹窗逻辑优化

This commit is contained in:
easy 2023-03-06 16:35:59 +08:00
parent 787c85b399
commit 3039c20e2f
7 changed files with 338 additions and 372 deletions

View File

@ -1,42 +1,42 @@
<template>
<div class="role-permiss-container">
<a-card>
<section class="card">
<h5>基本信息</h5>
<a-form ref="formRef" class="basic-form" :model="form.data" layout="vertical">
<a-form-item
<j-form ref="formRef" class="basic-form" :model="form.data" layout="vertical">
<j-form-item
name="name"
label="名称"
:rules="[{ required: true, message: '请输入名称' }]"
>
<a-input
<j-input
v-model:value="form.data.name"
placeholder="请输入角色名称"
:maxlength="64"
/>
</a-form-item>
<a-form-item name="name" label="说明">
<a-textarea
</j-form-item>
<j-form-item name="name" label="说明">
<j-textarea
v-model:value="form.data.description"
placeholder="请输入说明"
:maxlength="200"
show-count
/>
</a-form-item>
</a-form>
</a-card>
</j-form-item>
</j-form>
</section>
<a-card>
<section class="card">
<h5>权限分配</h5>
<PermissTree v-model:select-items="form.menus" />
<a-button
<j-button
type="primary"
:disabled="form.loading"
@click="form.clickSave"
style="margin-top: 24px;"
>保存</a-button
>保存</j-button
>
</a-card>
</section>
</div>
</template>
@ -86,8 +86,10 @@ form.getForm();
<style lang="less" scoped>
.role-permiss-container {
.ant-card {
.card {
margin-bottom: 24px;
background-color: #fff;
padding: 24px;
h5 {
position: relative;

View File

@ -1,134 +1,149 @@
<template>
<a-card class="role-user-container">
<Search :columns="query.columns" />
<div class="role-user-container">
<j-advanced-search
:columns="columns"
@search="(params:any)=>queryParams = {...params}"
/>
<j-pro-table
ref="tableRef"
:columns="table.columns"
:request="getUserByRole_api"
:columns="columns"
:request="table.getList"
model="TABLE"
:defaultParams="query.params"
:params="queryParams"
:rowSelection="{
selectedRowKeys: table._selectedRowKeys,
onChange: table.onSelectChange,
selectedRowKeys: selectedRowKeys,
onChange: (keys:string[])=>selectedRowKeys = keys,
}"
@cancelSelect="table.cancelSelect"
@cancelSelect="selectedRowKeys = []"
size="small"
>
<template #headerTitle>
<a-button type="primary" @click="table.clickAdd"
><plus-outlined />新增</a-button
>
<j-button type="primary" @click="dialogVisible = true">
<AIcon type="PlusOutlined" />新增
</j-button>
</template>
<template #status="slotProps">
<BadgeStatus
:status="slotProps.status"
:text="slotProps.status ? '正常' : '禁用'"
:statusNames="{
1: 'success',
0: 'error',
}"
></BadgeStatus>
</template>
<template #action="slotProps">
<a-space :size="16">
<a-popconfirm
title="确认解绑"
ok-text="确定"
cancel-text="取消"
@confirm="table.clickUnBind(slotProps)"
<j-space :size="16">
<PermissionButton
type="link"
:tooltip="{ title: '解绑' }"
:pop-confirm="{
title: `确认解绑`,
onConfirm: () => table.unbind([slotProps.id]),
}"
>
<a-tooltip>
<template #title>解绑</template>
<a-button style="padding: 0" type="link">
<disconnect-outlined />
</a-button>
</a-tooltip>
</a-popconfirm>
</a-space>
<AIcon type="DisconnectOutlined" />
</PermissionButton>
</j-space>
</template>
</j-pro-table>
<div class="dialogs">
<AddUserDialog :open="dialog.openAdd" @refresh="table.refresh" />
</div>
</a-card>
<AddUserDialog
v-if="dialogVisible"
v-model:visible="dialogVisible"
:role-id="roleId"
@refresh="table.refresh"
/>
</div>
</template>
<script setup lang="ts" name="RoleUser">
import { PlusOutlined, DisconnectOutlined } from '@ant-design/icons-vue';
import PermissionButton from '@/components/PermissionButton/index.vue';
import AddUserDialog from '../components/AddUserDialog.vue';
import { getUserByRole_api, unbindUser_api } from '@/api/system/role';
import { message } from 'ant-design-vue';
import userType from './index';
const route = useRoute();
const roleId = route.params.id as string;
const query = reactive<userType.queryType>({
columns: [
{
title: '姓名',
dataIndex: 'name',
key: 'name',
const roleId = useRoute().params.id as string;
const columns = [
{
title: '姓名',
dataIndex: 'name',
key: 'name',
search: {
type: 'string',
},
{
title: '用户名',
dataIndex: 'username',
key: 'username',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
},
],
params: {
terms: [
{
terms: [
{
column: 'id$in-dimension$role',
value: route.params.id,
},
],
},
],
},
});
{
title: '用户名',
dataIndex: 'username',
key: 'username',
search: {
type: 'string',
},
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
search: {
type: 'date',
},
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
search: {
type: 'select',
options: [
{
label: '正常',
value: 1,
},
{
label: '禁用',
value: 0,
},
],
},
scopedSlots: true,
},
{
title: '操作',
dataIndex: 'action',
key: 'action',
width: '200px',
scopedSlots: true,
},
];
const queryParams = ref({});
const tableRef = ref<Record<string, any>>({});
const table = reactive<userType.tableType>({
columns: [
{
title: '姓名',
dataIndex: 'name',
key: 'name',
},
{
title: '用户名',
dataIndex: 'username',
key: 'username',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
},
{
title: '操作',
dataIndex: 'action',
key: 'action',
scopedSlots: true,
},
],
tableData: [],
//
clickAdd: () => {
dialog.openAdd += 1;
},
//
clickUnBind: (row: any) => {
table.unbind([row.id]);
const selectedRowKeys = ref<string[]>([]);
const table = {
getList: (oParams: any) => {
const params = {
...oParams,
terms: [
{
terms: [
{
column: 'id$in-dimension$role',
value: roleId,
},
],
},
],
};
if (oParams.terms[0])
params.terms.unshift({
terms: oParams.terms[0].terms,
});
return getUserByRole_api(params);
},
//
unbind: (ids: string[] = []) => {
@ -143,20 +158,24 @@ const table = reactive<userType.tableType>({
refresh: () => {
tableRef.value.reload();
},
//
_selectedRowKeys: [] as string[],
onSelectChange: (keys: string[]) => {
table._selectedRowKeys = [...keys];
},
cancelSelect: () => {
table._selectedRowKeys = [];
},
});
};
//
const dialog = reactive({
openAdd: 0,
});
const dialogVisible = ref(false);
</script>
<style lang="less" scoped></style>
<style lang="less" scoped>
.role-user-container {
background-color: #fff;
:deep(.ant-table-tbody) {
.ant-table-cell {
.ant-space-item {
.ant-btn-link {
padding: 0;
}
}
}
}
}
</style>

View File

@ -1,123 +1,99 @@
<template>
<a-modal
v-model:visible="dialog.visible"
<j-modal
visible
title="新增"
width="1000px"
@ok="dialog.handleOk"
@ok="confirm"
@cancel="emits('update:visible', false)"
>
<Search :columns="query.columns" type="simple" />
<j-advanced-search
:columns="columns"
type="simple"
@search="(params:any)=>queryParams = {...params}"
/>
<j-pro-table
ref="tableRef"
:columns="table.columns"
:request="getUserByRole_api"
:columns="columns"
:request="getUserList"
model="TABLE"
:params="query.params"
:params="queryParams"
:rowSelection="{
selectedRowKeys: table._selectedRowKeys,
onChange: table.onSelectChange,
selectedRowKeys: selectedRowKeys,
onChange: (keys:string[])=>selectedRowKeys = keys,
}"
@cancelSelect="table.cancelSelect"
@cancelSelect="selectedRowKeys = []"
>
</j-pro-table>
<template #footer>
<a-button key="back" @click="dialog.visible = false">取消</a-button>
<a-button key="submit" type="primary" @click="dialog.handleOk"
>确定</a-button
>
</template>
</a-modal>
</j-modal>
</template>
<script setup lang="ts">
import { getUserByRole_api, bindUser_api } from '@/api/system/role';
import { message } from 'ant-design-vue';
const route = useRoute();
const emits = defineEmits(['refresh']);
const props = defineProps({
open: Number,
});
const emits = defineEmits(['refresh', 'update:visible']);
const props = defineProps<{
visible: boolean;
roleId: string
}>();
const query = reactive({
columns: [
{
title: '姓名',
dataIndex: 'name',
key: 'name',
const columns = [
{
title: '姓名',
dataIndex: 'name',
key: 'name',
search: {
type: 'string',
},
{
title: '用户名',
dataIndex: 'username',
key: 'username',
},
{
title: '用户名',
dataIndex: 'username',
key: 'username',
search: {
type: 'string',
},
],
params: {
},
];
const queryParams = ref({});
const selectedRowKeys = ref<string[]>([]);
const getUserList = (oParams: any) => {
const params = {
...oParams,
sorts: [{ name: 'createTime', order: 'desc' }],
terms: [
{
terms: [
{
column: 'id$in-dimension$role$not',
value: route.params.id,
value: props.roleId,
},
],
},
],
},
});
const tableRef = ref<Record<string, any>>({});
const table = reactive({
_selectedRowKeys: [] as string[],
columns: [
{
title: '姓名',
dataIndex: 'name',
key: 'name',
},
{
title: '用户名',
dataIndex: 'username',
key: 'username',
},
],
tableData: [],
onSelectChange: (keys: string[]) => {
table._selectedRowKeys = [...keys];
},
cancelSelect: () => {
table._selectedRowKeys = [];
},
});
};
if (oParams.terms[0])
params.terms.unshift({
terms: oParams.terms[0].terms,
});
return getUserByRole_api(params);
};
//
const dialog = reactive({
visible: false,
handleOk: () => {
if (table._selectedRowKeys.length < 1) {
message.error('请至少选择一项');
} else {
bindUser_api(
route.params.id as string,
table._selectedRowKeys,
).then((resp) => {
const confirm = () => {
if (selectedRowKeys.value.length < 1) {
message.error('请至少选择一项');
} else {
bindUser_api(props.roleId, selectedRowKeys.value).then(
(resp) => {
if (resp.status === 200) {
message.success('操作成功');
emits('refresh');
dialog.visible = false;
emits('update:visible', false);
}
});
}
},
});
watch(
() => props.open,
() => {
dialog.visible = true;
},
);
},
);
}
};
</script>
<style scoped></style>

View File

@ -1,6 +1,6 @@
<template>
<div class="permiss-tree-container">
<a-table
<j-table
:columns="columns"
:data-source="tableData"
:pagination="false"
@ -10,28 +10,28 @@
<!-- 表头 -->
<template #headerCell="{ column }">
<div v-if="column.key === 'menu'">
<a-checkbox
<j-checkbox
v-model:checked="selectedAll"
:indeterminate="indeterminate"
@change="selectAllChange"
>菜单权限</a-checkbox
>菜单权限</j-checkbox
>
</div>
<div v-else-if="column.key === 'data'">
<span style="">数据权限</span>
<a-tooltip>
<j-tooltip>
<template #title
>勾选任意数据权限均能看到自己创建的数据权限</template
>
<question-circle-outlined />
</a-tooltip>
<a-checkbox
<AIcon type="QuestionCircleOutlined" />
</j-tooltip>
<j-checkbox
v-model:checked="bulkShow"
@change="bulkValue = ''"
style="margin-left: 10px"
>批量设置</a-checkbox
>批量设置</j-checkbox
>
<a-select
<j-select
v-show="bulkShow"
v-model:value="bulkValue"
:size="'middle'"
@ -39,7 +39,7 @@
:options="bulkOptions"
@change="bulkChange"
placeholder="请选择"
></a-select>
></j-select>
</div>
<div v-else>
<span>{{ column.title }}</span>
@ -48,21 +48,21 @@
<!-- 表格内容 -->
<template #bodyCell="{ column, record }">
<div v-if="column.key === 'menu'">
<a-checkbox
<j-checkbox
v-model:checked="record.granted"
:indeterminate="record.indeterminate"
@change="menuChange(record, true)"
>{{ record.name }}</a-checkbox
>{{ record.name }}</j-checkbox
>
</div>
<div v-else-if="column.key === 'action'">
<div v-if="record.buttons && record.buttons.length > 0">
<a-checkbox
<j-checkbox
v-for="button in record.buttons"
v-model:checked="button.granted"
@change="actionChange(record)"
>{{ button.name }}</a-checkbox
>{{ button.name }}</j-checkbox
>
</div>
</div>
@ -72,13 +72,16 @@
不支持数据权限配置默认可查看全部数据
</span>
<div v-else-if="record.accessSupport.value === 'support'">
<a-radio-group v-model:value="record.selectAccesses">
<a-radio
<j-radio-group
v-model:value="record.selectAccesses"
@change="resetBulk"
>
<j-radio
:value="asset.supportId"
v-for="asset in record.assetAccesses"
>{{ asset.name }}</a-radio
>{{ asset.name }}</j-radio
>
</a-radio-group>
</j-radio-group>
</div>
<span
v-else-if="
@ -89,12 +92,11 @@
>
</div>
</template>
</a-table>
</j-table>
</div>
</template>
<script setup lang="ts">
import { QuestionCircleOutlined } from '@ant-design/icons-vue';
import { cloneDeep } from 'lodash-es';
import { getPrimissTree_api } from '@/api/system/role';
@ -167,6 +169,12 @@ const bulkChange = () => {
}
});
};
//
const resetBulk = () => {
bulkValue.value = '';
bulkShow.value = false;
};
// ------------------------------
const flatTableData: tableItemType[] = []; // -- 便
@ -273,6 +281,9 @@ function menuChange(
}
}
//
resetBulk();
//
const selectList = flatTableData.filter((item) => item.granted); //
if (selectList.length === flatTableData.length) {
@ -390,8 +401,3 @@ type tableItemType = {
assetAccesses?: any[];
};
</script>
<style lang="less" scoped>
.permiss-tree-container {
}
</style>

View File

@ -1,10 +1,10 @@
<template>
<page-container>
<div class="details-container">
<a-tabs v-model:activeKey="activeKey">
<a-tab-pane key="1" tab="权限分配"><Permiss /></a-tab-pane>
<a-tab-pane key="2" tab="用户管理"><User /></a-tab-pane>
</a-tabs>
<j-tabs v-model:activeKey="activeKey">
<j-tab-pane key="1" tab="权限分配"><Permiss /></j-tab-pane>
<j-tab-pane key="2" tab="用户管理"><User /></j-tab-pane>
</j-tabs>
</div>
</page-container>
</template>
@ -12,7 +12,6 @@
<script setup lang="ts" name="Detail">
import Permiss from './Permiss/index.vue';
import User from './User/index.vue';
const route = useRoute();
const activeKey = ref('1');
</script>

View File

@ -1,18 +1,20 @@
<template>
<a-modal
v-model:visible="dialog.visible"
visible
title="新增"
width="670px"
@ok="dialog.handleOk"
@cancel="emits('update:visible', false)"
@ok="confirm"
:confirm-loading="loading"
>
<a-form ref="formRef" :model="form.data" layout="vertical">
<a-form ref="formRef" :model="form" layout="vertical">
<a-form-item
name="name"
label="名称"
:rules="[{ required: true, message: '请输入名称' }]"
>
<a-input
v-model:value="form.data.name"
v-model:value="form.name"
placeholder="请输入角色名称"
allow-clear
:maxlength="64"
@ -20,72 +22,52 @@
</a-form-item>
<a-form-item name="name" label="说明">
<a-textarea
v-model:value="form.data.description"
v-model:value="form.description"
placeholder="请输入说明"
allow-clear
:maxlength="200"
/>
</a-form-item>
</a-form>
<template #footer>
<a-button key="back" @click="dialog.visible = false">取消</a-button>
<a-button
key="submit"
type="primary"
:loading="form.loading"
@click="dialog.handleOk"
>确定</a-button
>
</template>
</a-modal>
</template>
<script setup lang="ts">
import { FormInstance, message } from 'ant-design-vue';
import { saveRole_api } from '@/api/system/role';
const router = useRouter();
import { useMenuStore } from '@/store/menu';
const route = useRoute();
const { jumpPage } = useMenuStore();
const emits = defineEmits(['update:visible']);
const props = defineProps<{
visible: boolean;
}>();
//
const dialog = reactive({
visible: false,
handleOk: () => {
formRef.value
?.validate()
.then(() => saveRole_api(form.data))
.then((resp) => {
if (resp.status === 200) {
message.success('操作成功');
dialog.visible = false;
if (route.query.save) {
// @ts-ignore
window?.onSaveSuccess && window.onSaveSuccess(resp.result.id);
window.close();
} else router.push(`/system/Role/detail/${resp.result.id}`);
}
});
},
//
changeVisible: (status: boolean, defaultForm: object = {}) => {
dialog.visible = status;
form.data = { name: '', description: '', ...defaultForm };
},
});
//
const loading = ref(false);
const form = ref<any>({});
const formRef = ref<FormInstance>();
const form = reactive({
loading: false,
data: {
name: '',
description: '',
},
});
//
defineExpose({
openDialog: dialog.changeVisible,
});
const confirm = () => {
loading.value = true;
formRef.value
?.validate()
.then(() => saveRole_api(form.value))
.then((resp) => {
if (resp.status === 200) {
message.success('操作成功');
emits('update:visible', false);
if (route.query.save) {
// @ts-ignore
window?.onSaveSuccess(resp.result.id);
window.close();
} else jumpPage(`system/Role/detail`, { id: resp.result.id });
}
})
.finally(() => (loading.value = false));
};
//
</script>
<style scoped></style>

View File

@ -1,20 +1,23 @@
<template>
<page-container>
<a-card class="role-container">
<Search :columns="query.columns" />
<j-advanced-search
:columns="columns"
@search="(params:any)=>queryParams = params"
/>
<j-pro-table
ref="tableRef"
:columns="table.columns"
:columns="columns"
:request="getRoleList_api"
model="TABLE"
:params="query.params"
:params="queryParams"
>
<template #headerTitle>
<PermissionButton
type="primary"
:uhasPermission="`${permission}:add`"
@click="table.clickAdd"
@click="dialogVisible = true"
>
<AIcon type="PlusOutlined" />新增
</PermissionButton>
@ -47,9 +50,7 @@
</template>
</j-pro-table>
<div class="dialogs">
<AddDialog ref="addDialogRef" />
</div>
<AddDialog v-if="dialogVisible" v-model:visible="dialogVisible" />
</a-card>
</page-container>
</template>
@ -59,73 +60,56 @@ import PermissionButton from '@/components/PermissionButton/index.vue';
import AddDialog from './components/AddDialog.vue';
import { getRoleList_api, delRole_api } from '@/api/system/role';
import { message } from 'ant-design-vue';
import { useMenuStore } from '@/store/menu';
const permission = 'system/Role';
const { jumpPage } = useMenuStore();
const addDialogRef = ref(); //
const router = useRouter();
const route = useRoute();
const isSave = !!useRoute().query.save;
//
const query = reactive({
columns: [
{
title: '标识',
dataIndex: 'id',
key: 'id',
ellipsis: true,
fixed: 'left',
const columns = [
{
title: '标识',
dataIndex: 'id',
key: 'id',
ellipsis: true,
fixed: 'left',
search: {
type: 'string',
},
{
title: '名称',
dataIndex: 'name',
key: 'name',
ellipsis: true,
},
{
title: '名称',
dataIndex: 'name',
key: 'name',
ellipsis: true,
search: {
type: 'string',
},
{
title: '描述',
key: 'description',
ellipsis: true,
dataIndex: 'description',
filters: true,
onFilter: true,
},
{
title: '描述',
key: 'description',
ellipsis: true,
dataIndex: 'description',
search: {
type: 'string',
},
{
title: '操作',
valueType: 'option',
width: 200,
fixed: 'right',
},
],
params: {},
});
},
{
title: '操作',
dataIndex: 'action',
key: 'action',
width: 200,
fixed: 'right',
scopedSlots: true,
},
];
const queryParams = ref({});
//
const tableRef = ref<Record<string, any>>({});
const table = reactive({
columns: [
{
title: '标识',
dataIndex: 'id',
key: 'id',
},
{
title: '名称',
dataIndex: 'name',
key: 'name',
},
{
title: '说明',
dataIndex: 'description',
key: 'description',
},
{
title: '操作',
dataIndex: 'action',
key: 'action',
scopedSlots: true,
},
],
tableData: [],
const table = {
clickAdd: () => {
addDialogRef.value.openDialog(true, {});
},
@ -137,13 +121,11 @@ const table = reactive({
}
});
},
clickEdit: (row: any) => {
router.push(`/system/Role/detail/${row.id}`);
clickEdit: ({ id }: { id: string }) => {
jumpPage(`system/Role/Detail`, { id });
},
});
nextTick(() => {
route.query.save && table.clickAdd();
});
};
const dialogVisible = ref(isSave);
</script>
<style lang="less" scoped>