From: wang.yu Date: Tue, 18 Aug 2026 23:09:21 +0000 (+0800) Subject: feat: 设备模版列表→详情 + 全站界面截图嵌入设计文档 X-Git-Url: http://acesimba.cloud/gitweb/?a=commitdiff_plain;h=c0cfe808b4e17ad9578f4f3f711a53fef0d793ac;p=StationBuilder.git feat: 设备模版列表→详情 + 全站界面截图嵌入设计文档 - 设备模版改为默认展开列表、点击进入详情,支持按名称/说明搜索(v0.8) - 新增列表视图 CSS(.device-tpl-list / .tpl-thumb / .list-toolbar 等) - 使用 Chromium + Playwright 自动抓取 11 张页面截图,嵌入设计文档 5.13「界面截图(UI 总览)」,并替换 5.9/5.10 占位图、补充 5.11/5.12 实图 - 设计文档升至 v0.9,新增 changelog 条目 --- diff --git a/app/globals.css b/app/globals.css index a751758..f159897 100644 --- a/app/globals.css +++ b/app/globals.css @@ -230,4 +230,12 @@ .cp-editor input,.cp-editor select{width:100%;border:1px solid var(--line);border-radius:3px;height:30px;padding:0 7px;background:#fff;font-size:11px} .cp-editor input:focus,.cp-editor select:focus{outline:1px solid var(--blue)} .cp-range-custom{margin-top:5px} +/* ===== 设备模版:列表视图 ===== */ +.list-toolbar{margin-bottom:10px} +.list-toolbar .search{border:1px solid var(--line);border-radius:3px;height:32px;padding:0 10px;width:320px;background:#fff} +.list-toolbar .search:focus{outline:1px solid var(--blue)} +.device-tpl-list tbody tr{cursor:pointer} +.device-tpl-list tbody tr:hover{background:#f5f9fb} +.tpl-thumb{width:48px;height:34px;object-fit:cover;border:1px solid var(--line);border-radius:3px;display:block;background:#f2f5f7} +.tpl-thumb-empty{color:#c2c8cc} diff --git a/app/page.tsx b/app/page.tsx index 6d86733..03fabbc 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -463,7 +463,7 @@ export default function Home(){ ? setOpenDomainTemplateId(null)} onCreated={setOpenDomainTemplateId}/> : setOpenDomainTemplateId(id)} domainFilter={domainFilter} domainOptions={domainOptions}/>)} {page==="styleLibrary"&&} - {page==="deviceTemplates"&&} + {page==="deviceTemplates"&&} {page==="basic"&&} {page==="assets"&&} {page==="functions"&&} @@ -1057,14 +1057,14 @@ function DeviceImageField({imageUrl,onPick}:{imageUrl:string|null;onPick:(f:File ; } -function DeviceTemplateCard({dev,notify,onChange}:{dev:any;notify:(m:string)=>void;onChange:()=>void}){ +function DeviceTemplateCard({dev,notify,onChange,onBack}:{dev:any;notify:(m:string)=>void;onChange:()=>void;onBack:()=>void}){ const [name,setName]=useState(dev.name); const [description,setDesc]=useState(dev.description||""); const [imgPreview,setImgPreview]=useState(dev.image_path?`/api/db/device-templates/${dev.id}/image`:null); const [imgB64,setImgB64]=useState<{filename:string;mime:string;data:string}|null>(null); const [cps,setCps]=useState((dev.collection_points||[]).map((c:any)=>({...c,key:c.id,checked:false}))); const onPick=async(f:File)=>{ setImgPreview(URL.createObjectURL(f)); const b=await fileToBase64(f); setImgB64({filename:b.filename,mime:b.mime,data:b.data}); }; const save=async()=>{ const body:any={name,description}; if(imgB64) body.image=imgB64; await fetchDb(`/device-templates/${dev.id}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(body)}); notify("设备已保存"); onChange(); }; - const delDev=async()=>{ if(!confirm("删除该设备模板?")) return; await fetchDb(`/device-templates/${dev.id}`,{method:"DELETE"}); onChange(); }; + const delDev=async()=>{ if(!confirm("删除该设备模板?")) return; await fetchDb(`/device-templates/${dev.id}`,{method:"DELETE"}); onChange(); onBack(); }; const addCpRow=()=>setCps([...cps,{key:-(Date.now()),name:"",collect_note:"",unit:"",value_range:"",description:"",checked:false}]); const updCp=(k:number,field:string,val:any)=>setCps(cps.map(c=>c.key===k?{...c,[field]:val}:c)); const toggleCp=(k:number)=>setCps(cps.map(c=>c.key===k?{...c,checked:!c.checked}:c)); @@ -1120,21 +1120,43 @@ function DeviceTemplateCreate({notify,onDone,onCancel}:{notify:(m:string)=>void; ; } -function DeviceTemplates({notify,domainOptions}:{notify:(m:string)=>void;domainOptions:{id:number;name:string}[]}){ +function DeviceTemplates({notify}:{notify:(m:string)=>void}){ const [list,setList]=useState([]); const [loading,setLoading]=useState(true); - const [creating,setCreating]=useState(false); + const [openId,setOpenId]=useState(null); + const [q,setQ]=useState(""); const load=async()=>{ try{ setList(await fetchDb("/device-templates") as any); }catch(e:any){ notify("加载失败:"+e.message); } finally{ setLoading(false); } }; useEffect(()=>{ load(); },[]); - return <> + const filtered=list.filter(d=>{ if(!q.trim()) return true; const s=q.toLowerCase(); return (d.name||"").toLowerCase().includes(s) || (d.description||"").toLowerCase().includes(s); }); + const delDev=async(id:number)=>{ if(!confirm("删除该设备模板?")) return; await fetchDb(`/device-templates/${id}`,{method:"DELETE"}); load(); }; + if(openId===null) return <>
DEVICE TEMPLATE LIBRARY

