PrepareNetsForm.vue 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. <template>
  2. <div>
  3. <a-divider v-if="!allSuccess" orientation="left" class="mt-5 mb-3">
  4. {{ type === 'host' ? $t('cloudenv.text_175') : $t('cloudenv.text_176') }}
  5. </a-divider>
  6. <a-alert v-if="list.length > 0" class="mb-3 mt-3" :type="allSuccess? 'success' : 'warning'" show-icon>
  7. <template slot="message" v-if="type === 'host'">
  8. {{allSuccess ? $t('cloudenv.text_177') : $t('cloudenv.text_178', [noSuitableIps.join(' 、 '), noSuitableIps.length])}}
  9. </template>
  10. <template slot="message" v-if="type === 'guest'">
  11. {{allSuccess ? $t('cloudenv.text_179') : $t('cloudenv.text_180', [noSuitableIps.join(' 、 '), noSuitableIps.length]) }}
  12. </template>
  13. </a-alert>
  14. <a-form-item :label="$t('cloudenv.text_181')" v-if="!allSuccess">
  15. <a-radio-group v-if="type !== 'host'" v-decorator="['isCreate', { initialValue: true }]" button-style="solid">
  16. <a-radio-button :value="true">{{$t('cloudenv.text_182')}}</a-radio-button>
  17. <a-radio-button :value="false">{{$t('cloudenv.text_183')}}</a-radio-button>
  18. </a-radio-group>
  19. <div v-show="form.fc.getFieldValue('isCreate') || form.fc.getFieldValue('isCreate') === undefined">
  20. <a-row :gutter="8" v-for="k in form.fc.getFieldValue('keys')" :key="k">
  21. <a-col :span="4" :xxl="4" :xl="9" :xs="9">
  22. <a-form-item>
  23. <a-input :addon-before="$t('db.text_60')" v-decorator="formatDecorator(k, 'name')" :placeholder="$t('cloudenv.text_184')" />
  24. </a-form-item>
  25. </a-col>
  26. <a-col :span="4" :xxl="4" :xl="6" :xs="6">
  27. <a-form-item>
  28. <a-input :addon-before="$t('network.text_607')" @change="handleIpChange" v-decorator="formatDecorator(k, 'guest_ip_start')" :placeholder="$t('cloudenv.text_185')" />
  29. </a-form-item>
  30. </a-col>
  31. <a-col :span="4" :xxl="4" :xl="6" :xs="6">
  32. <a-form-item>
  33. <a-input :addon-before="$t('network.text_608')" @change="handleIpChange" v-decorator="formatDecorator(k, 'guest_ip_end')" :placeholder="$t('cloudenv.text_186')" />
  34. </a-form-item>
  35. </a-col>
  36. <a-col :span="3" :xxl="3" :xl="3" :xs="3">
  37. <a-form-item>
  38. <a-select class="w-100" :placeholder="$t('network.text_595')" v-decorator="formatDecorator(k, 'guest_ip_mask')" dropdownClassName="oc-select-dropdown">
  39. <a-select-option v-for="item in netMaskOptions" :key="item.value" :value="item.value">
  40. <span class="text-color-secondary option-prefix">{{$t('common_600')}}: </span>{{item.value}}
  41. </a-select-option>
  42. </a-select>
  43. </a-form-item>
  44. </a-col>
  45. <a-col :span="4" :xxl="4" :xl="6" :xs="6">
  46. <a-form-item>
  47. <a-input :addon-before="$t('network.text_610')" v-decorator="formatDecorator(k, 'guest_gateway')" :placeholder="$t('cloudenv.text_187')" />
  48. </a-form-item>
  49. </a-col>
  50. <a-col :span="3" :xxl="3" :xl="6" :xs="6">
  51. <a-form-item>
  52. <a-input addon-before="VLAN ID" v-decorator="formatDecorator(k, 'vlan', 'vlan_id')" placeholder="VLAN ID" />
  53. </a-form-item>
  54. </a-col>
  55. <a-col :span="2" :xxl="2" :xl="4" :xs="4">
  56. <a-button @click="handleRemove(k)" shape="circle" icon="minus" size="small" class="mt-2 ml-2" />
  57. </a-col>
  58. </a-row>
  59. <div class="d-flex align-items-center">
  60. <a-button type="primary" shape="circle" icon="plus" size="small" @click="handleAdd" />
  61. <a-button type="link" @click="handleAdd">{{$t('cloudenv.text_188')}}</a-button>
  62. </div>
  63. </div>
  64. <div v-show="!form.fc.getFieldValue('isCreate') && form.fc.getFieldValue('isCreate') !== undefined" class="mt-2">
  65. <a-alert :message="$t('cloudenv.text_189')" type="warning" show-icon />
  66. </div>
  67. </a-form-item>
  68. </div>
  69. </template>
  70. <script>
  71. import { uuid } from '@/utils/utils'
  72. import { isWithinRange } from '@/utils/validate'
  73. export default {
  74. name: 'PrepareNetsForm',
  75. props: {
  76. type: {
  77. type: String,
  78. default: 'host',
  79. },
  80. prepareNetData: {
  81. type: Object,
  82. required: true,
  83. },
  84. form: {
  85. type: Object,
  86. required: true,
  87. },
  88. },
  89. data () {
  90. return {
  91. loading: false,
  92. netInit: {},
  93. noSuitableIps: [],
  94. netMaskOptions: [
  95. { label: '16', value: '16' },
  96. { label: '17', value: '17' },
  97. { label: '18', value: '18' },
  98. { label: '19', value: '19' },
  99. { label: '20', value: '20' },
  100. { label: '21', value: '21' },
  101. { label: '22', value: '22' },
  102. { label: '23', value: '23' },
  103. { label: '24', value: '24' },
  104. { label: '25', value: '25' },
  105. { label: '26', value: '26' },
  106. { label: '27', value: '27' },
  107. { label: '28', value: '28' },
  108. { label: '29', value: '29' },
  109. { label: '30', value: '30' },
  110. ],
  111. formLayout: {
  112. wrapperCol: {
  113. md: { span: 18 },
  114. xl: { span: 20 },
  115. xxl: { span: 22 },
  116. },
  117. labelCol: {
  118. md: { span: 6 },
  119. xl: { span: 3 },
  120. xxl: { span: 2 },
  121. },
  122. },
  123. options: {
  124. name: {
  125. initialValue: undefined,
  126. validateTrigger: ['change', 'blur'],
  127. validateFirst: true,
  128. rules: [
  129. { required: true, message: this.$t('cloudenv.text_190') },
  130. { validator: this.$validate('resourceName') },
  131. ],
  132. },
  133. guest_ip_start: {
  134. validateTrigger: ['change', 'blur'],
  135. validateFirst: true,
  136. rules: [
  137. { required: true, message: this.$t('cloudenv.text_191') },
  138. { validator: this.$validate('IPv4') },
  139. ],
  140. },
  141. guest_ip_end: {
  142. validateTrigger: ['change', 'blur'],
  143. validateFirst: true,
  144. rules: [
  145. { required: true, message: this.$t('cloudenv.text_192') },
  146. { validator: this.$validate('IPv4') },
  147. ],
  148. },
  149. guest_ip_mask: {
  150. initialValue: '24',
  151. },
  152. guest_gateway: {
  153. validateTrigger: ['change', 'blur'],
  154. validateFirst: true,
  155. rules: [
  156. { required: true, message: this.$t('cloudenv.text_193') },
  157. { validator: this.$validate('IPv4') },
  158. { validator: this.validateGateway },
  159. ],
  160. },
  161. vlan: {
  162. validateTrigger: ['change', 'blur'],
  163. validateFirst: true,
  164. },
  165. },
  166. }
  167. },
  168. computed: {
  169. suggestedNetworks () {
  170. const _ = this.prepareNetData[`${this.type}_suggested_networks`]
  171. return _ && _.length > 0 ? _ : []
  172. },
  173. list () {
  174. if (this.prepareNetData && this.prepareNetData[`${this.type}s`] && this.prepareNetData[`${this.type}s`].length > 0) {
  175. return this.prepareNetData[`${this.type}s`]
  176. }
  177. return []
  178. },
  179. allSuccess () {
  180. return this.list.length > 0 && this.noSuitableIps.length === 0
  181. },
  182. },
  183. watch: {
  184. list (value) {
  185. if (value.length > 0 && !Object.keys(this.netInit).length) {
  186. this.initNets()
  187. }
  188. },
  189. },
  190. created () {
  191. this.form.fc.getFieldDecorator('keys', { initialValue: [], preserve: true })
  192. this.initNets()
  193. this.$nextTick(() => {
  194. this.form.fc.setFieldsValue({
  195. isCreate: this.list && this.list.length > 0,
  196. })
  197. })
  198. },
  199. mounted () {
  200. this.noSuitableIps = this.getNoSuitableIps()
  201. },
  202. methods: {
  203. getNoSuitableIps () {
  204. const ips = []
  205. for (let i = 0; i < this.list.length; i++) {
  206. const item = this.list[i]
  207. const { ip_nets } = item
  208. let isSuitableNetwork = false
  209. if (ip_nets && ip_nets.length) {
  210. isSuitableNetwork = ip_nets.every(o => o.suitable_network)
  211. }
  212. if (!item.suitable_network && !isSuitableNetwork) {
  213. ips.push(...item.ips)
  214. }
  215. }
  216. return ips
  217. },
  218. formatDecorator (k, id, initialValueKey) {
  219. let initialValue
  220. if (initialValueKey) {
  221. initialValue = this.netInit[k] ? this.netInit[k][initialValueKey] : undefined
  222. } else {
  223. initialValue = this.netInit[k] ? this.netInit[k][id] : undefined
  224. }
  225. return [`${k}.${id}`, {
  226. ...this.options[id],
  227. initialValue,
  228. }]
  229. },
  230. initNets () {
  231. const keys = []
  232. if (this.suggestedNetworks && this.suggestedNetworks.length > 0) {
  233. this.suggestedNetworks.forEach(net => {
  234. const key = uuid()
  235. keys.push(key)
  236. this.netInit[key] = net
  237. })
  238. }
  239. this.form.fc.setFieldsValue({
  240. keys,
  241. })
  242. },
  243. setSuitable () {
  244. const values = this.form.fc.getFieldsValue()
  245. if (this.list && this.list.length > 0) {
  246. this.list.forEach(item => {
  247. for (let i = 0; i < item.ips.length; i++) {
  248. const ip = item.ips[i]
  249. let isSuitable = false
  250. for (let i = 0; i < values.keys.length; i++) {
  251. const k = values.keys[i]
  252. const { guest_ip_start, guest_ip_end } = values[k]
  253. if (isWithinRange(ip, guest_ip_start, guest_ip_end)) {
  254. isSuitable = true
  255. break
  256. } else if (item.ip_nets[i].suitable_network) {
  257. isSuitable = true
  258. break
  259. }
  260. }
  261. item.isSuitable = isSuitable
  262. }
  263. })
  264. }
  265. },
  266. async handleIpChange (e) {
  267. await this.$nextTick()
  268. this.setSuitable()
  269. },
  270. handleAdd () {
  271. const { fc } = this.form
  272. const keys = fc.getFieldValue('keys')
  273. const nextKeys = keys.concat(uuid())
  274. fc.setFieldsValue({
  275. keys: nextKeys,
  276. })
  277. },
  278. handleRemove (k) {
  279. const { fc } = this.form
  280. const keys = fc.getFieldValue('keys')
  281. fc.setFieldsValue({
  282. keys: keys.filter(_ => _ !== k),
  283. }, () => {
  284. this.setSuitable()
  285. })
  286. },
  287. },
  288. }
  289. </script>