diff --git a/README.md b/README.md
index 3248b52..1b0d177 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,34 @@
-# Easy Data Collector 聚合站
+# Easy Data Collection 聚合站
-`sincos.cc` 单站架构:博客(首页)+ ResLib(License 申请系统)+ 子页板块。
+`sincos.cc` 单站架构:科技首页 + 前沿技术研究 + 工具开发(产品页)+ License 中心 + 资源中心 + 博客。
+
+## 站点结构
+
+```
+/ 科技首页(产品矩阵 / 研究 / 最新文章)
+/research/ 前沿技术研究聚合页
+ /research/neural/ Neural Research(NeuralMix AI)
+ /research/reslib/ ResLib 资源中心管理器
+/tools/ 工具开发产品页
+ /tools/sequence-diagram/ Sequence-Diagram 时序图设计器
+ /tools/uni-viewer/ Uni-Viewer 文件预览组件
+ /tools/engineer-craft/ Engineer Craft 工程设计平台
+ /tools/five-phases-observer/ 五行观察者 · GAP 公理协议
+ /tools/unitouch/ UniTouch Interface 工控交互
+ /tools/edc-lite-erp/ EDC Lite ERP
+/license/ License 中心
+ /license/apply 申请 License
+ /license/status 查询 / 下载
+ /license/package 资源包获取
+/resources/ 资源中心(私有服务入口)
+/blog/ 博客
+/admin 管理后台
+```
## 目录
```
-website/ FastAPI 后端(博客/ResLib/申请/管理后台,端口 8003)
+website/ FastAPI 后端(页面路由 / License 申请 / 管理后台,端口 8003)
blog/ 博客构建脚本 + 文章(markdown)
deploy/ 部署文档
```
@@ -25,4 +48,6 @@ uvicorn main:app --host 0.0.0.0 --port 8003
`blog/posts/*.md`(front matter: title/date/tags)→ `python -X utf8 blog/build.py`
生成结果输出到 `website/static/`(home.html / about.html / blog/)。
+构建脚本依赖 `markdown`(`pip install markdown`)。
+
部署详见 `deploy/DEPLOY.md`。
diff --git a/blog/build.py b/blog/build.py
index 0fe8448..23cbcf4 100644
--- a/blog/build.py
+++ b/blog/build.py
@@ -10,7 +10,6 @@ tags: 工业软件, ResLib
---
"""
import re
-import sys
from datetime import datetime
from pathlib import Path
@@ -22,26 +21,84 @@ OUT_BLOG = BASE.parent / "website" / "static" / "blog"
OUT_HOME = BASE.parent / "website" / "static" / "home.html"
OUT_ABOUT = BASE.parent / "website" / "static" / "about.html"
-SITE_NAME = "Easy Data Collector"
+SITE_NAME = "Easy Data Collection"
SEO_NAME = "江北的渔夫的空间"
-NAV = [
- ("/", "博客"),
- ("/reslib/", "ResLib"),
- ("/reslib/apply", "申请 License"),
- ("/reslib/status", "查询 / 下载"),
- ("/reslib/package", "资源包获取"),
- ("/neural/", "Neural Research"),
- ("http://124.220.63.9:25000", "Research Digest"),
+NAV_ITEMS = [
+ {
+ "key": "research",
+ "href": "/research/",
+ "label": "前沿技术研究",
+ "children": [
+ ("http://124.220.63.9:25000", "Research Digest"),
+ ("/research/neural/", "Neural Research"),
+ ("/research/reslib/", "ResLib"),
+ ],
+ },
+ {
+ "key": "tools",
+ "href": "/tools/",
+ "label": "工具开发",
+ "children": [
+ ("/tools/sequence-diagram/", "Sequence-Diagram"),
+ ("/tools/uni-viewer/", "Uni-Viewer"),
+ ("/tools/engineer-craft/", "Engineer Craft"),
+ ("/tools/five-phases-observer/", "The Five Phases Observer"),
+ ("/tools/unitouch/", "UniTouch Interface"),
+ ("/tools/edc-lite-erp/", "EDC Lite ERP"),
+ ],
+ },
+ {
+ "key": "resources",
+ "href": "/resources/",
+ "label": "资源中心",
+ "children": [],
+ },
+ {
+ "key": "license",
+ "href": "/license/",
+ "label": "License",
+ "children": [
+ ("/license/apply", "申请 License"),
+ ("/license/status", "查询 / 下载"),
+ ("/license/package", "资源包获取"),
+ ],
+ },
+ {
+ "key": "blog",
+ "href": "/blog/",
+ "label": "博客",
+ "children": [],
+ },
]
-def page_header(active: str, title: str = "") -> str:
+def nav_html(active: str = "") -> str:
+ parts = []
+ for item in NAV_ITEMS:
+ if not item["children"]:
+ cls = "nav-link active" if item["key"] == active else "nav-link"
+ parts.append(f' {item["label"]} ')
+ continue
+ parent_cls = "nav-link active" if item["key"] == active else "nav-link"
+ links = "\n".join(
+ f' {label} '
+ for href, label in item["children"]
+ )
+ parts.append(
+ f"""
"""
+ )
+ return "\n".join(parts)
+
+
+def page_header(active: str = "", title: str = "") -> str:
seo_title = f"{title} - {SEO_NAME}" if title else SEO_NAME
- links = "\n".join(
- f' {label} '
- for href, label in NAV
- )
return f"""
@@ -49,9 +106,10 @@ def page_header(active: str, title: str = "") -> str:
{seo_title}
-
+
+
@@ -62,7 +120,7 @@ def page_header(active: str, title: str = "") -> str:
{SITE_NAME}
-{links}
+{nav_html(active)}
☰
@@ -76,12 +134,20 @@ def page_footer() -> str:
-
"""
@@ -125,6 +191,51 @@ def fmt_date(s: str) -> str:
return s
+PRODUCT_CARDS = """
+
+ ◷
+ Flutter Desktop
+ Sequence-Diagram
+ 面向 PLC 流程节拍与相位角设计的时序图设计器,条形 / 圆周双视图。
+ 了解详情 →
+
+
+ ◉
+ Web Component
+ Uni-Viewer
+ 纯前端、不出网的文件预览组件,271 个扩展名、47 条预览链路。
+ 了解详情 →
+
+
+ ⚙
+ Vue 3 · Vite
+ Engineer Craft
+ 流程工业智能设计平台:31 个工程计算模块、URS 与 AI 审查。
+ 了解详情 →
+
+
+ ✦
+ GAP 公理协议
+ The Five Phases Observer
+ 90 域观测协议与 720 个可证伪锚点,让决策可编译、可证伪。
+ 了解详情 →
+
+
+ ▦
+ Flutter · MQTT
+ UniTouch Interface
+ 嵌入式工控机的设备控制软件,替代传统 HMI 的统一工控平台。
+ 了解详情 →
+
+
+ ▣
+ Electron · MySQL
+ EDC Lite ERP
+ 轻量资源计划与制造管理系统:物料编码、进销存、扫码称配全链路。
+ 了解详情 →
+ """
+
+
def build():
posts = [parse_post(p) for p in sorted(POSTS_DIR.glob("*.md"), reverse=True)]
posts.sort(key=lambda p: p["date"], reverse=True)
@@ -144,11 +255,16 @@ def build():
if not cards:
cards.append('暂无文章,敬请期待。
')
- blog_list = f"""{page_header("/blog/")}
+ blog_list = f"""{page_header("blog")}
+
+
+
BLOG · 博客
+
工程实践与研究记录
+
工业软件、标准件库、深度学习与工具开发的过程记录。
+
+
-
博客
-
工业软件、标准件库与数字化实践记录。
{''.join(cards)}
@@ -160,10 +276,10 @@ def build():
# ---------- 文章详情页 ----------
for p in posts:
tags = "".join(f'
{t} ' for t in p["tags"])
- html = f"""{page_header(p['slug'], p['title'])}
+ html = f"""{page_header("blog", p['title'])}