AttachResource.vue 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. <template>
  2. <base-dialog @cancel="cancelDialog">
  3. <div slot="header">{{$t('compute.bind_resource')}} - {{ resourceType === 'server' ? $t('dictionary.server') : $t('dictionary.disk') }}</div>
  4. <div slot="body">
  5. <a-alert class="mb-2" type="warning" :message="resourceType === 'disk' ? $t('compute.snapshotpolicy_bind_disk_tip') : $t('compute.snapshotpolicy_bind_server_tip')" />
  6. <dialog-selected-tips :count="params.data.length" :action="$t('compute.bind_resource')" :name="$t('dictionary.snapshotpolicy')" />
  7. <dialog-table :data="params.data" :columns="params.columns.slice(0, 3)" />
  8. <loader loading v-if="!bindedDisksLoaded && !bindedServersLoaded" />
  9. <a-form :form="form.fc" hideRequiredMark v-else>
  10. <a-form-item v-if="resourceType === 'disk'" :label="$t('compute.text_376')" v-bind="formItemLayout">
  11. <list-select
  12. v-if="form.fc.getFieldValue('disks')"
  13. v-decorator="decorators.disks"
  14. :list-props="diskProps"
  15. :multiple="true"
  16. :formatter="v => v.name" />
  17. </a-form-item>
  18. <a-form-item v-else :label="$t('dictionary.server')" v-bind="formItemLayout">
  19. <list-select
  20. v-if="form.fc.getFieldValue('servers')"
  21. v-decorator="decorators.servers"
  22. :list-props="serverProps"
  23. :multiple="true"
  24. :formatter="v => v.name" />
  25. </a-form-item>
  26. </a-form>
  27. </div>
  28. <div slot="footer">
  29. <a-button type="primary" @click="handleConfirm" :loading="loading">{{ $t('dialog.ok') }}</a-button>
  30. <a-button @click="cancelDialog">{{ $t('dialog.cancel') }}</a-button>
  31. </div>
  32. </base-dialog>
  33. </template>
  34. <script>
  35. import { mapGetters } from 'vuex'
  36. import * as R from 'ramda'
  37. import DialogMixin from '@/mixins/dialog'
  38. import WindowsMixin from '@/mixins/windows'
  39. import { HYPERVISORS_MAP } from '@/constants'
  40. import ListSelect from '@/sections/ListSelect'
  41. import DiskPropsMixin from '../mixins/diskProps'
  42. import ServerPropsMixin from '../mixins/serverProps'
  43. export default {
  44. name: 'AttachResourceDialog',
  45. components: {
  46. ListSelect,
  47. },
  48. mixins: [DialogMixin, WindowsMixin, DiskPropsMixin, ServerPropsMixin],
  49. data () {
  50. return {
  51. loading: false,
  52. resourceType: this.params.data[0].type,
  53. form: {
  54. fc: this.$form.createForm(this),
  55. },
  56. decorators: {
  57. disks: [
  58. 'disks',
  59. {
  60. initialValue: [],
  61. },
  62. ],
  63. servers: [
  64. 'servers',
  65. {
  66. initialValue: [],
  67. },
  68. ],
  69. },
  70. formItemLayout: {
  71. wrapperCol: {
  72. span: 21,
  73. },
  74. labelCol: {
  75. span: 3,
  76. },
  77. },
  78. disksInitLoaded: false,
  79. bindedDisks: [],
  80. bindedDisksLoaded: false,
  81. serversInitLoaded: false,
  82. bindedServers: [],
  83. bindedServersLoaded: false,
  84. }
  85. },
  86. computed: {
  87. ...mapGetters(['scope']),
  88. isAzure () {
  89. return this.params.data[0].provider === HYPERVISORS_MAP.azure.provider
  90. },
  91. isUCloud () {
  92. return this.params.data[0].provider === HYPERVISORS_MAP.ucloud.provider
  93. },
  94. message () {
  95. return this.$t('compute.text_1086')
  96. },
  97. diskParams () {
  98. return { limit: 20, tenant: this.params.data[0].tenant_id }
  99. },
  100. serverParams () {
  101. return { limit: 20, tenant: this.params.data[0].tenant_id, cloud_env: 'onpremise' }
  102. },
  103. },
  104. watch: {
  105. bindedDisks (val) {
  106. if (val) {
  107. const ids = val.map((item) => { return item.id })
  108. this.$nextTick(() => {
  109. this.form.fc.setFieldsValue({ disks: ids })
  110. })
  111. }
  112. },
  113. bindedServers (val) {
  114. if (val) {
  115. const ids = val.map((item) => { return item.id })
  116. this.$nextTick(() => {
  117. this.form.fc.setFieldsValue({ servers: ids })
  118. })
  119. }
  120. },
  121. },
  122. created () {
  123. if (this.resourceType === 'disk') {
  124. this.fetchBindedDisks()
  125. } else {
  126. this.fetchBindedServers()
  127. }
  128. },
  129. methods: {
  130. mapperDisks (data) {
  131. data = data.concat(this.bindedDisks)
  132. data = R.uniqBy(item => item.id, data)
  133. data = data.filter((item) => { return ['OneCloud', 'Qcloud', 'Aliyun'].includes(item.brand) && item.guest_count > 0 })
  134. return data
  135. },
  136. mapperServers (data) {
  137. data = data.concat(this.bindedServers)
  138. data = R.uniqBy(item => item.id, data)
  139. return data
  140. },
  141. async fetchBindedDisks () {
  142. const manager = new this.$Manager('disks')
  143. try {
  144. const { data: { data = [] } } = await manager.list({
  145. params: {
  146. scope: this.scope,
  147. snapshotpolicy_id: this.params.data[0].id,
  148. },
  149. })
  150. this.bindedDisks = data
  151. this.bindedDisksLoaded = true
  152. } catch (error) {
  153. throw error
  154. }
  155. },
  156. async fetchBindedServers () {
  157. const manager = new this.$Manager('servers')
  158. try {
  159. const { data: { data = [] } } = await manager.list({
  160. params: {
  161. scope: this.scope,
  162. snapshotpolicy_id: this.params.data[0].id,
  163. },
  164. })
  165. this.bindedServers = data
  166. this.bindedServersLoaded = true
  167. } catch (error) {
  168. throw error
  169. }
  170. },
  171. async handleConfirm () {
  172. const manager = new this.$Manager(this.resourceType === 'disk' ? 'disks' : 'servers')
  173. this.loading = true
  174. try {
  175. const values = await this.form.fc.validateFields()
  176. const ids = this.resourceType === 'disk' ? values.disks : values.servers
  177. const resource = this.resourceType === 'disk' ? this.getDisks(ids, this.bindedDisks) : this.getServers(ids, this.bindedServers)
  178. const data = {
  179. snapshotpolicy_id: this.params.data[0].id,
  180. }
  181. if (this.resourceType === 'disk') {
  182. if (resource.addDisks.length > 0) {
  183. await manager.batchPerformAction({
  184. ids: resource.addDisks,
  185. action: 'set-snapshotpolicy',
  186. data,
  187. })
  188. }
  189. if (resource.delDisks.length > 0) {
  190. await manager.batchPerformAction({
  191. ids: resource.delDisks,
  192. action: 'unbind-snapshotpolicy',
  193. data,
  194. })
  195. }
  196. } else {
  197. if (resource.addServers.length > 0) {
  198. await manager.batchPerformAction({
  199. ids: resource.addServers,
  200. action: 'set-snapshotpolicy',
  201. data,
  202. })
  203. }
  204. if (resource.delServers.length > 0) {
  205. const manager = new this.$Manager('snapshotpolicies')
  206. await manager.performAction({
  207. id: this.params.data[0].id,
  208. action: 'unbind-resources',
  209. data: {
  210. resources: resource.delServers.map((item) => { return { id: item, type: 'server' } }),
  211. },
  212. })
  213. }
  214. }
  215. this.params.refresh && this.params.refresh()
  216. this.cancelDialog()
  217. } finally {
  218. this.loading = false
  219. }
  220. },
  221. getDisks (newDisks = [], oldDisks = []) {
  222. const addDisks = []
  223. const delDisks = []
  224. const oldDiskIds = oldDisks.map((item) => { return item.id })
  225. newDisks.forEach((diskId) => {
  226. if (!oldDiskIds.includes(diskId)) {
  227. addDisks.push(diskId)
  228. }
  229. })
  230. oldDiskIds.forEach((diskId) => {
  231. if (!newDisks.includes(diskId)) {
  232. delDisks.push(diskId)
  233. }
  234. })
  235. return {
  236. addDisks,
  237. delDisks,
  238. }
  239. },
  240. getServers (newServers = [], oldServers = []) {
  241. const addServers = []
  242. const delServers = []
  243. const oldServerIds = oldServers.map((item) => { return item.id })
  244. newServers.forEach((serverId) => {
  245. if (!oldServerIds.includes(serverId)) {
  246. addServers.push(serverId)
  247. }
  248. })
  249. oldServerIds.forEach((serverId) => {
  250. if (!newServers.includes(serverId)) {
  251. delServers.push(serverId)
  252. }
  253. })
  254. return {
  255. addServers,
  256. delServers,
  257. }
  258. },
  259. },
  260. }
  261. </script>