feat(StorageConfig): enhance storage settings UI with separate configurations for logged-in and anonymous users

This commit is contained in:
ShiYu
2025-05-24 00:35:13 +08:00
parent 6da267a566
commit 5c5b63e82f
2 changed files with 244 additions and 158 deletions

View File

@@ -441,15 +441,22 @@ public class PictureService(
ImageFormat convertToFormat = ImageFormat.Original, ImageFormat convertToFormat = ImageFormat.Original,
int quality = 95) int quality = 95)
{ {
// 如果未指定存储类型,则从配置中获取默认存储类型 StorageType GetConfigStorageType(string configKey)
if (storageType == null)
{ {
var defaultStorageTypeStr = configuration["Storage:DefaultStorage"]; string? configValue = configuration[configKey];
if (string.IsNullOrEmpty(defaultStorageTypeStr) || !Enum.TryParse<StorageType>(defaultStorageTypeStr, out var defaultStorageType)) return !string.IsNullOrEmpty(configValue) &&
{ Enum.TryParse<StorageType>(configValue, out var configStorageType)
defaultStorageType = StorageType.Local; // 如果配置中没有或解析失败,使用本地存储作为默认 ? configStorageType
} : StorageType.Local;
storageType = defaultStorageType; }
if (userId == null)
{
storageType = GetConfigStorageType("Storage:AnonymousDefaultStorage");
}
else if (storageType == null)
{
storageType = GetConfigStorageType("Storage:DefaultStorage");
} }
string originalFileName = fileName; string originalFileName = fileName;

View File

@@ -190,161 +190,240 @@ const SystemConfig: React.FC = () => {
</TabPane> </TabPane>
<TabPane tab="存储设置" key="Storage"> <TabPane tab="存储设置" key="Storage">
<div style={{ {/* 存储类型配置卡片 */}
marginBottom: isMobile ? 16 : 20, <Card
display: 'flex', size="small"
flexDirection: isMobile ? 'column' : 'row', title="存储类型配置"
alignItems: isMobile ? 'flex-start' : 'center', style={{ marginBottom: isMobile ? 16 : 24 }}
gap: isMobile ? 8 : 0 bodyStyle={{ padding: isMobile ? '12px' : '16px' }}
}}> >
<span style={{ <div style={{
marginRight: isMobile ? 0 : 8, display: 'grid',
display: 'inline-block', gridTemplateColumns: isMobile ? '1fr' : 'repeat(auto-fit, minmax(300px, 1fr))',
width: isMobile ? 'auto' : 100, gap: isMobile ? 12 : 16,
marginBottom: isMobile ? 4 : 0 marginBottom: 0
}}> }}>
: {/* 登录用户默认存储 */}
</span> <div>
<Select <div style={{
value={configs.Storage?.DefaultStorage || 'Local'} marginBottom: 8,
onChange={(value) => { fontSize: 14,
handleSaveConfig('Storage', 'DefaultStorage', value); fontWeight: 500,
}} color: '#666'
style={{ width: isMobile ? '100%' : 200 }} }}>
size={isMobile ? "middle" : "large"}
> </div>
{storageOptions.map(option => ( <Select
<Option key={option.value} value={option.value}> value={configs.Storage?.DefaultStorage || 'Local'}
<div style={{ display: 'flex', alignItems: 'center' }}> onChange={(value) => {
{option.icon} handleSaveConfig('Storage', 'DefaultStorage', value);
<span style={{ marginLeft: 8 }}>{option.label}</span> }}
</div> style={{ width: '100%' }}
</Option> size="large"
))} placeholder="选择登录用户的默认存储方式"
</Select> >
</div> {storageOptions.map(option => (
<Option key={option.value} value={option.value}>
<div style={{ display: 'flex', alignItems: 'center' }}>
{option.icon}
<span style={{ marginLeft: 8 }}>{option.label}</span>
</div>
</Option>
))}
</Select>
<div style={{
fontSize: 12,
color: '#999',
marginTop: 4
}}>
</div>
</div>
<div style={{ {/* 匿名用户默认存储 */}
marginBottom: isMobile ? 16 : 20, <div>
display: 'flex', <div style={{
flexDirection: isMobile ? 'column' : 'row', marginBottom: 8,
alignItems: isMobile ? 'flex-start' : 'center', fontSize: 14,
gap: isMobile ? 8 : 0 fontWeight: 500,
}}> color: '#666'
<span style={{ }}>
marginRight: isMobile ? 0 : 8,
display: 'inline-block', </div>
width: isMobile ? 'auto' : 100, <Select
marginBottom: isMobile ? 4 : 0 value={configs.Storage?.AnonymousDefaultStorage || 'Local'}
onChange={(value) => {
handleSaveConfig('Storage', 'AnonymousDefaultStorage', value);
}}
style={{ width: '100%' }}
size="large"
placeholder="选择匿名用户的默认存储方式"
>
{storageOptions.map(option => (
<Option key={option.value} value={option.value}>
<div style={{ display: 'flex', alignItems: 'center' }}>
{option.icon}
<span style={{ marginLeft: 8 }}>{option.label}</span>
</div>
</Option>
))}
</Select>
<div style={{
fontSize: 12,
color: '#999',
marginTop: 4
}}>
</div>
</div>
</div>
</Card>
{/* 存储服务配置卡片 */}
<Card
size="small"
title="存储服务配置"
style={{ marginBottom: isMobile ? 16 : 24 }}
bodyStyle={{ padding: isMobile ? '12px' : '16px' }}
>
<div style={{ marginBottom: 16 }}>
<div style={{
marginBottom: 8,
fontSize: 14,
fontWeight: 500,
color: '#666'
}}>
</div>
<Select
value={storageType}
onChange={(value) => {
setStorageType(value);
}}
style={{ width: isMobile ? '100%' : '300px' }}
size="large"
placeholder="选择需要配置的存储服务类型"
>
{storageOptions.map(option => (
<Option key={option.value} value={option.value}>
<div style={{ display: 'flex', alignItems: 'center' }}>
{option.icon}
<span style={{ marginLeft: 8 }}>{option.label}</span>
</div>
</Option>
))}
</Select>
<div style={{
fontSize: 12,
color: '#999',
marginTop: 4
}}>
</div>
</div>
{/* 存储服务具体配置 */}
<div style={{
border: '1px solid #f0f0f0',
borderRadius: 6,
padding: isMobile ? 12 : 16,
backgroundColor: '#fafafa'
}}> }}>
: {storageType === 'Local' && (
</span> <div style={{ textAlign: 'center', color: '#999', padding: '20px 0' }}>
<Select
value={storageType} </div>
onChange={(value) => { )}
setStorageType(value);
}}
style={{ width: isMobile ? '100%' : 200 }}
size={isMobile ? "middle" : "large"}
>
{storageOptions.map(option => (
<Option key={option.value} value={option.value}>
<div style={{ display: 'flex', alignItems: 'center' }}>
{option.icon}
<span style={{ marginLeft: 8 }}>{option.label}</span>
</div>
</Option>
))}
</Select>
</div>
{storageType === 'Telegram' && ( {storageType === 'Telegram' && (
<ConfigGroup <ConfigGroup
groupName="Storage" groupName="Storage"
configs={{ configs={{
"TelegramStorageBotToken": configs.Storage?.TelegramStorageBotToken || '', "TelegramStorageBotToken": configs.Storage?.TelegramStorageBotToken || '',
"TelegramStorageChatId": configs.Storage?.TelegramStorageChatId || '' "TelegramStorageChatId": configs.Storage?.TelegramStorageChatId || ''
}} }}
onSave={handleSaveConfig} onSave={handleSaveConfig}
descriptions={{ descriptions={{
"TelegramStorageBotToken": 'Telegram 机器人令牌', "TelegramStorageBotToken": 'Telegram 机器人令牌',
"TelegramStorageChatId": 'Telegram 聊天ID' "TelegramStorageChatId": 'Telegram 聊天ID'
}} }}
isMobile={isMobile} isMobile={isMobile}
/> />
)} )}
{storageType === 'S3' && ( {storageType === 'S3' && (
<ConfigGroup <ConfigGroup
groupName="Storage" groupName="Storage"
configs={{ configs={{
"S3StorageAccessKey": configs.Storage?.S3StorageAccessKey || '', "S3StorageAccessKey": configs.Storage?.S3StorageAccessKey || '',
"S3StorageSecretKey": configs.Storage?.S3StorageSecretKey || '', "S3StorageSecretKey": configs.Storage?.S3StorageSecretKey || '',
"S3StorageBucketName": configs.Storage?.S3StorageBucketName || '', "S3StorageBucketName": configs.Storage?.S3StorageBucketName || '',
"S3StorageRegion": configs.Storage?.S3StorageRegion || '', "S3StorageRegion": configs.Storage?.S3StorageRegion || '',
"S3StorageEndpoint": configs.Storage?.S3StorageEndpoint || '', "S3StorageEndpoint": configs.Storage?.S3StorageEndpoint || '',
"S3StorageCdnUrl": configs.Storage?.S3StorageCdnUrl || '', "S3StorageCdnUrl": configs.Storage?.S3StorageCdnUrl || '',
"S3StorageUsePathStyleUrls": configs.Storage?.S3StorageUsePathStyleUrls || 'false' "S3StorageUsePathStyleUrls": configs.Storage?.S3StorageUsePathStyleUrls || 'false'
}} }}
onSave={handleSaveConfig} onSave={handleSaveConfig}
descriptions={{ descriptions={{
"S3StorageAccessKey": 'S3访问密钥', "S3StorageAccessKey": 'S3访问密钥',
"S3StorageSecretKey": 'S3私有密钥', "S3StorageSecretKey": 'S3私有密钥',
"S3StorageBucketName": 'S3存储桶名称', "S3StorageBucketName": 'S3存储桶名称',
"S3StorageRegion": 'S3区域 (例如:us-east-1)', "S3StorageRegion": 'S3区域 (例如:us-east-1)',
"S3StorageEndpoint": 'S3端点URL (可选,默认为AWS S3)', "S3StorageEndpoint": 'S3端点URL (可选,默认为AWS S3)',
"S3StorageCdnUrl": 'CDN URL (可选,用于加速文件访问)', "S3StorageCdnUrl": 'CDN URL (可选,用于加速文件访问)',
"S3StorageUsePathStyleUrls": '使用路径形式URLs (true/false,兼容非AWS服务)' "S3StorageUsePathStyleUrls": '使用路径形式URLs (true/false,兼容非AWS服务)'
}} }}
isMobile={isMobile} isMobile={isMobile}
/> />
)} )}
{storageType === 'Cos' && ( {storageType === 'Cos' && (
<ConfigGroup <ConfigGroup
groupName="Storage" groupName="Storage"
configs={{ configs={{
"CosStorageSecretId": configs.Storage?.CosStorageSecretId || '', "CosStorageSecretId": configs.Storage?.CosStorageSecretId || '',
"CosStorageSecretKey": configs.Storage?.CosStorageSecretKey || '', "CosStorageSecretKey": configs.Storage?.CosStorageSecretKey || '',
"CosStorageToken": configs.Storage?.CosStorageToken || '', "CosStorageToken": configs.Storage?.CosStorageToken || '',
"CosStorageBucketName": configs.Storage?.CosStorageBucketName || '', "CosStorageBucketName": configs.Storage?.CosStorageBucketName || '',
"CosStorageRegion": configs.Storage?.CosStorageRegion || '', "CosStorageRegion": configs.Storage?.CosStorageRegion || '',
"CosStorageCdnUrl": configs.Storage?.CosStorageCdnUrl || '', "CosStorageCdnUrl": configs.Storage?.CosStorageCdnUrl || '',
}} }}
onSave={handleSaveConfig} onSave={handleSaveConfig}
descriptions={{ descriptions={{
"CosStorageSecretId": '腾讯云COS密钥ID', "CosStorageSecretId": '腾讯云COS密钥ID',
"CosStorageSecretKey": '腾讯云COS私有密钥', "CosStorageSecretKey": '腾讯云COS私有密钥',
"CosStorageToken": '腾讯云COS临时令牌(可选)', "CosStorageToken": '腾讯云COS临时令牌(可选)',
"CosStorageBucketName": 'COS存储桶名称', "CosStorageBucketName": 'COS存储桶名称',
"CosStorageRegion": 'COS区域 (例如:ap-shanghai)', "CosStorageRegion": 'COS区域 (例如:ap-shanghai)',
"CosStorageCdnUrl": 'CDN URL (可选,用于加速文件访问)', "CosStorageCdnUrl": 'CDN URL (可选,用于加速文件访问)',
}} }}
isMobile={isMobile} isMobile={isMobile}
/> />
)} )}
{storageType === 'WebDAV' && ( {storageType === 'WebDAV' && (
<ConfigGroup <ConfigGroup
groupName="Storage" groupName="Storage"
configs={{ configs={{
"WebDAVServerUrl": configs.Storage?.WebDAVServerUrl || '', "WebDAVServerUrl": configs.Storage?.WebDAVServerUrl || '',
"WebDAVUserName": configs.Storage?.WebDAVUserName || '', "WebDAVUserName": configs.Storage?.WebDAVUserName || '',
"WebDAVPassword": configs.Storage?.WebDAVPassword || '', "WebDAVPassword": configs.Storage?.WebDAVPassword || '',
"WebDAVBasePath": configs.Storage?.WebDAVBasePath || '', "WebDAVBasePath": configs.Storage?.WebDAVBasePath || '',
"WebDAVPublicUrl": configs.Storage?.WebDAVPublicUrl || '', "WebDAVPublicUrl": configs.Storage?.WebDAVPublicUrl || '',
}} }}
onSave={handleSaveConfig} onSave={handleSaveConfig}
descriptions={{ descriptions={{
"WebDAVServerUrl": 'WebDAV 服务器 URL (例如: https://dav.example.com)', "WebDAVServerUrl": 'WebDAV 服务器 URL (例如: https://dav.example.com)',
"WebDAVUserName": 'WebDAV 用户名', "WebDAVUserName": 'WebDAV 用户名',
"WebDAVPassword": 'WebDAV 密码', "WebDAVPassword": 'WebDAV 密码',
"WebDAVBasePath": 'WebDAV 基础路径 (例如: files/upload)', "WebDAVBasePath": 'WebDAV 基础路径 (例如: files/upload)',
"WebDAVPublicUrl": 'WebDAV 公共访问 URL (可选,用于文件访问)', "WebDAVPublicUrl": 'WebDAV 公共访问 URL (可选,用于文件访问)',
}} }}
isMobile={isMobile} isMobile={isMobile}
/> />
)} )}
</div>
</Card>
</TabPane> </TabPane>
</Tabs> </Tabs>
)} )}