Create.vue 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. <template>
  2. <base-dialog @cancel="cancelDialog">
  3. <div slot="header">{{$t('network.text_696')}}</div>
  4. <div slot="body">
  5. <a-form
  6. :form="form.fc">
  7. <a-form-item v-bind="formItemLayout" :label="$t('network.text_205', [$t('dictionary.domain')])" v-if="$store.getters.isAdminMode">
  8. <domain-select v-decorator="decorators.project_domain" />
  9. </a-form-item>
  10. <a-form-item :label="$t('network.text_21')" v-bind="formItemLayout">
  11. <a-input v-decorator="decorators.name" :placeholder="$t('validator.resourceName')" />
  12. </a-form-item>
  13. <a-form-item :label="$t('common.description')" v-bind="formItemLayout">
  14. <a-textarea :auto-size="{ minRows: 1, maxRows: 3 }" v-decorator="decorators.description" :placeholder="$t('common_367')" />
  15. </a-form-item>
  16. <a-form-item label="VPC" v-bind="formItemLayout" :validateStatus="vpcValidateStatus" :help="vpcHelp" :required="true">
  17. <a-row :gutter="8">
  18. <a-col :span="12">
  19. <a-select
  20. v-decorator="decorators.area"
  21. @change="handleAreaChange"
  22. :placeholder="$t('network.text_199')">
  23. <a-select-option v-for="item in areas" :value="item.value" :key="item.value">
  24. <span class="text-color-secondary option-prefix">{{ $t('network.text_199') }}:</span>
  25. {{item.label}}
  26. </a-select-option>
  27. </a-select>
  28. </a-col>
  29. <a-col :span="12">
  30. <a-select
  31. v-decorator="decorators.vpc"
  32. placeholder="VPC">
  33. <a-select-option v-for="item in vpcs" :value="item.value" :key="item.value">
  34. <span class="text-color-secondary option-prefix">VPC:</span>
  35. {{item.label}}
  36. </a-select-option>
  37. </a-select>
  38. </a-col>
  39. </a-row>
  40. </a-form-item>
  41. <a-form-item :label="$t('network.text_24')" v-bind="formItemLayout">
  42. <a-select
  43. show-search
  44. :filterOption="filterOption"
  45. v-decorator="decorators.zone"
  46. :placeholder="$t('network.text_24')">
  47. <a-select-option v-for="item in zones" :value="item.value" :key="item.value">
  48. {{item.label}}
  49. </a-select-option>
  50. </a-select>
  51. </a-form-item>
  52. <a-form-item :label="$t('network.text_195')" v-bind="formItemLayout">
  53. <a-select
  54. v-decorator="decorators.bandwidth"
  55. :placeholder="$t('network.text_697')">
  56. <a-select-option v-for="item in bandwidthOptions" :value="item.value" :key="item.value">
  57. {{item.label}}
  58. </a-select-option>
  59. </a-select>
  60. </a-form-item>
  61. <a-form-item :label="$t('common.text00012')" class="mb-0" v-bind="formItemLayout">
  62. <tag
  63. v-decorator="decorators.__meta__" />
  64. </a-form-item>
  65. </a-form>
  66. </div>
  67. <div slot="footer">
  68. <a-button type="primary" @click="handleConfirm" :loading="loading">{{ $t('dialog.ok') }}</a-button>
  69. <a-button @click="cancelDialog">{{ $t('dialog.cancel') }}</a-button>
  70. </div>
  71. </base-dialog>
  72. </template>
  73. <script>
  74. import { mapGetters } from 'vuex'
  75. import { BAND_WIDTH_OPTION } from '../../../constants'
  76. import DialogMixin from '@/mixins/dialog'
  77. import WindowsMixin from '@/mixins/windows'
  78. import DomainSelect from '@/sections/DomainSelect'
  79. import Tag from '@/sections/Tag'
  80. import validateForm from '@/utils/validate'
  81. export default {
  82. name: 'WireCreateDialog',
  83. components: {
  84. DomainSelect,
  85. Tag,
  86. },
  87. mixins: [DialogMixin, WindowsMixin],
  88. data () {
  89. // 自定义校验名称重复
  90. const validateName = (rule, value, callback) => {
  91. // 编辑模式下不需要校验重复
  92. if (this.$route.query.id) {
  93. callback()
  94. }
  95. const wiresManager = new this.$Manager('wires')
  96. wiresManager.list({
  97. params: {
  98. filter: 'name.equals(' + value + ')',
  99. },
  100. })
  101. .then((res) => {
  102. const data = res.data.data
  103. if (data.length === 0) {
  104. callback()
  105. }
  106. callback(new Error(this.$t('network.text_698')))
  107. })
  108. }
  109. return {
  110. loading: false,
  111. vpcValidateStatus: '',
  112. vpcHelp: '',
  113. form: {
  114. fc: this.$form.createForm(this),
  115. },
  116. decorators: {
  117. area: [
  118. 'area',
  119. {
  120. rules: [
  121. { required: true, message: this.$t('network.text_286') },
  122. ],
  123. },
  124. ],
  125. vpc: [
  126. 'vpc',
  127. {
  128. rules: [
  129. { required: true, message: this.$t('network.text_274') },
  130. ],
  131. },
  132. ],
  133. zone: [
  134. 'zone',
  135. {
  136. rules: [
  137. { required: true, message: this.$t('network.text_24') },
  138. ],
  139. },
  140. ],
  141. name: [
  142. 'name',
  143. {
  144. initialValue: '',
  145. validateTrigger: ['change', 'blur'],
  146. validateFirst: true,
  147. rules: [
  148. { required: true, message: this.$t('network.text_116') },
  149. { validator: this.$validate('resourceName') },
  150. { validator: validateName, trigger: ['blur'] },
  151. ],
  152. },
  153. ],
  154. description: ['description'],
  155. bandwidth: [
  156. 'bandwidth',
  157. {
  158. rules: [
  159. { required: true, message: this.$t('network.text_699') },
  160. ],
  161. },
  162. ],
  163. project_domain: [
  164. 'project_domain',
  165. {
  166. initialValue: this.$store.getters.userInfo.projectDomainId,
  167. },
  168. ],
  169. __meta__: [
  170. '__meta__',
  171. {
  172. rules: [
  173. { validator: validateForm('tagName') },
  174. ],
  175. },
  176. ],
  177. },
  178. formItemLayout: {
  179. wrapperCol: {
  180. span: 20,
  181. },
  182. labelCol: {
  183. span: 4,
  184. },
  185. },
  186. areas: [],
  187. vpcs: [],
  188. zones: [],
  189. bandwidthOptions: BAND_WIDTH_OPTION,
  190. }
  191. },
  192. computed: {
  193. ...mapGetters(['isAdminMode', 'scope', 'userInfo']),
  194. },
  195. created () {
  196. this.fetchAreas()
  197. this.fetchZones()
  198. },
  199. methods: {
  200. fetchAreas () {
  201. const manager = new this.$Manager('cloudregions')
  202. manager.list({
  203. params: {
  204. is_on_premise: true,
  205. },
  206. }).then((res) => {
  207. this.areas = res.data.data.map((item) => {
  208. return {
  209. label: this._$t(item),
  210. value: item.id,
  211. }
  212. })
  213. if (this.areas.length) {
  214. const defaultValue = this.areas[0].value
  215. this.form.fc.setFieldsValue({
  216. [this.decorators.area[0]]: defaultValue,
  217. })
  218. this.handleAreaChange(defaultValue)
  219. }
  220. })
  221. },
  222. fetchVpcs (area) {
  223. const manager = new this.$Manager('vpcs')
  224. const params = {
  225. cloudregion_id: area,
  226. }
  227. if (this.isAdminMode) {
  228. params.project_domain = this.userInfo.domain.id
  229. } else {
  230. params.scope = this.scope
  231. }
  232. manager.list({ params }).then((res) => {
  233. this.vpcs = res.data.data.map((item) => {
  234. return {
  235. label: item.name,
  236. value: item.id,
  237. }
  238. })
  239. if (area === 'default') this.vpcs = this.vpcs.filter(({ value }) => value === 'default')
  240. if (this.vpcs.length) {
  241. this.form.fc.setFieldsValue({
  242. [this.decorators.vpc[0]]: this.vpcs[0].value,
  243. })
  244. }
  245. })
  246. },
  247. fetchZones () {
  248. const manager = new this.$Manager('zones')
  249. manager.list({
  250. params: {
  251. is_on_premise: true,
  252. },
  253. }).then((res) => {
  254. this.loadZoneOptions(res.data.data)
  255. })
  256. },
  257. loadZoneOptions (data) {
  258. const results = []
  259. for (let i = 0; i < data.length; i++) {
  260. const zone = data[i]
  261. let name = this._$t(zone)
  262. if (zone.name_cn) {
  263. name += '(' + zone.name_cn + ')'
  264. }
  265. results.push({ label: name, value: zone.id })
  266. }
  267. this.zones = results
  268. },
  269. handleAreaChange (e) {
  270. this.fetchVpcs(e)
  271. },
  272. doCreate (data) {
  273. const params = {
  274. project_domain: data.project_domain,
  275. name: data.name,
  276. description: data.description,
  277. zone_id: data.zone,
  278. vpc_id: data.vpc,
  279. bandwidth: data.bandwidth,
  280. __meta__: data.__meta__,
  281. }
  282. return this.params.onManager('create', {
  283. managerArgs: {
  284. data: params,
  285. },
  286. })
  287. },
  288. async handleConfirm () {
  289. this.loading = true
  290. try {
  291. if (!this.form.fc.getFieldValue('area')) {
  292. this.vpcValidateStatus = 'error'
  293. this.vpcHelp = this.$t('network.text_286')
  294. this.loading = false
  295. return
  296. } else if (!this.form.fc.getFieldValue('vpc')) {
  297. this.vpcValidateStatus = 'error'
  298. this.vpcHelp = this.$t('network.text_274')
  299. this.loading = false
  300. return
  301. }
  302. this.vpcValidateStatus = ''
  303. this.vpcHelp = ''
  304. const values = await this.form.fc.validateFields()
  305. await this.doCreate(values)
  306. this.loading = false
  307. this.cancelDialog()
  308. } catch (error) {
  309. this.loading = false
  310. }
  311. },
  312. filterOption (input, option) {
  313. const lastIdx = option.componentOptions.children.length - 1
  314. return (
  315. option.componentOptions.children[lastIdx].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
  316. )
  317. },
  318. },
  319. }
  320. </script>