| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457 |
- <template>
- <div>
- <template v-if="isInternal">
- <a-alert type="warning" class="mb-2" :message="$t('storage.internal_bucket_file')" />
- <data-empty />
- </template>
- <page-list
- v-else
- :list="list"
- :columns="columns"
- :group-actions="groupActions"
- :single-actions="singleActions"
- default-search-key="prefix"
- :placeholder="$t('storage.bucket_object_search_placeholder')">
- <div slot="table-prepend" class="d-flex align-items-center pt-2 pb-2">
- <span><a-icon type="folder-open" theme="filled" style="color: rgb(245,200, 61);font-size:15px" />{{$t('storage.text_150')}}</span>
- <a-breadcrumb>
- <a-breadcrumb-item>
- <a-button style="padding:0" type="link" @click="nextPage('')">{{data.name}}</a-button>
- </a-breadcrumb-item>
- <a-breadcrumb-item v-for="(value, key) in breadcrumbs" :key="key">
- <a-button style="padding:0" type="link" @click="nextPage(key)">{{value}}</a-button>
- </a-breadcrumb-item>
- </a-breadcrumb>
- </div>
- </page-list>
- </div>
- </template>
- <script>
- import { ACL_TYPE, FINANCE_INTERNAL } from '@Storage/constants/index.js'
- import { objectsModel } from '@Storage/views/bucket/utils/controller.js'
- import WindowsMixin from '@/mixins/windows'
- import ListMixin from '@/mixins/list'
- import { sizestrWithUnit } from '@/utils/utils'
- import i18n from '@/locales'
- const validDirName = (rule, value, callback) => {
- if (!value) {
- callback(new Error(i18n.t('storage.text_151')))
- } else if (value.startsWith('/')) {
- callback(new Error(i18n.t('storage.text_152')))
- } else if (value.includes('//')) {
- callback(new Error(i18n.t('storage.validDirName')))
- } else if (value === '..') {
- callback(new Error(i18n.t('storage.text_153')))
- } else {
- callback()
- }
- }
- export default {
- name: 'BucketStorageObjectList',
- mixins: [WindowsMixin, ListMixin],
- props: {
- id: String,
- data: {
- type: Object,
- },
- },
- data () {
- return {
- paths: [],
- prefix: '',
- nextFetchListLoading: false,
- list: this.$list.createList(this, {
- id: 'objectListForBucketStorageSidePage',
- resource: 'objects',
- getParams: this.getParams,
- ctx: [['buckets', this.data.id]],
- idKey: 'key',
- filterOptions: {
- prefix: {
- label: this.$t('storage.text_154'),
- formatter: val => {
- return `${this.prefix}${val}`
- },
- },
- },
- }),
- columns: [
- {
- field: 'name',
- title: this.$t('storage.text_154'),
- minWidth: 120,
- showOverflow: 'ellipsis',
- slots: {
- default: ({ row }) => {
- const { key } = row
- if (this.nextFetchListLoading && this.prefix === key) {
- return [<a-icon type="loading" />]
- }
- const rkey = key.replace(this.prefix, '')
- if (this.isDir(key)) {
- return [
- <div class="d-flex align-items-center">
- <a-icon type="folder" theme="filled" style="color: rgb(245,200, 61)" />
- <a class="text-truncate" style="margin-right: 3px" onClick={() => this.nextPage(key)} title={rkey}>{ rkey }</a>
- <copy message={rkey} />
- </div>,
- ]
- }
- return [
- <div class="d-flex align-items-center">
- <a-icon theme="filled" type="file" />
- <span class="text-truncate" title={rkey}>
- {rkey}
- </span>
- <copy message={rkey} />
- </div>,
- ]
- },
- },
- },
- {
- field: 'acl',
- title: this.$t('storage.text_93'),
- width: 120,
- formatter: ({ row }) => {
- return ACL_TYPE[row.acl] || row.acl || '-'
- },
- },
- {
- field: 'size_bytes',
- title: this.$t('storage.text_155'),
- minWidth: 100,
- formatter: ({ row }) => {
- return row.size_bytes ? sizestrWithUnit(row.size_bytes, 'B', 1024) : '-'
- },
- },
- {
- field: 'storage_class',
- title: this.$t('storage.text_38'),
- width: 120,
- formatter: ({ row }) => {
- return row.storage_class || '-'
- },
- },
- {
- field: 'last_modified',
- title: this.$t('storage.text_156'),
- width: 100,
- formatter: ({ row }) => {
- return row.last_modified ? this.$moment(row.last_modified).fromNow() : '-'
- },
- },
- ],
- groupActions: [
- {
- label: this.$t('storage.text_157'),
- action: () => {
- this.createDialog('ObjectsUploadFileDialog', {
- title: this.$t('storage.text_157'),
- list: this.list,
- resId: this.resId,
- resItem: this.data,
- resName: this.resName,
- prefix: this.prefix,
- })
- },
- meta: () => {
- const isValidate = !(this.data.brand === 'Azure' && !this.prefix)
- return {
- buttonType: 'primary',
- validate: isValidate,
- tooltip: !isValidate && this.$t('storage.text_158'),
- }
- },
- },
- {
- label: this.$t('storage.text_159'),
- action: (row) => {
- this.createDialog('SmartFormDialog', {
- title: this.$t('storage.text_159'),
- data: [row],
- list: this.list,
- width: 600,
- formItemLayout: {
- wrapperCol: {
- span: 19,
- },
- labelCol: {
- span: 5,
- },
- },
- callback: async (data) => {
- const manager = new this.$Manager(`buckets/${this.resId}/makedir`, 'v2')
- data.key = `${this.prefix}${data.key}/`
- await manager.create({ data })
- this.list.fetchData()
- },
- decorators: {
- key: ['key', {
- rules: [
- { required: true, message: this.$t('storage.text_151') },
- { type: 'string', min: 1, max: 254, message: this.$t('storage.text_160'), trigger: 'blur' },
- { validator: validDirName, trigger: 'blur' },
- ],
- },
- {
- label: this.$t('storage.text_161'),
- placeholder: this.$t('storage.text_162'),
- extra: () => {
- return (
- <div>
- <div>{ this.$t('storage.text_173') }</div>
- <div class='mt-1'>{ this.$t('storage.text_174') }</div>
- <div class='mt-1'>{ this.$t('storage.text_175') }</div>
- <div class='mt-1'>{ this.$t('storage.text_176') }</div>
- </div>
- )
- },
- },
- ],
- },
- })
- },
- },
- {
- label: this.$t('storage.text_33'),
- actions: (row) => {
- return [
- {
- label: this.$t('storage.text_163'),
- action: () => {
- this.createDialog('ObjectsUpdateHttpDialog', {
- title: this.$t('storage.text_163'),
- data: this.list.selectedItems,
- resId: this.resId,
- resName: this.resName,
- columns: this.columns,
- list: this.list,
- refresh: () => {
- this.nextPage(this.prefix)
- },
- })
- },
- meta: () => {
- return {
- validate: this.list.selectedItems.every(row => !this.isDir(row.key)),
- }
- },
- },
- {
- label: this.$t('storage.text_138'),
- action: () => {
- this.createDialog('ObjectsUpdateAclDialog', {
- title: this.$t('storage.text_138'),
- bucket: this.data,
- data: this.list.selectedItems,
- resName: this.resName,
- columns: this.columns,
- list: this.list,
- refresh: this.refresh,
- })
- },
- meta: () => {
- return {
- validate: this.list.selectedItems.every(row => !this.isDir(row.key)),
- }
- },
- },
- {
- label: this.$t('storage.text_36'),
- action: () => {
- this.createDialog('ObjectsDeleteDialog', {
- alert: this.$t('storage.text_164'),
- data: this.list.selectedItems,
- columns: this.columns,
- title: this.$t('storage.text_36'),
- resId: this.resId,
- list: this.list,
- name: this.$t('storage.text_112'),
- })
- },
- },
- ]
- },
- meta: () => {
- return {
- validate: !!this.list.selectedItems.length,
- }
- },
- },
- ],
- singleActions: [
- {
- label: this.$t('storage.text_165'),
- action: (row) => {
- objectsModel.getUrl(row, this.data.id, this.accessUrl).then((url) => {
- // url && window.open(url, '__blank')
- const a = document.createElement('a')
- document.body.appendChild(a)
- a.href = url
- a.click()
- document.body.removeChild(a)
- })
- },
- meta: row => {
- return {
- validate: !this.isDir(row.key),
- }
- },
- },
- {
- label: this.$t('storage.text_65'),
- actions: (row) => {
- return [
- {
- label: this.$t('storage.text_166'),
- action: () => {
- // await curl = controller.getUrl(row, this.data.name)
- this.createDialog('ObjectsCreateUrlDialog', {
- title: this.$t('storage.text_167'),
- data: [row],
- resId: this.resId,
- resName: this.resName,
- accessUrl: this.accessUrl,
- columns: this.columns,
- list: this.list,
- })
- },
- meta: () => {
- return {
- validate: !this.isDir(row.key),
- }
- },
- },
- {
- label: this.$t('storage.text_138'),
- action: () => {
- this.createDialog('ObjectsUpdateAclDialog', {
- title: this.$t('storage.text_138'),
- data: [row],
- bucket: this.data,
- resName: this.resName,
- columns: this.columns,
- list: this.list,
- refresh: this.refresh,
- name: this.isDir(row.key) ? this.$t('storage.text_168') : this.$t('storage.text_112'),
- })
- },
- meta: () => {
- return {
- validate: !this.isDir(row.key),
- }
- },
- },
- {
- label: this.$t('storage.text_163'),
- action: () => {
- this.createDialog('ObjectsUpdateHttpDialog', {
- title: this.$t('storage.text_163'),
- data: [row],
- resName: this.resName,
- resId: this.resId,
- columns: this.columns,
- list: this.list,
- refresh: () => {
- this.nextPage(this.prefix)
- },
- })
- },
- meta: () => {
- return {
- validate: !this.isDir(row.key),
- }
- },
- },
- {
- label: this.$t('storage.text_36'),
- action: () => {
- this.createDialog('ObjectsDeleteDialog', {
- alert: this.$t('storage.text_164'),
- data: [row],
- columns: this.columns,
- title: this.$t('storage.text_36'),
- resName: this.resName,
- resId: this.resId,
- list: this.list,
- name: this.isDir(row.key) ? this.$t('storage.text_168') : this.$t('storage.text_112'),
- })
- },
- },
- ]
- },
- // meta: row => {
- // return {
- // validate: !this.isDir(row.key),
- // }
- // },
- },
- ],
- }
- },
- computed: {
- resId () {
- return this.data.id
- },
- resName () {
- return this.data.name
- },
- accessUrl () {
- if (this.data.access_urls && this.data.access_urls.length > 0) {
- const accessUrls = this.data.access_urls
- for (let i = 0; i < accessUrls.length; i++) {
- if (accessUrls[i].primary) {
- return accessUrls[i].url
- }
- }
- return accessUrls[0].url
- }
- return ''
- },
- breadcrumbs () {
- const _ = {}
- if (this.prefix) {
- const paths = this.prefix.split('/')
- if (paths && paths.length > 0) {
- paths.forEach((path, index) => {
- if (path === '') return false
- const k = paths.slice(0, index + 1).join('/')
- _[k + '/'] = path
- })
- }
- }
- return _
- },
- isInternal () {
- return FINANCE_INTERNAL.includes(this.data.location)
- },
- },
- created () {
- !this.isInternal && this.list.fetchData()
- this.initSidePageTab('detail')
- },
- methods: {
- isDir (key) {
- return key.endsWith('/')
- },
- async nextPage (key, index) {
- // 表示根目录,根目录不需要prefix
- this.prefix = key
- this.nextFetchListLoading = true
- await this.list.changeFilter({})
- await this.list.fetchData()
- this.nextFetchListLoading = false
- },
- getParams () {
- const _ = {}
- if (this.prefix) {
- _.prefix = this.prefix
- }
- return _
- },
- },
- }
- </script>
|