feat: add storage type support and update the configuration interface.

This commit is contained in:
ShiYu
2025-05-19 17:22:39 +08:00
parent d326970e8d
commit 61f254450c
5 changed files with 89 additions and 18 deletions
+2 -1
View File
@@ -78,7 +78,8 @@ public class PictureController(IPictureService pictureService,IConfigService con
request.File.ContentType, request.File.ContentType,
userId, userId,
(PermissionType)request.Permission!, (PermissionType)request.Permission!,
request.AlbumId request.AlbumId,
request.StorageType
); );
var picture = result.Picture; var picture = result.Picture;
@@ -10,4 +10,6 @@ public class UploadPictureRequest
public int? Permission { get; set; } = 1; public int? Permission { get; set; } = 1;
public int? AlbumId { get; set; } = null; public int? AlbumId { get; set; } = null;
public StorageType? StorageType { get; set; } = null;
} }
+1 -1
View File
@@ -32,7 +32,7 @@ public interface IPictureService
int? userId, int? userId,
PermissionType permission = PermissionType.Public, PermissionType permission = PermissionType.Public,
int? albumId = null, int? albumId = null,
StorageType storageType = StorageType.Telegram StorageType? storageType = null
); );
Task<ExifInfo> GetPictureExifInfoAsync(int pictureId); Task<ExifInfo> GetPictureExifInfoAsync(int pictureId);
+14 -3
View File
@@ -436,13 +436,24 @@ public class PictureService(
int? userId, int? userId,
PermissionType permission = PermissionType.Public, PermissionType permission = PermissionType.Public,
int? albumId = null, int? albumId = null,
StorageType storageType = StorageType.Local) StorageType? storageType = null)
{ {
// 如果未指定存储类型,则从配置中获取默认存储类型
if (storageType == null)
{
var defaultStorageTypeStr = configuration["Storage:DefaultStorage"];
if (string.IsNullOrEmpty(defaultStorageTypeStr) || !Enum.TryParse<StorageType>(defaultStorageTypeStr, out var defaultStorageType))
{
defaultStorageType = StorageType.Local; // 如果配置中没有或解析失败,使用本地存储作为默认
}
storageType = defaultStorageType;
}
string fileExtension = Path.GetExtension(fileName); string fileExtension = Path.GetExtension(fileName);
string newFileName = $"{Guid.NewGuid()}{fileExtension}"; string newFileName = $"{Guid.NewGuid()}{fileExtension}";
// 获取对应的存储提供者 // 获取对应的存储提供者
var storageProvider = storageProviderFactory.GetProvider(storageType); var storageProvider = storageProviderFactory.GetProvider(storageType.Value);
// 使用存储提供者保存文件 // 使用存储提供者保存文件
string relativePath = await storageProvider.SaveAsync(fileStream, fileName, contentType); string relativePath = await storageProvider.SaveAsync(fileStream, fileName, contentType);
@@ -493,7 +504,7 @@ public class PictureService(
User = user, User = user,
Permission = permission, Permission = permission,
AlbumId = albumId, AlbumId = albumId,
StorageType = storageType, StorageType = storageType.Value,
ProcessingStatus = isAnonymous ? ProcessingStatus.Completed : ProcessingStatus.Pending, ProcessingStatus = isAnonymous ? ProcessingStatus.Completed : ProcessingStatus.Pending,
ThumbnailPath = isAnonymous ? relativePath : null ThumbnailPath = isAnonymous ? relativePath : null
}; };
+60 -3
View File
@@ -1,9 +1,11 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { Tabs, Card, message, Spin } from 'antd'; import { Tabs, Card, message, Spin, Select } from 'antd';
import { CloudOutlined, DatabaseOutlined } from '@ant-design/icons';
import { getAllConfigs, setConfig } from '../../api'; import { getAllConfigs, setConfig } from '../../api';
import ConfigGroup from './ConfigGroup.tsx'; import ConfigGroup from './ConfigGroup.tsx';
const { TabPane } = Tabs; const { TabPane } = Tabs;
const { Option } = Select;
interface ConfigStructure { interface ConfigStructure {
[key: string]: { [key: string]: {
@@ -15,6 +17,7 @@ const SystemConfig: React.FC = () => {
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [configs, setConfigs] = useState<ConfigStructure>({}); const [configs, setConfigs] = useState<ConfigStructure>({});
const [activeKey, setActiveKey] = useState('AI'); const [activeKey, setActiveKey] = useState('AI');
const [storageType, setStorageType] = useState('Telegram');
// 获取所有配置项 // 获取所有配置项
const fetchConfigs = async () => { const fetchConfigs = async () => {
@@ -32,6 +35,11 @@ const SystemConfig: React.FC = () => {
}); });
setConfigs(configGroups); setConfigs(configGroups);
// 设置初始存储类型
if (configGroups.Storage?.DefaultStorage) {
setStorageType(configGroups.Storage.DefaultStorage);
}
} else { } else {
message.error('获取配置失败: ' + response.message); message.error('获取配置失败: ' + response.message);
} }
@@ -72,6 +80,13 @@ const SystemConfig: React.FC = () => {
} }
}; };
// 存储类型选项
const storageOptions = [
{ value: 'Telegram', label: 'Telegram存储', icon: <CloudOutlined style={{ color: '#0088cc' }} /> },
{ value: 'Local', label: '本地存储', icon: <DatabaseOutlined style={{ color: '#52c41a' }} /> },
// 未来可以添加更多存储选项
];
useEffect(() => { useEffect(() => {
fetchConfigs(); fetchConfigs();
}, []); }, []);
@@ -151,11 +166,52 @@ const SystemConfig: React.FC = () => {
</TabPane> </TabPane>
<TabPane tab="存储设置" key="Storage"> <TabPane tab="存储设置" key="Storage">
<div style={{ marginBottom: 20 }}>
<span style={{ marginRight: 8, display: 'inline-block', width: 100 }}>:</span>
<Select
value={configs.Storage?.DefaultStorage || 'Telegram'}
onChange={(value) => {
handleSaveConfig('Storage', 'DefaultStorage', value);
}}
style={{ width: 200 }}
>
{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>
<div style={{ marginBottom: 20 }}>
<span style={{ marginRight: 8, display: 'inline-block', width: 100 }}>:</span>
<Select
value={storageType}
onChange={(value) => {
setStorageType(value);
}}
style={{ width: 200 }}
>
{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' && (
<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={{
@@ -163,6 +219,7 @@ const SystemConfig: React.FC = () => {
"TelegramStorageChatId": 'Telegram 聊天ID' "TelegramStorageChatId": 'Telegram 聊天ID'
}} }}
/> />
)}
</TabPane> </TabPane>
</Tabs> </Tabs>
)} )}