import { Button as AntButton, Drawer, Dropdown, QRCode, Tag } from "antd";
import { AimOutlined, ApartmentOutlined, BarsOutlined, BlockOutlined, CaretDownOutlined, CaretRightOutlined, ControlOutlined, CopyOutlined, DeleteOutlined, DownloadOutlined, EditOutlined, EllipsisOutlined, EyeOutlined, LinkOutlined, PlusOutlined, PlusSquareOutlined, RobotOutlined, SearchOutlined, SnippetsOutlined, UploadOutlined, ZoomInOutlined, ZoomOutOutlined } from "@ant-design/icons";
-type PageKey = "login" | "projects" | "siteEdit" | "basic" | "assets" | "pageConfig" | "functions" | "generate" | "result" | "preview" | "domains" | "domainDetail" | "styleLibrary" | "deviceTemplates" | "toolSettings" | "domainSettings" | "dashboard" | "report-dashboard" | "report-doc" | "basic-components" | "func-components" | "filters" | "datasource";
+type PageKey = "login" | "projects" | "siteEdit" | "basic" | "assets" | "pageConfig" | "functions" | "generate" | "result" | "preview" | "domains" | "domainDetail" | "styleLibrary" | "deviceTemplates" | "toolSettings" | "domainSettings" | "dashboard" | "report-dashboard" | "report-doc" | "basic-components" | "func-components" | "filters" | "datasource" | "monitor-dashboard" | "twin-model" | "ops-template" | "knowledge-template";
type ModalKey = "" | "feedback" | "download" | "history" | "prompt" | "completePrompt";
const meta: Record<PageKey, { label: string; icon: string; subtitle: string }> = {
"func-components":{label:"功能组件库",icon:"",subtitle:""},
filters:{label:"筛选器",icon:"",subtitle:""},
datasource:{label:"数据源",icon:"",subtitle:""},
+ "monitor-dashboard":{label:"监控仪表板",icon:"",subtitle:""},
+ "twin-model":{label:"数字孪生模型",icon:"",subtitle:""},
+ "ops-template":{label:"运维模板",icon:"",subtitle:""},
+ "knowledge-template":{label:"知识模板",icon:"",subtitle:""},
};
const [page,setPage]=useState<PageKey>("projects");
const [projectNavOpen,setProjectNavOpen]=useState(true);
const [extensionNavOpen,setExtensionNavOpen]=useState(true);
- const [reportNavOpen,setReportNavOpen]=useState(true);
const [resourceNavOpen,setResourceNavOpen]=useState(true);
const [systemNavOpen,setSystemNavOpen]=useState(true);
const [toast,setToast]=useState("");
if(page==="login")return <Login onLogin={()=>go("projects")}/>;
const projectArea = (["projects","siteEdit","basic","assets","pageConfig","functions","generate","result","preview"] as PageKey[]).includes(page);
- const resourceArea = (["domains","domainDetail","deviceTemplates","styleLibrary"] as PageKey[]).includes(page);
+ const domainArea = (["domains","domainDetail"] as PageKey[]).includes(page);
+ const resourceArea = (["deviceTemplates","monitor-dashboard","twin-model","ops-template","knowledge-template"] as PageKey[]).includes(page);
const systemArea = (["toolSettings","domainSettings"] as PageKey[]).includes(page);
const extensionArea = (["dashboard","report-dashboard","report-doc","basic-components","func-components","filters","datasource"] as PageKey[]).includes(page);
const siteEditMeta = meta[siteEditSection];
<aside className="company-side-nav">
<nav className="side-menu" aria-label="StationBuilder 主菜单">
<section className={projectArea?"menu-section current":"menu-section"}>
- <button className="menu-section-title" aria-expanded={projectNavOpen} onClick={()=>setProjectNavOpen(v=>!v)}><span>站点管理</span>{projectNavOpen?<CaretDownOutlined/>:<CaretRightOutlined/>}</button>
- {projectNavOpen&&<div className="menu-section-items">
- <button className={page==="projects"?"active":""} onClick={()=>go("projects")}><span>站点列表</span></button>
- <button className={page==="siteEdit"?"active":""} onClick={()=>go("siteEdit",sites[0]?.id)}><span>站点编辑</span></button>
- </div>}
+ <button className="menu-section-title" onClick={()=>go("projects")}><span>站点管理</span></button>
+ </section>
+ <section className={domainArea?"menu-section current":"menu-section"}>
+ <button className="menu-section-title" onClick={()=>{setDomainFilter(null);go("domains");}}><span>领域方案</span></button>
</section>
<section className={resourceArea?"menu-section extension-menu-section current":"menu-section extension-menu-section"}>
<button className="menu-section-title" aria-expanded={resourceNavOpen} onClick={()=>setResourceNavOpen(v=>!v)}><span>建站资源</span>{resourceNavOpen?<CaretDownOutlined/>:<CaretRightOutlined/>}</button>
{resourceNavOpen&&<div className="menu-section-items">
- <button className={(page==="domains"||page==="domainDetail")?"active":""} onClick={()=>{setDomainFilter(null);go("domains");}}><span>领域方案</span></button>
<button className={page==="deviceTemplates"?"active":""} onClick={()=>go("deviceTemplates")}><span>设备模板</span></button>
- <button className={page==="styleLibrary"?"active":""} onClick={()=>go("styleLibrary")}><span>页面样式</span></button>
- <div className="extension-submenu">
- <button className="extension-menu-item extension-submenu-title" aria-expanded={reportNavOpen} onClick={()=>setReportNavOpen(v=>!v)}><span>监控仪表板</span>{reportNavOpen?<CaretDownOutlined/>:<CaretRightOutlined/>}</button>
- {reportNavOpen&&<div className="extension-third-menu">
- <button className={page==="filters"?"extension-third-menu-item clickable active":"extension-third-menu-item clickable"} onClick={()=>go("filters")}>筛选器</button>
- </div>}
- </div>
- <button className={page==="report-dashboard"?"active":""} onClick={()=>go("report-dashboard")}><span>仪表板报表</span></button>
- <button className={page==="report-doc"?"active":""} onClick={()=>go("report-doc")}><span>文档报表</span></button>
+ <button className={page==="monitor-dashboard"?"active":""} onClick={()=>go("monitor-dashboard")}><span>监控仪表板</span></button>
+ <button className={page==="twin-model"?"active":""} onClick={()=>go("twin-model")}><span>数字孪生模型</span></button>
+ <button className={page==="ops-template"?"active":""} onClick={()=>go("ops-template")}><span>运维模板</span></button>
+ <button className={page==="knowledge-template"?"active":""} onClick={()=>go("knowledge-template")}><span>知识模板</span></button>
</div>}
</section>
<section className={systemArea?"menu-section current":"menu-section"}>
</>
)}
</div></aside>
- <main className="workspace"><div className="crumb">iStation StationBuilder / <b>{["domains","domainDetail","styleLibrary","deviceTemplates","toolSettings","domainSettings"].includes(page)?meta[page].label:page==="projects"?"站点列表":page==="siteEdit"?`站点管理 / 站点编辑 / ${siteEditMeta.label}`:`站点详情 / ${meta[page].label}`}</b></div><div className="page-heading"><div><h1>{page==="siteEdit"?siteEditMeta.label:meta[page].label}</h1><p>{page==="siteEdit"?siteEditMeta.subtitle:meta[page].subtitle}</p></div><div>{page==="projects"&&<Button onClick={()=>go("basic","new")}>+ 新建站点</Button>}{page==="siteEdit"&&<label className="site-edit-switcher"><span>当前站点</span><select value={siteId??""} onChange={async e=>{const id=Number(e.target.value);if(id!==siteId&&!(await confirmUnsaved())){e.target.value=String(siteId??'');return;}await loadSite(id);window.history.replaceState({},"",`?page=siteEdit&id=${id}`);}}>{sites.map(item=><option key={item.id} value={item.id}>{item.name||"未命名站点"}</option>)}</select></label>}{page==="domains"&&openDomainTemplateId==null&&<Button onClick={()=>setOpenDomainTemplateId("create")}>+ 新增领域方案</Button>}{page==="domains"&&openDomainTemplateId!=null&&<Button secondary onClick={()=>setOpenDomainTemplateId(null)}>← 返回方案列表</Button>}{domainFilter!=null&&page==="domains"&&openDomainTemplateId==null&&<Button secondary onClick={()=>{setDomainFilter(null);}}>清除领域筛选:{domainOptions.find(d=>d.id===domainFilter)?.name||""}</Button>}{page==="domainSettings"&&<Button onClick={()=>{setNewDomainName("");setAddingDomain(true);}}>+ 新增领域</Button>}</div></div>{page==="siteEdit"&&<SiteEditTabs section={siteEditSection} onChange={setSiteEditSection}/>} {SITE_EDIT_STEPS.includes(page as SiteEditSection)&&<Steps page={page} go={go}/>}<div className="content">
+ <main className="workspace"><div className="crumb">iStation StationBuilder / <b>{["domains","domainDetail","styleLibrary","deviceTemplates","toolSettings","domainSettings","monitor-dashboard","twin-model","ops-template","knowledge-template"].includes(page)?meta[page].label:page==="projects"?"站点列表":page==="siteEdit"?`站点管理 / 站点编辑 / ${siteEditMeta.label}`:`站点详情 / ${meta[page].label}`}</b></div><div className="page-heading"><div><h1>{page==="siteEdit"?siteEditMeta.label:meta[page].label}</h1><p>{page==="siteEdit"?siteEditMeta.subtitle:meta[page].subtitle}</p></div><div>{page==="projects"&&<Button onClick={()=>go("basic","new")}>+ 新建站点</Button>}{page==="siteEdit"&&<label className="site-edit-switcher"><span>当前站点</span><select value={siteId??""} onChange={async e=>{const id=Number(e.target.value);if(id!==siteId&&!(await confirmUnsaved())){e.target.value=String(siteId??'');return;}await loadSite(id);window.history.replaceState({},"",`?page=siteEdit&id=${id}`);}}>{sites.map(item=><option key={item.id} value={item.id}>{item.name||"未命名站点"}</option>)}</select></label>}{page==="domains"&&openDomainTemplateId==null&&<Button onClick={()=>setOpenDomainTemplateId("create")}>+ 新增领域方案</Button>}{page==="domains"&&openDomainTemplateId!=null&&<Button secondary onClick={()=>setOpenDomainTemplateId(null)}>← 返回方案列表</Button>}{domainFilter!=null&&page==="domains"&&openDomainTemplateId==null&&<Button secondary onClick={()=>{setDomainFilter(null);}}>清除领域筛选:{domainOptions.find(d=>d.id===domainFilter)?.name||""}</Button>}{page==="domainSettings"&&<Button onClick={()=>{setNewDomainName("");setAddingDomain(true);}}>+ 新增领域</Button>}</div></div>{page==="siteEdit"&&<SiteEditTabs section={siteEditSection} onChange={setSiteEditSection}/>} {SITE_EDIT_STEPS.includes(page as SiteEditSection)&&<Steps page={page} go={go}/>}<div className="content">
{page==="projects"&&<Projects view={view} setView={setView} sites={sites} loading={loading} go={go} loadSite={loadSite} notify={notify} onDelete={deleteSites} onCreateSub={createSubSite}/>}
{page==="dashboard"&&<Dashboard/>}
{page==="report-dashboard"&&<ImagePage src="/t/stationbuilder/ext-pages/report-dashboard.jpg"/>}
: <CompanyDomainLibrary go={go} notify={notify} onOpen={(id:number)=>setOpenDomainTemplateId(id)} domainFilter={domainFilter} domainOptions={domainOptions}/>)}
{page==="styleLibrary"&&<CompanyPageStyleLibrary pageStyles={pageStyles} loadPageStyles={loadPageStyles} notify={notify}/>}
{page==="deviceTemplates"&&<CompanyDeviceTemplates notify={notify} onViewCpPrompt={viewDeviceCpCompletePrompt} go={go} siteId={siteId}/>}
+ {page==="monitor-dashboard"&&<ResourcePlaceholder title="监控仪表板"/>}
+ {page==="twin-model"&&<ResourcePlaceholder title="数字孪生模型"/>}
+ {page==="ops-template"&&<ResourcePlaceholder title="运维模板"/>}
+ {page==="knowledge-template"&&<ResourcePlaceholder title="知识模板"/>}
{page==="toolSettings"&&<InternalToolSettings model={model} onModelChange={setModel} notify={notify}/>}
{page==="domainSettings"&&<DomainSettings domains={domainOptions} notify={notify} onDeleted={handleDomainDeleted}/>}
{(page==="basic"||(page==="siteEdit"&&siteEditSection==="basic"))&&<Basic site={site} domains={domains} onChange={saveSiteBasic} onAddDomain={addDomain} onUpload={uploadFile} saving={saving} notify={notify} onViewCompletePrompt={viewCompletePrompt} go={go} siteId={siteId} siteHierarchy={siteHierarchy}/>}
return <div className="content dashboard-page"><img src={src} alt="" loading="lazy"/></div>;
}
+function ResourcePlaceholder({title}:{title:string}){
+ return <Panel title={title}><div className="empty-state">该模块正在建设中,敬请期待。</div></Panel>;
+}
+
function Modal({type,close,notify,promptData,feedbackCube,refineCube,refining,refineLog}:{type:Exclude<ModalKey,"">;close:()=>void;notify:(m:string)=>void;promptData?:{name:string;text:string}|null;feedbackCube?:Cube|null;refineCube?:(cube:Cube, feedback:string)=>void;refining?:boolean;refineLog?:string;}){
const [feedbackText,setFeedbackText]=useState("");
const refineConsoleRef=useRef<HTMLPreElement>(null);