App.jsx
3.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import React, { useState, useEffect } from 'react';
import Sidebar from './components/Sidebar';
import CreateForm from './components/CreateForm';
import TaskDetail from './components/TaskDetail';
import { ToastProvider, useToast } from './components/Toast';
import { fetchBackends } from './api';
import { getH3Base, getToken, setToken } from './utils';
function tidFromPath() {
if (typeof window === 'undefined') return null;
let p = window.location.pathname;
const base = getH3Base();
if (base && p.startsWith(base)) p = p.slice(base.length);
const m = p.match(/^\/task\.html\/(.+)$/);
return m ? decodeURIComponent(m[1]) : null;
}
function MainApp() {
const { addToast } = useToast();
const [selectedId, setSelectedId] = useState(() => tidFromPath());
const [initialFormValues, setInitialFormValues] = useState(null);
const [backendInfo, setBackendInfo] = useState(null);
// 路由同步
useEffect(() => {
const handlePopState = () => {
const tid = tidFromPath();
setSelectedId(tid);
};
window.addEventListener('popstate', handlePopState);
return () => window.removeEventListener('popstate', handlePopState);
}, []);
// 定时刷新后端状态
const loadBackends = async () => {
const info = await fetchBackends();
if (info) setBackendInfo(info);
};
useEffect(() => {
loadBackends();
const timer = setInterval(loadBackends, 6000);
return () => clearInterval(timer);
}, []);
const handleSelectTask = (id) => {
setSelectedId(id);
const base = getH3Base();
window.history.pushState(null, '', `${base}/task.html/${encodeURIComponent(id)}`);
};
const handleCreateTask = () => {
setSelectedId(null);
setInitialFormValues(null);
const base = getH3Base();
window.history.pushState(null, '', `${base}/newtask.html`);
};
const handleRerunTask = (job) => {
setSelectedId(null);
setInitialFormValues(job.req || {});
const base = getH3Base();
window.history.pushState(null, '', `${base}/newtask.html`);
addToast('已将历史任务参数灌入表单,可直接微调或提交', 'info');
};
const handleManageToken = () => {
const cur = getToken();
const next = window.prompt('设置 H3 访问令牌 (Access Token),留空清除:', cur);
if (next !== null) {
setToken(next);
addToast(next ? '令牌已保存' : '令牌已清除', 'info');
}
};
return (
<div className="flex h-screen w-screen overflow-hidden bg-slate-50 text-slate-800 font-sans">
{/* 左侧任务栏 (包含系统配置入口) */}
<Sidebar
selectedId={selectedId}
onSelectTask={handleSelectTask}
onCreateTask={handleCreateTask}
onRerunTask={handleRerunTask}
backendInfo={backendInfo}
onRefreshBackends={loadBackends}
onManageToken={handleManageToken}
/>
{/* 右侧主工作区 (纯净流式布局,绝不在右上角悬浮危险遮挡元素) */}
<main className="flex-1 h-full overflow-y-auto relative flex flex-col bg-white">
<div className="flex-1 w-full">
{selectedId ? (
<TaskDetail
taskId={selectedId}
onBack={handleCreateTask}
onRerun={handleRerunTask}
/>
) : (
<CreateForm
initialValues={initialFormValues}
onCreated={handleSelectTask}
/>
)}
</div>
</main>
</div>
);
}
export default function App() {
return (
<ToastProvider>
<MainApp />
</ToastProvider>
);
}