diff --git a/components/object/info.vue b/components/object/info.vue
index e3e7bf4..2777acd 100644
--- a/components/object/info.vue
+++ b/components/object/info.vue
@@ -4,22 +4,27 @@
- {{ t("Download") }}
+ {{ t('Download') }}
(showPreview = true)">
- {{ t("Preview") }}
+ {{ t('Preview') }}
(showTagView = true)">
- {{ t("Tags") }}
+ {{ t('Tags') }}
+
+
+
+
+ {{ t('Version') }}
(showRetentionView = true)">
- {{ t("Retention") }}
+ {{ t('Retention') }}
{{ object?.ETag }}
-
{{ object?.LastModified }}
+
{{
+ object?.LastModified
+ }}
@@ -51,16 +62,17 @@
v-model:value="legalHold"
:loading="legalHoldLoading"
:round="false"
- @update:value="handleChangeLegalStatus">
+ @update:value="handleChangeLegalStatus"
+ >
- {{ t("Enabled") }}
+ {{ t('Enabled') }}
- {{ t("Disabled") }}
+ {{ t('Disabled') }}
- {{ t("Disabled") }}
+ {{ t('Disabled') }}
@@ -70,10 +82,12 @@
- {{ t("Retention Mode") + ": " + (retentionMode ? retentionMode : t("None")) }}
+ {{
+ t('Retention Mode') + ': ' + (retentionMode ? retentionMode : t('None'))
+ }}
- {{ t("Retention RetainUntilDate") + ": " + retainUntilDate }}
+ {{ t('Retention RetainUntilDate') + ': ' + retainUntilDate }}
@@ -82,15 +96,28 @@
- {{ t("Copy") }}
+ {{
+ t('Copy')
+ }}
-
+
-
+
+ @close="handledeleteTag(index)"
+ >
{{ tag.Key }}:{{ tag.Value }}
@@ -107,11 +135,14 @@
-
+
- {{ t("Add") }}
- {{ t("Cancel") }}
+ {{ t('Add') }}
+ {{ t('Cancel') }}
@@ -121,33 +152,40 @@
v-model:show="showRetentionView"
preset="card"
:title="t('Retention') + t('Policy')"
- class="max-w-screen-md">
+ class="max-w-screen-md"
+ >
+ class="w-[500px]"
+ >
- {{ t("COMPLIANCE") }}
- {{ t("GOVERNANCE") }}
+ {{ t('COMPLIANCE') }}
+ {{ t('GOVERNANCE') }}
-
+
+ clearable
+ />
- {{ t("Confirm") }}
- {{ t("Reset") }}
- {{ t("Cancel") }}
+ {{ t('Confirm') }}
+ {{ t('Reset') }}
+ {{ t('Cancel') }}
@@ -155,16 +193,24 @@
+
diff --git a/components/object/list.vue b/components/object/list.vue
index 19b42fc..42bc1dc 100644
--- a/components/object/list.vue
+++ b/components/object/list.vue
@@ -278,6 +278,7 @@ watch(
);
const contents = computed(() => data.value?.contents || []);
+console.log('🚀 ~ contents:', contents.value);
const commonPrefixes = computed(() => data.value?.commonPrefixes || []);
const nextToken = computed(() => data.value?.nextContinuationToken || null);
diff --git a/components/object/preview-modal.vue b/components/object/preview-modal.vue
index 1879de4..a0ac876 100644
--- a/components/object/preview-modal.vue
+++ b/components/object/preview-modal.vue
@@ -13,10 +13,19 @@
-
+
-
+
{{ fileContent }}
- {{ key }}
- {{ object?.ContentLength }}
+ {{ key }}
+ {{
+ object?.ContentLength
+ }}
{{ object?.ContentType }}
- {{ object?.ETag }}
- {{ object?.LastModified }}
+ {{ object?.ETag }}
+ {{
+ object?.LastModified
+ }}
-
+
-
+
{{ tag.Key }}:{{ tag.Value }}
@@ -86,87 +106,91 @@
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
-const { t } = useI18n()
-const router = useRouter()
+const { t } = useI18n();
+const router = useRouter();
const { $s3Client } = useNuxtApp();
const message = useMessage();
-const props = defineProps<{ bucket: string; objectKey: string }>()
+const props = defineProps<{ bucket: string; objectKey: string }>();
-const bucketName = computed(() => props.bucket as string)
-const { getObjectTagging, putObjectTagging, deleteObjectTagging } = useObject({ bucket: bucketName.value })
+const bucketName = computed(() => props.bucket as string);
+const { getObjectTagging, putObjectTagging, deleteObjectTagging } = useObject({
+ bucket: bucketName.value,
+});
// 当前路径的前缀, example: '/folder1/folder2/'
-const key = computed(() => decodeURIComponent(props.objectKey as string))
+const key = computed(() => decodeURIComponent(props.objectKey as string));
// 预览内容
-const showPreview = ref(false)
+const showPreview = ref(false);
// 标签
-const showTagView = ref(false)
+const showTagView = ref(false);
const tagFormValue = ref({
Key: '',
- Value: ''
-})
+ Value: '',
+});
interface Tag {
- Key: string
- Value: string
+ Key: string;
+ Value: string;
}
// 获取tags
-const tags = ref([])
+const tags = ref([]);
const getTags = async () => {
- const resp: any = await getObjectTagging(key.value)
- tags.value = resp.TagSet || []
+ const resp: any = await getObjectTagging(key.value);
+ tags.value = resp.TagSet || [];
+};
+getTags();
-}
-getTags()
-
-const dialog = useDialog()
+const dialog = useDialog();
// 删除标签
const handledeleteTag = async (index: number) => {
dialog.error({
- title: t("Warning"),
- content: t("Delete Tag Confirm"),
- positiveText: t("Confirm"),
- negativeText: t("Cancel"),
+ title: t('Warning'),
+ content: t('Delete Tag Confirm'),
+ positiveText: t('Confirm'),
+ negativeText: t('Cancel'),
onPositiveClick: async () => {
- putObjectTagging(key.value, { TagSet: tags.value.filter((item, keyIndex) => keyIndex !== index) })
+ putObjectTagging(key.value, {
+ TagSet: tags.value.filter((item, keyIndex) => keyIndex !== index),
+ })
.then(() => {
- message.success(t("Tag Update Success"))
- getTags()
- })
- .catch((error) => {
- message.error(t("Tag Delete Failed", { error: error.message }))
+ message.success(t('Tag Update Success'));
+ getTags();
})
+ .catch(error => {
+ message.error(t('Tag Delete Failed', { error: error.message }));
+ });
},
});
-
-
-}
+};
const submitTagForm = async () => {
const tag = {
Key: tagFormValue.value.Key,
- Value: tagFormValue.value.Value
- }
+ Value: tagFormValue.value.Value,
+ };
putObjectTagging(key.value, {
- TagSet: [...tags.value, tag]
+ TagSet: [...tags.value, tag],
}).then(() => {
- message.success(t('Tag Set Success'))
- getTags()
- })
-
-}
+ message.success(t('Tag Set Success'));
+ getTags();
+ });
+};
const objectApi = useObject({ bucket: bucketName.value });
// 在服务端获取数据
-const { data: object, status, refresh } = useAsyncData(`head-object&${key}`, () => objectApi.headObject(key.value))
+const {
+ data: object,
+ status,
+ refresh,
+} = useAsyncData(`head-object&${key}`, () => objectApi.headObject(key.value));
const download = async () => {
const msg = message.loading(t('Getting URL'));
const url = await objectApi.getSignedUrl(key.value);
msg.destroy();
- window.open(url, '_blank')
-}
+ window.open(url, '_blank');
+};
const copySignedUrl = async () => {
const msg = message.loading(t('Getting URL'));
@@ -174,12 +198,10 @@ const copySignedUrl = async () => {
await navigator.clipboard.writeText(url);
msg.destroy();
message.success(t('URL Copied'));
-}
+};
const deleteObject = async () => {
await objectApi.deleteObject(key.value);
message.success(t('Delete Success'));
router.back();
-}
-
-
+};
diff --git a/composables/useObject.ts b/composables/useObject.ts
index 85b9b48..507ce43 100644
--- a/composables/useObject.ts
+++ b/composables/useObject.ts
@@ -11,8 +11,9 @@ import {
PutObjectRetentionCommand,
GetObjectLegalHoldCommand,
PutObjectLegalHoldCommand,
-} from "@aws-sdk/client-s3";
-import { getSignedUrl as _getSignedUrl } from "@aws-sdk/s3-request-presigner";
+ ListObjectVersionsCommand,
+} from '@aws-sdk/client-s3';
+import { getSignedUrl as _getSignedUrl } from '@aws-sdk/s3-request-presigner';
export function useObject({ bucket, region }: { bucket: string; region?: string }) {
const $client = useNuxtApp().$s3Client;
@@ -54,18 +55,26 @@ export function useObject({ bucket, region }: { bucket: string; region?: string
return await $client.send(new DeleteObjectCommand(params));
};
- const listObject = async (bucket: string, prefix: string | undefined = undefined, pageSize: number = 25) => {
+ const listObject = async (
+ bucket: string,
+ prefix: string | undefined = undefined,
+ pageSize: number = 25
+ ) => {
const params = {
Bucket: bucket,
Prefix: prefix,
MaxKeys: pageSize,
- Delimiter: "/",
+ Delimiter: '/',
};
return await $client.send(new ListObjectsV2Command(params));
};
- async function mapAllFiles(bucketName: string, prefix: string, callback: (fileKey: string) => void) {
+ async function mapAllFiles(
+ bucketName: string,
+ prefix: string,
+ callback: (fileKey: string) => void
+ ) {
let isTruncated = true;
let continuationToken: string | undefined = undefined;
@@ -82,7 +91,7 @@ export function useObject({ bucket, region }: { bucket: string; region?: string
try {
const data = await $client.send(new ListObjectsV2Command(params));
- data.Contents?.forEach((item) => {
+ data.Contents?.forEach(item => {
if (item.Key) {
callback(item.Key);
}
@@ -91,7 +100,7 @@ export function useObject({ bucket, region }: { bucket: string; region?: string
isTruncated = data.IsTruncated || false;
continuationToken = data.NextContinuationToken;
} catch (error) {
- console.error("Error listing files: ", error);
+ console.error('Error listing files: ', error);
throw error;
}
}
@@ -138,7 +147,7 @@ export function useObject({ bucket, region }: { bucket: string; region?: string
}
return response;
} catch (error: any) {
- if (error.message?.includes("Deserialization error")) {
+ if (error.message?.includes('Deserialization error')) {
return { Retention: null };
}
throw error;
@@ -173,6 +182,15 @@ export function useObject({ bucket, region }: { bucket: string; region?: string
return await $client.send(new PutObjectLegalHoldCommand(params));
}
+ async function getObjectVersions(key: string) {
+ const params = {
+ Bucket: bucket,
+ Prefix: key,
+ };
+
+ return await $client.send(new ListObjectVersionsCommand(params));
+ }
+
return {
headObject,
putObject,
@@ -187,5 +205,6 @@ export function useObject({ bucket, region }: { bucket: string; region?: string
putObjectRetention,
getObjectLegalHold,
putObjectLegalHold,
+ getObjectVersions,
};
}