mirror of
https://github.com/rustfs/console.git
synced 2026-09-19 01:47:44 +08:00
feat: 用户组 编辑 删除
This commit is contained in:
@@ -8,15 +8,19 @@
|
||||
class="max-w-screen-md"
|
||||
:segmented="{
|
||||
content: true,
|
||||
action: true,
|
||||
action: true
|
||||
}">
|
||||
<n-card>
|
||||
<n-tabs type="card">
|
||||
<n-tab-pane name="users" tab="成员">
|
||||
<users-user-group-members :group="group" @search="getGroupData(group.name)"></users-user-group-members>
|
||||
<users-group-members
|
||||
:group="group"
|
||||
@search="getGroupData(group.name)"></users-group-members>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="policy" tab="策略">
|
||||
<users-user-group-policies :group="group" @search="getGroupData(group.name)"></users-user-group-policies>
|
||||
<users-group-policies
|
||||
:group="group"
|
||||
@search="getGroupData(group.name)"></users-group-policies>
|
||||
</n-tab-pane>
|
||||
<template #suffix>
|
||||
状态
|
||||
@@ -35,39 +39,39 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
// import { groupMembers, groupPolicies } from './';
|
||||
const visible = ref(false);
|
||||
const { getGroup, updateGroup } = useGroups();
|
||||
const visible = ref(false)
|
||||
const { getGroup, updateGroup } = useGroups()
|
||||
|
||||
interface GroupInfo {
|
||||
name: string;
|
||||
members: string[];
|
||||
status: string;
|
||||
name: string
|
||||
members: string[]
|
||||
status: string
|
||||
}
|
||||
|
||||
const group = ref<GroupInfo>({
|
||||
name: '',
|
||||
members: [],
|
||||
status: 'enabled',
|
||||
});
|
||||
status: 'enabled'
|
||||
})
|
||||
|
||||
// 用户组的状态发生变化
|
||||
const handerGroupStatusChange = async (val: string) => {
|
||||
await updateGroup(group.value.name, { ...group.value, status: val });
|
||||
await getGroupData(group.value.name);
|
||||
};
|
||||
await updateGroup(group.value.name, { ...group.value, status: val })
|
||||
await getGroupData(group.value.name)
|
||||
}
|
||||
async function openDialog(row: any) {
|
||||
await getGroupData(row.name);
|
||||
visible.value = true;
|
||||
getGroupData(row.name)
|
||||
visible.value = true
|
||||
}
|
||||
|
||||
// 获取用户信息
|
||||
async function getGroupData(name: string) {
|
||||
group.value = await getGroup(name);
|
||||
group.value = await getGroup(name)
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
openDialog,
|
||||
});
|
||||
openDialog
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
<template>
|
||||
<div>
|
||||
<n-card>
|
||||
<n-form ref="formRef" :model="searchForm" label-placement="left" :show-feedback="false">
|
||||
<n-form
|
||||
ref="formRef"
|
||||
:model="searchForm"
|
||||
label-placement="left"
|
||||
:show-feedback="false">
|
||||
<n-flex justify="space-between" v-if="!editStatus">
|
||||
<n-form-item class="!w-64" label="" path="name">
|
||||
<n-input placeholder="搜索用户" @input="filterName" />
|
||||
@@ -20,7 +24,11 @@
|
||||
</n-flex>
|
||||
<n-flex justify="space-between" v-else>
|
||||
<n-form-item class="!w-96" label="选择用户组的成员" path="members">
|
||||
<n-select v-model:value="members" filterable multiple :options="users" />
|
||||
<n-select
|
||||
v-model:value="members"
|
||||
filterable
|
||||
multiple
|
||||
:options="users" />
|
||||
</n-form-item>
|
||||
<n-space>
|
||||
<NFlex>
|
||||
@@ -41,23 +49,28 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { type DataTableColumns, type DataTableInst, NButton, NSpace } from 'naive-ui';
|
||||
const { listUsers } = useUsers();
|
||||
const { updateGroup } = useGroups();
|
||||
import {
|
||||
type DataTableColumns,
|
||||
type DataTableInst,
|
||||
NButton,
|
||||
NSpace
|
||||
} from 'naive-ui'
|
||||
const { listUsers } = useUsers()
|
||||
const { updateGroupMembers } = useGroups()
|
||||
|
||||
const messge = useMessage();
|
||||
const messge = useMessage()
|
||||
const props = defineProps({
|
||||
group: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const searchForm = reactive({
|
||||
name: '',
|
||||
});
|
||||
name: ''
|
||||
})
|
||||
interface RowData {
|
||||
name: string;
|
||||
name: string
|
||||
}
|
||||
|
||||
const columns: DataTableColumns<RowData> = [
|
||||
@@ -66,63 +79,65 @@ const columns: DataTableColumns<RowData> = [
|
||||
align: 'left',
|
||||
key: 'name',
|
||||
filter(value, row) {
|
||||
return !!row.name.includes(value.toString());
|
||||
},
|
||||
},
|
||||
];
|
||||
return !!row.name.includes(value.toString())
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 搜索过滤
|
||||
const tableRef = ref<DataTableInst>();
|
||||
const tableRef = ref<DataTableInst>()
|
||||
function filterName(value: string) {
|
||||
tableRef.value &&
|
||||
tableRef.value.filter({
|
||||
name: [value],
|
||||
});
|
||||
name: [value]
|
||||
})
|
||||
}
|
||||
const listData = computed(() => {
|
||||
return (
|
||||
props.group.members.map((item: string) => {
|
||||
return {
|
||||
name: item,
|
||||
};
|
||||
name: item
|
||||
}
|
||||
}) || []
|
||||
);
|
||||
});
|
||||
)
|
||||
})
|
||||
|
||||
/********************编辑****************/
|
||||
const editStatus = ref(false);
|
||||
const editStatus = ref(false)
|
||||
// 用户列表
|
||||
const users = ref([]);
|
||||
const users = ref<any[]>([])
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search'): void;
|
||||
}>();
|
||||
(e: 'search'): void
|
||||
}>()
|
||||
const getUserList = async () => {
|
||||
const res = await listUsers();
|
||||
const res = await listUsers()
|
||||
users.value = Object.entries(res).map(([username, info]) => ({
|
||||
label: username,
|
||||
value: username,
|
||||
...(typeof info === 'object' ? info : {}) // 展开用户信息
|
||||
}))
|
||||
}
|
||||
getUserList()
|
||||
|
||||
users.value = res.users.map((item: any) => {
|
||||
return {
|
||||
label: item.accessKey,
|
||||
value: item.accessKey,
|
||||
};
|
||||
});
|
||||
};
|
||||
getUserList();
|
||||
|
||||
const members = ref(props.group.members);
|
||||
const members = ref(props.group.members)
|
||||
const changeMebers = async () => {
|
||||
try {
|
||||
await updateGroup(props.group.name, {
|
||||
...props.group,
|
||||
// 修改组的成员
|
||||
await updateGroupMembers({
|
||||
group: props.group.name,
|
||||
members: members.value,
|
||||
});
|
||||
messge.success('修改成功');
|
||||
editStatus.value = false;
|
||||
emit('search');
|
||||
isRemove: false,
|
||||
groupStatus: 'enabled'
|
||||
})
|
||||
|
||||
messge.success('修改成功')
|
||||
editStatus.value = false
|
||||
emit('search')
|
||||
} catch {
|
||||
messge.error('修改失败');
|
||||
messge.error('修改失败')
|
||||
}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
<template>
|
||||
<div>
|
||||
<n-card>
|
||||
<n-form ref="formRef" :model="searchForm" label-placement="left" :show-feedback="false">
|
||||
<n-form
|
||||
ref="formRef"
|
||||
:model="searchForm"
|
||||
label-placement="left"
|
||||
:show-feedback="false">
|
||||
<n-flex justify="space-between" v-if="!editStatus">
|
||||
<n-form-item class="!w-64" label="" path="name">
|
||||
<n-input placeholder="搜索策略" @input="filterName" />
|
||||
@@ -20,7 +24,11 @@
|
||||
</n-flex>
|
||||
<n-flex justify="space-between" v-else>
|
||||
<n-form-item class="!w-96" label="选择用户组的策略" path="policies">
|
||||
<n-select v-model:value="name" filterable multiple :options="polices" />
|
||||
<n-select
|
||||
v-model:value="name"
|
||||
filterable
|
||||
multiple
|
||||
:options="polices" />
|
||||
</n-form-item>
|
||||
<n-space>
|
||||
<NFlex>
|
||||
@@ -41,22 +49,27 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { type DataTableColumns, type DataTableInst, NButton, NSpace } from 'naive-ui';
|
||||
const { listPolicies, setPolicyMultiple } = usePolicies();
|
||||
import {
|
||||
type DataTableColumns,
|
||||
type DataTableInst,
|
||||
NButton,
|
||||
NSpace
|
||||
} from 'naive-ui'
|
||||
const { listPolicies, setUserOrGroupPolicy } = usePolicies()
|
||||
|
||||
const messge = useMessage();
|
||||
const messge = useMessage()
|
||||
const props = defineProps({
|
||||
group: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const searchForm = reactive({
|
||||
name: '',
|
||||
});
|
||||
name: ''
|
||||
})
|
||||
interface RowData {
|
||||
name: string;
|
||||
name: string
|
||||
}
|
||||
|
||||
const columns: DataTableColumns<RowData> = [
|
||||
@@ -65,62 +78,64 @@ const columns: DataTableColumns<RowData> = [
|
||||
align: 'left',
|
||||
key: 'name',
|
||||
filter(value, row) {
|
||||
return !!row.name.includes(value.toString());
|
||||
},
|
||||
},
|
||||
];
|
||||
return !!row.name.includes(value.toString())
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 搜索过滤
|
||||
const tableRef = ref<DataTableInst>();
|
||||
const tableRef = ref<DataTableInst>()
|
||||
function filterName(value: string) {
|
||||
tableRef.value &&
|
||||
tableRef.value.filter({
|
||||
name: [value],
|
||||
});
|
||||
name: [value]
|
||||
})
|
||||
}
|
||||
const listData = computed(() => {
|
||||
return (
|
||||
props.group?.policy?.split(',').map((item: string) => {
|
||||
return {
|
||||
name: item,
|
||||
};
|
||||
name: item
|
||||
}
|
||||
}) || []
|
||||
);
|
||||
});
|
||||
)
|
||||
})
|
||||
|
||||
/********************编辑****************/
|
||||
const editStatus = ref(false);
|
||||
const editStatus = ref(false)
|
||||
// 策略列表
|
||||
const polices = ref([]);
|
||||
const polices = ref<any[]>([])
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search'): void;
|
||||
}>();
|
||||
(e: 'search'): void
|
||||
}>()
|
||||
const getPoliciesList = async () => {
|
||||
const res = await listPolicies();
|
||||
polices.value = res.policies.map((item: any) => {
|
||||
const res = await listPolicies()
|
||||
polices.value = Object.keys(res).map((key) => {
|
||||
return {
|
||||
label: item.name,
|
||||
value: item.name,
|
||||
};
|
||||
});
|
||||
};
|
||||
getPoliciesList();
|
||||
label: key,
|
||||
value: key
|
||||
}
|
||||
})
|
||||
}
|
||||
getPoliciesList()
|
||||
|
||||
const name = ref(props.group?.policy?.split(',') || []);
|
||||
const name = ref(props.group?.policy?.split(',') || [])
|
||||
const changePolicies = async () => {
|
||||
try {
|
||||
await setPolicyMultiple({
|
||||
groups: [encodeURIComponent(props.group.name)],
|
||||
name: name.value,
|
||||
});
|
||||
messge.success('修改成功');
|
||||
editStatus.value = false;
|
||||
emit('search');
|
||||
await setUserOrGroupPolicy({
|
||||
policyName: name.value,
|
||||
userOrGroup: encodeURIComponent(props.group.name),
|
||||
isGroup: true
|
||||
})
|
||||
|
||||
messge.success('修改成功')
|
||||
editStatus.value = false
|
||||
emit('search')
|
||||
} catch {
|
||||
messge.error('修改失败');
|
||||
messge.error('修改失败')
|
||||
}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
<template>
|
||||
<div>
|
||||
<n-form class="mb-4 mt-2" ref="formRef" :model="searchForm" label-placement="left" :show-feedback="false">
|
||||
<n-form
|
||||
class="mb-4 mt-2"
|
||||
ref="formRef"
|
||||
:model="searchForm"
|
||||
label-placement="left"
|
||||
:show-feedback="false">
|
||||
<n-flex justify="space-between">
|
||||
<n-form-item label="" path="name">
|
||||
<n-input placeholder="搜索用户组" @input="filterName" />
|
||||
@@ -13,7 +18,10 @@
|
||||
</template>
|
||||
删除选中项
|
||||
</NButton> -->
|
||||
<NButton :disabled="!checkedKeys.length" secondary @click="allocationPolicy">
|
||||
<NButton
|
||||
:disabled="!checkedKeys.length"
|
||||
secondary
|
||||
@click="allocationPolicy">
|
||||
<template #icon>
|
||||
<Icon name="ri:group-2-fill"></Icon>
|
||||
</template>
|
||||
@@ -39,14 +47,26 @@
|
||||
:row-key="rowKey"
|
||||
@update:checked-row-keys="handleCheck" />
|
||||
<users-group-edit ref="editItemRef"></users-group-edit>
|
||||
<users-group-new v-model:visible="newItemVisible" @search="getDataList" ref="newItemRef"></users-group-new>
|
||||
<users-group-set-policies-mutiple :checkedKeys="checkedKeys" ref="policiesRef"></users-group-set-policies-mutiple>
|
||||
<users-group-new
|
||||
v-model:visible="newItemVisible"
|
||||
@search="getDataList"
|
||||
ref="newItemRef"></users-group-new>
|
||||
<users-group-set-policies-mutiple
|
||||
:checkedKeys="checkedKeys"
|
||||
ref="policiesRef"></users-group-set-policies-mutiple>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { type DataTableColumns, type DataTableInst, type DataTableRowKey, NButton, NPopconfirm, NSpace } from "naive-ui"
|
||||
import { Icon } from "#components"
|
||||
import {
|
||||
type DataTableColumns,
|
||||
type DataTableInst,
|
||||
type DataTableRowKey,
|
||||
NButton,
|
||||
NPopconfirm,
|
||||
NSpace
|
||||
} from 'naive-ui'
|
||||
import { Icon } from '#components'
|
||||
// import { groupEdit, newGroup, setPoliciesMutiple } from '../components';
|
||||
|
||||
const { $api } = useNuxtApp()
|
||||
@@ -55,7 +75,7 @@ const message = useMessage()
|
||||
const group = useGroups()
|
||||
|
||||
const searchForm = reactive({
|
||||
name: "",
|
||||
name: ''
|
||||
})
|
||||
interface RowData {
|
||||
name: string
|
||||
@@ -63,62 +83,62 @@ interface RowData {
|
||||
|
||||
const columns: DataTableColumns<RowData> = [
|
||||
{
|
||||
type: "selection",
|
||||
type: 'selection'
|
||||
},
|
||||
{
|
||||
title: "名称",
|
||||
align: "left",
|
||||
key: "name",
|
||||
title: '名称',
|
||||
align: 'left',
|
||||
key: 'name',
|
||||
filter(value, row) {
|
||||
return !!row.name.includes(value.toString())
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
key: "actions",
|
||||
align: "center",
|
||||
title: '操作',
|
||||
key: 'actions',
|
||||
align: 'center',
|
||||
width: 180,
|
||||
render: (row: any) => {
|
||||
return h(
|
||||
NSpace,
|
||||
{
|
||||
justify: "center",
|
||||
justify: 'center'
|
||||
},
|
||||
{
|
||||
default: () => [
|
||||
h(
|
||||
NButton,
|
||||
{
|
||||
size: "small",
|
||||
size: 'small',
|
||||
secondary: true,
|
||||
onClick: () => openEditItem(row),
|
||||
onClick: () => openEditItem(row)
|
||||
},
|
||||
{
|
||||
default: () => "",
|
||||
icon: () => h(Icon, { name: "ri:edit-2-line" }),
|
||||
default: () => '',
|
||||
icon: () => h(Icon, { name: 'ri:edit-2-line' })
|
||||
}
|
||||
),
|
||||
h(
|
||||
NPopconfirm,
|
||||
{ onPositiveClick: () => deleteItem(row) },
|
||||
{
|
||||
default: () => "确认删除",
|
||||
default: () => '确认删除',
|
||||
trigger: () =>
|
||||
h(
|
||||
NButton,
|
||||
{ size: "small", secondary: true },
|
||||
{ size: 'small', secondary: true },
|
||||
{
|
||||
default: () => "",
|
||||
icon: () => h(Icon, { name: "ri:delete-bin-5-line" }),
|
||||
default: () => '',
|
||||
icon: () => h(Icon, { name: 'ri:delete-bin-5-line' })
|
||||
}
|
||||
),
|
||||
)
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
]
|
||||
}
|
||||
)
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 搜索过滤
|
||||
@@ -126,7 +146,7 @@ const tableRef = ref<DataTableInst>()
|
||||
function filterName(value: string) {
|
||||
tableRef.value &&
|
||||
tableRef.value.filter({
|
||||
name: [value],
|
||||
name: [value]
|
||||
})
|
||||
}
|
||||
const listData = ref<any[]>([])
|
||||
@@ -141,12 +161,12 @@ const getDataList = async () => {
|
||||
listData.value =
|
||||
res?.map((item: string) => {
|
||||
return {
|
||||
name: item,
|
||||
name: item
|
||||
}
|
||||
}) || []
|
||||
checkedKeys.value = []
|
||||
} catch (error) {
|
||||
message.error("获取数据失败")
|
||||
message.error('获取数据失败')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,16 +193,27 @@ function openEditItem(row: any) {
|
||||
/** ***********************************删除 */
|
||||
async function deleteItem(row: any) {
|
||||
try {
|
||||
const res = await group.updateGroupMembers({
|
||||
// 获取组的成员
|
||||
const info = await group.getGroup(row.name)
|
||||
// 清空组的成员
|
||||
await group.updateGroupMembers({
|
||||
group: row.name,
|
||||
members: info.members,
|
||||
isRemove: true,
|
||||
groupStatus: 'enabled'
|
||||
})
|
||||
const t = await group.getGroup(row.name)
|
||||
// 删除组
|
||||
await group.updateGroupMembers({
|
||||
group: row.name,
|
||||
members: [],
|
||||
isRemove: true,
|
||||
groupStatus: "enabled",
|
||||
groupStatus: 'enabled'
|
||||
})
|
||||
message.success("删除成功")
|
||||
message.success('删除成功')
|
||||
getDataList()
|
||||
} catch (error) {
|
||||
message.error("删除失败")
|
||||
message.error('删除失败')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,13 +229,13 @@ function handleCheck(keys: DataTableRowKey[]) {
|
||||
}
|
||||
function deleteByList() {
|
||||
dialog.error({
|
||||
title: "警告",
|
||||
content: "你确定要删除所有选中的用户组吗?",
|
||||
positiveText: "确定",
|
||||
negativeText: "取消",
|
||||
title: '警告',
|
||||
content: '你确定要删除所有选中的用户组吗?',
|
||||
positiveText: '确定',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: () => {
|
||||
if (!checkedKeys.value.length) {
|
||||
message.error("请至少选择一项")
|
||||
message.error('请至少选择一项')
|
||||
return
|
||||
}
|
||||
checkedKeys.value.forEach(async (element: any) => {
|
||||
@@ -212,7 +243,7 @@ function deleteByList() {
|
||||
})
|
||||
|
||||
getDataList()
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user