feat: add file storage settings and uploads

This commit is contained in:
2026-05-13 20:23:45 +08:00
parent 0d0d0b9115
commit fc5dfd6bc5
21 changed files with 3401 additions and 72 deletions
+76 -1
View File
@@ -2,6 +2,10 @@ import { useEffect, useMemo, useRef, useState, type FormEvent } from 'react';
import type {
BaseModelCatalogItem,
CatalogProvider,
FileStorageChannel,
FileStorageSettings,
FileStorageSettingsUpdateRequest,
FileStorageChannelUpsertRequest,
GatewayAccessRuleBatchRequest,
GatewayAccessRule,
GatewayAccessRuleUpsertRequest,
@@ -34,17 +38,21 @@ import {
batchApiKeyAccessRules,
createAccessRule,
createApiKey,
createFileStorageChannel,
createGatewayUser,
createPlatform,
createTenant,
createUserGroup,
deleteAccessRule,
deleteApiKey,
deleteFileStorageChannel,
deleteGatewayUser,
deletePlatform,
deleteTenant,
deleteUserGroup,
getHealth,
listFileStorageChannels,
getFileStorageSettings,
getNetworkProxyConfig,
getRunnerPolicy,
getWalletSummary,
@@ -78,6 +86,8 @@ import {
setUserWalletBalance,
type HealthResponse,
updateAccessRule,
updateFileStorageChannel,
updateFileStorageSettings,
updateGatewayUser,
updatePlatform,
updatePlatformDynamicPriority,
@@ -135,6 +145,8 @@ type DataKey =
| 'playgroundModels'
| 'modelCatalog'
| 'networkProxyConfig'
| 'fileStorageChannels'
| 'fileStorageSettings'
| 'platforms'
| 'models'
| 'providers'
@@ -179,6 +191,8 @@ export function App() {
});
const [playgroundModels, setPlaygroundModels] = useState<PlatformModel[]>([]);
const [networkProxyConfig, setNetworkProxyConfig] = useState<GatewayNetworkProxyConfig | null>(null);
const [fileStorageChannels, setFileStorageChannels] = useState<FileStorageChannel[]>([]);
const [fileStorageSettings, setFileStorageSettings] = useState<FileStorageSettings | null>(null);
const [providers, setProviders] = useState<CatalogProvider[]>([]);
const [baseModels, setBaseModels] = useState<BaseModelCatalogItem[]>([]);
const [pricingRules, setPricingRules] = useState<PricingRule[]>([]);
@@ -296,6 +310,8 @@ export function App() {
auditLogs,
apiKeys,
baseModels,
fileStorageChannels,
fileStorageSettings,
modelCatalog,
models,
networkProxyConfig,
@@ -315,7 +331,7 @@ export function App() {
users,
walletAccounts,
walletTransactions,
}), [accessRules, apiKeys, auditLogs, baseModels, modelCatalog, modelRateLimits, modelRateLimitsUpdatedAt, models, networkProxyConfig, platforms, pricingRuleSets, pricingRules, providers, rateLimitWindows, runnerPolicy, runtimePolicySets, taskResult, tasks, tenants, userGroups, users, walletAccounts, walletTransactions]);
}), [accessRules, apiKeys, auditLogs, baseModels, fileStorageChannels, fileStorageSettings, modelCatalog, modelRateLimits, modelRateLimitsUpdatedAt, models, networkProxyConfig, platforms, pricingRuleSets, pricingRules, providers, rateLimitWindows, runnerPolicy, runtimePolicySets, taskResult, tasks, tenants, userGroups, users, walletAccounts, walletTransactions]);
async function refresh(nextToken = token) {
await ensureRouteData(nextToken, true);
@@ -388,6 +404,12 @@ export function App() {
case 'networkProxyConfig':
setNetworkProxyConfig(await getNetworkProxyConfig(nextToken));
return;
case 'fileStorageChannels':
setFileStorageChannels((await listFileStorageChannels(nextToken)).items);
return;
case 'fileStorageSettings':
setFileStorageSettings(await getFileStorageSettings(nextToken));
return;
case 'playgroundModels':
setPlaygroundModels((await listPlayableModels(nextToken)).items);
return;
@@ -818,6 +840,53 @@ export function App() {
}
}
async function saveFileStorageChannel(input: FileStorageChannelUpsertRequest, channelId?: string) {
setCoreState('loading');
setCoreMessage('');
try {
const item = channelId
? await updateFileStorageChannel(token, channelId, input)
: await createFileStorageChannel(token, input);
setFileStorageChannels((current) => [item, ...current.filter((channel) => channel.id !== item.id)]);
setCoreState('ready');
setCoreMessage(channelId ? '文件存储渠道已更新。' : '文件存储渠道已新增。');
} catch (err) {
setCoreState('error');
setCoreMessage(err instanceof Error ? err.message : channelId ? '更新文件存储渠道失败' : '新增文件存储渠道失败');
throw err;
}
}
async function saveFileStorageSettings(input: FileStorageSettingsUpdateRequest) {
setCoreState('loading');
setCoreMessage('');
try {
const settings = await updateFileStorageSettings(token, input);
setFileStorageSettings(settings);
setCoreState('ready');
setCoreMessage('文件存储全局策略已更新。');
} catch (err) {
setCoreState('error');
setCoreMessage(err instanceof Error ? err.message : '更新文件存储全局策略失败');
throw err;
}
}
async function removeFileStorageChannel(channelId: string) {
setCoreState('loading');
setCoreMessage('');
try {
await deleteFileStorageChannel(token, channelId);
setFileStorageChannels((current) => current.filter((channel) => channel.id !== channelId));
setCoreState('ready');
setCoreMessage('文件存储渠道已删除。');
} catch (err) {
setCoreState('error');
setCoreMessage(err instanceof Error ? err.message : '删除文件存储渠道失败');
throw err;
}
}
async function batchSaveAPIKeyAccessRules(input: GatewayAccessRuleBatchRequest) {
setCoreState('loading');
setCoreMessage('');
@@ -867,6 +936,7 @@ export function App() {
setModelCatalog({ items: [], filters: { capabilities: [], providers: [] }, summary: { modelCount: 0, sourceCount: 0 } });
setPlaygroundModels([]);
setNetworkProxyConfig(null);
setFileStorageChannels([]);
setProviders([]);
setBaseModels([]);
setPricingRules([]);
@@ -1039,6 +1109,7 @@ export function App() {
onDeletePricingRuleSet={removePricingRuleSet}
onDeleteRuntimePolicySet={removeRuntimePolicySet}
onDeleteAccessRule={removeAccessRule}
onDeleteFileStorageChannel={removeFileStorageChannel}
onDeleteTenant={removeTenant}
onDeleteUser={removeUser}
onDeleteUserGroup={removeUserGroup}
@@ -1054,6 +1125,8 @@ export function App() {
onSaveRuntimePolicySet={saveRuntimePolicySet}
onBatchAccessRules={batchSaveAccessRules}
onSaveAccessRule={saveAccessRule}
onSaveFileStorageChannel={saveFileStorageChannel}
onSaveFileStorageSettings={saveFileStorageSettings}
onSaveTenant={saveTenant}
onSaveUser={saveUser}
onSetUserWalletBalance={saveUserWalletBalance}
@@ -1267,6 +1340,8 @@ function dataKeysForRoute(
return ['auditLogs'];
case 'accessRules':
return ['accessRules', 'userGroups', 'platforms', 'models'];
case 'systemSettings':
return ['fileStorageSettings', 'fileStorageChannels'];
default:
return [];
}