Detail.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. <template>
  2. <detail
  3. :on-manager="onManager"
  4. :data="data"
  5. :base-info="baseInfo"
  6. :extra-info="extraInfo"
  7. statusModule="bucket"
  8. resource="buckets"
  9. auto-hidden-columns-key="oss_hidden_columns" />
  10. </template>
  11. <script>
  12. // import BrandIcon from '@/sections/BrandIcon'
  13. import { ACL_TYPE, LOCATION_MAP } from '@Storage/constants/index.js'
  14. import { sizestrWithUnit } from '@/utils/utils'
  15. import WindowsMixin from '@/mixins/windows'
  16. import {
  17. getBrandTableColumn,
  18. getCopyWithContentTableColumn,
  19. getPublicScopeTableColumn,
  20. } from '@/utils/common/tableColumn'
  21. import {
  22. getUserTagColumn,
  23. // getExtTagColumn,
  24. } from '@/utils/common/detailColumn'
  25. import { HYPERVISORS_MAP } from '@/constants'
  26. import i18n from '@/locales'
  27. const RenderSizeTitle = {
  28. props: ['data'],
  29. data () {
  30. return {
  31. loading: false,
  32. }
  33. },
  34. methods: {
  35. async fetchSync () {
  36. this.loading = true
  37. try {
  38. const { data } = await this.bucketsM.performAction({
  39. id: this.data.id,
  40. action: 'sync',
  41. data: {
  42. stats_only: true,
  43. },
  44. })
  45. this.data.size_bytes = data.size_bytes
  46. this.data.object_cnt = data.object_cnt
  47. } catch (err) {
  48. throw err
  49. } finally {
  50. this.loading = false
  51. }
  52. },
  53. },
  54. created () {
  55. this.bucketsM = new this.$Manager('buckets')
  56. this.fetchSync()
  57. },
  58. render () {
  59. return (
  60. <div>{ this.$t('storage.text_172') } <a onClick={this.fetchSync}><a-icon type="sync" spin={this.loading} /></a></div>
  61. )
  62. },
  63. }
  64. export default {
  65. name: 'BucketDetail',
  66. mixins: [WindowsMixin],
  67. props: {
  68. onManager: {
  69. type: Function,
  70. required: true,
  71. },
  72. refresh: {
  73. type: Function,
  74. required: true,
  75. },
  76. data: {
  77. type: Object,
  78. required: true,
  79. },
  80. columns: {
  81. type: Array,
  82. },
  83. },
  84. data () {
  85. return {
  86. syncLoading: false,
  87. websiteData: {},
  88. baseInfo: [
  89. getUserTagColumn({ onManager: this.onManager, resource: 'bucket', columns: () => this.columns, tipName: this.$t('storage.text_18') }),
  90. // getExtTagColumn({ onManager: this.onManager, resource: 'bucket', columns: () => this.columns, tipName: this.$t('storage.text_18') }),
  91. getPublicScopeTableColumn({ vm: this, resource: 'buckets' }),
  92. getBrandTableColumn(),
  93. getCopyWithContentTableColumn({
  94. field: 'region',
  95. title: this.$t('storage.text_47'),
  96. hideField: true,
  97. slotCallback: row => {
  98. if (!row.cloudregion) return '-'
  99. return [
  100. <side-page-trigger permission='areas_get' name='CloudregionSidePage' id={row.cloudregion_id} vm={this}>{ row.cloudregion }</side-page-trigger>,
  101. ]
  102. },
  103. }),
  104. {
  105. field: 'location',
  106. title: this.$t('storage.location'),
  107. slots: {
  108. default: ({ row }) => {
  109. return LOCATION_MAP[row.location] || row.location || '-'
  110. },
  111. },
  112. },
  113. {
  114. field: 'storage_class',
  115. title: this.$t('storage.text_38'),
  116. },
  117. ],
  118. }
  119. },
  120. computed: {
  121. isSupportReferer () {
  122. if (this.data.provider === HYPERVISORS_MAP.qcloud.provider || this.data.provider === HYPERVISORS_MAP.aliyun.provider) {
  123. return true
  124. }
  125. return false
  126. },
  127. extraInfo () {
  128. const referer = {
  129. title: ({ row }, h) => {
  130. return h('div', {
  131. class: 'detail-title',
  132. }, [
  133. <span class='ml-2'>{i18n.t('storage.text_213')}</span>,
  134. <a-tooltip>
  135. { !this.isSupportReferer
  136. ? (this._isOwner
  137. ? (HYPERVISORS_MAP[row.provider.toLowerCase()]
  138. ? <template slot="title">{i18n.t('storage.text_235', [HYPERVISORS_MAP[row.provider.toLowerCase()].label])}</template>
  139. : '')
  140. : this.$t('storage.text_257'))
  141. : null }
  142. <a-button type="link" class="ml-2" disabled={ !this.isSupportReferer && this._isOwner } onClick={() => this.handleSetReferer(row)}>{ i18n.t('common.setting') }</a-button>
  143. </a-tooltip>,
  144. ])
  145. },
  146. items: [],
  147. hidden: () => this.$isScopedPolicyMenuHidden('oss_hidden_columns.referer'),
  148. }
  149. if (this.data.referer) {
  150. const others = [
  151. {
  152. field: 'referer.enabled',
  153. title: this.$t('storage.text_214'),
  154. formatter: ({ row }) => {
  155. return row.referer.enabled ? this.$t('storage.text_215') : this.$t('storage.text_216')
  156. },
  157. },
  158. ]
  159. referer.items = referer.items.concat(others)
  160. if (this.data.referer.enabled) {
  161. const refers = [
  162. {
  163. field: 'referer.allow_empty_refer',
  164. title: this.$t('storage.text_208'),
  165. formatter: ({ row }) => {
  166. if (!row.referer.enabled) {
  167. return '-'
  168. }
  169. return row.referer.allow_empty_refer ? this.$t('storage.text_217') : this.$t('storage.text_218')
  170. },
  171. },
  172. {
  173. field: 'referer.referer_type',
  174. title: this.$t('storage.text_86'),
  175. slots: {
  176. default: ({ row }) => {
  177. if (row.referer.enabled && row.referer.referer_type) {
  178. if (row.referer.referer_type === 'White-List') {
  179. return this.$t('storage.text_206')
  180. } else if (row.referer.referer_type === 'Black-List') {
  181. return this.$t('storage.black_list')
  182. }
  183. return row.referer.referer_type
  184. }
  185. return '-'
  186. },
  187. },
  188. },
  189. {
  190. field: 'referer.domain_list',
  191. title: this.$t('storage.text_219'),
  192. slots: {
  193. default: ({ row }) => {
  194. return row.referer.domain_list ? row.referer.domain_list.map(item => {
  195. return (
  196. <list-body-cell-wrap hideField copy title={ item } message={ item }>
  197. <span>{ item }</span>
  198. </list-body-cell-wrap>
  199. )
  200. }) : '-'
  201. },
  202. },
  203. },
  204. ]
  205. referer.items = referer.items.concat(refers)
  206. }
  207. }
  208. const ret = [
  209. {
  210. title: this.$t('storage.text_139'),
  211. field: 'url',
  212. slots: {
  213. default: ({ row }, h) => {
  214. if (!this.data.access_urls) {
  215. return '-'
  216. }
  217. const columns = [
  218. {
  219. field: 'url',
  220. title: 'URL',
  221. slots: {
  222. default: ({ row }) => {
  223. return [
  224. <div>
  225. <a href={row.url}>{row.url}</a>
  226. <copy class="ml-1" message={row.url} />
  227. </div>]
  228. },
  229. },
  230. },
  231. {
  232. field: 'description',
  233. title: this.$t('storage.text_140'),
  234. },
  235. ]
  236. return [
  237. <vxe-grid class="mb-2" data={ this.data.access_urls || [] } columns={ columns } />,
  238. ]
  239. },
  240. },
  241. hidden: () => this.$isScopedPolicyMenuHidden('oss_hidden_columns.url'),
  242. },
  243. {
  244. title: this.$t('storage.text_220'),
  245. field: 'cdn_domains',
  246. slots: {
  247. default: ({ row }, h) => {
  248. if (!this.data.cdn_domains) {
  249. return '-'
  250. }
  251. const columns = [
  252. {
  253. field: 'domain',
  254. title: this.$t('storage.text_221'),
  255. slots: {
  256. default: ({ row }) => {
  257. return [
  258. <div>
  259. <a href={row.domain}>{row.domain}</a>
  260. <copy class="ml-1" message={row.domain} />
  261. </div>]
  262. },
  263. },
  264. },
  265. {
  266. field: 'status',
  267. title: this.$t('storage.text_41'),
  268. formatter: ({ cellValue, row }) => {
  269. const map = {
  270. rejected: this.$t('storage.text_222'),
  271. processing: this.$t('storage.text_223'),
  272. online: this.$t('storage.text_224'),
  273. offline: this.$t('storage.text_225'),
  274. }
  275. return map[cellValue] || '-'
  276. },
  277. },
  278. {
  279. field: 'area',
  280. title: this.$t('storage.text_226'),
  281. formatter: ({ cellValue, row }) => {
  282. const map = {
  283. mainland: this.$t('storage.text_227'),
  284. overseas: this.$t('storage.text_228'),
  285. global: this.$t('storage.text_229'),
  286. }
  287. return map[cellValue] || '-'
  288. },
  289. },
  290. ]
  291. return [
  292. <vxe-grid class="mb-2" data={ this.data.cdn_domains || [] } columns={ columns } />,
  293. ]
  294. },
  295. },
  296. hidden: () => this.$isScopedPolicyMenuHidden('oss_hidden_columns.cdn_domains'),
  297. },
  298. {
  299. title: this.$t('storage.text_230'),
  300. items: [
  301. {
  302. field: 'website_url',
  303. title: this.$t('storage.text_231'),
  304. slots: {
  305. default: ({ row }, h) => {
  306. return [
  307. <list-body-cell-wrap class="float-left" copy row={ row } field='website_url' title={ row.website_url } />,
  308. <a-tooltip>
  309. { row.provider !== HYPERVISORS_MAP.qcloud.provider
  310. ? (this._isOwner
  311. ? (HYPERVISORS_MAP[row.provider.toLowerCase()]
  312. ? <template slot="title">{i18n.t('storage.text_236', [HYPERVISORS_MAP[row.provider.toLowerCase()].label])}</template>
  313. : '')
  314. : this.$t('storage.text_257'))
  315. : null }
  316. <a-button type="link" class="float-left ml-2" style="display: grid;" disabled={ row.provider !== HYPERVISORS_MAP.qcloud.provider && this._isOwner } onClick={() => this.handleSetWebsite(row)}>{ this.$t('common.setting') }</a-button>
  317. </a-tooltip>,
  318. ]
  319. },
  320. },
  321. },
  322. ],
  323. hidden: () => this.$isScopedPolicyMenuHidden('oss_hidden_columns.website_url'),
  324. },
  325. {
  326. title: <RenderSizeTitle data={this.data} />,
  327. items: [
  328. {
  329. field: 'size_bytes',
  330. title: this.$t('storage.text_141'),
  331. formatter: ({ row }) => {
  332. return sizestrWithUnit(row.size_bytes, 'B', 1024)
  333. },
  334. },
  335. {
  336. field: 'object_cnt',
  337. title: this.$t('storage.text_142'),
  338. formatter: ({ row }) => {
  339. return this.$t('storage.text_143', [row.object_cnt || 0])
  340. },
  341. },
  342. ],
  343. hidden: () => this.$isScopedPolicyMenuHidden('oss_hidden_columns.size'),
  344. },
  345. {
  346. title: this.$t('storage.text_144'),
  347. items: [
  348. {
  349. field: 'size_bytes_limit',
  350. title: this.$t('storage.text_59'),
  351. formatter: ({ row }) => {
  352. if (row.size_bytes_limit > 0) {
  353. return sizestrWithUnit(row.size_bytes_limit, 'B', 1024)
  354. } else {
  355. return this.$t('storage.text_145')
  356. }
  357. },
  358. },
  359. {
  360. field: 'object_cnt_limit',
  361. title: this.$t('storage.text_135'),
  362. formatter: ({ row }) => {
  363. if (row.object_cnt_limit > 0) {
  364. return this.$t('storage.text_146', [row.object_cnt_limit])
  365. } else {
  366. return this.$t('storage.text_145')
  367. }
  368. },
  369. },
  370. ],
  371. hidden: () => this.$isScopedPolicyMenuHidden('oss_hidden_columns.size_limit'),
  372. },
  373. {
  374. title: this.$t('storage.text_147'),
  375. items: [
  376. {
  377. field: 'acl',
  378. title: this.$t('storage.text_93'),
  379. slots: {
  380. default: ({ row }, h) => {
  381. return [
  382. <span>{ ACL_TYPE[row.acl] || row.acl }</span>,
  383. <a onClick={() => this.handleSetAcl(row)} class='ml-2'>{ this.$t('common.setting') }</a>,
  384. ]
  385. },
  386. },
  387. },
  388. ],
  389. hidden: () => this.$isScopedPolicyMenuHidden('oss_hidden_columns.acl'),
  390. },
  391. referer,
  392. ]
  393. return ret
  394. },
  395. _isOwner () {
  396. if (this.$store.getters.scope === 'project' && this.data.tenant_id !== this.$store.getters.auth.tenant) return false
  397. return this.$isOwner(this.data).validate
  398. },
  399. },
  400. created () {
  401. this.bucketsM = new this.$Manager('buckets')
  402. // 目前进腾讯云支持
  403. if (this.data.provider === HYPERVISORS_MAP.qcloud.provider) {
  404. this.fetchWebsite()
  405. this.fetchCdnDomain()
  406. }
  407. if (this.isSupportReferer) {
  408. this.fetchReferer()
  409. }
  410. },
  411. methods: {
  412. async fetchWebsite () {
  413. this.loading = true
  414. try {
  415. const { data } = await this.bucketsM.getSpecific({
  416. id: this.data.id,
  417. spec: 'website',
  418. })
  419. this.$set(this.data, 'website_url', data.url)
  420. this.websiteData = data
  421. } catch (err) {
  422. throw err
  423. } finally {
  424. this.loading = false
  425. }
  426. },
  427. async fetchReferer () {
  428. this.loading = true
  429. try {
  430. const { data } = await this.bucketsM.getSpecific({
  431. id: this.data.id,
  432. spec: 'referer',
  433. })
  434. this.$set(this.data, 'referer', data)
  435. } catch (err) {
  436. throw err
  437. } finally {
  438. this.loading = false
  439. }
  440. },
  441. async fetchCdnDomain () {
  442. this.loading = true
  443. try {
  444. const { data: { data } } = await this.bucketsM.getSpecific({
  445. id: this.data.id,
  446. spec: 'cdn-domain',
  447. })
  448. this.$set(this.data, 'cdn_domains', data)
  449. } catch (err) {
  450. throw err
  451. } finally {
  452. this.loading = false
  453. }
  454. },
  455. handleSetAcl (row) {
  456. this.createDialog('ObjectsUpdateAclDialog', {
  457. title: this.$t('storage.text_138'),
  458. data: [row],
  459. bucket: row,
  460. resName: row.name,
  461. columns: this.columns,
  462. list: this.list,
  463. refresh: this.refresh,
  464. })
  465. },
  466. handleSetWebsite (row) {
  467. this.$router.push({
  468. path: '/bucket/setstaticwebsit',
  469. query: {
  470. id: row.id,
  471. ...this.websiteData,
  472. },
  473. })
  474. },
  475. handleSetReferer (row) {
  476. this.createDialog('SetAntiLeechDialog', {
  477. name: this.$t('storage.text_18'),
  478. data: [row],
  479. columns: this.columns,
  480. onManager: this.onManager,
  481. refresh: this.refresh,
  482. success: () => {
  483. this.fetchReferer()
  484. },
  485. })
  486. },
  487. },
  488. }
  489. </script>