Detail.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. <template>
  2. <div>
  3. <a-alert type="warning" class="mb-2" :showIcon="false" :message="$t('system.text_589')" 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 WindowsMixin from '@/mixins/windows'
  21. import {
  22. getUserTagColumn,
  23. getExtTagColumn,
  24. } from '@/utils/common/detailColumn'
  25. import VmInstanceList from '@Compute/views/vminstance/components/List'
  26. import ServertemplateList from '@Compute/views/servertemplate/components/List'
  27. import DiskList from '@Compute/views/disk/components/List'
  28. import ImageList from '@Compute/views/image/components/List'
  29. import HostImageList from '@Compute/views/host-image/components/List'
  30. import SnapshotList from '@Compute/views/snapshot/components/List'
  31. import InstanceSnapshotList from '@Compute/views/snapshot-instance/components/List'
  32. import SnapshotPolicyList from '@Compute/views/snapshotpolicy/components/List'
  33. import SecgroupList from '@Compute/views/secgroup/components/List'
  34. import NetworkList from '@Network/views/network/components/List'
  35. import EipList from '@Network/views/eip/components/List'
  36. import LbList from '@Network/views/lb/components/List'
  37. import LbaclsList from '@Network/views/lbacls/components/List'
  38. import LbcertList from '@Network/views/lbcerts/components/List'
  39. import ExternalprojectList from '@Cloudenv/views/externalproject/components/List'
  40. import BucketStorageList from '@Storage/views/bucket/components/List'
  41. import RDSList from '@DB/views/rds/components/List'
  42. import RedisList from '@DB/views/redis/components/List'
  43. import { transformLabel } from '../../policy/utils'
  44. import { RESOURCES_MAP } from '../../policy/constants'
  45. import ProjectAdmin from '../components/ProjectAdmin'
  46. const RESOURCES_BASE = {
  47. servers: {},
  48. servertemplates: {},
  49. disks: {},
  50. images: {},
  51. guestimages: {},
  52. snapshots: {},
  53. instance_snapshots: {},
  54. snapshotpolicies: {},
  55. secgroups: {},
  56. networks: {},
  57. eips: {},
  58. }
  59. const RESOURCES_LOAD = {
  60. loadbalancers: {},
  61. loadbalanceracls: {},
  62. loadbalancercertificates: {},
  63. }
  64. const RESOURCES_OTHER = {
  65. externalprojects: {},
  66. buckets: {},
  67. dbinstances: {},
  68. elasticcaches: {},
  69. }
  70. export default {
  71. name: 'ProjectDetail',
  72. components: [
  73. VmInstanceList,
  74. ServertemplateList,
  75. DiskList,
  76. ImageList,
  77. HostImageList,
  78. SnapshotList,
  79. InstanceSnapshotList,
  80. SnapshotPolicyList,
  81. SecgroupList,
  82. NetworkList,
  83. EipList,
  84. LbList,
  85. LbaclsList,
  86. LbcertList,
  87. ExternalprojectList,
  88. BucketStorageList,
  89. RDSList,
  90. RedisList,
  91. ProjectAdmin,
  92. ],
  93. mixins: [WindowsMixin],
  94. props: {
  95. data: {
  96. type: Object,
  97. required: true,
  98. },
  99. onManager: {
  100. type: Function,
  101. required: true,
  102. },
  103. resource: String,
  104. columns: Array,
  105. },
  106. data () {
  107. return {
  108. loading: false,
  109. nameRules: [
  110. { required: true, message: this.$t('system.text_168') },
  111. ],
  112. resourceListComponent: {
  113. servers: {
  114. component: VmInstanceList,
  115. params: {
  116. pending_delete: 'all',
  117. },
  118. },
  119. servertemplates: {
  120. component: ServertemplateList,
  121. params: {},
  122. },
  123. disks: {
  124. component: DiskList,
  125. params: {
  126. pending_delete: 'all',
  127. },
  128. },
  129. images: {
  130. component: ImageList,
  131. params: {
  132. pending_delete: 'all',
  133. },
  134. },
  135. guestimages: {
  136. component: HostImageList,
  137. params: {
  138. pending_delete: 'all',
  139. },
  140. },
  141. snapshots: {
  142. component: SnapshotList,
  143. params: {},
  144. },
  145. instance_snapshots: {
  146. component: InstanceSnapshotList,
  147. params: {},
  148. },
  149. snapshotpolicies: {
  150. component: SnapshotPolicyList,
  151. params: {},
  152. },
  153. secgroups: {
  154. component: SecgroupList,
  155. params: {},
  156. },
  157. networks: {
  158. component: NetworkList,
  159. params: {},
  160. },
  161. eips: {
  162. component: EipList,
  163. params: {},
  164. },
  165. loadbalancers: {
  166. component: LbList,
  167. params: {},
  168. },
  169. loadbalanceracls: {
  170. component: LbaclsList,
  171. params: {},
  172. },
  173. loadbalancercertificates: {
  174. component: LbcertList,
  175. params: {},
  176. },
  177. externalprojects: {
  178. component: ExternalprojectList,
  179. params: {},
  180. },
  181. buckets: {
  182. component: BucketStorageList,
  183. params: {},
  184. },
  185. dbinstances: {
  186. component: RDSList,
  187. params: {},
  188. },
  189. elasticcaches: {
  190. component: RedisList,
  191. params: {},
  192. },
  193. },
  194. baseInfo: [
  195. getUserTagColumn({ onManager: this.onManager, resource: 'domain', params: { service: 'identity' }, columns: () => this.columns, tipName: this.$t('dictionary.project') }),
  196. getExtTagColumn({ onManager: this.onManager, resource: 'domain', params: { service: 'identity' }, columns: () => this.columns, tipName: this.$t('dictionary.project') }),
  197. {
  198. field: 'organization',
  199. title: this.$t('dictionary.organization'),
  200. formatter: ({ row }) => {
  201. const { organization = {} } = row
  202. const tags = this.getTags(organization)
  203. if (tags) {
  204. return tags.join(';')
  205. }
  206. return '-'
  207. },
  208. slots: {
  209. default: ({ row }) => {
  210. const { organization = {} } = row
  211. const tags = this.getTags(organization)
  212. if (tags) {
  213. const list = tags.map(item => <a-tag class="mr-1 mb-1">{item}</a-tag>)
  214. return [...list]
  215. }
  216. return '-'
  217. },
  218. },
  219. },
  220. {
  221. field: 'group_count',
  222. title: this.$t('system.text_457'),
  223. slots: {
  224. default: ({ row }) => {
  225. if (!row.group_count) return '0'
  226. return [<a onClick={ () => this.$emit('tab-change', 'project-directly-under-user-list') }>{row.group_count}</a>]
  227. },
  228. },
  229. },
  230. {
  231. field: 'user_count',
  232. title: this.$t('system.text_458'),
  233. slots: {
  234. default: ({ row }) => {
  235. if (!row.user_count) return '0'
  236. return [<a onClick={ () => this.$emit('tab-change', 'project-directly-under-user-list') }>{row.user_count}</a>]
  237. },
  238. },
  239. },
  240. {
  241. field: 'admin',
  242. title: this.$t('iam.project_admin'),
  243. slots: {
  244. default: ({ row }) => {
  245. return [<ProjectAdmin row={ row } manager={ this.onManager } onOk={this.ok} />]
  246. },
  247. },
  248. },
  249. ],
  250. }
  251. },
  252. computed: {
  253. extResources () {
  254. return this.data.ext_resource ? this.data.ext_resource : {}
  255. },
  256. extraInfo () {
  257. if (!this.extResources) {
  258. return null
  259. }
  260. const serverRes = {
  261. title: this.$t('system.text_587'),
  262. items: Object.keys(RESOURCES_BASE).map((key) => {
  263. return {
  264. field: key,
  265. title: transformLabel(RESOURCES_MAP[key]) || key,
  266. formatter: () => {
  267. const txt = this.extResources[key] ? this.$t('system.text_459', [this.extResources[key]]) : this.$t('system.text_460')
  268. const comp = this.resourceListComponent[key] ? this.resourceListComponent[key] : null
  269. if (txt && comp) {
  270. return [
  271. <a onClick={
  272. () => {
  273. this.createDialog('ProjectResourcesDialog',
  274. {
  275. component: comp.component,
  276. id: key,
  277. params: {
  278. ...comp.params,
  279. projects: [this.data.id],
  280. },
  281. title: transformLabel(RESOURCES_MAP[key]) || key,
  282. })
  283. }
  284. }>{ txt }</a>,
  285. ]
  286. } else {
  287. return txt
  288. }
  289. },
  290. }
  291. }),
  292. }
  293. const loadRes = {
  294. title: this.$t('system.loadbalance_resource_statistics'),
  295. items: Object.keys(RESOURCES_LOAD).map((key) => {
  296. return {
  297. field: key,
  298. title: transformLabel(RESOURCES_MAP[key]) || key,
  299. formatter: () => {
  300. const txt = this.extResources[key] ? this.$t('system.text_459', [this.extResources[key]]) : this.$t('system.text_460')
  301. const comp = this.resourceListComponent[key] ? this.resourceListComponent[key] : null
  302. if (txt && comp) {
  303. return [
  304. <a onClick={
  305. () => {
  306. this.createDialog('ProjectResourcesDialog',
  307. {
  308. component: comp.component,
  309. id: key,
  310. params: {
  311. ...comp.params,
  312. projects: [this.data.id],
  313. },
  314. title: transformLabel(RESOURCES_MAP[key]) || key,
  315. })
  316. }
  317. }>{ txt }</a>,
  318. ]
  319. } else {
  320. return txt
  321. }
  322. },
  323. }
  324. }),
  325. }
  326. const otherRes = {
  327. title: this.$t('system.other_resource_statistics'),
  328. items: Object.keys(RESOURCES_OTHER).map((key) => {
  329. return {
  330. field: key,
  331. title: transformLabel(RESOURCES_MAP[key]) || key,
  332. formatter: () => {
  333. const txt = this.extResources[key] ? this.$t('system.text_459', [this.extResources[key]]) : this.$t('system.text_460')
  334. const comp = this.resourceListComponent[key] ? this.resourceListComponent[key] : null
  335. if (txt && comp) {
  336. return [
  337. <a onClick={
  338. () => {
  339. this.createDialog('ProjectResourcesDialog',
  340. {
  341. component: comp.component,
  342. id: key,
  343. params: {
  344. ...comp.params,
  345. projects: [this.data.id],
  346. },
  347. title: transformLabel(RESOURCES_MAP[key]) || key,
  348. })
  349. }
  350. }>{ txt }</a>,
  351. ]
  352. } else {
  353. return txt
  354. }
  355. },
  356. }
  357. }),
  358. }
  359. return [serverRes, loadRes, otherRes]
  360. },
  361. },
  362. methods: {
  363. refresh () {
  364. this.loading = true
  365. new this.$Manager('scope-resource', 'v1').performClassAction({
  366. action: 'refresh',
  367. }).then((res) => {
  368. this.loading = false
  369. this.$bus.$emit('SystemProjectsListRefresh', true)
  370. }).catch(() => {
  371. this.loading = false
  372. })
  373. },
  374. ok () {
  375. this.$bus.$emit('refresh-detail')
  376. },
  377. getTags (org) {
  378. const tags = []
  379. if (org && org.nodes && org.nodes.length > 0) {
  380. const labels = org.nodes[org.nodes.length - 1].labels
  381. const keys = org.keys
  382. for (let i = 0; i < labels.length; i++) {
  383. tags.push(`${keys[i].replace('org:', '')}:${labels[i]}`)
  384. }
  385. }
  386. return tags
  387. },
  388. },
  389. }
  390. </script>