EditAttributes.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. <template>
  2. <div>
  3. <page-header :title="$t('network.text_606')" style="margin-bottom: 7px;" />
  4. <page-body needMarginBottom>
  5. <a-form class="mt-3" :form="form.fc">
  6. <a-divider orientation="left">{{$t('network.text_397')}}</a-divider>
  7. <a-form-item :label="$t('network.text_21')" v-bind="formItemLayout">
  8. <a-input v-decorator="decorators.name" :placeholder="$t('validator.resourceName')" />
  9. </a-form-item>
  10. <a-form-item :label="$t('network.text_198')" v-bind="formItemLayout">
  11. <a-radio-group v-decorator="decorators.platform_type">
  12. <a-radio-button
  13. v-for="item of platformOpts"
  14. :key="item.key"
  15. :disabled="item.key !== 'idc'"
  16. :value="item.key">{{ item.label }}</a-radio-button>
  17. </a-radio-group>
  18. </a-form-item>
  19. <a-form-item :label="$t('network.text_574')" v-bind="formItemLayout">
  20. <a-radio-group v-decorator="decorators.server_type" @change="handleServerTypeChange">
  21. <a-radio-button
  22. v-for="item of serverTypeOpts"
  23. :key="item.key"
  24. :disabled="item.key !== server_type"
  25. :value="item.key">{{ item.label }}</a-radio-button>
  26. </a-radio-group>
  27. </a-form-item>
  28. <a-form-item :label="$t('network.text_607')" v-bind="formItemLayout">
  29. <a-input v-decorator="decorators.guest_ip_start" :disabled="!isClassicNetwork" />
  30. </a-form-item>
  31. <a-form-item :label="$t('network.text_608')" v-bind="formItemLayout">
  32. <a-input v-decorator="decorators.guest_ip_end" :disabled="!isClassicNetwork" />
  33. </a-form-item>
  34. <a-form-item :label="$t('network.text_609')" v-bind="formItemLayout">
  35. <a-select v-decorator="decorators.guest_ip_mask" :disabled="!isClassicNetwork">
  36. <a-select-option v-for="item in netMaskOptions" :key="item.value" :value="item.value">
  37. {{item.label}}
  38. </a-select-option>
  39. </a-select>
  40. </a-form-item>
  41. <a-form-item :label="$t('network.text_610')" v-bind="formItemLayout">
  42. <a-input v-decorator="decorators.guest_gateway" :disabled="!isClassicNetwork" />
  43. </a-form-item>
  44. <a-form-item :label="$t('network.ipv6.ip_start.label')" v-bind="formItemLayout">
  45. <a-input v-decorator="decorators.guest_ip6_start" :disabled="!isClassicNetwork" />
  46. </a-form-item>
  47. <a-form-item :label="$t('network.ipv6.ip_end.label')" v-bind="formItemLayout">
  48. <a-input v-decorator="decorators.guest_ip6_end" :disabled="!isClassicNetwork" />
  49. </a-form-item>
  50. <a-form-item :label="$t('network.ipv6.ip_mask.label')" v-bind="formItemLayout">
  51. <a-select v-decorator="decorators.guest_ip6_mask" :disabled="!isClassicNetwork">
  52. <a-select-option v-for="item in net6MaskOptions" :key="item.value" :value="item.value">
  53. {{item.label}}
  54. </a-select-option>
  55. </a-select>
  56. </a-form-item>
  57. <a-form-item :label="$t('network.ipv6.gateway.label')" v-bind="formItemLayout">
  58. <a-input v-decorator="decorators.guest_gateway6" :disabled="!isClassicNetwork" />
  59. </a-form-item>
  60. <a-form-item label="VLAN ID" v-bind="formItemLayout">
  61. <a-input v-decorator="decorators.vlan_id" :disabled="!isClassicNetwork" />
  62. </a-form-item>
  63. <a-collapse :bordered="false" :active-key="getDefaultActiveKey">
  64. <a-collapse-panel :header="$t('network.text_94')" key="1" forceRender>
  65. <a-form-item :label="$t('network.text_743')" v-bind="formItemLayout" v-if="hasBgpType">
  66. <a-input v-decorator="decorators.bgp_type" />
  67. <span slot="extra">{{$t('network.text_744')}}</span>
  68. </a-form-item>
  69. <a-form-item v-bind="formItemLayout">
  70. <span slot="label">{{$t('network.text_583')}}<help-tooltip class="ml-1" name="networkPolicy" /></span>
  71. <a-radio-group v-decorator="decorators.alloc_policy">
  72. <a-radio-button
  73. v-for="item of allocPolicyoptions"
  74. :key="item.key"
  75. :value="item.key">{{ item.label }}</a-radio-button>
  76. </a-radio-group>
  77. </a-form-item>
  78. <a-form-item :label="$t('network.dns_server')" v-bind="formItemLayout">
  79. <a-input :placeholder="$t('validator.IPs')" v-decorator="decorators.guest_dns" />
  80. </a-form-item>
  81. <a-form-item v-bind="formItemLayout">
  82. <span slot="label">{{$t('network.text_586')}}<help-tooltip class="ml-1" name="networkDomain" /></span>
  83. <a-input :placeholder="$t('validator.domain')" v-decorator="decorators.guest_domain" />
  84. </a-form-item>
  85. <a-form-item :label="$t('network.ntp_server')" v-bind="formItemLayout">
  86. <a-input :placeholder="$t('validator.IPs_or_domains')" v-decorator="decorators.guest_ntp" />
  87. </a-form-item>
  88. <a-form-item label="dhcp_relay" v-bind="formItemLayout">
  89. <a-input class="w-50" v-decorator="decorators.guest_dhcp" :placeholder="$t('validator.IPs')" />
  90. </a-form-item>
  91. </a-collapse-panel>
  92. </a-collapse>
  93. </a-form>
  94. </page-body>
  95. <page-footer>
  96. <template v-slot:right>
  97. <a-button type="primary" @click="handleSubmit" class="ml-3" :loading="submiting">{{$t('network.text_606')}}</a-button>
  98. <a-button class="ml-3" @click="() => $router.back()">{{$t('common.cancel')}}</a-button>
  99. </template>
  100. </page-footer>
  101. </div>
  102. </template>
  103. <script>
  104. import { REGEXP } from '@/utils/validate'
  105. export default {
  106. name: 'EditAttributes',
  107. data () {
  108. return {
  109. submiting: false,
  110. form: {
  111. fc: this.$form.createForm(this),
  112. },
  113. formItemLayout: {
  114. wrapperCol: {
  115. md: { span: 18 },
  116. xl: { span: 20 },
  117. xxl: { span: 22 },
  118. },
  119. labelCol: {
  120. md: { span: 6 },
  121. xl: { span: 4 },
  122. xxl: { span: 2 },
  123. },
  124. },
  125. decorators: {
  126. name: [
  127. 'name',
  128. {
  129. initialValue: '',
  130. validateTrigger: ['change', 'blur'],
  131. validateFirst: true,
  132. rules: [
  133. { required: true, message: this.$t('network.text_116') },
  134. { validator: this.$validate('resourceName') },
  135. ],
  136. },
  137. ],
  138. platform_type: [
  139. 'platform_type',
  140. {
  141. initialValue: 'idc',
  142. validateTrigger: ['change', 'blur'],
  143. },
  144. ],
  145. server_type: [
  146. 'server_type',
  147. {
  148. initialValue: 'guest',
  149. validateTrigger: ['change', 'blur'],
  150. rules: [
  151. { required: true, message: this.$t('network.text_592') },
  152. ],
  153. },
  154. ],
  155. guest_ip_start: [
  156. 'guest_ip_start',
  157. {
  158. validateTrigger: ['change', 'blur'],
  159. validateFirst: true,
  160. rules: [
  161. // { required: true, message: this.$t('network.text_593') },
  162. { validator: this.$validate('IPv4', false) },
  163. ],
  164. },
  165. ],
  166. guest_ip_end: [
  167. 'guest_ip_end',
  168. {
  169. validateTrigger: ['change', 'blur'],
  170. validateFirst: true,
  171. rules: [
  172. // { required: true, message: this.$t('network.text_594') },
  173. { validator: this.$validate('IPv4', false) },
  174. ],
  175. },
  176. ],
  177. guest_ip_mask: [
  178. 'guest_ip_mask',
  179. {
  180. initialValue: '16',
  181. },
  182. ],
  183. guest_gateway: [
  184. 'guest_gateway',
  185. {
  186. validateTrigger: ['change', 'blur'],
  187. validateFirst: true,
  188. rules: [
  189. // { required: true, message: this.$t('network.text_611') },
  190. { validator: this.$validate('IPv4', false) },
  191. { validator: this.validateGateway },
  192. ],
  193. },
  194. ],
  195. guest_ip6_start: [
  196. 'guest_ip6_start',
  197. {
  198. validateTrigger: ['change', 'blur'],
  199. validateFirst: true,
  200. rules: [
  201. { validator: this.$validate('IPv6', false) },
  202. ],
  203. },
  204. ],
  205. guest_ip6_end: [
  206. 'guest_ip6_end',
  207. {
  208. validateTrigger: ['change', 'blur'],
  209. validateFirst: true,
  210. rules: [
  211. { validator: this.$validate('IPv6', false) },
  212. ],
  213. },
  214. ],
  215. guest_ip6_mask: [
  216. 'guest_ip6_mask',
  217. {
  218. initialValue: '64',
  219. },
  220. ],
  221. guest_gateway6: [
  222. 'guest_gateway6',
  223. {
  224. validateTrigger: ['change', 'blur'],
  225. validateFirst: true,
  226. rules: [
  227. { validator: this.$validate('IPv6', false) },
  228. { validator: this.validateGateway6 },
  229. ],
  230. },
  231. ],
  232. vlan_id: [
  233. 'vlan_id',
  234. ],
  235. alloc_policy: [
  236. 'alloc_policy',
  237. {
  238. initialValue: 'none',
  239. },
  240. ],
  241. guest_dhcp: [
  242. 'guest_dhcp',
  243. {
  244. validateFirst: true,
  245. rules: [
  246. { validator: this.$validate('IPs', false) },
  247. ],
  248. },
  249. ],
  250. guest_dns: [
  251. 'guest_dns',
  252. {
  253. initialValue: '',
  254. validateTrigger: ['change', 'blur'],
  255. rules: [
  256. { validator: this.$validate('IPs', false) },
  257. ],
  258. },
  259. ],
  260. guest_domain: [
  261. 'guest_domain',
  262. {
  263. initialValue: '',
  264. validateTrigger: ['change', 'blur'],
  265. rules: [
  266. { validator: this.$validate('domain', false) },
  267. ],
  268. },
  269. ],
  270. guest_ntp: [
  271. 'guest_ntp',
  272. {
  273. initialValue: '',
  274. validateTrigger: ['change', 'blur'],
  275. rules: [
  276. { validator: this.$validate('IPs_or_domains', false) },
  277. ],
  278. },
  279. ],
  280. bgp_type: [
  281. 'bgp_type',
  282. ],
  283. },
  284. params: {
  285. wire: {
  286. scope: this.$store.getters.scope,
  287. },
  288. },
  289. platformOpts: [
  290. { label: this.$t('network.text_207'), key: 'idc' },
  291. { label: this.$t('network.text_208'), key: 'private' },
  292. { label: this.$t('network.text_209'), key: 'public' },
  293. ],
  294. serverTypeOpts: [
  295. { label: this.$t('network.text_226'), key: 'guest' },
  296. { label: this.$t('network.text_598'), key: 'baremetal' },
  297. // { label: this.$t('network.text_599'), key: 'container' },
  298. { label: 'PXE', key: 'pxe' },
  299. { label: 'IPMI', key: 'ipmi' },
  300. { label: this.$t('network.text_221'), key: 'eip' },
  301. { label: this.$t('network.server_type.hostlocal.text'), key: 'hostlocal' },
  302. ],
  303. allocPolicyoptions: [
  304. { label: this.$t('network.text_600'), key: 'none' },
  305. { label: this.$t('network.text_601'), key: 'stepdown' },
  306. { label: this.$t('network.text_602'), key: 'stepup' },
  307. { label: this.$t('network.text_603'), key: 'random' },
  308. ],
  309. netMaskOptions: [
  310. { label: '16', value: '16' },
  311. { label: '17', value: '17' },
  312. { label: '18', value: '18' },
  313. { label: '19', value: '19' },
  314. { label: '20', value: '20' },
  315. { label: '21', value: '21' },
  316. { label: '22', value: '22' },
  317. { label: '23', value: '23' },
  318. { label: '24', value: '24' },
  319. { label: '25', value: '25' },
  320. { label: '26', value: '26' },
  321. { label: '27', value: '27' },
  322. { label: '28', value: '28' },
  323. { label: '29', value: '29' },
  324. { label: '30', value: '30' },
  325. ],
  326. net6MaskOptions: [
  327. { label: '64', value: '64' },
  328. { label: '72', value: '72' },
  329. { label: '80', value: '80' },
  330. { label: '88', value: '88' },
  331. { label: '96', value: '96' },
  332. { label: '104', value: '104' },
  333. { label: '112', value: '112' },
  334. { label: '120', value: '120' },
  335. { label: '124', value: '124' },
  336. ],
  337. wire_id: '',
  338. cloudEnv: '',
  339. vpcId: '',
  340. server_type: 'guest',
  341. }
  342. },
  343. computed: {
  344. isClassicNetwork () {
  345. return this.vpcId === 'default'
  346. },
  347. getDefaultActiveKey () {
  348. if (this.vpcId === 'default') {
  349. return '0' // hide
  350. } else {
  351. return '1' // show
  352. }
  353. },
  354. hasBgpType () {
  355. return this.server_type === 'eip' || this.server_type === 'guest' || this.server_type === 'baremetal' || this.server_type === 'hostlocal'
  356. },
  357. },
  358. provide () {
  359. return {
  360. form: this.form,
  361. }
  362. },
  363. mounted () {
  364. this.bindData()
  365. },
  366. methods: {
  367. fetchData () {
  368. return new this.$Manager('networks').get({ id: this.$route.query.network_id })
  369. },
  370. handleServerTypeChange (e) {
  371. this.server_type = e.target.value
  372. },
  373. async bindData () {
  374. const { data } = await this.fetchData()
  375. this.form.fc.setFieldsValue({
  376. name: data.name,
  377. server_type: data.server_type,
  378. guest_ip_start: data.guest_ip_start,
  379. guest_ip_end: data.guest_ip_end,
  380. guest_ip_mask: data.guest_ip_mask,
  381. guest_gateway: data.guest_gateway,
  382. guest_ip6_start: data.guest_ip6_start,
  383. guest_ip6_end: data.guest_ip6_end,
  384. guest_ip6_mask: data.guest_ip6_mask,
  385. guest_gateway6: data.guest_gateway6,
  386. vlan_id: data.vlan_id || '',
  387. alloc_policy: data.alloc_policy,
  388. guest_dns: data.guest_dns || '',
  389. guest_domain: data.guest_domain || '',
  390. guest_ntp: data.guest_ntp || '',
  391. guest_dhcp: data.guest_dhcp || '',
  392. })
  393. this.form.fc.getFieldDecorator('bgp_type', { initialValue: data.bgp_type })
  394. this.wire_id = data.wire_id
  395. this.cloudEnv = data.cloud_env
  396. this.vpcId = data.vpc_id
  397. this.server_type = data.server_type
  398. },
  399. validateGateway (rule, value, callback) {
  400. if (!value) {
  401. return callback()
  402. }
  403. // 只需要查看是否是以 0 结尾
  404. const ipItems = value.split('.')
  405. if (ipItems[ipItems.length - 1] === '0') {
  406. callback(new Error(this.$t('network.text_591')))
  407. } else {
  408. callback()
  409. }
  410. },
  411. validateGateway6 (rule, value, callback) {
  412. if (!value) {
  413. return callback()
  414. }
  415. // 只需要查看是否是以 0 结尾
  416. const ipItems = value.split(':')
  417. if (ipItems[ipItems.length - 1] === '0') {
  418. callback(new Error(this.$t('network.text_591')))
  419. } else {
  420. callback()
  421. }
  422. },
  423. validateDhcpRelay (rule, value, callback) {
  424. if (!value) {
  425. callback()
  426. } else if (!REGEXP.IPv4s.regexp.test(value)) {
  427. callback(new Error(this.$t('common.tips.input', ['IPv4'])))
  428. }
  429. callback()
  430. },
  431. doUpdate (data) {
  432. return new this.$Manager('networks').update({
  433. id: this.$route.query.network_id,
  434. data,
  435. })
  436. },
  437. async handleSubmit () {
  438. this.submiting = true
  439. try {
  440. let values = await this.form.fc.validateFields()
  441. values = {
  442. ...values,
  443. wire_id: this.wire_id,
  444. }
  445. if (!((values.guest_ip_start && values.guest_ip_end) || (values.guest_ip6_start && values.guest_ip6_end))) {
  446. this.$message.warning(this.$t('network.required_ipv4_or_ipv6_1'))
  447. this.submiting = false
  448. return
  449. }
  450. await this.doUpdate(values)
  451. this.$store.commit('keepAlive/ADD_DELAY_EVENT', { name: 'ResourceListSingleRefresh', params: [this.$route.query.network_id] })
  452. const networkPath = this.$router.resolve(this.$route.path)
  453. this.$router.push({ path: networkPath.resolved.matched[0].path })
  454. } catch (err) {
  455. throw err
  456. } finally {
  457. this.submiting = false
  458. }
  459. },
  460. },
  461. }
  462. </script>