11<script setup lang="ts">
22import { computed , reactive , ref } from ' vue'
3- import type { FormInstance , FormRules } from ' element-plus'
3+ import type { FormInstance } from ' element-plus'
44import RoleApi from ' @/api/admin/system/role'
55import UserManageApi from ' @/api/admin/system/user-manage'
66import WorkspaceApi from ' @/api/admin/system/workspace'
@@ -13,93 +13,74 @@ import {
1313} from ' @/api/types'
1414import { useStore } from ' @/stores'
1515import { MsgSuccess } from ' @/utils/message'
16+ import MemberWorkspaceSetting from ' ./components/MemberWorkspaceSetting.vue'
17+
18+ defineOptions ({ name: ' AddRoleMemberDrawer' })
1619
1720const props = defineProps <{ currentRole: RoleItem }>()
1821const emit = defineEmits <{ refresh: [] }>()
1922const { auth } = useStore ()
2023
2124const visible = ref (false )
2225const loading = ref (false )
23- const optionsLoading = ref (false )
2426const formRef = ref <FormInstance >()
25- const memberRows = reactive <CreateRoleMemberItem []>([])
26- const userOptions = ref <SystemUserOption []>([])
27- const workspaceOptions = ref <WorkspaceItem []>([])
27+ const memberForm = reactive <{ members: CreateRoleMemberItem [] }>({ members: [] })
2828const showWorkspace = computed (() => props .currentRole .type !== ROLE_TYPE .ADMIN && auth .isEE )
29- const rules: FormRules = {
30- user_ids: [{ required: true , message: ' 请选择用户' , trigger: ' change' }],
31- workspace_ids: [{ required: true , message: ' 请选择工作空间' , trigger: ' change' }],
32- }
33- let searchTimer: ReturnType <typeof setTimeout > | null = null
3429
35- function createEmptyRow(): CreateRoleMemberItem {
36- return { user_ids: [], ... (showWorkspace .value ? { workspace_ids: [] } : {}) }
37- }
30+ /* 成员与工作空间选项 */
31+ const userOptions = ref <SystemUserOption []>([])
32+ const userOptionsLoading = ref (false )
33+ const workspaceOptions = ref <WorkspaceItem []>([])
34+ const workspaceOptionsLoading = ref (false )
3835
39- function loadOptions( query ? : string ) {
40- optionsLoading .value = true
41- return Promise . all ([
42- UserManageApi . getAllUsers ( query ? { nick_name: query } : undefined ),
43- showWorkspace . value ? WorkspaceApi . getSystemWorkspaceList () : Promise . resolve ([]),
44- ] )
45- . then (([ users , workspaces ]) => {
46- userOptions . value = users
47- workspaceOptions . value = workspaces
36+ function loadUserOptions( keyword = ' ' ) {
37+ userOptionsLoading .value = true
38+ return UserManageApi . getAllUsers ( keyword ? { nick_name: keyword } : undefined )
39+ . then (( users ) => {
40+ const selectedUserIds = new Set ( memberForm . members . flatMap (({ user_ids }) => user_ids ))
41+ const selectedUserOptions = userOptions . value . filter (({ id }) => selectedUserIds . has ( id ) )
42+ userOptions . value = [
43+ ... new Map ([ ... selectedUserOptions , ... users ]. map (( user ) => [ user . id , user ])). values (),
44+ ]
4845 })
4946 .finally (() => {
50- optionsLoading .value = false
47+ userOptionsLoading .value = false
5148 })
5249}
5350
54- function handleRemoteSearch(query : string ) {
55- if (searchTimer ) clearTimeout (searchTimer )
56- searchTimer = setTimeout (() => loadOptions (query ), 300 )
57- }
58-
59- function handleAddRow() {
60- memberRows .push (createEmptyRow ())
61- }
62-
63- function handleDeleteRow(index : number ) {
64- if (memberRows .length > 1 ) memberRows .splice (index , 1 )
65- }
51+ function loadWorkspaceOptions() {
52+ if (! showWorkspace .value ) return Promise .resolve ()
6653
67- function resetData() {
68- memberRows .splice (0 , memberRows .length , createEmptyRow ())
69- userOptions .value = []
70- workspaceOptions .value = []
71- loading .value = false
72- optionsLoading .value = false
73- formRef .value ?.clearValidate ()
74- if (searchTimer ) {
75- clearTimeout (searchTimer )
76- searchTimer = null
77- }
54+ workspaceOptionsLoading .value = true
55+ return WorkspaceApi .getSystemWorkspaceList ()
56+ .then ((workspaces ) => {
57+ workspaceOptions .value = workspaces
58+ })
59+ .finally (() => {
60+ workspaceOptionsLoading .value = false
61+ })
7862}
7963
8064function open() {
81- resetData ()
65+ memberForm . members = [{ user_ids: [], workspace_ids: [] }]
8266 visible .value = true
83- loadOptions ()
84- }
85-
86- function close() {
87- visible .value = false
88- resetData ()
67+ return Promise .all ([loadUserOptions (), loadWorkspaceOptions ()])
8968}
9069
9170function submit() {
9271 formRef .value ?.validate ((valid ) => {
9372 if (! valid ) return
94- const members = memberRows .map ((row ) => ({
95- user_ids: row .user_ids ,
73+
74+ const members = memberForm .members .map ((member ) => ({
75+ user_ids: [... member .user_ids ],
9676 workspace_ids:
9777 props .currentRole .type === ROLE_TYPE .ADMIN
9878 ? [' None' ]
9979 : auth .isPE
10080 ? [' default' ]
101- : row . workspace_ids ,
81+ : [ ... ( member . workspace_ids ?? [])] ,
10282 }))
83+
10384 loading .value = true
10485 RoleApi .postRoleMembers (props .currentRole .id , { members })
10586 .then (() => {
@@ -113,74 +94,38 @@ function submit() {
11394 })
11495}
11596
97+ function close() {
98+ visible .value = false
99+ resetData ()
100+ }
101+
102+ function resetData() {
103+ memberForm .members = []
104+ loading .value = false
105+ userOptions .value = []
106+ userOptionsLoading .value = false
107+ workspaceOptions .value = []
108+ workspaceOptionsLoading .value = false
109+ formRef .value ?.clearValidate ()
110+ }
111+
116112defineExpose ({ open })
117113 </script >
118114
119115<template >
120- <MkDrawer v-model =" visible " title="添加成员" size="600" @closed =" resetData " >
121- <el-form ref =" formRef" :model =" memberRows" label-position =" top" >
122- <el-scrollbar >
123- <div v-for =" (row, index) in memberRows" :key =" index" class =" mb-3 flex items-end gap-2" >
124- <el-form-item
125- :label =" index === 0 ? '用户' : ''"
126- :prop =" `${index}.user_ids`"
127- :rules =" rules.user_ids"
128- class =" mb-0 flex-1"
129- >
130- <el-select
131- v-model =" row.user_ids"
132- class =" w-full"
133- filterable
134- remote
135- multiple
136- collapse-tags
137- collapse-tags-tooltip
138- reserve-keyword
139- :remote-method =" handleRemoteSearch"
140- :loading =" optionsLoading"
141- placeholder =" 请选择用户"
142- >
143- <el-option
144- v-for =" user in userOptions"
145- :key =" user.id"
146- :label =" user.nick_name || user.username"
147- :value =" user.id"
148- />
149- </el-select >
150- </el-form-item >
151- <el-form-item
152- v-if =" showWorkspace"
153- :label =" index === 0 ? '工作空间' : ''"
154- :prop =" `${index}.workspace_ids`"
155- :rules =" rules.workspace_ids"
156- class =" mb-0 flex-1"
157- >
158- <el-select
159- v-model =" row.workspace_ids"
160- class =" w-full"
161- filterable
162- multiple
163- collapse-tags
164- collapse-tags-tooltip
165- placeholder =" 请选择工作空间"
166- >
167- <el-option
168- v-for =" workspace in workspaceOptions"
169- :key =" workspace.id"
170- :label =" workspace.name"
171- :value =" workspace.id"
172- />
173- </el-select >
174- </el-form-item >
175- <el-button text :disabled =" memberRows.length === 1" @click =" handleDeleteRow(index)"
176- ><MkIcon name="icon_delete-trash_outlined"
177- /></el-button >
178- </div >
179- </el-scrollbar >
180- <el-button text type =" primary" @click =" handleAddRow"
181- ><MkIcon name="icon_add_outlined" />添加</el-button
182- >
116+ <MkDrawer v-model =" visible " title="添加成员" @closed =" resetData " >
117+ <el-form ref =" formRef" :model =" memberForm" label-position =" top" >
118+ <MemberWorkspaceSetting
119+ v-model =" memberForm .members "
120+ :remote-user-method =" loadUserOptions "
121+ :show-workspace =" showWorkspace "
122+ :user-loading =" userOptionsLoading "
123+ :user-options =" userOptions "
124+ :workspace-loading =" workspaceOptionsLoading "
125+ :workspace-options =" workspaceOptions "
126+ />
183127 </el-form >
128+
184129 <template #footer >
185130 <el-button @click =" close" >取消</el-button >
186131 <el-button type =" primary" :loading =" loading" @click =" submit" >添加</el-button >
0 commit comments