index.vue 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. <template>
  2. <div>
  3. <a-form-item :label="label" v-bind="formItemLayout">
  4. <a-row>
  5. <a-radio-group v-decorator="decorators.type" @change="handleTypeChange">
  6. <a-radio-button
  7. v-for="item of types"
  8. :key="item.key"
  9. :value="item.key">{{ item.label }}</a-radio-button>
  10. </a-radio-group>
  11. </a-row>
  12. <a-row class="mt-4" v-if="isBind">
  13. <base-select
  14. remote
  15. v-decorator="decorators.eip"
  16. resource="eips"
  17. :params="params"
  18. :showSync="true"
  19. :select-props="{ allowClear: true, placeholder: $t('compute.text_145') }" />
  20. </a-row>
  21. </a-form-item>
  22. <a-form-item :label="$t('compute.text_1359')" v-if="isNew && showBgpTypes" v-bind="formItemLayout">
  23. <a-select v-decorator="decorators.bgp_type">
  24. <a-select-option v-for="item in bgpTypeOptions" :value="item" :key="item">{{ item === '' ? $t('compute.text_1352') : BGP_TYPES_MAP[item] ? BGP_TYPES_MAP[item].label : item }}</a-select-option>
  25. </a-select>
  26. </a-form-item>
  27. <a-form-item :label="$t('compute.text_1360')" v-if="isNew" v-bind="formItemLayout">
  28. <a-radio-group v-decorator="decorators.charge_type" @change="handleChargeTypeChange">
  29. <a-radio-button
  30. v-for="item of chargeTypes"
  31. :key="item.key"
  32. :value="item.key">{{ item.label }}</a-radio-button>
  33. </a-radio-group>
  34. </a-form-item>
  35. <a-form-item :label="$t('compute.bandwidth.title')" v-if="isNew" v-bind="formItemLayout">
  36. <div class="d-flex">
  37. <a-tooltip placement="top" :title="$t('compute.text_1324', [maxBindWidth])">
  38. <a-input-number
  39. :min="1"
  40. :max="maxBindWidth"
  41. :step="1"
  42. :formatter="format"
  43. :parse="format"
  44. v-decorator="decorators.bandwidth" />
  45. Mbps
  46. </a-tooltip>
  47. </div>
  48. </a-form-item>
  49. </div>
  50. </template>
  51. <script>
  52. import * as R from 'ramda'
  53. import { mapGetters } from 'vuex'
  54. import { EIP_TYPES_MAP as types } from '@Compute/constants'
  55. import { typeClouds } from '@/utils/common/hypervisor'
  56. import { HYPERVISORS_MAP } from '@/constants'
  57. import i18n from '@/locales'
  58. import { BGP_TYPES, BGP_TYPES_MAP } from '@/constants/network'
  59. const chargeTypes = {
  60. traffic: {
  61. key: 'traffic',
  62. label: i18n.t('compute.text_20'),
  63. },
  64. bandwidth: {
  65. key: 'bandwidth',
  66. label: i18n.t('compute.text_21'),
  67. },
  68. }
  69. export default {
  70. name: 'EipConfig',
  71. props: {
  72. decorators: {
  73. type: Object,
  74. required: true,
  75. },
  76. eipParams: Object,
  77. hypervisor: String,
  78. hiddenNoneType: Boolean,
  79. cloudEnv: String,
  80. form: {
  81. type: Object,
  82. },
  83. formItemLayout: {
  84. type: Object,
  85. default: () => ({
  86. wrapperCol: {
  87. md: { span: 18 },
  88. xl: { span: 20 },
  89. xxl: { span: 22 },
  90. },
  91. labelCol: {
  92. md: { span: 6 },
  93. xl: { span: 4 },
  94. xxl: { span: 2 },
  95. },
  96. }),
  97. },
  98. showBind: {
  99. type: Boolean,
  100. default: true,
  101. },
  102. showNew: {
  103. type: Boolean,
  104. default: true,
  105. },
  106. hasPublicIp: {
  107. type: Boolean,
  108. default: false,
  109. },
  110. },
  111. data () {
  112. return {
  113. BGP_TYPES_MAP,
  114. type: this.decorators.type[1] && this.decorators.type[1].initialValue,
  115. chargeType: this.decorators.charge_type[1] && this.decorators.charge_type[1].initialValue,
  116. bgpTypeOptions: [],
  117. }
  118. },
  119. computed: {
  120. ...mapGetters(['scope']),
  121. isOnpremise () {
  122. return this.cloudEnv === 'onpremise'
  123. },
  124. isAliyun () {
  125. return this.hypervisor === HYPERVISORS_MAP.aliyun.hypervisor
  126. },
  127. isPrivateEnv () {
  128. const privateHyper = []
  129. for (const key in typeClouds.hypervisorMap) {
  130. if (typeClouds.hypervisorMap[key].env === 'private') {
  131. privateHyper.push(typeClouds.hypervisorMap[key].hypervisor)
  132. }
  133. }
  134. return privateHyper.includes(this.hypervisor)
  135. },
  136. showBgpTypes () {
  137. if (!this.bgpTypeOptions || this.bgpTypeOptions.length === 0) {
  138. return false
  139. }
  140. if (this.bgpTypeOptions.length === 1 && this.bgpTypeOptions[0] === '') {
  141. return false
  142. }
  143. return this.cloudEnv == null || this.cloudEnv === 'idc' || this.isOnpremise || this.isAliyun
  144. },
  145. types () {
  146. const ret = { ...types }
  147. if (!this.showBind) { // 主机创建不支持绑定已有EIP
  148. delete ret.bind
  149. }
  150. if (!this.showNew) {
  151. delete ret.new
  152. }
  153. // 私有云不支持新建
  154. if (this.isPrivateEnv) {
  155. delete ret.new
  156. }
  157. // 是否隐藏暂不需要选项
  158. if (this.hiddenNoneType) {
  159. delete ret.none
  160. }
  161. if (!this.hasPublicIp) {
  162. delete ret.public
  163. }
  164. return ret
  165. },
  166. chargeTypes () {
  167. const ret = { ...chargeTypes }
  168. // 腾讯云、Azure、aws、google不支持按固定带宽计费
  169. if ([
  170. typeClouds.hypervisorMap.azure.key,
  171. typeClouds.hypervisorMap.aws.key,
  172. typeClouds.hypervisorMap.google.key,
  173. ].includes(this.hypervisor)) {
  174. delete ret.bandwidth
  175. }
  176. if (this.hypervisor == null || this.hypervisor === 'kvm') {
  177. delete ret.traffic
  178. }
  179. return ret
  180. },
  181. isNew () {
  182. return this.type === 'new' || this.type === 'public'
  183. },
  184. isBind () {
  185. return this.type === 'bind'
  186. },
  187. maxBindWidth () {
  188. const trafficMax = {
  189. huawei: {
  190. max: 300,
  191. },
  192. }
  193. const brandWidthMax = {
  194. huawei: {
  195. max: 2000,
  196. },
  197. aliyun: {
  198. max: 500,
  199. },
  200. }
  201. if (this.chargeType === 'bandwidth') {
  202. return (
  203. brandWidthMax[this.hypervisor] &&
  204. brandWidthMax[this.hypervisor].max
  205. ) || (this.hypervisor === 'kvm' ? 10000 : 200)
  206. }
  207. return (
  208. trafficMax[this.hypervisor] &&
  209. trafficMax[this.hypervisor].max
  210. ) || (this.hypervisor === 'kvm' ? 10000 : 200)
  211. },
  212. sliderMarks () {
  213. let ret = { 100: '100Mbps' }
  214. if (this.chargeType === 'bandwidth') {
  215. if (this.maxBindWidth > 400) {
  216. ret = { 400: '400Mbps' }
  217. }
  218. }
  219. ret = { ...ret, ...{ 1: '1Mbps', [this.maxBindWidth]: `${this.maxBindWidth}Mbps` } }
  220. return ret
  221. },
  222. params () {
  223. if (!this.eipParams || R.isEmpty(this.eipParams)) return {}
  224. return {
  225. ...{
  226. usable: true,
  227. scope: this.scope,
  228. limit: 20,
  229. },
  230. ...this.eipParams,
  231. }
  232. },
  233. label () {
  234. if (this.hasPublicIp) return this.$t('compute.text_1374')
  235. return this.$t('compute.text_107')
  236. },
  237. },
  238. watch: {
  239. types (val) {
  240. const values = Object.values(val)
  241. if (values.length) {
  242. if (this.form && this.form.fc) {
  243. const type = values[0].key
  244. this.type = type
  245. this.form.fc.setFieldsValue({
  246. [this.decorators.type[0]]: type,
  247. })
  248. }
  249. }
  250. },
  251. 'form.fd.eip_type' (newValue) {
  252. if (newValue === 'new') {
  253. if (this.isAliyun) {
  254. this.bgpTypeOptions = BGP_TYPES.map(item => item.value)
  255. } else {
  256. this.fetchBgpType()
  257. }
  258. } else {
  259. this.bgpTypeOptions = []
  260. }
  261. },
  262. },
  263. created () {
  264. this.fetchBgpType()
  265. },
  266. methods: {
  267. initData (data) {
  268. this.$nextTick(() => {
  269. setTimeout(() => {
  270. if (data.eip_charge_type) {
  271. this.form.fc.setFieldsValue({ [this.decorators.type[0]]: 'new' })
  272. this.handleTypeChange({ target: { value: 'new' } })
  273. this.form.fd.eip_type = 'new'
  274. } else if (data.public_ip_charge_type) {
  275. this.form.fc.setFieldsValue({ [this.decorators.type[0]]: 'public' })
  276. this.handleTypeChange({ target: { value: 'public' } })
  277. this.form.fd.eip_type = 'public'
  278. }
  279. setTimeout(() => {
  280. if (data.eip_charge_type) {
  281. this.form.fc.setFieldsValue({
  282. [this.decorators.charge_type[0]]: data.eip_charge_type,
  283. [this.decorators.bandwidth[0]]: data.eip_bw,
  284. [this.decorators.bgp_type[0]]: data.eip_bgp_type,
  285. })
  286. } else if (data.public_ip_charge_type) {
  287. this.form.fc.setFieldsValue({
  288. [this.decorators.charge_type[0]]: data.public_ip_charge_type,
  289. [this.decorators.bandwidth[0]]: data.public_ip_bw,
  290. [this.decorators.bgp_type[0]]: data.public_ip_bgp_type,
  291. })
  292. }
  293. }, 1000)
  294. }, 1000)
  295. })
  296. },
  297. fetchBgpType () {
  298. if (this.isAliyun) return
  299. new this.$Manager('networks/distinct-field').list({
  300. params: {
  301. usable: true,
  302. limit: 0,
  303. field: 'bgp_type',
  304. scope: this.$store.getters.scope,
  305. server_type: 'eip',
  306. },
  307. }).then(({ data }) => {
  308. this.bgpTypeOptions = data.bgp_type
  309. })
  310. },
  311. handleTypeChange (e) {
  312. this.type = e.target.value
  313. if (this.type === 'new' || this.type === 'public') {
  314. this.$nextTick(() => {
  315. if (R.has('traffic', this.chargeTypes)) {
  316. return this.form.fc.setFieldsValue({ eip_charge_type: 'traffic' })
  317. }
  318. this.form.fc.setFieldsValue({ eip_charge_type: 'bandwidth' })
  319. })
  320. }
  321. },
  322. handleChargeTypeChange (e) {
  323. this.chargeType = e.target.value
  324. },
  325. format (val) {
  326. return +val || 1
  327. },
  328. },
  329. }
  330. </script>