diff --git a/console/src/locales/zh-CN.yaml b/console/src/locales/zh-CN.yaml index 9b288c28b..2d1a67ab6 100644 --- a/console/src/locales/zh-CN.yaml +++ b/console/src/locales/zh-CN.yaml @@ -498,7 +498,7 @@ core: size: 文件大小 owner: 上传者 creation_time: 上传时间 - permalink: 原始链接 + permalink: 链接 preview: click_to_exit: 点击退出预览 video_not_support: 当前浏览器不支持该视频播放 diff --git a/console/src/locales/zh-TW.yaml b/console/src/locales/zh-TW.yaml index b9f1172d1..1c799febb 100644 --- a/console/src/locales/zh-TW.yaml +++ b/console/src/locales/zh-TW.yaml @@ -498,7 +498,7 @@ core: size: 文件大小 owner: 上傳者 creation_time: 上傳時間 - permalink: 原始連結 + permalink: 連結 preview: click_to_exit: 點擊離開預覽 video_not_support: 當前瀏覽器不支援該影片播放 diff --git a/console/src/modules/contents/attachments/components/AttachmentDetailModal.vue b/console/src/modules/contents/attachments/components/AttachmentDetailModal.vue index c676b686a..fbc4a0eb2 100644 --- a/console/src/modules/contents/attachments/components/AttachmentDetailModal.vue +++ b/console/src/modules/contents/attachments/components/AttachmentDetailModal.vue @@ -15,16 +15,17 @@ import { isImage } from "@/utils/image"; import { formatDatetime } from "@/utils/date"; import { useFetchAttachmentGroup } from "../composables/use-attachment-group"; import { useQuery } from "@tanstack/vue-query"; +import AttachmentPermalinkList from "./AttachmentPermalinkList.vue"; const props = withDefaults( defineProps<{ visible: boolean; - attachment: Attachment | null; + attachment: Attachment | undefined; mountToBody?: boolean; }>(), { visible: false, - attachment: null, + attachment: undefined, mountToBody: false, } ); @@ -68,7 +69,10 @@ const onVisibleChange = (visible: boolean) => { emit("update:visible", visible); if (!visible) { onlyPreview.value = false; - emit("close"); + + setTimeout(() => { + emit("close"); + }, 200); } }; @@ -187,9 +191,7 @@ const onVisibleChange = (visible: boolean) => { - - {{ attachment?.status?.permalink }} - + diff --git a/console/src/modules/contents/attachments/components/AttachmentPermalinkList.vue b/console/src/modules/contents/attachments/components/AttachmentPermalinkList.vue new file mode 100644 index 000000000..23f410f3d --- /dev/null +++ b/console/src/modules/contents/attachments/components/AttachmentPermalinkList.vue @@ -0,0 +1,74 @@ + + + diff --git a/console/src/modules/contents/attachments/composables/use-attachment.ts b/console/src/modules/contents/attachments/composables/use-attachment.ts index 60b51b85b..1ba65628a 100644 --- a/console/src/modules/contents/attachments/composables/use-attachment.ts +++ b/console/src/modules/contents/attachments/composables/use-attachment.ts @@ -1,5 +1,5 @@ import type { Attachment, Group, Policy, User } from "@halo-dev/api-client"; -import type { Ref } from "vue"; +import { computed, type Ref } from "vue"; import { ref, watch } from "vue"; import type { AttachmentLike } from "@halo-dev/console-shared"; import { apiClient } from "@/utils/api-client"; @@ -7,6 +7,8 @@ import { Dialog, Toast } from "@halo-dev/components"; import type { Content, Editor } from "@halo-dev/richtext-editor"; import { useQuery } from "@tanstack/vue-query"; import { useI18n } from "vue-i18n"; +import { useClipboard } from "@vueuse/core"; +import { matchMediaType } from "@/utils/media-type"; interface useAttachmentControlReturn { attachments: Ref; @@ -327,3 +329,71 @@ export function useAttachmentSelect( onAttachmentSelect, }; } + +export function useAttachmentPermalinkCopy( + attachment: Ref +) { + const { copy } = useClipboard(); + const { t } = useI18n(); + + const mediaType = computed(() => { + return attachment.value?.spec.mediaType; + }); + + const isImage = computed(() => { + return mediaType.value && matchMediaType(mediaType.value, "image/*"); + }); + + const isVideo = computed(() => { + return mediaType.value && matchMediaType(mediaType.value, "video/*"); + }); + + const isAudio = computed(() => { + return mediaType.value && matchMediaType(mediaType.value, "audio/*"); + }); + + const htmlText = computed(() => { + const { permalink } = attachment.value?.status || {}; + const { displayName } = attachment.value?.spec || {}; + + if (isImage.value) { + return `${displayName}`; + } else if (isVideo.value) { + return ``; + } else if (isAudio.value) { + return ``; + } + return `${displayName}`; + }); + + const markdownText = computed(() => { + const { permalink } = attachment.value?.status || {}; + const { displayName } = attachment.value?.spec || {}; + if (isImage.value) { + return `![${displayName}](${permalink})`; + } + return `[${displayName}](${permalink})`; + }); + + const handleCopy = (format: "markdown" | "html" | "url") => { + const { permalink } = attachment.value?.status || {}; + + if (!permalink) return; + + if (format === "url") { + copy(permalink); + } else if (format === "markdown") { + copy(markdownText.value); + } else if (format === "html") { + copy(htmlText.value); + } + + Toast.success(t("core.common.toast.copy_success")); + }; + + return { + htmlText, + markdownText, + handleCopy, + }; +}