App.jsx 3.52 KB
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>
  );
}