};
return <><div className="result-header"><div><span className="site-icon big">⬡</span><section><h2>{site.name || "未命名站点"}</h2><p>{site.status==="generated"?"生成完成":"草稿"} · {site.updated_at}</p></section><Status>{site.status==="generated"?"生成完成":"草稿"}</Status></div><div><Button secondary onClick={()=>setModal("history")}>版本历史</Button><Button secondary onClick={()=>go("assets")}>修改配置</Button><Button onClick={()=>window.open(`/api/db/sites/${site.id}/package`,`_blank`)}>⇩ 下载全部</Button></div></div>
<div className="kpi-row">{[[site.assets.filter(a=>a.type).length,"Asset 资产","类设备"],[site.mu.length,"MU 页面","已配置"],[generated.length,"Cube 页面",generated.length===site.cubes.length?"校验全部通过":"部分未生成"],[generated.length+1,"交付文件","JSON+ZIP"]].map(x=><div key={x[1]}><span>{x[1]}</span><b>{x[0]}</b><small>{x[2]}</small></div>)}</div>
- <div className="result-layout"><div><Panel title="页面结果" tools={<Button secondary onClick={()=>viewSitePrompt()}>查看站点提示词</Button>}><div className="result-pages">{site.cubes.map((cube,i)=><article key={i}><DashboardThumb siteId={site.id} cube={cube} /><div><header><Status>{cube.status==="generated"?"校验通过":"未生成"}</Status><small>Cube</small></header><h3>{cube.name}</h3><p>{cube.content || "无描述"}</p><footer><Button secondary onClick={()=>openPreview(cube)}>预览</Button>{cube.id&&<Button secondary onClick={()=>fetch(`/api/db/sites/${site.id}/cubes/${cube.id}/file`).then(r=>r.blob()).then(b=>downloadBlob(b, cube.gen_filename||`${cube.name}.json`))}>⇩ JSON</Button>}{cube.id&&<Button secondary onClick={()=>viewPrompt(cube.id, cube.name, cube.content)}>提示词</Button>}{cube.status==="generated"&&<Button secondary onClick={()=>openFeedback(cube)}>✎ 修改意见</Button>}</footer></div></article>)}</div></Panel></div></div></>;
+ <div className="result-layout"><div><Panel title="页面结果" tools={<Button secondary onClick={()=>viewSitePrompt()}>查看站点提示词</Button>}><div className="result-pages">{site.cubes.map((cube,i)=><article key={i}><DashboardThumb siteId={site.id} cube={cube} /><div><header><Status>{cube.status==="generated"?"校验通过":"未生成"}</Status><small>Cube</small></header><h3>{cube.name}</h3><p>{cube.content || "无描述"}</p><footer><Button secondary onClick={()=>openPreview(cube)}>预览</Button>{cube.id&&<Button secondary onClick={()=>fetch(`/api/db/sites/${site.id}/cubes/${cube.id}/file`).then(r=>r.blob()).then(b=>downloadBlob(b, cube.gen_filename||`${cube.name}.json`))}>⇩ JSON</Button>}{cube.id&&<Button secondary onClick={()=>viewPrompt(cube.id, cube.name, cube.content)}>提示词</Button>}{cube.gen_file_id&&<Button secondary onClick={()=>openFeedback(cube)}>✎ 修改意见</Button>}</footer></div></article>)}</div></Panel></div></div></>;
}
function Preview({site,tab,setTab,setModal,notify}:{site:SiteDetail|null;tab:"info"|"json"|"feedback";setTab:(t:"info"|"json"|"feedback")=>void;setModal:(m:ModalKey)=>void;notify:(m:string)=>void}){
<tr><td>结果头(状态 / 修改配置 / 下载全部 / 版本历史)</td><td>概览与操作入口</td><td>当前 site</td><td>「修改配置」回 assets;「下载全部」取 package;「版本历史」开模态</td></tr>
<tr><td>KPI 条</td><td>资产/MU/Cube/交付文件统计</td><td>本地计算</td><td>纯展示</td></tr>
<tr><td>页面结果卡片(缩略图 + 状态 + 预览/JSON/提示词/修改意见)</td><td>逐页查看与操作</td><td>GET /api/db/sites/:id/cubes/:cid/file</td><td>缩略图由 dashboard-renderer 渲染生成 JSON;各按钮分别预览/下载/看提示词/提修改意见</td></tr>
- <tr><td>「✎ 修改意见」</td><td>对单页提反馈并重新生成</td><td>POST /api/db/sites/:id/cubes/:cid/refine 流式</td><td>打开反馈模态,提交后在当前页 JSON 基础上按意见重新生成;提交后模态内「修改意见」下方出现黑底白字的 <b>AI 生成工作流</b> 只读终端,实时滚动展示 CLI/AI/Skill 过程与进度,完成后自动刷新结果并关闭模态</td></tr>
+ <tr><td>「✎ 修改意见」</td><td>对单页提反馈并重新生成</td><td>POST /api/db/sites/:id/cubes/:cid/refine 流式</td><td>只要该页<b>已有生成文件</b>(含「生成失败」但留有 JSON 的页面)即显示此按钮;打开反馈模态,提交后在当前页 JSON 基础上按意见重新生成;提交后模态内「修改意见」下方出现黑底白字的 <b>AI 生成工作流</b> 只读终端,实时滚动展示 CLI/AI/Skill 过程与进度,完成后自动刷新结果并关闭模态</td></tr>
</table>
<p class="note">页面结果卡片默认<b>纵向单列</b>排列(上下结构),每张卡片占满整行,便于在多个 Cube 页面间逐张查看与操作;每张卡片底部并排展示「预览 / JSON / 提示词 / 修改意见」四个按钮。</p>