Create.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. <template>
  2. <base-dialog @cancel="cancelDialog">
  3. <div slot="header">{{$t('cloudenv.create_extrnal_project')}}</div>
  4. <div slot="body">
  5. <steps class="my-3" v-model="step" />
  6. <a-form-model
  7. class="mt-3"
  8. ref="form"
  9. :model="fd"
  10. :rules="rules">
  11. <a-form-model-item v-if="step.currentStep === 0" prop="extrnal_project_name" :label="$t('cloudenv.text_95')" v-bind="formItemLayout">
  12. <a-input v-model="fd.extrnal_project_name" />
  13. </a-form-model-item>
  14. <a-form-model-item v-if="step.currentStep === 0 && isAzure" prop="provider" :label="$t('dictionary.cloudprovider')" v-bind="formItemLayout">
  15. <base-select
  16. v-model="fd.provider"
  17. :params="cloudproviderParams"
  18. filterable
  19. resource="cloudproviders" />
  20. </a-form-model-item>
  21. <template v-if="step.currentStep === 1">
  22. <a-form-model-item :label="$t('cloudenv.text_360')" prop="type" v-bind="formItemLayout">
  23. <a-radio-group v-model="fd.type">
  24. <template v-for="item of typeOptions">
  25. <a-radio-button :key="item.key" :value="item.key">{{ item.label }}</a-radio-button>
  26. </template>
  27. </a-radio-group>
  28. </a-form-model-item>
  29. <template v-if="fd.type === 'select'">
  30. <a-form-model-item prop="project" :label="params.projectLabel || $t('res.project')" v-bind="formItemLayout">
  31. <a-row :gutter="8">
  32. <a-col :span="12">
  33. <a-select v-model="domain" show-search @search="getConditionDomains" :filter-option="false" allow-clear dropdownClassName="oc-select-dropdown">
  34. <template v-for="item of domains">
  35. <a-select-option :key="item.id" :value="item.id">
  36. <span class="text-color-secondary option-prefix">{{ $t('res.domain') }}: </span>{{ item.name }}
  37. </a-select-option>
  38. </template>
  39. </a-select>
  40. </a-col>
  41. <a-col :span="12">
  42. <a-select v-model="fd.project" show-search @search="fetchProjects" :filter-option="false" allow-clear dropdownClassName="oc-select-dropdown">
  43. <template v-for="item of projects">
  44. <a-select-option :key="item.id" :value="item.id">
  45. <span class="text-color-secondary option-prefix">{{ $t('res.project') }}: </span>{{ item.name }}
  46. </a-select-option>
  47. </template>
  48. </a-select>
  49. </a-col>
  50. </a-row>
  51. </a-form-model-item>
  52. </template>
  53. <a-form-model-item v-if="fd.type === 'create'" prop="local_project_name" :label="$t('cloudenv.text_95')" v-bind="formItemLayout">
  54. <a-input v-model="fd.local_project_name" />
  55. </a-form-model-item>
  56. </template>
  57. </a-form-model>
  58. </div>
  59. <div slot="footer">
  60. <a-button type="primary" @click="handleConfirm" :loading="loading">{{ createText }}</a-button>
  61. <a-button @click="cancelDialog">{{ cancelText }}</a-button>
  62. </div>
  63. </base-dialog>
  64. </template>
  65. <script>
  66. import { mapGetters } from 'vuex'
  67. import step from '@/mixins/step'
  68. import DialogMixin from '@/mixins/dialog'
  69. import WindowsMixin from '@/mixins/windows'
  70. import { HYPERVISORS_MAP } from '@/constants'
  71. export default {
  72. name: 'ExternalProjectCreateDialog',
  73. mixins: [DialogMixin, WindowsMixin, step],
  74. data () {
  75. return {
  76. loading: false,
  77. domain: '',
  78. domains: [],
  79. domainLoading: false,
  80. projects: [],
  81. fd: {
  82. extrnal_project_name: '',
  83. local_project_name: '',
  84. type: 'select',
  85. project: '',
  86. },
  87. rules: {
  88. extrnal_project_name: [
  89. { required: true, message: this.$t('cloudenv.text_190') },
  90. { validator: this.$validate('externalProjectName') },
  91. ],
  92. local_project_name: [
  93. { required: true, message: this.$t('cloudenv.text_190') },
  94. { validator: this.$validate('externalProjectName') },
  95. ],
  96. project: [
  97. { required: true, message: this.$t('rules.project') },
  98. ],
  99. provider: [
  100. { required: true, message: this.$t('common_588') },
  101. ],
  102. },
  103. formItemLayout: this.params.formItemLayout || {
  104. wrapperCol: {
  105. span: 21,
  106. },
  107. labelCol: {
  108. span: 3,
  109. },
  110. },
  111. step: {
  112. steps: [
  113. { title: this.$t('cloudenv.create_extrnal_project'), key: 'create-extrnal' },
  114. { title: this.$t('cloudenv.link_local_project'), key: 'link-local' },
  115. ],
  116. currentStep: 0,
  117. },
  118. typeOptions: [
  119. { key: 'select', label: this.$t('cloudenv.select_local_project') },
  120. { key: 'create', label: this.$t('cloudenv.create_local_project') },
  121. ],
  122. projectMsg: {},
  123. }
  124. },
  125. computed: {
  126. ...mapGetters(['scope', 'userInfo', 'l3PermissionEnable', 'isAdminMode']),
  127. createText () {
  128. return this.step.currentStep ? this.$t('dialog.ok') : this.$t('cloudenv.text_104')
  129. },
  130. cancelText () {
  131. return this.step.currentStep ? this.$t('common.skip') : this.$t('dialog.cancel')
  132. },
  133. isAzure () {
  134. return this.params.cloudaccount && this.params.cloudaccount.provider === HYPERVISORS_MAP.azure.provider
  135. },
  136. cloudproviderParams () {
  137. return {
  138. scope: this.scope,
  139. cloudaccount_id: this.params.cloudaccount.id,
  140. }
  141. },
  142. },
  143. watch: {
  144. domain (val, oldVal) {
  145. if (val !== oldVal) {
  146. this.fd.project = ''
  147. this.fetchProjects()
  148. }
  149. },
  150. },
  151. destroyed () {
  152. this.dm = null
  153. this.pm = null
  154. },
  155. created () {
  156. this.dm = new this.$Manager('domains', 'v1')
  157. this.pm = new this.$Manager('projects', 'v1')
  158. this.getConditionDomains()
  159. },
  160. methods: {
  161. async getConditionDomains (query) {
  162. // 域管理后台只能选自己所在的domain
  163. // 全局共享 -> all scope domain
  164. // 多域共享 -> account domain + share_domains
  165. const cloudaccountDomain = {
  166. id: this.params.cloudaccount.domain_id,
  167. name: this.params.cloudaccount.project_domain,
  168. }
  169. if (!this.l3PermissionEnable) {
  170. const domains = [cloudaccountDomain]
  171. this.domains = domains
  172. this.domain = this.domains[0].id
  173. }
  174. if (!this.isAdminMode) {
  175. const domains = [
  176. {
  177. name: this.userInfo.projectDomain,
  178. id: this.userInfo.projectDomainId,
  179. },
  180. ]
  181. this.domains = domains
  182. this.domain = this.domains[0].id
  183. return
  184. }
  185. const { public_scope = 'none', shared_domains = [] } = this.params.cloudaccount
  186. let domains = []
  187. if (public_scope === 'none') {
  188. domains = [cloudaccountDomain]
  189. }
  190. if (public_scope === 'domain') {
  191. domains = shared_domains
  192. domains.push(cloudaccountDomain)
  193. }
  194. if (public_scope === 'system') {
  195. this.domainLoading = true
  196. try {
  197. const params = {
  198. scope: this.scope,
  199. limit: 20,
  200. }
  201. if (query) {
  202. params.filter = `name.contains(${query})`
  203. }
  204. const response = await this.dm.list({
  205. params,
  206. })
  207. const data = response.data.data || []
  208. domains = data
  209. } catch (error) {
  210. throw error
  211. } finally {
  212. this.domainLoading = false
  213. }
  214. }
  215. this.domains = domains
  216. this.domain = (this.domains[0] && this.domains[0].id) || ''
  217. },
  218. async fetchProjects (query) {
  219. const params = {
  220. scope: this.scope,
  221. domain_id: this.domain,
  222. limit: 20,
  223. }
  224. if (query) {
  225. params.filter = `name.contains(${query})`
  226. }
  227. try {
  228. const response = await this.pm.list({
  229. params,
  230. })
  231. const projects = response.data.data || []
  232. if (this.projectMsg.project_id && !this.projects.some(item => item.id === this.projectMsg.project_id)) {
  233. projects.push({
  234. id: this.projectMsg.project_id,
  235. name: this.projectMsg.project,
  236. })
  237. }
  238. this.projects = projects
  239. this.fd.project = this.projectMsg.project_id || ''
  240. } catch (error) {
  241. throw error
  242. }
  243. },
  244. async doCreateExtrnalProject (values) {
  245. const data = {
  246. name: values.extrnal_project_name,
  247. cloudaccount_id: this.params.cloudaccount.id,
  248. }
  249. if (this.isAzure) {
  250. data.manager_id = values.provider
  251. }
  252. return this.params.onManager('create', {
  253. managerArgs: {
  254. data,
  255. },
  256. })
  257. },
  258. async doChangeProject (values) {
  259. return this.params.onManager('batchPerformAction', {
  260. id: [values.id],
  261. managerArgs: {
  262. action: 'change-project',
  263. data: {
  264. project: values.project,
  265. },
  266. },
  267. })
  268. },
  269. async doCreateLocalProject (values) {
  270. return this.pm.create({
  271. data: {
  272. domain: this.domain,
  273. name: values.local_project_name,
  274. },
  275. })
  276. },
  277. async handleConfirm () {
  278. if (!this.params.cloudaccount) return
  279. this.loading = true
  280. try {
  281. await this.$refs.form.validate()
  282. if (this.step.currentStep === 0) {
  283. const { data } = await this.doCreateExtrnalProject(this.fd)
  284. this.fd.local_project_name = data.name
  285. this.fd.domain_id = data.domain_id
  286. this.step.currentStep = 1
  287. this.projectMsg = { project_id: data.project_id, project: data.project, id: data.id }
  288. } else if (this.step.currentStep === 1) {
  289. if (this.fd.type === 'select') {
  290. await this.doChangeProject({ id: this.projectMsg.id, project: this.fd.project })
  291. } else {
  292. const { data } = await this.doCreateLocalProject(this.fd)
  293. this.projectMsg.project_id = data.id
  294. this.projectMsg.project = data.name
  295. await this.doChangeProject({ id: this.projectMsg.id, project: data.id })
  296. }
  297. this.cancelDialog()
  298. }
  299. this.loading = false
  300. } catch (error) {
  301. this.loading = false
  302. throw error
  303. }
  304. },
  305. },
  306. }
  307. </script>