mirror of
https://github.com/Kuingsmile/PicList.git
synced 2025-01-22 14:28:12 -05:00
✨ Feature(custom): support use presigned url for image preview
ISSUES CLOSED: #265
This commit is contained in:
parent
cd48b24a21
commit
4209838925
@ -392,6 +392,7 @@ MANAGE_SETTING_CLEAR_CACHE_TIPS: After clearing, the file list will be reloaded
|
||||
MANAGE_SETTING_CLEAR_CACHE_PROMPT: Are you sure you want to clear the file list cache database?
|
||||
MANAGE_SETTING_CLEAR_CACHE_BUTTON: Clear
|
||||
MANAGE_SETTING_ISSHOWTHUMBNAIL_TITLE: Display the original image instead of format icon (requires public access permissions)
|
||||
MANAGE_SETTING_ISUSEPRESIGNEDURL_TITLE: Use presigned URL for image display
|
||||
MANAGE_SETTING_ISSHOWLIST_TITLE: Default display mode for the file list
|
||||
MANAGE_SETTING_ISSHOWLIST_ON: List
|
||||
MANAGE_SETTING_ISSHOWLIST_OFF: Card
|
||||
|
@ -394,6 +394,7 @@ MANAGE_SETTING_CLEAR_CACHE_TIPS: 清空后下次进入新目录时将会重新
|
||||
MANAGE_SETTING_CLEAR_CACHE_PROMPT: 确定要清空文件列表缓存数据库吗?
|
||||
MANAGE_SETTING_CLEAR_CACHE_BUTTON: 清空
|
||||
MANAGE_SETTING_ISSHOWTHUMBNAIL_TITLE: 图片显示为原图而非默认文件格式图标(需要存储桶可公开访问)
|
||||
MANAGE_SETTING_ISUSEPRESIGNEDURL_TITLE: 使用预签名URL预览图片
|
||||
MANAGE_SETTING_ISSHOWLIST_TITLE: 文件列表默认显示方式
|
||||
MANAGE_SETTING_ISSHOWLIST_ON: 列表
|
||||
MANAGE_SETTING_ISSHOWLIST_OFF: 卡片
|
||||
|
@ -392,6 +392,7 @@ MANAGE_SETTING_CLEAR_CACHE_TIPS: 清空後下次進入新目錄時將會重新
|
||||
MANAGE_SETTING_CLEAR_CACHE_PROMPT: 確定要清空檔案列表快取資料庫嗎?
|
||||
MANAGE_SETTING_CLEAR_CACHE_BUTTON: 清空
|
||||
MANAGE_SETTING_ISSHOWTHUMBNAIL_TITLE: 顯示圖片的原始圖像而非預設的檔案格式圖示(需要存儲桶公開訪問權限)
|
||||
MANAGE_SETTING_ISUSEPRESIGNEDURL_TITLE: 使用預簽名URL预览圖片
|
||||
MANAGE_SETTING_ISSHOWLIST_TITLE: 檔案列表預設顯示方式
|
||||
MANAGE_SETTING_ISSHOWLIST_ON: 列表
|
||||
MANAGE_SETTING_ISSHOWLIST_OFF: 卡片
|
||||
|
51
src/renderer/components/ImagePreSign.vue
Normal file
51
src/renderer/components/ImagePreSign.vue
Normal file
@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<el-image :src="imageSource" fit="contain" style="height: 100px; width: 100%; margin: 0 auto">
|
||||
<template #placeholder>
|
||||
<el-icon>
|
||||
<Loading />
|
||||
</el-icon>
|
||||
</template>
|
||||
<template #error>
|
||||
<el-image :src="iconPath" fit="contain" style="height: 100px; width: 100%; margin: 0 auto" />
|
||||
</template>
|
||||
</el-image>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, watch, computed } from 'vue'
|
||||
import { Loading } from '@element-plus/icons-vue'
|
||||
|
||||
import { getFileIconPath } from '@/manage/utils/common'
|
||||
import { IRPCActionType } from '#/types/enum'
|
||||
import { triggerRPC } from '@/utils/common'
|
||||
|
||||
const preSignedUrl = ref('')
|
||||
|
||||
const props = defineProps<{
|
||||
item: {
|
||||
key: string
|
||||
isImage: boolean
|
||||
fileName: string | null | undefined
|
||||
}
|
||||
alias: string
|
||||
url: string
|
||||
config: any
|
||||
isShowThumbnail: boolean
|
||||
}>()
|
||||
|
||||
const imageSource = computed(() => {
|
||||
return props.isShowThumbnail && props.item.isImage
|
||||
? preSignedUrl.value
|
||||
: require(`../manage/pages/assets/icons/${getFileIconPath(props.item.fileName ?? '')}`)
|
||||
})
|
||||
|
||||
const iconPath = computed(() => require(`../manage/pages/assets/icons/${getFileIconPath(props.item.fileName ?? '')}`))
|
||||
|
||||
async function getUrl() {
|
||||
preSignedUrl.value = await triggerRPC<any>(IRPCActionType.MANAGE_GET_PRE_SIGNED_URL, props.alias, props.config)
|
||||
}
|
||||
|
||||
watch(() => [props.url, props.item], getUrl, { deep: true })
|
||||
|
||||
onMounted(getUrl)
|
||||
</script>
|
65
src/renderer/components/ImagePreSignTsx.tsx
Normal file
65
src/renderer/components/ImagePreSignTsx.tsx
Normal file
@ -0,0 +1,65 @@
|
||||
import { ElImage, ElIcon } from 'element-plus'
|
||||
import { defineComponent, ref, onMounted, watch, computed } from 'vue'
|
||||
import { Loading } from '@element-plus/icons-vue'
|
||||
|
||||
import { getFileIconPath } from '@/manage/utils/common'
|
||||
import { IRPCActionType } from '#/types/enum'
|
||||
import { triggerRPC } from '@/utils/common'
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
isShowThumbnail: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
item: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
alias: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
config: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
setup(props) {
|
||||
const preSignedUrl = ref('')
|
||||
|
||||
const imageSource = computed(() => {
|
||||
return props.isShowThumbnail && props.item.isImage
|
||||
? preSignedUrl.value
|
||||
: require(`../manage/pages/assets/icons/${getFileIconPath(props.item.fileName ?? '')}`)
|
||||
})
|
||||
const iconPath = computed(() =>
|
||||
require(`../manage/pages/assets/icons/${getFileIconPath(props.item.fileName ?? '')}`)
|
||||
)
|
||||
|
||||
async function getUrl() {
|
||||
preSignedUrl.value = await triggerRPC<any>(IRPCActionType.MANAGE_GET_PRE_SIGNED_URL, props.alias, props.config)
|
||||
}
|
||||
|
||||
watch(() => [props.url, props.item], getUrl, { deep: true })
|
||||
onMounted(getUrl)
|
||||
|
||||
return () => (
|
||||
<ElImage src={imageSource.value} fit='contain' style='height: 100px;width: 100%;margin: 0 auto;'>
|
||||
{{
|
||||
placeholder: () => (
|
||||
<ElIcon>
|
||||
<Loading />
|
||||
</ElIcon>
|
||||
),
|
||||
error: () => <ElImage src={iconPath.value} fit='contain' style='height: 100px;width: 100%;margin: 0 auto;' />
|
||||
}}
|
||||
</ElImage>
|
||||
)
|
||||
}
|
||||
})
|
@ -5,7 +5,7 @@
|
||||
<span v-for="(segment, index) in segments" :key="index" :style="segment.style">
|
||||
{{ segment.text }}
|
||||
</span>
|
||||
<el-tooltip :content="tooltip" effect="dark" placement="right" :persistent="false" teleported>
|
||||
<el-tooltip v-if="tooltip" :content="tooltip" effect="dark" placement="right" :persistent="false" teleported>
|
||||
<el-icon>
|
||||
<InfoFilled />
|
||||
</el-icon>
|
||||
|
@ -391,12 +391,7 @@ https://www.baidu.com/img/bd_logo1.png"
|
||||
shadow="hover"
|
||||
>
|
||||
<el-image
|
||||
v-if="
|
||||
!item.isDir &&
|
||||
currentPicBedName !== 'webdavplist' &&
|
||||
currentPicBedName !== 'sftp' &&
|
||||
currentPicBedName !== 'local'
|
||||
"
|
||||
v-if="!item.isDir && !['webdavplist', 'sftp', 'local', 's3plist'].includes(currentPicBedName)"
|
||||
:src="
|
||||
isShowThumbnail && item.isImage
|
||||
? item.url
|
||||
@ -419,6 +414,39 @@ https://www.baidu.com/img/bd_logo1.png"
|
||||
/>
|
||||
</template>
|
||||
</el-image>
|
||||
<el-image
|
||||
v-else-if="!item.isDir && currentPicBedName === 's3plist' && !isUsePreSignedUrl"
|
||||
:src="
|
||||
isShowThumbnail && item.isImage
|
||||
? item.url
|
||||
: require(`./assets/icons/${getFileIconPath(item.fileName ?? '')}`)
|
||||
"
|
||||
fit="contain"
|
||||
style="height: 100px; width: 100%; margin: 0 auto"
|
||||
@click="handleClickFile(item)"
|
||||
>
|
||||
<template #placeholder>
|
||||
<el-icon>
|
||||
<Loading />
|
||||
</el-icon>
|
||||
</template>
|
||||
<template #error>
|
||||
<el-image
|
||||
:src="require(`./assets/icons/${getFileIconPath(item.fileName ?? '')}`)"
|
||||
fit="contain"
|
||||
style="height: 100px; width: 100%; margin: 0 auto"
|
||||
/>
|
||||
</template>
|
||||
</el-image>
|
||||
<ImagePreSign
|
||||
v-else-if="!item.isDir && currentPicBedName === 's3plist' && isUsePreSignedUrl"
|
||||
:is-show-thumbnail="isShowThumbnail"
|
||||
:item="item"
|
||||
:alias="configMap.alias"
|
||||
:url="item.url"
|
||||
:config="handleGetS3Config(item)"
|
||||
@click="handleClickFile(item)"
|
||||
/>
|
||||
<ImageWebdav
|
||||
v-else-if="!item.isDir && currentPicBedName === 'webdavplist' && item.isImage"
|
||||
:is-show-thumbnail="isShowThumbnail"
|
||||
@ -1222,8 +1250,10 @@ import { textFileExt } from '@/manage/utils/textfile'
|
||||
import { videoExt } from '@/manage/utils/videofile'
|
||||
|
||||
import ImageWebdav from '@/components/ImageWebdav.vue'
|
||||
import ImagePreSign from '@/components/ImagePreSign.vue'
|
||||
import ImageLocal from '@/components/ImageLocal.vue'
|
||||
import ImageWebdavTsx from '@/components/ImageWebdavTsx'
|
||||
import ImagePreSignTsx from '@/components/ImagePreSignTsx'
|
||||
|
||||
import { T as $T } from '@/i18n'
|
||||
|
||||
@ -1231,7 +1261,7 @@ import { getExtension, trimPath } from '#/utils/common'
|
||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '#/utils/static'
|
||||
import { IUploadTask, IDownloadTask } from '#/types/manage'
|
||||
import { sendRPC, triggerRPC } from '@/utils/common'
|
||||
import { IRPCActionType } from 'root/src/universal/types/enum'
|
||||
import { IRPCActionType } from '#/types/enum'
|
||||
|
||||
/*
|
||||
configMap:{
|
||||
@ -1378,6 +1408,7 @@ const calculateAllFileSize = computed(
|
||||
'0'
|
||||
)
|
||||
const isShowThumbnail = computed(() => manageStore.config.settings.isShowThumbnail ?? false)
|
||||
const isUsePreSignedUrl = computed(() => manageStore.config.settings.isUsePreSignedUrl ?? false)
|
||||
const isAutoRefresh = computed(() => manageStore.config.settings.isAutoRefresh ?? false)
|
||||
const isIgnoreCase = computed(() => manageStore.config.settings.isIgnoreCase ?? false)
|
||||
|
||||
@ -2901,6 +2932,18 @@ function singleRename() {
|
||||
})
|
||||
}
|
||||
|
||||
function handleGetS3Config(item: any) {
|
||||
return {
|
||||
bucketName: configMap.bucketName,
|
||||
region: configMap.bucketConfig.Location,
|
||||
key: item.key,
|
||||
customUrl: currentCustomDomain.value,
|
||||
expires: manageStore.config.settings.PreSignedExpire,
|
||||
githubPrivate: configMap.bucketConfig.private,
|
||||
rawUrl: item.url
|
||||
}
|
||||
}
|
||||
|
||||
async function getPreSignedUrl(item: any) {
|
||||
const param = {
|
||||
// tcyun
|
||||
@ -3180,32 +3223,42 @@ const columns: Column<any>[] = [
|
||||
reference: () =>
|
||||
!item.isDir ? (
|
||||
currentPicBedName.value !== 'webdavplist' ? (
|
||||
<ElImage
|
||||
src={
|
||||
isShowThumbnail.value
|
||||
? item.isImage
|
||||
? item.url
|
||||
currentPicBedName.value === 's3plist' && item.isImage && isUsePreSignedUrl.value ? (
|
||||
<ImagePreSignTsx
|
||||
isShowThumbnail={isShowThumbnail.value}
|
||||
item={item}
|
||||
config={handleGetS3Config(item)}
|
||||
url={item.url}
|
||||
alias={configMap.alias}
|
||||
/>
|
||||
) : (
|
||||
<ElImage
|
||||
src={
|
||||
isShowThumbnail.value
|
||||
? item.isImage
|
||||
? item.url
|
||||
: require(`./assets/icons/${getFileIconPath(item.fileName ?? '')}`)
|
||||
: require(`./assets/icons/${getFileIconPath(item.fileName ?? '')}`)
|
||||
: require(`./assets/icons/${getFileIconPath(item.fileName ?? '')}`)
|
||||
}
|
||||
fit='contain'
|
||||
style={{ width: '20px', height: '20px' }}
|
||||
>
|
||||
{{
|
||||
placeholder: () => (
|
||||
<ElIcon>
|
||||
<Loading />
|
||||
</ElIcon>
|
||||
),
|
||||
error: () => (
|
||||
<ElImage
|
||||
src={require(`./assets/icons/${getFileIconPath(item.fileName ?? '')}`)}
|
||||
fit='contain'
|
||||
style={{ width: '20px', height: '20px' }}
|
||||
/>
|
||||
)
|
||||
}}
|
||||
</ElImage>
|
||||
}
|
||||
fit='contain'
|
||||
style={{ width: '20px', height: '20px' }}
|
||||
>
|
||||
{{
|
||||
placeholder: () => (
|
||||
<ElIcon>
|
||||
<Loading />
|
||||
</ElIcon>
|
||||
),
|
||||
error: () => (
|
||||
<ElImage
|
||||
src={require(`./assets/icons/${getFileIconPath(item.fileName ?? '')}`)}
|
||||
fit='contain'
|
||||
style={{ width: '20px', height: '20px' }}
|
||||
/>
|
||||
)
|
||||
}}
|
||||
</ElImage>
|
||||
)
|
||||
) : item.isImage ? (
|
||||
<ImageWebdavTsx
|
||||
isShowThumbnail={isShowThumbnail.value}
|
||||
@ -3235,6 +3288,14 @@ const columns: Column<any>[] = [
|
||||
config={handleGetWebdavConfig()}
|
||||
url={item.url}
|
||||
/>
|
||||
) : currentPicBedName.value === 's3plist' && item.isImage && isUsePreSignedUrl.value ? (
|
||||
<ImagePreSignTsx
|
||||
isShowThumbnail={isShowThumbnail.value}
|
||||
item={item}
|
||||
config={handleGetS3Config(item)}
|
||||
url={item.url}
|
||||
alias={configMap.alias}
|
||||
/>
|
||||
) : (
|
||||
<ElImage
|
||||
src={item.isImage ? item.url : require(`./assets/icons/${getFileIconPath(item.fileName ?? '')}`)}
|
||||
|
@ -214,6 +214,7 @@ const form = ref<IStringKeyMap>({
|
||||
isAutoRefresh: false,
|
||||
isShowThumbnail: false,
|
||||
isShowList: false,
|
||||
isUsePreSignedUrl: false,
|
||||
isIgnoreCase: false,
|
||||
isForceCustomUrlHttps: false,
|
||||
isEncodeUrl: false,
|
||||
@ -246,6 +247,7 @@ const switchFieldsList = [
|
||||
'isAutoRefresh',
|
||||
'isShowThumbnail',
|
||||
'isShowList',
|
||||
'isUsePreSignedUrl',
|
||||
'isForceCustomUrlHttps',
|
||||
'isEncodeUrl',
|
||||
'isUploadKeepDirStructure',
|
||||
@ -254,7 +256,7 @@ const switchFieldsList = [
|
||||
'randomStringRename',
|
||||
'customRename'
|
||||
]
|
||||
const switchFieldsNoTipsList = ['isShowThumbnail', 'isShowList']
|
||||
const switchFieldsNoTipsList = ['isShowThumbnail', 'isShowList', 'isUsePreSignedUrl']
|
||||
const switchFieldsHasActiveTextList = ['isShowList']
|
||||
|
||||
const switchFieldsConfigList = switchFieldsList.map(item => ({
|
||||
|
1
src/universal/types/i18n.d.ts
vendored
1
src/universal/types/i18n.d.ts
vendored
@ -368,6 +368,7 @@ interface ILocales {
|
||||
MANAGE_SETTING_CLEAR_CACHE_PROMPT: string
|
||||
MANAGE_SETTING_CLEAR_CACHE_BUTTON: string
|
||||
MANAGE_SETTING_ISSHOWTHUMBNAIL_TITLE: string
|
||||
MANAGE_SETTING_ISUSEPRESIGNEDURL_TITLE: string
|
||||
MANAGE_SETTING_ISSHOWLIST_TITLE: string
|
||||
MANAGE_SETTING_ISSHOWLIST_ON: string
|
||||
MANAGE_SETTING_ISSHOWLIST_OFF: string
|
||||
|
Loading…
Reference in New Issue
Block a user