Add.vue 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. <template>
  2. <base-dialog @cancel="cancelDialog">
  3. <div slot="header">{{$t('common_114')}}</div>
  4. <div slot="body">
  5. <!--a-alert :showIcon="false" banner class="mb-2">
  6. <div slot="message">{{$t('system.text_453', [$t('dictionary.policy', $t('dictionary.role'))]) }}
  7. </div>
  8. </a-alert-->
  9. <dialog-selected-tips :name="$t('dictionary.project')" :count="params.data.length" :action="$t('common_114')" />
  10. <dialog-table :data="params.data" :columns="params.columns.slice(0, 2)" />
  11. <a-form
  12. :form="form.fc">
  13. <a-form-item :label="$t('system.text_48')" v-bind="formItemLayout">
  14. <a-radio-group v-model="type" @change="handleTypeChange">
  15. <a-radio-button
  16. v-for="item of typeOptions"
  17. :key="item.value"
  18. :value="item.value">
  19. {{item.label}}
  20. </a-radio-button>
  21. </a-radio-group>
  22. </a-form-item>
  23. <a-form-item :label="$t('dictionary.domain')" v-bind="formItemLayout" v-if="isAdminMode">
  24. <base-select
  25. v-decorator="decorators.domain"
  26. version="v1"
  27. resource="domains"
  28. filterable
  29. :params="domainParams"
  30. :select-props="{ placeholder: $t('rules.project') }"
  31. @change="domainChange" />
  32. </a-form-item>
  33. <a-form-item v-if="type === 'group'" :label="$t('dictionary.group')" v-bind="formItemLayout" key="group">
  34. <base-select
  35. v-decorator="decorators.groups"
  36. resource="groups"
  37. version="v1"
  38. remote
  39. :params="groupsParams"
  40. :remote-fn="q => ({ filter: `name.contains(${q})` })"
  41. :cancel-token="groupsCancelToken"
  42. :destroyedCallBack="groupDestroyed"
  43. :select-props="{ mode: 'multiple' }">
  44. <template v-slot:optionTemplate="{ options }">
  45. <a-select-option v-for="item in options" :key="item.id" :value="item.id" :disabled="item.__disabled">
  46. <div class="d-flex">
  47. <span class="text-truncate flex-fill mr-2">{{ item.name }}</span>
  48. <!-- template v-if="domain_id === 'default'" -->
  49. <span style="color: #8492a6; font-size: 13px">{{ $t('dictionary.domain') }}:{{ item.project_domain }}</span>
  50. <!-- /template -->
  51. </div>
  52. </a-select-option>
  53. </template>
  54. </base-select>
  55. </a-form-item>
  56. <a-form-item v-if="type === 'user'" :label="$t('dictionary.user')" v-bind="formItemLayout" key="user">
  57. <base-select
  58. v-decorator="decorators.users"
  59. resource="users"
  60. version="v1"
  61. :params="usersParams"
  62. remote
  63. :remote-fn="q => ({ filter: `name.contains(${q})` })"
  64. :cancel-token="usersCancelToken"
  65. :destroyedCallBack="userDestroyed"
  66. :select-props="{ mode: 'multiple' }"
  67. @update:items="userSelectChange">
  68. <template v-slot:optionTemplate="{ options }">
  69. <a-select-option v-for="item in options" :key="item.id" :value="item.id" :disabled="item.__disabled">
  70. <div class="d-flex">
  71. <span class="text-truncate flex-fill mr-2">{{ item.name }}</span>
  72. <!-- template v-if="domain_id === 'default'" -->
  73. <span style="color: #8492a6; font-size: 13px">{{ $t('dictionary.domain') }}:{{ item.project_domain }}</span>
  74. <!-- /template -->
  75. </div>
  76. </a-select-option>
  77. </template>
  78. </base-select>
  79. </a-form-item>
  80. <a-form-item :label="$t('dictionary.role')" v-bind="formItemLayout">
  81. <base-select
  82. v-decorator="decorators.roles"
  83. resource="roles"
  84. version="v1"
  85. remote
  86. :params="rolesParams"
  87. :remote-fn="q => ({ filter: `name.contains(${q})` })"
  88. :select-props="{ mode: 'multiple' }">
  89. <template v-slot:optionTemplate="{ options }">
  90. <a-select-option v-for="item in options" :key="item.id" :value="item.id" :disabled="item.__disabled">
  91. <div class="d-flex">
  92. <span class="text-truncate flex-fill mr-2">{{ item.name }}</span>
  93. <template v-if="domain_id === 'default'">
  94. <span style="color: #8492a6; font-size: 13px">{{ $t('dictionary.domain') }}:{{ item.project_domain }}</span>
  95. </template>
  96. </div>
  97. </a-select-option>
  98. </template>
  99. </base-select>
  100. </a-form-item>
  101. <a-form-item v-if="type === 'user' && isSelectedUserDisabled" :label="$t('iam.enabled_user')" v-bind="formItemLayout" :extra="$t('iam.some_user_can_enabled')">
  102. <a-switch
  103. :checkedChildren="$t('common_292')"
  104. :unCheckedChildren="$t('common_293')"
  105. v-decorator="decorators.enable_all_users" />
  106. </a-form-item>
  107. </a-form>
  108. </div>
  109. <div slot="footer">
  110. <a-button type="primary" @click="handleConfirm" :loading="loading">{{ $t('dialog.ok') }}</a-button>
  111. <a-button @click="cancelDialog">{{ $t('dialog.cancel') }}</a-button>
  112. </div>
  113. </base-dialog>
  114. </template>
  115. <script>
  116. import axios from 'axios'
  117. import { mapGetters } from 'vuex'
  118. import DialogMixin from '@/mixins/dialog'
  119. import WindowsMixin from '@/mixins/windows'
  120. export default {
  121. name: 'ProjectAddUserOrGroupDialog',
  122. mixins: [DialogMixin, WindowsMixin],
  123. data () {
  124. const domainId = this.params.data[0].domain_id
  125. return {
  126. loading: false,
  127. domain_id: domainId,
  128. form: {
  129. fc: this.$form.createForm(this),
  130. },
  131. decorators: {
  132. domain: [
  133. 'domain',
  134. {
  135. initialValue: domainId,
  136. },
  137. ],
  138. groups: [
  139. 'groups',
  140. {
  141. rules: [
  142. {
  143. required: true,
  144. message: this.$t('rules.group'),
  145. },
  146. ],
  147. },
  148. ],
  149. users: [
  150. 'users',
  151. {
  152. rules: [
  153. {
  154. required: true,
  155. message: this.$t('rules.user'),
  156. },
  157. ],
  158. },
  159. ],
  160. roles: [
  161. 'roles',
  162. {
  163. rules: [
  164. {
  165. required: true,
  166. message: this.$t('rules.role'),
  167. },
  168. ],
  169. },
  170. ],
  171. enable_all_users: [
  172. 'enable_all_users',
  173. {
  174. initialValue: false,
  175. },
  176. ],
  177. },
  178. formItemLayout: {
  179. wrapperCol: {
  180. span: 20,
  181. },
  182. labelCol: {
  183. span: 4,
  184. },
  185. },
  186. type: 'user',
  187. typeOptions: [
  188. {
  189. label: this.$t('common_312'),
  190. value: 'user',
  191. },
  192. {
  193. label: this.$t('common_308'),
  194. value: 'group',
  195. },
  196. ],
  197. selectedUsers: [],
  198. }
  199. },
  200. computed: {
  201. ...mapGetters(['scope', 'isAdminMode']),
  202. domainOptions () {
  203. const ret = [
  204. { label: this.params.data[0].project_domain, value: this.params.data[0].domain_id },
  205. ]
  206. return ret
  207. },
  208. groupsParams () {
  209. if (this.domain_id !== 'default') {
  210. return {
  211. scope: this.scope,
  212. domain_id: this.domain_id,
  213. }
  214. }
  215. return {
  216. scope: this.scope,
  217. domain_id: this.domain_id,
  218. }
  219. },
  220. usersParams () {
  221. if (this.domain_id !== 'default') {
  222. return {
  223. scope: this.scope,
  224. domain_id: this.domain_id,
  225. limit: 20,
  226. }
  227. }
  228. return {
  229. scope: this.scope,
  230. domain_id: this.domain_id,
  231. limit: 20,
  232. }
  233. },
  234. rolesParams () {
  235. return {
  236. scope: this.scope,
  237. domain_id: this.domain_id,
  238. limit: 20,
  239. }
  240. },
  241. domainParams () {
  242. return {
  243. scope: this.scope,
  244. }
  245. },
  246. isSelectedUserDisabled () {
  247. return this.selectedUsers.some(item => !item.enabled)
  248. },
  249. },
  250. // watch: {
  251. // domain_id () {
  252. // this.form.fc.resetFields()
  253. // },
  254. // },
  255. destroyed () {
  256. this.manager = null
  257. },
  258. created () {
  259. this.manager = new this.$Manager('projects', 'v1')
  260. this.groupsCancelToken = new axios.CancelToken(cancel => { this.groupsCancel = cancel })
  261. this.usersCancelToken = new axios.CancelToken(cancel => { this.usersCancel = cancel })
  262. },
  263. methods: {
  264. handleTypeChange (e) {
  265. if (e.target.value === 'group') {
  266. this.groupsCancelToken = new axios.CancelToken(cancel => { this.groupsCancel = cancel })
  267. } else {
  268. this.usersCancelToken = new axios.CancelToken(cancel => { this.usersCancel = cancel })
  269. }
  270. },
  271. groupDestroyed () {
  272. this.groupsCancel()
  273. },
  274. userDestroyed () {
  275. this.usersCancel()
  276. },
  277. async handleConfirm () {
  278. this.loading = true
  279. try {
  280. const values = await this.form.fc.validateFields()
  281. await this.manager.performAction({
  282. id: this.params.data[0].id,
  283. action: 'join',
  284. data: values,
  285. })
  286. this.loading = false
  287. this.$bus.$emit('ProjectDirectlyUnderUserListRefresh')
  288. this.params.success()
  289. this.cancelDialog()
  290. } catch (error) {
  291. this.loading = false
  292. throw error
  293. }
  294. },
  295. domainChange (val) {
  296. this.domain_id = val
  297. },
  298. userSelectChange (val) {
  299. this.selectedUsers = val
  300. },
  301. },
  302. }
  303. </script>