This commit is contained in:
parent
32c378445f
commit
7bcbfe7288
@ -122,7 +122,10 @@ func SetAccountGroupMembership(ctx *context.Context, w http.ResponseWriter, req
|
||||
return
|
||||
}
|
||||
InvalidateSecurityRuntimeUser(user.ID, user.Account)
|
||||
response.NewSuccessResponse(map[string]any{"user_id": user.ID}).FPrint(w)
|
||||
response.NewSuccessResponse(map[string]any{
|
||||
"user_id": user.ID,
|
||||
"membership_version": user.SecurityVersion + 1,
|
||||
}).FPrint(w)
|
||||
}
|
||||
|
||||
func writeAccountGroupError(w http.ResponseWriter, err error) {
|
||||
|
||||
@ -3,7 +3,7 @@ import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { http } from '@/utils/axios'
|
||||
import { isRecentAuthenticationCancelled, requestWithRecentAuthentication } from '@/utils/recentAuthentication'
|
||||
|
||||
export function useAccountGroups(globalStatus) {
|
||||
export function useAccountGroups(globalStatus, onMembershipSaved = () => {}) {
|
||||
const accountGroups = ref([])
|
||||
const groupsLoading = ref(false)
|
||||
const groupsError = ref('')
|
||||
@ -125,6 +125,13 @@ export function useAccountGroups(globalStatus) {
|
||||
group_ids: [...membershipSelection.value]
|
||||
}))
|
||||
if (response?.errorNo !== 0) throw new Error(response?.errorMsg || '保存成员分组失败')
|
||||
const updatedUser = {
|
||||
...membershipUser.value,
|
||||
GroupIDs: [...membershipSelection.value],
|
||||
MembershipVersion: response.data.membership_version
|
||||
}
|
||||
membershipUser.value = updatedUser
|
||||
onMembershipSaved(updatedUser)
|
||||
membershipVisible.value = false
|
||||
ElMessage.success('成员分组已更新,目标账号需重新登录')
|
||||
await refreshGroups()
|
||||
|
||||
@ -217,3 +217,32 @@
|
||||
.membership-select {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.membership-summary {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.membership-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.membership-tags :deep(.el-tag) {
|
||||
height: auto;
|
||||
white-space: normal;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.membership-hint {
|
||||
margin: 8px 0 0;
|
||||
color: var(--pm-text-secondary);
|
||||
font-size: 12px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
@ -48,7 +48,9 @@ export function canManageRecoveryCode(user) {
|
||||
export function usePage() {
|
||||
const globalStatus = useGlobalStatusStore()
|
||||
|
||||
const groups = useAccountGroups(globalStatus)
|
||||
const groups = useAccountGroups(globalStatus, user => {
|
||||
if (selectedUser.value?.ID === user.ID) selectedUser.value = user
|
||||
})
|
||||
|
||||
const userInfoDialog = ref(false)
|
||||
|
||||
@ -56,6 +58,21 @@ export function usePage() {
|
||||
|
||||
const selectedUser = ref(null)
|
||||
|
||||
const selectedMembershipGroups = computed(() => {
|
||||
const user = selectedUser.value
|
||||
if (!user) return []
|
||||
return groups.accountGroups.value.filter(group =>
|
||||
groups.canManageGroups.value
|
||||
? (user.GroupIDs || [0]).includes(group.id)
|
||||
: group.rows.some(member => member.ID === user.ID)
|
||||
)
|
||||
})
|
||||
|
||||
const openMembershipDialog = () => {
|
||||
if (submitting.value || !selectedUser.value) return
|
||||
groups.editMembership(selectedUser.value)
|
||||
}
|
||||
|
||||
const recoveryCodeDialogVisible = ref(false)
|
||||
|
||||
const externalEmailDialogVisible = ref(false)
|
||||
@ -219,6 +236,8 @@ export function usePage() {
|
||||
roleChanged,
|
||||
submitting,
|
||||
selectedUser,
|
||||
selectedMembershipGroups,
|
||||
openMembershipDialog,
|
||||
editingCurrentUser,
|
||||
recoveryCodeWebManaged,
|
||||
recoveryCodeDialogVisible,
|
||||
|
||||
@ -119,7 +119,7 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<el-dialog v-model="membershipVisible" title="设置账号所属分组" width="450px" :close-on-click-modal="!groupSaving" :close-on-press-escape="!groupSaving" :show-close="!groupSaving">
|
||||
<el-dialog v-model="membershipVisible" title="设置账号所属分组" width="450px" :close-on-click-modal="!groupSaving" :close-on-press-escape="!groupSaving" :show-close="!groupSaving" append-to-body>
|
||||
<p>账号:{{ membershipUser?.Account }}</p>
|
||||
<el-form label-position="top">
|
||||
<el-form-item label="所属分组">
|
||||
@ -188,6 +188,33 @@
|
||||
</span>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item v-if="editModel === 'edit'" label="所属分组">
|
||||
<div class="membership-summary">
|
||||
<div class="membership-tags">
|
||||
<el-tag
|
||||
v-for="group in selectedMembershipGroups"
|
||||
:key="group.id"
|
||||
effect="plain"
|
||||
>
|
||||
{{ group.name }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="canManageGroups"
|
||||
:disabled="submitting || groupSaving || groupsLoading || Boolean(groupsError)"
|
||||
@click="openMembershipDialog"
|
||||
>
|
||||
分组管理
|
||||
</el-button>
|
||||
</div>
|
||||
<p v-if="canManageGroups" class="membership-hint">
|
||||
分组单独保存,不会提交本窗口其他修改;选择数量按账号已保存的权限级别校验。
|
||||
</p>
|
||||
<p v-else class="membership-hint">
|
||||
仅显示你有权查看的分组,成员归属由超级管理员维护。
|
||||
</p>
|
||||
</el-form-item>
|
||||
|
||||
<div v-if="editModel === 'edit'" class="security-edit-grid">
|
||||
<div class="security-edit-item">
|
||||
<div>
|
||||
@ -301,6 +328,8 @@ const {
|
||||
roleChanged,
|
||||
submitting,
|
||||
selectedUser,
|
||||
selectedMembershipGroups,
|
||||
openMembershipDialog,
|
||||
editingCurrentUser,
|
||||
recoveryCodeWebManaged,
|
||||
recoveryCodeDialogVisible,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user