fix(router): support /aura basename deployment

main
sp mac bookpro 2605 2026-05-28 16:17:27 +08:00
parent 83e4fab788
commit 604d549a79
5 changed files with 20 additions and 13 deletions

View File

@ -1,10 +1,13 @@
import axios from 'axios';
const AURA_API_BASE = 'https://api.redhare.cc/aura/v1';
const API_BASE_URL = 'https://api.hoyidata.com/aura/v1';
const APP_BASE = (import.meta.env.BASE_URL || '/').replace(/\/$/, '');
const withAppBase = (path: string) => `${APP_BASE}${path.startsWith('/') ? path : `/${path}`}`;
const withApiBase = (path: string) => `${API_BASE_URL}${path.startsWith('/') ? path : `/${path}`}`;
const isMockAuth = () => typeof localStorage !== 'undefined' && localStorage.getItem('mock-auth') === '1';
export const api = axios.create({
baseURL: 'https://api.hoyidata.com/aura/v1',
baseURL: API_BASE_URL,
timeout: 90000,
withCredentials: true // 关键:跨域请求带 cookie
});
@ -13,9 +16,10 @@ export const api = axios.create({
api.interceptors.response.use(
(r) => r,
(err) => {
if (err?.response?.status === 401 && !location.pathname.startsWith('/login') && !isMockAuth()) {
const isLoginPage = location.pathname === '/login' || location.pathname === withAppBase('/login');
if (err?.response?.status === 401 && !isLoginPage && !isMockAuth()) {
const next = encodeURIComponent(location.pathname + location.search);
location.href = `/login?next=${next}`;
location.href = `${withAppBase('/login')}?next=${next}`;
}
return Promise.reject(err);
}
@ -309,7 +313,7 @@ export const SessionAPI = {
.then((r) => r.data),
/** 导出会话为文件并触发浏览器下载 */
exportSession: (agentId: string, sessionId: string, format: 'md' | 'json' = 'md') => {
const url = `/api/agents/${agentId}/sessions/${sessionId}/export?format=${format}`;
const url = withApiBase(`/agents/${agentId}/sessions/${sessionId}/export?format=${format}`);
const a = document.createElement('a');
a.href = url;
a.rel = 'noopener';
@ -747,7 +751,7 @@ export function streamWorkflowRun(
}
): () => void {
const qs = input ? `?input=${encodeURIComponent(JSON.stringify(input))}` : '';
const url = `/api/workflows/${workflowId}/run-stream${qs}`;
const url = withApiBase(`/workflows/${workflowId}/run-stream${qs}`);
const es = new EventSource(url, { withCredentials: true } as any);
es.addEventListener('ready', (e: any) => handlers.onReady?.(JSON.parse(e.data)));
es.addEventListener('step_start', (e: any) => handlers.onStepStart?.(JSON.parse(e.data)));

View File

@ -124,7 +124,7 @@ function ThemeProvider({ children }: { children: React.ReactNode }) {
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<ThemeProvider>
<BrowserRouter>
<BrowserRouter basename={import.meta.env.BASE_URL}>
<App />
</BrowserRouter>
</ThemeProvider>

View File

@ -16,6 +16,7 @@ export default function SharedSessionPage() {
const [loading, setLoading] = useState(true);
const [err, setErr] = useState<string>('');
const { message } = AntApp.useApp();
const loginHref = `${(import.meta.env.BASE_URL || '/').replace(/\/$/, '')}/login`;
useEffect(() => {
if (!token) return;
@ -121,7 +122,7 @@ export default function SharedSessionPage() {
marginTop: 40
}}
>
Agent Studio · <a href="/login" style={{ color: 'var(--color-brand)' }}> agent</a>
Agent Studio · <a href={loginHref} style={{ color: 'var(--color-brand)' }}> agent</a>
</div>
</div>
</div>

1
src/vite-env.d.ts vendored Normal file
View File

@ -0,0 +1 @@
/// <reference types="vite/client" />

View File

@ -2,12 +2,13 @@ import { defineConfig, loadEnv } from 'vite';
import react from '@vitejs/plugin-react';
// 默认走 Go 后端 :4001要回退 Node 后端就 set VITE_API_TARGET=http://localhost:4000
export default defineConfig(({ mode }) => {
export default defineConfig(({ command, mode }) => {
const env = loadEnv(mode, process.cwd(), '');
const target = env.VITE_API_TARGET || 'https://api.hoyidata.com';
return {
base: '/aura/', // <-- 关键修改:设置构建的基础路径
// 本地开发走根路径,生产构建部署到 /aura 子路径
base: command === 'serve' ? '/' : '/aura/',
plugins: [react()],
server: {
port: 3001,