BottomBar.vue 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. <template>
  2. <page-footer isForm>
  3. <template class="content" v-slot:left>
  4. <div
  5. v-for="(tip, idx) of tips"
  6. :key="idx"
  7. class="d-flex flex-column justify-content-center flex-grow-1">
  8. <div
  9. v-for="obj of tip"
  10. :key="obj.label"
  11. class="d-flex align-items-center">
  12. <span class="label" :class="obj.labelClass">{{ obj.label }}:</span>
  13. <template v-if="obj.value">
  14. <span class="value text-truncate" :class="obj.valueClass">{{ obj.value }}</span>
  15. </template>
  16. <template v-else>
  17. <span class="value placeholder text-truncate" :class="obj.valueClass">-</span>
  18. </template>
  19. </div>
  20. </div>
  21. </template>
  22. <template v-slot:right>
  23. <price-fetcher v-if="!isPrivate" :values="values" :customPriceKey="customPriceKey" :extraPriceItems="extraPriceItems" :cloudAccountId="cloudAccountId" />
  24. <div class="btns-wrapper d-flex align-items-center">
  25. <a-button @click="doCreate" :loading="loading" type="primary" class="ml-3">{{$t('db.text_41')}}</a-button>
  26. <a-button class="ml-3" @click="handleCancel">{{$t('common.cancel')}}</a-button>
  27. </div>
  28. </template>
  29. </page-footer>
  30. </template>
  31. <script>
  32. import { sizestr } from '@/utils/utils'
  33. import { Manager } from '@/utils/manager'
  34. import PriceFetcher from '@/components/PriceFetcher'
  35. import { SERVER_TYPE } from '@Compute/constants'
  36. import { findPlatform } from '@/utils/common/hypervisor'
  37. export default {
  38. name: 'BottomBar',
  39. components: {
  40. PriceFetcher,
  41. },
  42. inject: ['form'],
  43. props: {
  44. values: {
  45. type: Object,
  46. },
  47. cloudAccountId: String,
  48. provider: String,
  49. },
  50. data () {
  51. return {
  52. loading: false,
  53. }
  54. },
  55. computed: {
  56. tips () {
  57. const { sku = {} } = this.values
  58. const ret = [
  59. [
  60. { label: this.$t('db.text_60'), labelClass: 'label-w-50', value: this.values.generate_name, valueClass: 'name-value' },
  61. { label: this.$t('db.text_40'), labelClass: 'label-w-50', value: sku.region },
  62. ],
  63. [
  64. { label: this.$t('db.text_109'), labelClass: 'label-w-80', value: this.$t('db.text_110', [sizestr(sku.vmem_size_mb, 'M', 1024)]) },
  65. { label: this.$t('db.text_111'), labelClass: 'label-w-50', value: sku.name },
  66. ],
  67. [
  68. { label: this.$t('db.text_112'), labelClass: 'label-w-80', value: `${this.values.engine || '-'}${this.values.engine_version || ''}` },
  69. ],
  70. ]
  71. return ret
  72. },
  73. isPrivate () {
  74. return findPlatform((this.provider || '').toLowerCase(), 'provider') === SERVER_TYPE.private
  75. },
  76. },
  77. methods: {
  78. customPriceKey () {
  79. const { sku } = this.values
  80. if (!sku) return
  81. if (sku.rate && sku.rate.price_key) {
  82. return sku.rate.price_key
  83. }
  84. const { region_ext_id, provider, name, category, engine } = sku
  85. let pvt = provider.toLowerCase()
  86. if (sku.cloud_env) pvt = sku.cloud_env.toLowerCase() // 阿里金融云
  87. if (pvt === 'google') {
  88. return `${pvt}::${region_ext_id}::::rds::${category}_${engine}_${name}`
  89. } else if (pvt === 'qcloud') {
  90. return `${pvt}::${region_ext_id}::::rds::${category}_${name}`
  91. } else {
  92. return `${pvt}::${region_ext_id}::::rds::${name}`
  93. }
  94. },
  95. extraPriceItems () {
  96. const { sku, disk_size_gb } = this.values
  97. if (!sku || !disk_size_gb) return
  98. const { storage_type, provider, category, engine } = sku
  99. const pvt = provider.toLowerCase()
  100. const items = []
  101. if (pvt === 'huawei' || pvt.includes('aliyun') || pvt === 'google' || pvt === 'qcloud') {
  102. items.push({ resource_type: 'rds_storage', resource_key: `${category}_${engine}_${storage_type}`, amount: disk_size_gb })
  103. } else {
  104. items.push({ resource_type: 'rds_storage', resource_key: storage_type, amount: disk_size_gb })
  105. }
  106. return items
  107. },
  108. validateForm () {
  109. let f = false
  110. this.form.fc.validateFieldsAndScroll({ scroll: { alignWithTop: true, offsetTop: 100 } }, (err, values) => {
  111. const { sku } = values
  112. if (err !== null) {
  113. console.log(err)
  114. }
  115. f = (err === null) && (sku && sku.name)
  116. })
  117. return f
  118. },
  119. formatParams () {
  120. const params = {
  121. ...this.values,
  122. }
  123. if (params.zones) {
  124. const { zones } = params
  125. const zoneArr = zones.split('+')
  126. if (zoneArr && zoneArr.length > 0) {
  127. for (let i = 0; i < zoneArr.length; i++) {
  128. params[`zone${i + 1}`] = zoneArr[i]
  129. }
  130. }
  131. delete params.zones
  132. }
  133. if (params.sku) {
  134. const { sku } = params
  135. params.instance_type = sku.name
  136. delete params.sku
  137. }
  138. params.secgroup_ids = params.secgroup
  139. delete params.secgroup
  140. // 到期释放
  141. if (params.durationStandard !== 'none') {
  142. params.duration = params.duration || params.durationStandard
  143. }
  144. delete params.durationStandard
  145. return params
  146. },
  147. async doCreate () {
  148. if (!this.validateForm()) return false
  149. this.loading = true
  150. const manager = new Manager('dbinstances', 'v2')
  151. try {
  152. await manager.create({ data: this.formatParams() })
  153. this.$router.push('/rds')
  154. } catch (err) {
  155. throw err
  156. } finally {
  157. this.loading = false
  158. }
  159. },
  160. handleCancel () {
  161. this.$emit('cancel')
  162. },
  163. },
  164. }
  165. </script>
  166. <style lang="less" scoped>
  167. @import '../../../../../../src/styles/less/theme';
  168. .create-server-result-wrap {
  169. position: relative;
  170. .content {
  171. width: 80%;
  172. .label {
  173. color: #999;
  174. &.label-w-50 {
  175. width: 50px;
  176. }
  177. &.label-w-80 {
  178. width: 80px;
  179. }
  180. }
  181. .value {
  182. max-width: 300px;
  183. &.name-value {
  184. width: 100px;
  185. }
  186. &.placeholder {
  187. color: #888;
  188. font-style: italic;
  189. }
  190. }
  191. .prices {
  192. .hour {
  193. color: @error-color;
  194. font-size: 24px;
  195. }
  196. .tips {
  197. color: #999;
  198. font-size: 12px;
  199. }
  200. }
  201. }
  202. .btns-wrapper {
  203. position: absolute;
  204. right: 20px;
  205. }
  206. .errors-wrap {
  207. position: absolute;
  208. right: 0;
  209. bottom: 100px;
  210. width: 300px;
  211. padding: 15px;
  212. opacity: 1;
  213. transform: translateX(0);
  214. background-color: #fef0f0;
  215. box-shadow: -5px -5px 5px rgba(0, 0, 0, 0.1);
  216. border-top-left-radius: 3px;
  217. .title {
  218. color: @error-color;
  219. > i {
  220. font-size: 28px;
  221. }
  222. > span {
  223. font-size: 13px;
  224. font-weight: bold;
  225. }
  226. }
  227. .divider {
  228. margin: 15px 0;
  229. background-color: #dcdfe6;
  230. height: 1px;
  231. }
  232. .list {
  233. padding: 0 15px;
  234. color: @error-color;
  235. li {
  236. line-height: 1.8;
  237. list-style-type: disc;
  238. }
  239. &.sec-list {
  240. li {
  241. list-style-type: circle;
  242. }
  243. }
  244. }
  245. }
  246. .errors-slide-fade-enter-active {
  247. transition: all 0.3s ease;
  248. }
  249. .errors-slide-fade-leave-active {
  250. transition: all 0.3s cubic-bezier(1, 0.5, 0.8, 1);
  251. }
  252. .errors-slide-fade-enter,
  253. .errors-slide-fade-leave-to {
  254. transform: translateX(300px);
  255. opacity: 0;
  256. }
  257. }
  258. .prices {
  259. .hour {
  260. color: @error-color;
  261. font-size: 24px;
  262. }
  263. .tips {
  264. color: #999;
  265. font-size: 12px;
  266. }
  267. }
  268. </style>