feat: 用户组 编辑 删除

This commit is contained in:
cxymds
2025-02-22 22:25:42 +08:00
parent 4cb32c13e5
commit b3cc45ac60
5 changed files with 219 additions and 154 deletions
+22 -18
View File
@@ -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>
+61 -46
View File
@@ -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>
+59 -44
View File
@@ -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>
+73 -42
View File
@@ -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>