设备模版

独立维护设备模版及其采集点,编辑后可在领域方案中按需选用。

- setCreating(true)}>+ 新增设备模版}> - {creating && {setCreating(false);load();}} onCancel={()=>setCreating(false)}/>} + setOpenId("create")}>+ 新增设备模版}> +
setQ(e.target.value)}/>
{loading?

加载中…

: - list.length===0 && !creating?

暂无设备模版,点击「+ 新增设备模版」创建。

: -
{list.map((d:any)=>)}
} + filtered.length===0?

{list.length===0?"暂无设备模版,点击「+ 新增设备模版」创建。":"无匹配结果"}

: + + {filtered.map((d:any)=>( + setOpenId(d.id)}> + + + + + + + ))}
图片名称说明采集点操作
{d.image_path? : —}{d.name}{d.description||""}{(d.collection_points||[]).length}e.stopPropagation()}>
}
; + if(openId==="create") return <> +
+ { await load(); setOpenId(id); }} onCancel={()=>setOpenId(null)}/> + ; + const dev=list.find(d=>d.id===openId); + if(!dev) return

加载中…

; + return <> +
+ setOpenId(null)}/> + ; } function DeviceTemplatePicker({tmplId,go,selectedIds,notify,onChange}:{tmplId:number;go:(p:PageKey)=>void;selectedIds:number[];notify:(m:string)=>void;onChange:()=>void}){ diff --git a/public/design-doc-assets/assets.png b/public/design-doc-assets/assets.png new file mode 100644 index 0000000..cfb723b Binary files /dev/null and b/public/design-doc-assets/assets.png differ diff --git a/public/design-doc-assets/basic.png b/public/design-doc-assets/basic.png new file mode 100644 index 0000000..2e66b40 Binary files /dev/null and b/public/design-doc-assets/basic.png differ diff --git a/public/design-doc-assets/device-detail.png b/public/design-doc-assets/device-detail.png new file mode 100644 index 0000000..31b1e51 Binary files /dev/null and b/public/design-doc-assets/device-detail.png differ diff --git a/public/design-doc-assets/device-templates.png b/public/design-doc-assets/device-templates.png new file mode 100644 index 0000000..8d73306 Binary files /dev/null and b/public/design-doc-assets/device-templates.png differ diff --git a/public/design-doc-assets/domain-detail.png b/public/design-doc-assets/domain-detail.png new file mode 100644 index 0000000..1f39247 Binary files /dev/null and b/public/design-doc-assets/domain-detail.png differ diff --git a/public/design-doc-assets/domains.png b/public/design-doc-assets/domains.png new file mode 100644 index 0000000..1b6c830 Binary files /dev/null and b/public/design-doc-assets/domains.png differ diff --git a/public/design-doc-assets/functions.png b/public/design-doc-assets/functions.png new file mode 100644 index 0000000..fa2d9e4 Binary files /dev/null and b/public/design-doc-assets/functions.png differ diff --git a/public/design-doc-assets/generate.png b/public/design-doc-assets/generate.png new file mode 100644 index 0000000..22acee7 Binary files /dev/null and b/public/design-doc-assets/generate.png differ diff --git a/public/design-doc-assets/login.png b/public/design-doc-assets/login.png new file mode 100644 index 0000000..1f8f0ff Binary files /dev/null and b/public/design-doc-assets/login.png differ diff --git a/public/design-doc-assets/projects.png b/public/design-doc-assets/projects.png new file mode 100644 index 0000000..e58f682 Binary files /dev/null and b/public/design-doc-assets/projects.png differ diff --git a/public/design-doc-assets/style-library.png b/public/design-doc-assets/style-library.png new file mode 100644 index 0000000..4e01e3e Binary files /dev/null and b/public/design-doc-assets/style-library.png differ diff --git a/public/design-doc.html b/public/design-doc.html index bebce90..aacaae3 100644 --- a/public/design-doc.html +++ b/public/design-doc.html @@ -85,7 +85,7 @@
-

文档版本:v0.7 最后更新:2026-08-18 修改人:wang.yu 状态:开发中(演示数据已标注)

+

文档版本:v0.9 最后更新:2026-08-18 修改人:wang.yu 状态:开发中(演示数据已标注)

StationBuilder 产品与交互设计方案

1. 文档说明

@@ -156,7 +156,7 @@ 1 基本属性 / 2 资产 / 3 功能与菜单 / 4 生成确认StationBuilder / 生成向导生成向导分步导航前端 state点击 go 对应页;当前步骤高亮;已完成步骤可回跳 站点结果 / 页面预览StationBuilder / 方案交付查看生成结果与预览—点击 go("result" / "preview");当前页高亮 领域方案领域方案库 / 方案库导航方案库列表(列表/卡片切换)与详情GET /api/db/domain-templates、GET /api/domains点击 go("domains");列表页右上角可在「列表 / 卡片」间切换;点击某方案(列表「编辑」或卡片本身)以同页内嵌编辑器打开详情(openDomainTemplateId state 控制)。「+ 新增领域方案」切到新增表单;「清除领域筛选」返回全部 - 设备模版领域方案库 / 方案库导航独立页面,编辑设备模版与采集点GET /api/db/device-templates点击 go("deviceTemplates");列表展示全部设备模版,可新增 / 编辑 / 删除;每个设备模版维护名称 / 说明 / 图片 / 所属领域(多选) / 采集点。设备模版在此独立维护,方案详情中通过「选用设备模版」勾选引用 + 设备模版领域方案库 / 方案库导航独立页面,编辑设备模版与采集点GET /api/db/device-templates点击 go("deviceTemplates");默认展开列表视图(缩略图 / 名称 / 说明 / 采集点数 / 操作),支持按名称或说明搜索;点击行进入该设备模版的详情编辑(名称 / 说明 / 图片 / 采集点),可返回列表。列表上方「+ 新增设备模版」进入新建表单。设备模版在此独立维护,方案详情中通过「选用设备模版」勾选引用 领域分类(动态)领域方案库 / 领域分类按领域筛选方案列表(二级菜单)GET /api/domains(动态渲染)点击某领域 → go("domains") 且 domainFilter=该领域 id,列表自动只显示该领域方案;当前领域高亮;「清除领域筛选」返回全部 全部页面样式页面样式库 / 样式库导航样式库列表GET /api/db/page-styles点击 go("styleLibrary");当前页高亮 @@ -270,7 +270,7 @@

5.9 领域方案库(domains)

领域方案库已从硬编码演示改为真实数据库驱动。列表与详情编辑器同一页面内通过 openDomainTemplateId state 切换:null=列表,"create"=新增表单,number=该方案详情编辑器。列表支持列表 / 卡片两种视图切换(右上角视图切换按钮,view state 控制);点击左侧「领域分类」下的某个领域会按 domainFilter 自动筛选该领域方案。

下图展示了领域方案库列表与「+ 新增领域方案」入口:

-
领域方案库列表
领域方案库:方案列表与新增入口(示意图,待替换为实际截图)。
+
领域方案库列表
领域方案库:列表视图,支持列表/卡片切换、按领域分类筛选,点击「编辑」进入方案详情。
@@ -281,7 +281,7 @@

5.10 方案详情(domainDetail / 内嵌编辑器)

详情为同一页面内嵌编辑器,所有内容均可编辑,数据持久化到领域方案库相关表。各面板如下:

下图展示了一个领域方案的详情编辑器(模板信息 + 设备模板 + 领域页面等面板):

-
方案详情编辑器
领域方案详情编辑器(示意图,待替换为实际截图)。
+
方案详情编辑器
领域方案详情编辑器:模板信息、选用设备模版、领域页面、模板菜单、知识文档、运维流程等面板。
元素功能数据来源交互效果
领域方案列表表格展示全部领域方案(模板名称 / 所属领域 / 版本 / 状态 / 创建人 / 设备·页面·文档数 / 操作)GET /api/db/domain-templates(含 domain_name、device_count、page_count、doc_count)每行「编辑」→ 打开该方案详情编辑器;「删除」→ 确认后 DELETE /api/db/domain-templates/:id(级联删除 device_template_domain_templates)并刷新;空列表提示「点击右上角新增」
@@ -294,6 +294,8 @@
面板 / 元素功能数据来源 / 接口交互效果
模板信息编辑所属领域 / 名称 / 版本 / 状态 / 创建人 / 描述GET /api/db/domain-templates/:id 详情;PUT /api/db/domain-templates/:id 保存「保存模板信息」写回并重新加载

5.11 页面样式库(styleLibrary)

+

下图为页面样式库的实际界面,展示缩略图卡片网格与「+ 新增样式」入口:

+
页面样式库
页面样式库:16:9 缩略图卡片网格,可新增 / 编辑 / 删除样式。
@@ -302,15 +304,32 @@
元素功能数据来源交互效果
样式卡片网格(缩略图 + 名称 + 编辑/删除)浏览已有样式GET /api/db/page-styles3 列布局,缩略图按 16:9 比例自适应高度(object-fit:contain,整页完整可见、不被截断);缩略图点开大图预览;编辑/删除生效

5.12 设备模版(deviceTemplates)

-

独立的「设备模版」页,维护可复用的设备模版与采集点,供领域方案在详情中「选用设备模版」引用。列表为整宽卡片(.device-list 单列),每个卡片即一个设备模版的编辑区。

+

独立的「设备模版」页,维护可复用的设备模版与采集点,供领域方案在详情中「选用设备模版」引用。设备模版数量可能成百上千,因此采用默认展开列表、点击进入详情的方式(而非整页卡片栅格):列表为紧凑表格(.device-tpl-list),含缩略图 / 名称 / 说明 / 采集点数 / 操作,并支持按名称或说明实时搜索;点击任意行进入该设备模版的详情编辑区,详情内「← 返回列表」回到列表。列表上方「+ 新增设备模版」进入新建表单(创建后定位到新建设备的详情)。

+
设备模版列表
设备模版列表:默认展开表格视图,支持搜索,点击行进入详情编辑。
+
设备模版详情
设备模版详情:名称 / 说明 / 设备图片、长方形预览区、采集点表格编辑(新增 / 批量删除 / 保存 / 数值范围下拉)。
- +
元素功能数据来源 / 接口交互效果
设备图片以长方形预览区展示设备图片,点击预览区即上传 / 更换GET /api/db/device-templates/:id/image(服务端按 image_path 落盘 data/db/uploads/devices/);PUT /api/db/device-templates/:id(image base64)预览区固定高度、object-fit:cover 不再溢出;上传后即时本地预览,保存时写回;删除图片 尚未实现
设备名称 / 说明编辑设备基本信息GET /api/db/device-templates/:id;PUT /api/db/device-templates/:id「保存设备」写回名称和说明(不再维护设备侧「所属领域」,改为由领域 / 方案侧选用)
采集点(表格编辑)表格方式维护采集点:名称 / 说明 / 单位 / 数值范围 / 描述;可新增一行、勾选删除一行或多行、保存GET /api/db/device-templates/:id 的 collection_points;POST /api/db/device-templates/:id/collection-points(新建,带全字段);PUT / DELETE /api/db/collection-points/:id「+ 新增一行」追加空白可编辑行;表头复选框全选,行内复选框多选,「删除选中」批量 DELETE;「保存采集点」对新建行 POST、对已有行 PUT;数值范围为下拉选择器(预设 0~100 / 0~1000 / -20~80 / -40~85 / 0~50 / 0~5 / 0~1 / 0~100%,或「自定义…」输入)
新增设备模版新建设备模版(名称 / 说明 / 图片)POST /api/db/device-templates列表上方「+ 新增设备模版」展开表单,创建后自动出现在列表中
新增设备模版新建设备模版(名称 / 说明 / 图片)POST /api/db/device-templates列表上方「+ 新增设备模版」进入新建表单,创建后自动打开该设备模版的详情编辑区
+

5.13 界面截图(UI 总览)

+

以下截图覆盖了当前 StationBuilder 原型中可访问的主要页面。截图在 1440×900 视口下使用 Playwright + Chromium 自动抓取,图片存放于 public/design-doc-assets/。

+ +
登录页
登录页:iStation StationBuilder 统一登录入口。
+
站点项目
站点项目:全部站点列表、统计概览、筛选与新建入口。
+
站点基本属性
站点基本属性:站点名称、域名、业务描述、关键词、文件上传等基本信息维护。
+
Asset 资产设置
Asset 资产设置:设备类型、数量、命名规则与资产层级预览。
+
功能与菜单
功能与菜单:MU 页面选择、Cube 扩展页面编辑、页面样式选择、菜单结构预览。
+
生成确认
生成确认:选择生成范围、执行 AI 生成,并实时查看生成进度。
+
领域方案库
领域方案库:列表/卡片视图切换、按领域分类筛选。
+
领域方案详情
领域方案详情:模板信息、选用设备模版、领域页面、模板菜单、知识文档、运维流程占位。
+
设备模版列表
设备模版列表:紧凑表格、搜索、点击进入详情。
+
设备模版详情
设备模版详情:设备基本信息、图片、采集点表格编辑。
+
页面样式库
页面样式库:样式缩略图网格与新增/编辑入口。
+

6. 生成流程(端到端)

    @@ -376,6 +395,8 @@

    11.1 版本变更记录(Changelog)

    + +
    版本日期修改人说明
    v0.92026-08-18wang.yu使用 Chromium + Playwright 自动抓取全站可访问页面截图,统一嵌入设计文档:新增 5.13「界面截图(UI 总览)」,覆盖登录页、站点项目、站点基本属性、Asset 资产、功能与菜单、生成确认、领域方案库、领域方案详情、设备模版列表/详情、页面样式库(共 11 张)。替换 5.9 / 5.10 中两张 placeholder.svg 为真实截图;在 5.11 / 5.12 补充真实界面图。截图文件置于 public/design-doc-assets/。
    v0.82026-08-18wang.yu设备模版改为「默认展开列表、点击进入详情」:列表为紧凑表格(缩略图 / 名称 / 说明 / 采集点数 / 操作),支持按名称或说明实时搜索;点击行进入该设备模版的详情编辑区(名称 / 说明 / 图片 / 采集点),可「← 返回列表」;「+ 新增设备模版」进入新建表单,创建后定位到新建设备的详情。面向成百上千设备模版的可扩展性。同步更新 4.2 导航表、5.12 章节。
    v0.72026-08-18wang.yu设备模版页交互优化:设备图片改为长方形预览区(点击上传,不再溢出);移除设备侧「所属领域」多选(改为由领域/方案侧选用设备);采集点改为整宽表格编辑,支持新增一行、勾选批量删除、保存,数值范围改为下拉选择器(预设 + 自定义);修复打开卡片时 collection_points 未加载导致的 runtime error,列表接口补充返回 collection_points。后端新增 GET /api/db/device-templates/:id/image 图片服务。新增 5.12 章节。
    v0.62026-08-18wang.yu领域方案库重构为多菜单:列表页支持「列表 / 卡片」视图切换与按领域分类筛选;新增独立的「设备模版」页(前端 DeviceTemplates,独立维护设备模版与采集点);方案详情的设备面板改为「选用设备模版」(DeviceTemplatePicker,勾选即重写 device_template_domain_templates 关联,未找到可跳转新增);领域分类改为由 GET /api/domains 动态渲染的二级菜单。后端 domain-templates 更新支持 device_template_ids 重关联。同步更新 4.2 / 5.9 / 5.10 章节。
    v0.52026-08-18wang.yu设计方案支持页面截图:新增 figure / 图注 样式(自动编号),撰写方式参考 MachineCube 手册(小节标题 + 说明 +「下图」引用 + 配图 + 图注);图片置于 public/design-doc-assets/。新增「版本变更记录」,每次修改升级小版本号并登记修改人 / 日期。