diff --git a/src/renderer/i18n/locales/en.json b/src/renderer/i18n/locales/en.json index 7d6bb5de..28f2d57e 100644 --- a/src/renderer/i18n/locales/en.json +++ b/src/renderer/i18n/locales/en.json @@ -654,6 +654,9 @@ }, "selectDownloadFolderTips": "Select download directory", "selectDownloadFolderTitle": "Choose download folder", + "thumbnailSuffixPlaceholder": "Example: ?imageMogr2/thumbnail/200x200", + "thumbnailSuffixTips": "Only affects image previews in the cloud management list. Copy, download, and delete still use the original URL", + "thumbnailSuffixTitle": "Image preview thumbnail suffix", "timestampRenameTips": "When enabled, uploaded files will be renamed to a timestamp", "timestampRenameTitle": "Timestamp rename on upload (highest priority)", "title": "Manage General Settings" diff --git a/src/renderer/i18n/locales/zh-CN.json b/src/renderer/i18n/locales/zh-CN.json index 2702cda8..ba6007db 100644 --- a/src/renderer/i18n/locales/zh-CN.json +++ b/src/renderer/i18n/locales/zh-CN.json @@ -654,6 +654,9 @@ }, "selectDownloadFolderTips": "选择下载目录", "selectDownloadFolderTitle": "选择下载文件夹", + "thumbnailSuffixPlaceholder": "例如:?imageMogr2/thumbnail/200x200", + "thumbnailSuffixTips": "仅影响云管理列表中的图片预览,不会改变复制链接、下载或删除使用的原始地址", + "thumbnailSuffixTitle": "图片预览缩略图后缀", "timestampRenameTips": "开启后,上传的文件将自动重命名为时间戳", "timestampRenameTitle": "上传文件时间戳重命名(最高优先级)", "title": "管理通用设置" diff --git a/src/renderer/i18n/locales/zh-TW.json b/src/renderer/i18n/locales/zh-TW.json index 44d8083c..4c5eb038 100644 --- a/src/renderer/i18n/locales/zh-TW.json +++ b/src/renderer/i18n/locales/zh-TW.json @@ -654,6 +654,9 @@ }, "selectDownloadFolderTips": "選擇下載目錄", "selectDownloadFolderTitle": "選擇下載資料夾", + "thumbnailSuffixPlaceholder": "例如:?imageMogr2/thumbnail/200x200", + "thumbnailSuffixTips": "僅影響雲端管理列表中的圖片預覽,不會變更複製連結、下載或刪除使用的原始地址", + "thumbnailSuffixTitle": "圖片預覽縮圖後綴", "timestampRenameTips": "啟用後,上傳的檔案將自動更名為時間戳", "timestampRenameTitle": "上傳檔案時間戳重新命名(最高優先級)", "title": "管理通用設置" diff --git a/src/renderer/manage/pages/BucketPage.vue b/src/renderer/manage/pages/BucketPage.vue index f8c50aea..ae916502 100644 --- a/src/renderer/manage/pages/BucketPage.vue +++ b/src/renderer/manage/pages/BucketPage.vue @@ -327,7 +327,7 @@ > @@ -1189,6 +1189,7 @@ import { } from '@/manage/utils/common' import { getConfig, saveConfig } from '@/manage/utils/dataSender' import { textFileExt } from '@/manage/utils/textfile' +import { appendThumbnailSuffix } from '@/manage/utils/thumbnailUrl' import { videoExt } from '@/manage/utils/videofile' import { trimPath } from '@/utils/common' import { useDragEventListeners } from '@/utils/drag' @@ -1403,6 +1404,7 @@ const calculateAllFileSize = computed( '0', ) const isShowThumbnail = computed(() => manageStore.config.settings.isShowThumbnail ?? false) +const thumbnailSuffix = computed(() => manageStore.config.settings.thumbnailSuffix ?? '') const isUsePreSignedUrl = computed(() => manageStore.config.settings.isUsePreSignedUrl ?? false) const isAutoRefresh = computed(() => manageStore.config.settings.isAutoRefresh ?? false) const isIgnoreCase = computed(() => manageStore.config.settings.isIgnoreCase ?? false) @@ -1468,6 +1470,10 @@ watch( const getExtension = (fileName: string) => window.node.path.extname(fileName).slice(1) +function getThumbnailUrl(url: string) { + return appendThumbnailSuffix(url, thumbnailSuffix.value) +} + function getList() { if (!searchText.value) { return currentPageFilesInfo diff --git a/src/renderer/manage/pages/ManageSetting.vue b/src/renderer/manage/pages/ManageSetting.vue index 1527204c..c0ebe551 100644 --- a/src/renderer/manage/pages/ManageSetting.vue +++ b/src/renderer/manage/pages/ManageSetting.vue @@ -56,20 +56,30 @@ :placeholder="t('pages.manage.setting.copyFormat.customTips')" /> - - - - - - + ({ customRename: false, isAutoRefresh: false, isShowThumbnail: false, + thumbnailSuffix: '', isUsePreSignedUrl: false, isIgnoreCase: false, isForceCustomUrlHttps: false, diff --git a/src/renderer/manage/utils/thumbnailUrl.ts b/src/renderer/manage/utils/thumbnailUrl.ts new file mode 100644 index 00000000..7106bada --- /dev/null +++ b/src/renderer/manage/utils/thumbnailUrl.ts @@ -0,0 +1,14 @@ +export function appendThumbnailSuffix(url: string, suffix?: string): string { + const normalizedSuffix = suffix?.trim() ?? '' + if (!url || !normalizedSuffix) return url + + if (normalizedSuffix.startsWith('?')) { + return `${url}${url.includes('?') ? '&' : '?'}${normalizedSuffix.slice(1)}` + } + + if (normalizedSuffix.startsWith('&')) { + return `${url}${url.includes('?') ? '&' : '?'}${normalizedSuffix.slice(1)}` + } + + return `${url}${normalizedSuffix}` +} diff --git a/tests/thumbnail-url.test.ts b/tests/thumbnail-url.test.ts new file mode 100644 index 00000000..ee8e27bd --- /dev/null +++ b/tests/thumbnail-url.test.ts @@ -0,0 +1,36 @@ +import { describe, expect, it } from 'vitest' + +import { appendThumbnailSuffix } from '../src/renderer/manage/utils/thumbnailUrl' + +describe('appendThumbnailSuffix', () => { + it('keeps the original URL when the suffix is empty', () => { + const url = 'https://example.com/image.png' + + expect(appendThumbnailSuffix(url, '')).toBe(url) + expect(appendThumbnailSuffix(url)).toBe(url) + }) + + it('appends query-style suffixes to URLs without query strings', () => { + expect(appendThumbnailSuffix('https://example.com/image.png', '?imageMogr2/thumbnail/200x200')).toBe( + 'https://example.com/image.png?imageMogr2/thumbnail/200x200', + ) + }) + + it('converts query-style suffixes to additional parameters when the URL already has a query string', () => { + expect(appendThumbnailSuffix('https://example.com/image.png?version=1', '?imageMogr2/thumbnail/200x200')).toBe( + 'https://example.com/image.png?version=1&imageMogr2/thumbnail/200x200', + ) + }) + + it('normalizes ampersand-prefixed suffixes when the URL has no query string', () => { + expect(appendThumbnailSuffix('https://example.com/image.png', '&x-oss-process=image/resize,w_200')).toBe( + 'https://example.com/image.png?x-oss-process=image/resize,w_200', + ) + }) + + it('appends path-style suffixes unchanged', () => { + expect(appendThumbnailSuffix('https://example.com/image.png', '/thumbnail/200x200')).toBe( + 'https://example.com/image.png/thumbnail/200x200', + ) + }) +})