Files
Sansheng-Intelligence/README.md
T

472 lines
25 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 三笙AI情报局独立版
三笙AI情报局是面向家纺、服装和跨境电商经营者的静态情报站参考实现。本仓库从 `AI-News-Radar` 主项目中独立出来,供公司 C# 后端研发、前端研发、测试和运维人员理解现有业务,再重构为长期稳定版本。
> 先明确边界:仓库名称中包含“AI”,但当前版本 **没有调用任何 LLM、多模态理解模型或生图模型**。没有 Qwen、Gemini、OpenAI 等模型请求,没有提示词模板,也没有“先让文本模型理解用户输入,再调用生图模型”的两阶段链路。现有智能能力来自一手信源抓取、规则解析、结构化计算、去重排序、公共机器翻译和静态 SEO/GEO 生成。
## 当前基线
当前提交数据以 `data/*.json` 为准,业务基准日为 **2026-08-17**:
| 指标 | 当前值 |
|---|---:|
| 严格权威源 | 59/59 |
| 日历原始事件 / 聚合机会 | 1261 / 640 |
| 今日必看 | 24 |
| 展会 | 79 |
| 政策与召回 | 48 |
| 标准事实 | 4 |
| 跨境平台 | 28 |
| 跨境活动 | 65 |
| 趋势与灵感内容 | 208 |
这些数字是可回归的仓库快照,不是写死在页面里的宣传数字。每次数据更新后,应以 `textile-intelligence.json.summary`、`source_target/source_success` 和 `textile-trends.json.total_items` 重新核对。
## 五分钟理解系统
```mermaid
flowchart LR
A[政府/平台/展会/博物馆等公开来源] --> B[Python 定时抓取]
B --> C[证据词、状态码、语种和结构校验]
C --> D[规则解析、规范化、聚合、去重和排序]
D --> E[命中缓存或调用 Google 公共翻译接口]
E --> F[生成两份公开 JSON]
F --> G[生成首页、详情页、栏目页、Sitemap、JSON-LD、llms.txt]
G --> H[原子替换 dist]
H --> I[IIS/Nginx/对象存储/CDN 只提供静态文件]
```
生产访问端不需要 Python、Node、数据库、模型服务或 GitHub Pages。Python 只运行在更新节点;最终仅发布 `dist/`。
## 核心功能
| 功能 | 用户看到的结果 | 当前实现 |
|---|---|---|
| 今日必看 | 混合展示备货、展会、政策、活动和趋势任务 | 规则评分、截止日期、经营相关度和风险排序 |
| 备货日历 | 节日、国家、备货窗口、产品建议、平台动作 | 多来源日历规范化后按日期、名称和地区聚合 |
| 展会通 | 展期、城市、主办方、官方报名和译文入口 | 固定官方源与动态目录合并,优先保留官方报名页 |
| 政策预警 | 关税、召回、标签、知识产权和平台规则 | 权威来源证据校验,事实与经营建议分区 |
| 跨境活动 | 线上/线下活动、倒计时、报名入口和筛选 | 官方活动优先,行业媒体只承担发现作用 |
| 平台渠道 | 市场、品类、卖家准入和官方入驻入口 | 静态核验目录与信源状态组合 |
| 趋势雷达 | 趋势文章、灵感图库、时装趋势和原图查看 | RSS/HTML/博物馆公开 API,URL 与标题规则去重 |
| SEO/GEO | 可直接索引的中文正文和稳定实体页面 | 静态 HTML、canonical、JSON-LD、Sitemap、robots、llms.txt |
平台渠道页只向用户展示“平台官网”和“官方入驻”两个真实业务入口。类目 URL 仅作为内部研究数据保留,不在前台展示;消费者官网和类目页不提供网页翻译,只有非中文官方入驻页才显示“辅助翻译入驻说明”。
## AI、模型与渠道清单
### 当前没有的模型链路
| 能力 | 当前状态 | 说明 |
|---|---|---|
| LLM 文本理解 | 未接入 | 不调用 Qwen、Gemini、OpenAI 或其他大语言模型 |
| 多模态图片理解 | 未接入 | 不把用户图片或源站图片发送给视觉模型 |
| 文生图/图生图 | 未接入 | 灵感图库图片来自公开博物馆或来源站;活动无图时使用 CSS 文字海报 |
| 提示词拼接 | 不存在 | 没有 system/user prompt、提示词变量或模型输出 JSON |
| 用户内容实时模型审核 | 不存在 | 当前站点没有用户投稿、聊天或生图输入 |
因此,C# 重构时不要创建“模型编排服务”、提示词数据库或生图任务队列来复刻当前功能。以后若产品明确加入模型能力,应作为独立版本设计,不能把未来方案写成当前依赖。
### 当前唯一的机器翻译请求
构建节点会对部分外文标题和摘要执行一次普通 HTTP 翻译请求。它不是 LLM,也不是生图模型:
```text
GET https://translate.googleapis.com/translate_a/single
client=gtx
sl=auto
tl=zh-CN
dt=t
q={规范化后的原文标题或摘要}
```
变量只有 `q`;`sl` 固定为自动识别,`tl` 固定为简体中文。返回数组中每个翻译片段的首字段会按顺序拼接为中文。调用前先以完整原文字符串查询 `data/textile-zh-cache.json`,命中则不请求;未命中才请求,并限制每次任务的新翻译数量:
| 内容 | 单次最多新增翻译 |
|---|---:|
| 趋势标题与摘要 | 250 |
| 日历标题 | 260 |
| 展会标题与摘要 | 200 |
| 政策标题/摘要 | 72 |
| 活动标题 | 72 |
请求失败时保留缓存中的上一版中文或官方原文,不会把线上字段清空。该 `client=gtx` 公共端点没有项目 API Key 和商业 SLA;稳定版若要求服务等级、配额和合规审计,应由公司统一替换为正式采购的翻译服务,但必须保持“缓存优先、失败保留上一版、官方原文可访问”的语义。
### 网页译文入口
网页翻译按钮只生成跳转 URL,不抓取也不保存整页译文:
```text
Google: https://translate.google.com/translate?sl=auto&tl=zh-CN&u={URL 编码后的官网地址}
Yandex: https://translate.yandex.com/translate?url={URL 编码后的官网地址}&lang={源语种}-zh
```
处理规则:
- 简体中文正文、`.cn` 域名、`bizevent.ccpit.org` 等已知中文页面不显示译文按钮。
- 中国大陆 IP 默认使用 Yandex;明确的非中国 IP 默认使用 Google,并以另一渠道为备用。
- IP 依次通过 Cloudflare trace、`country.is`、`ipwho.is` 判断;全部失败后再参考浏览器语种和时区。
- `cpsc.gov`、`zatca.gov.sa` 等已验证不支持 Google 网页代理的域名只提供 Yandex。
- `abai.kgd.gov.kz` 已验证两边都不可用,只保留本站中文摘要和官方原文。
- 官方来源/报名按钮始终优先于译文按钮;报名、付款、验证码和资料提交必须回官方域名。
## 数据请求与处理流程
### 1. 输入
系统输入不是用户提示词,而是以下公开数据:
- 政府、海关、监管机构和标准组织的 HTML、JSON、RSS。
- 平台、展会和主办方官网的页面与公开接口。
- Met、V&A 等博物馆的公开藏品信息和图片地址。
- 已人工登记的信源元数据:ID、栏目、地区、URL、证据词、中文说明和经营动作。
### 2. 抓取前处理
- 固定浏览器 User-Agent、语言头、连接/读取超时和有限重试。
- 规范化 URL、文本空白、日期、地区、平台和节日名称。
- 对已知证书兼容问题只在指定域名使用兼容适配器,禁止全局关闭 TLS 校验。
- 动态 API Key 只从目标官网公开前端配置中提取并立即用于同站请求,不在仓库保存密钥。
### 3. 抓取后校验
- 同时检查 HTTP 状态、内容类型、最终 URL、正文长度和登记的证据词;HTTP 200 不等于成功。
- 为响应正文计算内容指纹,记录 `verified_at`、`content_hash` 和变更状态。
- 严格源任一失败时,`--strict` 更新直接退出,正式 JSON 和 `dist/` 不被半成品覆盖。
- 活动发现源必须回到主办方或平台官方报名页;行业媒体页不能冒充官方来源。
### 4. 结构化、去重和排序
- 日历:规范化节日名、日期和地区后聚合;当地名称折叠为辅助信息。
- 展会:规范化展名、开始日和城市;官方固定源覆盖动态目录的弱字段。
- 活动:以真实报名 URL、标题、日期和地区去重;中文站不生成翻译入口。
- 趋势:先按 URL 去重,再按稳定 ID、标题和来源处理;V&A 泛化标题会加入藏品编号,避免多个 `Hanging/Pattern` 被误认为相同内容。
- 今日必看:从各栏目混合选取可行动事项,按截止日期、经营相关性、影响和风险排序。
### 5. 发布
`scripts/update_all.py` 在 `runtime/update-*` 临时目录完成抓取、翻译、JSON 校验和站点预构建。只有全部成功后才替换正式数据,并把旧四份 JSON 压缩到 `runtime/snapshots/`。快照最多 14 份、总计不超过 120 MiB。
`scripts/build_site.py` 仅把以下运行数据复制到公开目录:
- `dist/data/textile-intelligence.json`
- `dist/data/textile-trends.json`
翻译缓存、源状态、日志和快照不会进入 `dist/`。
## 审核、预处理和后处理边界
当前没有用户生成内容,所以没有实时内容安全审核接口。现有“审核”是数据质量审核,不是模型审核:
- 信源必须预登记并通过证据词和权威层级验证。
- 页面语种、日期、URL、地区和栏目在进入正式 JSON 前规范化。
- 付费墙、失效站点、二次转载和无来源图片按规则排除。
- 机器翻译、官方事实和本站经营建议分别标注,不能混写成官方结论。
- 前端不自行补造事实;缺字段时隐藏对应控件,不显示伪数据或占位按钮。
未来若加入搜索框自由文本、用户评论、文件上传或模型生图,才需要在 API 边界增加长度、格式、恶意 URL、版权、隐私和内容安全审核。该能力不属于当前版本。
## 前端必须保留的职责
即使后端改写为 C#,以下工作仍必须由前端完成:
- 七个业务入口、趋势子分类、搜索和地区/平台/参与方式筛选。
- IP 结果返回后选择 Google/Yandex 译文按钮;检测完成前不展示错误渠道。
- 官方来源和官方报名链接在译文入口左侧,所有外链新窗口打开并隔离 opener。
- 日历倒计时、活动状态、移动端单列布局和触控尺寸。
- 灵感图库原图浮层、三笙 Logo 加载动画、关闭/下载/键盘操作。
- 主题切换、分享、折叠的更新时间与源状态详情。
- 只消费公开 JSON;不得请求 `textile-zh-cache.json` 或源状态文件。
事实聚合、内容指纹、去重、业务评分和翻译缓存应留在更新服务或后端,不能散落到 UI 组件里。
## 目录与入口
```text
public/ 独立 HTML、CSS、ES Modules、本地字体、Logo 和平台图标
data/ 正式 JSON、源状态与中文翻译缓存
scripts/ 抓取、翻译、聚合、去重、SEO 和原子发布
docs/ 数据契约、信源、流水线、C# 交接、SEO/GEO 和运维说明
runtime/ 计划任务、临时目录和本地快照;不参与公开发布
dist/ 可直接部署的静态产物;构建生成,不提交版本库
tests/ Python 数据契约测试与 Node 前端契约测试
```
主要入口:
| 文件 | 职责 |
|---|---|
| `scripts/update_all.py` | 完整更新事务和原子发布入口 |
| `scripts/update_textile_intelligence.py` | 日历、展会、政策、平台、活动、今日必看主聚合 |
| `scripts/update_textile_trends.py` | 趋势文章、图库和时装趋势抓取 |
| `scripts/intelligence_sources.py` | 严格权威源注册表 |
| `scripts/intelligence_web_translation.py` | 页面语种和 Google/Yandex 链接策略 |
| `scripts/build_site.py` | 复制公开资产和数据、调用 SEO 构建、替换 `dist/` |
| `scripts/build_seo.py` | 栏目页、详情页、年份页和结构化数据 |
| `public/assets/js/render-intelligence-core.js` | 情报站核心 UI、筛选和翻译按钮 |
## 本地运行
Windows 11 可直接双击:
1. `start.bat`:缺少 `dist/` 时先构建,再自动寻找从 `8765` 开始的空闲端口。
2. `update.bat`:首次创建 `.venv`,从清华 PyPI 镜像安装依赖,严格更新并构建。
3. `install-schedule.bat`:安装每天 09:30 的 Windows 计划任务。
命令行:
```powershell
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
.\.venv\Scripts\python.exe scripts\update_all.py
.\.venv\Scripts\python.exe scripts\serve.py
```
只基于仓库快照构建,不联网更新数据:
```powershell
$env:SANSHENG_SITE_URL='https://intel.example.com'
.\.venv\Scripts\python.exe scripts\build_site.py --site-url $env:SANSHENG_SITE_URL
```
## C# 稳定版重构建议
最低风险的迁移顺序:
1. 冻结 `docs/DATA-CONTRACT.md` 描述的 JSON v2,C# 先读取当前两份公开 JSON。
2. 用 Worker Service 或独立计划任务承载采集,禁止在 ASP.NET Web 请求中同步抓取 59 个源。
3. 使用 `HttpClient`、`System.Text.Json` 和正式 HTML 解析器逐个迁移稳定源;每迁移一个源,与 Python 对同一 URL 双跑比对。
4. 将 `Source`、`FetchRun`、`IntelligenceItem`、`ItemSource`、`UserPreference`、`UserTask` 分表保存;自动事实与人工结论分离。
5. API 稳定后再迁移前端;服务端渲染静态正文,客户端仅增强筛选、收藏、任务和翻译渠道选择。
6. 最后切换正式域名 canonical,并为旧 URL 建立 301 映射。
C# 实现必须保留以下语义:稳定 ID、UTC `generated_at`、业务 `as_of_date`、内容指纹、源证据、严格失败不发布、缓存翻译失败不清空、官方事实/机器翻译/经营分析分区、原子发布和可回滚快照。
不要一次性重写全部抓取器,也不要先引入 LLM。先让 C# 后端稳定消费现有 JSON,再按源逐步替换,最容易定位数据差异和回滚。
## 复现主站的全自动更新与部署
独立站不依赖 GitHub Actions 或 Pages,但现有命令可以直接接入 GitHub Actions、Gitea Runner、Windows 计划任务和 Linux `systemd`。研发人员应先按实际网络与服务器条件选择方案,不要在 Web 请求中执行抓取。
| 条件 | 推荐方案 | 更新节点 | Web 节点 |
| --- | --- | --- | --- |
| 希望最快复现主站效果 | 私有 GitHub 仓库 + GitHub Actions + Cloudflare Pages | GitHub Hosted Runner | Cloudflare Pages |
| 公司有可访问全部源站的 Server | Gitea Runner、Windows 计划任务或 Linux `systemd` | 公司 Server | 同机 IIS/Nginx,或另一台内网 Web Server |
| Web Server 无外网,但有其他外网节点 | 外网更新节点生成 `dist/`,通过制品库、SFTP、SMB 或对象存储传入 | 外网更新节点 | 只接收并发布 `dist/` |
| 公司任何机器都不能访问部分境外源 | 合规代理、统一出口、GitHub Hosted Runner 或外部更新 Worker | 具备合法网络出口的节点 | 内网 Web Server |
### 最快复现:私有 GitHub 仓库 + GitHub Actions
该方案最接近个人主站:GitHub Actions 每天抓取、测试、构建并提交新数据;Cloudflare Pages 监听数据提交并重新发布 `dist/`。GitHub 仓库必须设为私有,避免把翻译缓存、信源状态和运行信息公开。
1. 在 GitHub 创建一个私有空仓库,把公司 Gitea 中的本项目推送到该仓库的 `main` 分支。这个 GitHub 仓库可以只是研发复现环境,不要求替代公司 Gitea 主仓库。
2. 打开 `Settings -> Actions -> General -> Workflow permissions`,选择 `Read and write permissions`,允许工作流提交更新后的数据快照。
3. 打开 `Settings -> Secrets and variables -> Actions -> Variables`,创建:
- `SANSHENG_SITE_URL`:独立站最终访问根地址,不带末尾 `/`。
- `PUBLIC_SITE_URL`:已经部署完成并可访问的站点根地址;尚未部署时可以暂不创建。
4. 在 GitHub 仓库创建 `.github/workflows/update-standalone.yml`:
```yaml
name: Update Sansheng Intelligence
on:
workflow_dispatch:
schedule:
# UTC 01:30,即北京时间 09:30。
- cron: "30 1 * * *"
concurrency:
group: update-sansheng-intelligence-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: write
jobs:
update:
runs-on: ubuntu-latest
timeout-minutes: 35
env:
SANSHENG_SITE_URL: ${{ vars.SANSHENG_SITE_URL }}
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup Python
uses: actions/setup-python@v6
with:
python-version: "3.11"
cache: pip
cache-dependency-path: requirements.txt
- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: "24"
- name: Validate configuration
run: |
if [ -z "$SANSHENG_SITE_URL" ]; then
echo "Repository variable SANSHENG_SITE_URL is required"
exit 1
fi
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Update data and build dist
run: python scripts/update_all.py --site-url "$SANSHENG_SITE_URL"
- name: Run contracts
run: |
python -m unittest discover -s tests -p "test_*.py"
node --test tests/test_frontend.mjs
- name: Commit data snapshots
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add \
data/textile-intelligence.json \
data/textile-trends.json \
data/textile-intelligence-source-status.json \
data/textile-zh-cache.json
if git diff --cached --quiet; then
echo "No data changes to commit"
else
git commit -m "chore: update sansheng intelligence snapshot"
git push
fi
- name: Upload static artifact
uses: actions/upload-artifact@v4
with:
name: sansheng-intelligence-dist
path: dist/
if-no-files-found: error
retention-days: 7
- name: Verify public deployment
if: ${{ vars.PUBLIC_SITE_URL != '' }}
run: |
python scripts/verify_public_snapshot.py \
--base-url "${{ vars.PUBLIC_SITE_URL }}" \
--expected-file data/textile-intelligence.json \
--retries 12 \
--interval 30
```
5. 在 GitHub 的 `Actions` 页面手动运行一次 `Update Sansheng Intelligence`。首次验收应确认:抓取成功、测试通过、仓库出现数据提交、`sansheng-intelligence-dist` 制品可以下载并直接由静态服务器访问。
6. 若使用 Cloudflare Pages,在 Pages 项目中连接这个 GitHub 仓库并配置:
- 生产分支:`main`。
- 构建命令:`python scripts/build_site.py --site-url "$SANSHENG_SITE_URL"`。
- 输出目录:`dist`。
- 环境变量:`SANSHENG_SITE_URL` 使用与 GitHub 仓库变量相同的正式站点根地址。
7. Cloudflare Pages 会在 Actions 推送数据提交后自动构建。设置 `PUBLIC_SITE_URL` 后,Actions 最后一步会比较公开 JSON 与本次数据;公开站仍是旧快照时工作流会失败,不能把“构建成功”误当成“部署成功”。
GitHub Hosted Runner 的公网出口通常比内地 Server 更适合抓取境外官方源,但仍可能被个别源站按机房 IP、地区或反爬规则拒绝。项目的严格模式会保留旧版并拒绝发布不完整数据;不要为了让工作流变绿而删除 `--strict` 或绕过 `source_target == source_success`。
### 有外网访问能力的 Windows/Linux Server
这种环境不需要 GitHub,也不需要 Pages。Server 直接从公司 Gitea 检出代码,作为更新节点运行:
```text
检出或更新代码
-> 创建 Python 虚拟环境并安装 requirements.txt
-> 设置 SANSHENG_SITE_URL
-> 运行 update_all.py
-> 运行 Python 与 Node 契约测试
-> 得到不可变的 dist/ 制品
-> 发布到 IIS/Nginx 新版本目录
-> 请求公开 JSON 校验 generated_at 和 as_of_date
```
Windows Server 可以复用 `update.bat` 和 `install-schedule.bat`,或由 Task Scheduler/Windows Service 定时运行:
```powershell
git pull --ff-only
$env:SANSHENG_SITE_URL='https://实际独立站域名'
.\.venv\Scripts\python.exe scripts\update_all.py --site-url $env:SANSHENG_SITE_URL
.\.venv\Scripts\python.exe -m unittest discover -s tests -p 'test_*.py'
node --test tests\test_frontend.mjs
```
Linux Server 使用同一组 Python 命令,由 `systemd timer`、Cron 或 Gitea Runner 调度;构建成功后把 `dist/` 同步到新的 Nginx 版本目录,再通过 `current` 软链接原子切换。完整的 Windows/IIS、Linux/Nginx、版本目录和回滚方式见 [Java/C# 自托管方案](docs/SELF_HOSTING_JAVA_CSHARP.md)。
### Web Server 没有外网,但存在外网更新节点
这是公司内网环境的推荐架构。外网更新节点可以是 GitHub Hosted Runner、公司代理区 Server、境外云主机或具备统一出口的 Gitea Runner;内网 Web Server 不运行抓取代码。
1. 外网更新节点运行 `update_all.py`,生成完整 `dist/`。
2. 将 `dist/` 压缩为带版本时间和提交 SHA 的制品,并生成 SHA-256。
3. 通过公司制品库、对象存储、SFTP、SMB 或人工审批通道传入内网。
4. Web Server 把制品解压到新版本目录,校验 SHA-256、JSON、Sitemap 和首页。
5. 验证通过后切换 IIS 物理路径或 Nginx `current` 软链接;失败则继续服务旧版本。
6. 发布完成后,在能访问公开站点的节点运行 `verify_public_snapshot.py`。
Web 节点只接收 `dist/`。不要把仓库、`.venv`、`data/textile-zh-cache.json`、`data/textile-intelligence-source-status.json`、`runtime/` 或抓取日志放进网站目录。IIS/Nginx 必须优先返回真实静态文件,不能让 `/data/*.json` 被 SPA fallback 替换成首页 HTML。
### 任何可用机器都没有境外网络能力
这种情况下不能复现“全部官方源自动更新”。代码无法替代网络出口,也不能安全地用空数据或旧时间伪装成功。只能选择以下路径之一:
- 由公司网络团队提供合规的 `HTTP_PROXY`、`HTTPS_PROXY`、统一出口或官方域名白名单。
- 使用 GitHub Hosted Runner、外部更新 Worker 或具有合法外网能力的云主机生成制品,再传入内网。
- 由研发人员在具备外网能力的工作站运行 `update.bat`,人工提交带 SHA-256 的 `dist/` 制品。
- 明确缩减信源范围,并同步调整数据契约、严格源数量和产品承诺;不能静默跳过不可访问源。
如果没有任何合规外网节点,也不允许人工制品交接,就只能基于仓库里最后一次已验证快照运行 `build_site.py`,可以持续提供静态站,但不能声称数据仍在自动更新。
仓库不预置绑定具体服务器账号的 Gitea 部署 workflow,因为 Runner 标签、发布协议、IIS/Nginx 路径、制品库和密钥名必须由公司环境决定。确定这些参数后,把本节相同命令接入现有流水线即可,不需要修改抓取、数据结构或前端代码。
## SEO/GEO 基线
- 品牌实体统一为“三笙AI情报局”,简称“三笙AI”;“家纺AI”是能力词,不替代品牌。
- 核心主题覆盖家纺AI、三笙AI、家纺情报、跨境家纺平台、家纺跨境平台。
- `SANSHENG_SITE_URL` 是 canonical、Open Graph、Sitemap 和 `llms.txt` 的唯一域名来源。
- 独立版不覆盖 `https://www.sanshengai.net/` 根目录,未确定正式域名前不要修改线上 canonical。
- 每条静态详情包含可直接索引的中文正文,不要求搜索引擎执行 JavaScript。
- 页面区分官方事实、机器翻译和本站经营建议,结构化数据不把分析冒充官方原文。
## 测试与发布门槛
```powershell
python -m unittest discover -s tests -p 'test_*.py'
node tests\test_frontend.mjs
python scripts\build_site.py --site-url http://127.0.0.1:8765
```
发布前至少确认:
- Python 与 Node 契约测试全部通过。
- `source_target == source_success`,核心栏目非空。
- `dist/index.html`、`robots.txt`、`sitemap.xml`、`llms.txt` 和两份公开 JSON 存在。
- 桌面、390px 和 375px 移动端无横向溢出,七个入口可发现。
- 中文站不出现译文按钮,已知 Google/Yandex 阻断域名选择正确。
- 随机抽查 canonical、JSON-LD、官方链接、报名链接、日期和图库原图。
## 提交与更新日志规范
每次影响代码、数据结构、业务规则、信源、部署或 UI 的提交,都必须先在 [CHANGELOG.md](CHANGELOG.md) 顶部增加日期条目,至少写明:
- 改了什么、为什么改、影响哪些目录或数据字段。
- 修复了什么可观察问题,是否有兼容性变化。
- 实际运行过的测试和构建命令。
- 回滚该提交后需要同步回滚的数据、缓存或静态目录。
提交信息正文应与日志条目一致,禁止只写“update”“fix”或“优化”。普通回滚使用 `git revert <commit>`,不要重写共享分支历史。
## 进一步文档
- [更新日志](CHANGELOG.md)
- [信源手册](docs/SOURCES.md)
- [数据契约](docs/DATA-CONTRACT.md)
- [更新流水线](docs/PIPELINE.md)
- [C# 后端与前端交接](docs/CSHARP-NODE-HANDOFF.md)
- [SEO/GEO 规范](docs/SEO-GEO.md)
- [运维手册](docs/OPERATIONS.md)
- [Java/C# 脱离 GitHub 与 Pages 的自托管方案](docs/SELF_HOSTING_JAVA_CSHARP.md)