Detail.vue 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. <template>
  2. <div>
  3. <a-alert type="warning" class="mb-2" :showIcon="false" :message="$t('system.text_586')" banner />
  4. <div class="d-flex justify-content-start">
  5. <a-button :disabled="loading" @click="refresh">
  6. <a-icon v-if="loading" type="sync" spin />
  7. <a-icon v-else type="sync" />
  8. </a-button>
  9. </div>
  10. <detail
  11. :data="data"
  12. :base-info="baseInfo"
  13. :extra-info="extraInfo"
  14. :on-manager="onManager"
  15. :resource="resource"
  16. :nameRules="nameRules" />
  17. </div>
  18. </template>
  19. <script>
  20. import { sizestrWithUnit } from '@/utils/utils'
  21. import {
  22. getEnabledTableColumn,
  23. } from '@/utils/common/tableColumn'
  24. import {
  25. getUserTagColumn,
  26. getExtTagColumn,
  27. } from '@/utils/common/detailColumn'
  28. export default {
  29. name: 'GroupDetail',
  30. props: {
  31. data: {
  32. type: Object,
  33. required: true,
  34. },
  35. onManager: {
  36. type: Function,
  37. required: true,
  38. },
  39. resource: String,
  40. columns: Array,
  41. },
  42. data () {
  43. return {
  44. loading: false,
  45. nameRules: [
  46. { required: true, message: this.$t('system.text_168') },
  47. ],
  48. domainUsageMap: {},
  49. baseInfo: [
  50. getUserTagColumn({ onManager: this.onManager, resource: 'domain', columns: () => this.columns, tipName: this.$t('dictionary.domain') }),
  51. getExtTagColumn({ onManager: this.onManager, resource: 'domain', columns: () => this.columns, tipName: this.$t('dictionary.domain') }),
  52. {
  53. field: 'idp',
  54. title: this.$t('system.text_165'),
  55. },
  56. getEnabledTableColumn(),
  57. ],
  58. usageColumns: [
  59. {
  60. title: 'CPU',
  61. field: 'cpu',
  62. formatter: ({ row }) => {
  63. return this.$t('IAM.text_4', [row.cpu])
  64. },
  65. },
  66. {
  67. title: this.$t('system.text_86'),
  68. field: 'mem',
  69. formatter: ({ row }) => {
  70. return sizestrWithUnit(row.mem, 'M', 1024)
  71. },
  72. },
  73. {
  74. title: this.$t('system.text_87'),
  75. field: 'diskList',
  76. width: '30%',
  77. slots: {
  78. default: ({ row }) => {
  79. if (!row.diskList.length) return '-'
  80. return row.diskList.map(item => {
  81. return <div>{sizestrWithUnit(item.value, 'M', 1024)}{this.$t('IAM.text_8', [this.$te(`common.storage.${item.medium_type}`) ? this.$t(`common.storage.${item.medium_type}`) : item.medium_type])}</div>
  82. })
  83. },
  84. },
  85. },
  86. {
  87. title: 'GPU',
  88. field: 'gpu',
  89. width: '15%',
  90. slots: {
  91. default: ({ row }) => {
  92. return [<div>
  93. <div>{this.$t('IAM.text_5', [row.gpu.gpu])}{this.$t('IAM.text_8', [this.$t('IAM.text_9')])}</div>
  94. <div>{this.$t('IAM.text_5', [row.gpu.gpu_server])}{this.$t('IAM.text_8', [this.$t('common_407')])}</div>
  95. </div>]
  96. },
  97. },
  98. },
  99. {
  100. title: this.$t('system.text_30'),
  101. field: 'vm',
  102. formatter: ({ row }) => {
  103. return this.$t('IAM.text_6', [row.vm])
  104. },
  105. },
  106. {
  107. title: 'EIP',
  108. field: 'eip',
  109. formatter: ({ row }) => {
  110. return this.$t('IAM.text_7', [row.eip])
  111. },
  112. },
  113. {
  114. title: this.$t('IAM.text_2'),
  115. field: 'mb',
  116. formatter: ({ row }) => {
  117. return sizestrWithUnit(row.mb, 'M', 1024)
  118. },
  119. },
  120. ],
  121. }
  122. },
  123. computed: {
  124. extResources () {
  125. return this.data.ext_resource ? this.data.ext_resource : {}
  126. },
  127. usageData () {
  128. return [{
  129. cpu: this.domainUsageMap['domain.servers.cpu'] || 0,
  130. mem: this.domainUsageMap['domain.servers.memory'] || 0,
  131. diskList: this.genDiskTypeList(this.domainUsageMap),
  132. gpu: {
  133. gpu: this.domainUsageMap.isolated_devices || 0,
  134. gpu_server: this.domainUsageMap['domain.servers.isolated_devices'] || 0,
  135. },
  136. vm: this.domainUsageMap['domain.servers'] || 0,
  137. eip: this.domainUsageMap['domain.eip'] || 0,
  138. mb: (this.domainUsageMap['domain.eip.floating_ip.bandwidth.mb'] || 0) + (this.domainUsageMap['domain.eip.public_ip.bandwidth.mb'] || 0),
  139. }]
  140. },
  141. extraInfo () {
  142. const serverRes = {
  143. title: this.$t('system.text_173'),
  144. items: [
  145. {
  146. field: 'vpcs',
  147. title: 'VPC',
  148. formatter: ({ row }) => {
  149. return this.$t('system.text_459', [this.extResources.vpcs || 0])
  150. },
  151. },
  152. {
  153. field: 'dns_zones',
  154. title: this.$t('dictionary.dns_zone'),
  155. formatter: ({ row }) => {
  156. return this.$t('system.text_459', [this.extResources.dns_zones || 0])
  157. },
  158. },
  159. {
  160. field: 'idp_count',
  161. title: this.$t('dictionary.identity_provider'),
  162. formatter: ({ row }) => {
  163. return this.$t('system.text_459', [row.idp_count || 0])
  164. },
  165. },
  166. {
  167. field: 'project_count',
  168. title: this.$t('dictionary.project'),
  169. slots: {
  170. default: ({ row }, h) => {
  171. const ret = [
  172. <a onClick={ () => this.$emit('tab-change', 'project-list') }>{this.$t('system.text_459', [row.project_count || 0])}</a>,
  173. ]
  174. return ret
  175. },
  176. },
  177. },
  178. {
  179. field: 'group_count',
  180. title: this.$t('dictionary.group'),
  181. formatter: ({ row }) => {
  182. return this.$t('system.text_459', [row.group_count || 0])
  183. },
  184. },
  185. {
  186. field: 'user_count',
  187. title: this.$t('dictionary.user'),
  188. slots: {
  189. default: ({ row }, h) => {
  190. const ret = [
  191. <a onClick={ () => this.$emit('tab-change', 'user-list') }>{this.$t('system.text_459', [row.user_count || 0])}</a>,
  192. ]
  193. return ret
  194. },
  195. },
  196. },
  197. {
  198. field: 'policy_count',
  199. title: this.$t('dictionary.policy'),
  200. formatter: ({ row }) => {
  201. return this.$t('system.text_459', [row.policy_count || 0])
  202. },
  203. },
  204. {
  205. field: 'role_count',
  206. title: this.$t('dictionary.role'),
  207. slots: {
  208. default: ({ row }, h) => {
  209. const ret = [
  210. <a onClick={ () => this.$emit('tab-change', 'role-list') }>{this.$t('system.text_459', [row.role_count || 0])}</a>,
  211. ]
  212. return ret
  213. },
  214. },
  215. },
  216. ],
  217. }
  218. const multiCloudRes = {
  219. title: this.$t('system.multicloud_resource_statistics'),
  220. items: [
  221. {
  222. field: 'cloudaccounts',
  223. title: this.$t('dictionary.cloudaccount'),
  224. slots: {
  225. default: ({ row }, h) => {
  226. const ret = [
  227. <a onClick={ () => this.$emit('tab-change', 'cloudaccount-list') }>{this.$t('system.text_459', [this.extResources.cloudaccounts || 0])}</a>,
  228. ]
  229. return ret
  230. },
  231. },
  232. },
  233. {
  234. field: 'cloudusers',
  235. title: this.$t('dictionary.clouduser'),
  236. formatter: ({ row }) => {
  237. return this.$t('system.text_459', [this.extResources.cloudusers || 0])
  238. },
  239. },
  240. {
  241. field: 'cloudgroups',
  242. title: this.$t('dictionary.cloudgroup'),
  243. formatter: ({ row }) => {
  244. return this.$t('system.text_459', [this.extResources.cloudgroups || 0])
  245. },
  246. },
  247. {
  248. field: 'proxysettings',
  249. title: this.$t('dictionary.proxysetting'),
  250. formatter: ({ row }) => {
  251. return this.$t('system.text_459', [this.extResources.proxysettings || 0])
  252. },
  253. },
  254. ],
  255. }
  256. const usageRes = {
  257. title: this.$t('IAM.text_3'),
  258. field: 'usage',
  259. slots: {
  260. default: ({ row }, h) => {
  261. return [
  262. <vxe-grid class="mb-2" resizable data={ this.usageData } columns={ this.usageColumns } />,
  263. ]
  264. },
  265. },
  266. }
  267. return [usageRes, serverRes, multiCloudRes]
  268. },
  269. },
  270. created () {
  271. this.fetchUsage()
  272. },
  273. methods: {
  274. refresh () {
  275. this.loading = true
  276. new this.$Manager('scope-resource', 'v1').performClassAction({
  277. action: 'refresh',
  278. }).then((res) => {
  279. this.loading = false
  280. this.$bus.$emit('SystemDomainsListRefresh', true)
  281. }).catch(() => {
  282. this.loading = false
  283. })
  284. },
  285. async fetchUsage () {
  286. const res = await new this.$Manager('rpc', 'v2').get({
  287. resource: 'rpc',
  288. id: 'usages/general-usage',
  289. params: {
  290. scope: 'domain',
  291. domain_id: this.data.id,
  292. },
  293. })
  294. this.domainUsageMap = res.data || {}
  295. },
  296. genDiskTypeList (map) {
  297. const list = []
  298. const keys = Object.keys(map)
  299. keys.map(key => {
  300. if (key.indexOf('domain.disks.attached.storage_type') === 0 && key !== 'domain.disks.attached.storage_type') {
  301. const newKey = key.replace('domain.disks.attached.storage_type.', '')
  302. if (newKey && map[key]) {
  303. list.push({ medium_type: newKey, value: map[key] })
  304. }
  305. }
  306. })
  307. return list
  308. },
  309. },
  310. }
  311. </script>