Phase 3.1: OSS storage config management (MinIO/AliyunOSS/AWS S3)

Backend:
- Add OSSStorageConfig model (models.py)
- Create storage_admin.py API (9 endpoints): stats, CRUD, toggle, set-default, test connection
- Register route /app/api/admin/storage in main.py
- Create oss_storage_configs table in MySQL

Frontend:
- Add Storage.tsx admin page (713 lines) with stats, table, create/edit modal
- Register /admin/storage route in App.tsx
- Add nav item and icon in AdminLayout.tsx
- Add 9 API methods in api/index.ts
This commit is contained in:
qyyfw committed 2026-07-03 14:45:10 +08:00
1 parent 5d1ad26874
commit b2ba75a666
7 files changed
+2265 -468

No files matched your search

+251 -126
View File
@@ -1,128 +1,253 @@
import React, { useState, useEffect } from 'react';␍
import { Routes, Route, Navigate } from 'react-router-dom';␍
import type { User } from '@/types';␍
import { AuthContext, AuthContextType } from '@/contexts/AuthContext';␍
import { authAPI } from '@/api';␍
␍
// Layouts␍
import FrontLayout from '@/components/layout/FrontLayout';␍
import AdminLayout from '@/components/layout/AdminLayout';␍
␍
// Front Pages␍
import LandingPage from '@/pages/front/LandingPage';␍
import LoginPage from '@/pages/front/LoginPage';␍
import ChatPage from '@/pages/front/ChatPage';␍
import ChannelPage from '@/pages/front/ChannelPage';␍
import KnowledgePage from '@/pages/front/KnowledgePage';␍
import MarketPage from '@/pages/front/MarketPage';␍
import TokenDashboardPage from '@/pages/front/TokenDashboardPage';␍
import PricingPage from '@/pages/front/PricingPage';␍
import ProfilePage from '@/pages/front/ProfilePage';␍
import NotificationPage from '@/pages/front/NotificationPage';␍
import AssetsPage from '@/pages/front/AssetsPage';␍
import NovelPreviewPage from '@/pages/front/NovelPreviewPage';␍
import EvolutionDashboard from '@/pages/front/EvolutionDashboard';␍
␍
// Admin Pages␍
import AdminDashboard from '@/pages/admin/Dashboard';␍
import AdminUsers from '@/pages/admin/Users';␍
import AdminModels from '@/pages/admin/Models';␍
import AdminSiteSettings from '@/pages/admin/SiteSettings';␍
import AdminPayment from '@/pages/admin/Payment';␍
import AdminServices from '@/pages/admin/Services';␍
import AdminMembership from '@/pages/admin/Membership';␍
import AdminAds from '@/pages/admin/Ads';␍
import AdminMarket from '@/pages/admin/Market';␍
import AdminLogs from '@/pages/admin/Logs';␍
import AdminSkills from '@/pages/admin/Skills'
import React, { useState, useEffect } from 'react';
import { Routes, Route, Navigate } from 'react-router-dom';
import type { User } from '@/types';
import { AuthContext, AuthContextType } from '@/contexts/AuthContext';
import { authAPI } from '@/api';
// Layouts
import FrontLayout from '@/components/layout/FrontLayout';
import AdminLayout from '@/components/layout/AdminLayout';
// Front Pages
import LandingPage from '@/pages/front/LandingPage';
import LoginPage from '@/pages/front/LoginPage';
import ChatPage from '@/pages/front/ChatPage';
import ChannelPage from '@/pages/front/ChannelPage';
import KnowledgePage from '@/pages/front/KnowledgePage';
import MarketPage from '@/pages/front/MarketPage';
import TokenDashboardPage from '@/pages/front/TokenDashboardPage';
import PricingPage from '@/pages/front/PricingPage';
import ProfilePage from '@/pages/front/ProfilePage';
import NotificationPage from '@/pages/front/NotificationPage';
import AssetsPage from '@/pages/front/AssetsPage';
import NovelPreviewPage from '@/pages/front/NovelPreviewPage';
import EvolutionDashboard from '@/pages/front/EvolutionDashboard';
// Admin Pages
import AdminDashboard from '@/pages/admin/Dashboard';
import AdminUsers from '@/pages/admin/Users';
import AdminModels from '@/pages/admin/Models';
import AdminSiteSettings from '@/pages/admin/SiteSettings';
import AdminPayment from '@/pages/admin/Payment';
import AdminServices from '@/pages/admin/Services';
import AdminMembership from '@/pages/admin/Membership';
import AdminAds from '@/pages/admin/Ads';
import AdminMarket from '@/pages/admin/Market';
import AdminLogs from '@/pages/admin/Logs';
import AdminSkills from '@/pages/admin/Skills'
import AdminAgents from '@/pages/admin/Agents'
import AdminKnowledge from '@/pages/admin/Knowledge';;␍
␍
const App: React.FC = () => {␍
const [user, setUser] = useState<User | null>(null);␍
const [loading, setLoading] = useState(true);␍
␍
// 初始化:从localStorage恢复登录状态␍
useEffect(() => {␍
const token = localStorage.getItem('aiflow_token');␍
const cachedUser = localStorage.getItem('aiflow_user');␍
if (token && cachedUser) {␍
try {␍
setUser(JSON.parse(cachedUser));␍
} catch {␍
localStorage.removeItem('aiflow_token');␍
localStorage.removeItem('aiflow_user');␍
}␍
}␍
setLoading(false);␍
}, []);␍
␍
const login = (u: User) => {␍
setUser(u);␍
localStorage.setItem('aiflow_user', JSON.stringify(u));␍
};␍
const logout = () => {␍
setUser(null);␍
localStorage.removeItem('aiflow_token');␍
localStorage.removeItem('aiflow_user');␍
};␍
const isAdmin = user?.role === 'admin';␍
␍
if (loading) {␍
return <div className="loading-screen">加载中...</div>;␍
}␍
␍
return (␍
<AuthContext.Provider value={{ user, login, logout, isAdmin }}>␍
<Routes>␍
{/* Login */}␍
<Route path="/login" element={␍
user ? (isAdmin ? <Navigate to="/admin" /> : <Navigate to="/chat" />) : <LoginPage />␍
} />␍
␍
{/* Root - Landing for guests, redirect for authenticated users */}␍
<Route path="/" element={␍
user ? (isAdmin ? <Navigate to="/admin" /> : <Navigate to="/chat" />) : <LandingPage />␍
} />␍
␍
{/* Front Routes (authenticated only) */}␍
<Route path="/" element={<FrontLayout />}>␍
<Route path="chat" element={<ChatPage />} />␍
<Route path="chat/:id" element={<ChatPage />} />␍
<Route path="channels" element={<ChannelPage />} />␍
<Route path="knowledge" element={<KnowledgePage />} />␍
<Route path="market" element={<MarketPage />} />␍
<Route path="token" element={<TokenDashboardPage />} />␍
<Route path="pricing" element={<PricingPage />} />␍
<Route path="profile" element={<ProfilePage />} />␍
<Route path="notifications" element={<NotificationPage />} />␍
<Route path="assets" element={<AssetsPage />} />␍
<Route path="assets/novel/:id" element={<NovelPreviewPage />} />␍
<Route path="evolution" element={<EvolutionDashboard />} />␍
</Route>␍
␍
{/* Admin Routes */}␍
<Route path="/admin" element={<AdminLayout />}>␍
<Route index element={<AdminDashboard />} />␍
<Route path="users" element={<AdminUsers />} />␍
<Route path="models" element={<AdminModels />} />␍
<Route path="settings" element={<AdminSiteSettings />} />␍
<Route path="payment" element={<AdminPayment />} />␍
<Route path="services" element={<AdminServices />} />␍
<Route path="membership" element={<AdminMembership />} />␍
<Route path="ads" element={<AdminAds />} />␍
<Route path="market" element={<AdminMarket />} />␍
<Route path="logs" element={<AdminLogs />} />␍
␍
<Route path="skills" element={<AdminSkills />} />
<Route path="agents" element={<AdminAgents />} />
import AdminKnowledge from '@/pages/admin/Knowledge';
import AdminStorage from '@/pages/admin/Storage';;
const App: React.FC = () => {
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);
// 初始化:从localStorage恢复登录状态
useEffect(() => {
const token = localStorage.getItem('aiflow_token');
const cachedUser = localStorage.getItem('aiflow_user');
if (token && cachedUser) {
try {
setUser(JSON.parse(cachedUser));
} catch {
localStorage.removeItem('aiflow_token');
localStorage.removeItem('aiflow_user');
}
}
setLoading(false);
}, []);
const login = (u: User) => {
setUser(u);
localStorage.setItem('aiflow_user', JSON.stringify(u));
};
const logout = () => {
setUser(null);
localStorage.removeItem('aiflow_token');
localStorage.removeItem('aiflow_user');
};
const isAdmin = user?.role === 'admin';
if (loading) {
return <div className="loading-screen">加载中...</div>;
}
return (
<AuthContext.Provider value={{ user, login, logout, isAdmin }}>
<Routes>
{/* Login */}
<Route path="/login" element={
user ? (isAdmin ? <Navigate to="/admin" /> : <Navigate to="/chat" />) : <LoginPage />
} />
{/* Root - Landing for guests, redirect for authenticated users */}
<Route path="/" element={
user ? (isAdmin ? <Navigate to="/admin" /> : <Navigate to="/chat" />) : <LandingPage />
} />
{/* Front Routes (authenticated only) */}
<Route path="/" element={<FrontLayout />}>
<Route path="chat" element={<ChatPage />} />
<Route path="chat/:id" element={<ChatPage />} />
<Route path="channels" element={<ChannelPage />} />
<Route path="knowledge" element={<KnowledgePage />} />
<Route path="market" element={<MarketPage />} />
<Route path="token" element={<TokenDashboardPage />} />
<Route path="pricing" element={<PricingPage />} />
<Route path="profile" element={<ProfilePage />} />
<Route path="notifications" element={<NotificationPage />} />
<Route path="assets" element={<AssetsPage />} />
<Route path="assets/novel/:id" element={<NovelPreviewPage />} />
<Route path="evolution" element={<EvolutionDashboard />} />
</Route>
{/* Admin Routes */}
<Route path="/admin" element={<AdminLayout />}>
<Route index element={<AdminDashboard />} />
<Route path="users" element={<AdminUsers />} />
<Route path="models" element={<AdminModels />} />
<Route path="settings" element={<AdminSiteSettings />} />
<Route path="payment" element={<AdminPayment />} />
<Route path="services" element={<AdminServices />} />
<Route path="membership" element={<AdminMembership />} />
<Route path="ads" element={<AdminAds />} />
<Route path="market" element={<AdminMarket />} />
<Route path="logs" element={<AdminLogs />} />
<Route path="skills" element={<AdminSkills />} />
<Route path="agents" element={<AdminAgents />} />
<Route path="knowledge" element={<AdminKnowledge />} />
</Route>␍
␍
<Route path="*" element={<Navigate to="/" />} />␍
</Routes>␍
</AuthContext.Provider>␍
);␍
};␍
␍
export default App;␍
<Route path="storage" element={<AdminStorage />} />
</Route>
<Route path="*" element={<Navigate to="/" />} />
</Routes>
</AuthContext.Provider>
);
};
export default App;