mirror of
https://github.com/DrizzleTime/Foxel.git
synced 2026-08-25 01:59:36 +08:00
feat(StorageConfig): enhance storage settings UI with separate configurations for logged-in and anonymous users
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
@@ -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={{
|
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||||
marginBottom: isMobile ? 16 : 20,
|
{option.icon}
|
||||||
display: 'flex',
|
<span style={{ marginLeft: 8 }}>{option.label}</span>
|
||||||
flexDirection: isMobile ? 'column' : 'row',
|
</div>
|
||||||
alignItems: isMobile ? 'flex-start' : 'center',
|
</Option>
|
||||||
gap: isMobile ? 8 : 0
|
))}
|
||||||
}}>
|
</Select>
|
||||||
<span style={{
|
<div style={{
|
||||||
marginRight: isMobile ? 0 : 8,
|
fontSize: 12,
|
||||||
display: 'inline-block',
|
color: '#999',
|
||||||
width: isMobile ? 'auto' : 100,
|
marginTop: 4
|
||||||
marginBottom: isMobile ? 4 : 0
|
}}>
|
||||||
|
已登录用户上传文件时的默认存储位置
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 匿名用户默认存储 */}
|
||||||
|
<div>
|
||||||
|
<div style={{
|
||||||
|
marginBottom: 8,
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: 500,
|
||||||
|
color: '#666'
|
||||||
|
}}>
|
||||||
|
匿名用户默认存储
|
||||||
|
</div>
|
||||||
|
<Select
|
||||||
|
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>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user