同步家纺情报 v2 数据、59 个严格权威源、趋势图库、移动端交互、Google/Yandex 翻译门控及静态 SEO/GEO 构建。 补充面向 C# 研发的 README,明确当前无 LLM、多模态与生图模型,记录翻译请求参数、缓存与失败策略、数据处理边界、前端职责和无 GitHub Pages 部署流程。 新增按日期倒序维护的 CHANGELOG,记录影响、验证与代码/数据/dist 回滚方法。 验证:11 个 Python 契约测试、13 个 Node 前端测试通过;静态构建生成 1096 个 Sitemap URL。
53 lines
1.6 KiB
Python
53 lines
1.6 KiB
Python
#!/usr/bin/env python3
|
|
"""启动本地静态服务并自动选择可用端口。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import socket
|
|
import sys
|
|
import webbrowser
|
|
from functools import partial
|
|
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
|
|
|
|
def available_port(start: int) -> int:
|
|
for port in range(start, start + 20):
|
|
with socket.socket() as probe:
|
|
try:
|
|
probe.bind(("127.0.0.1", port))
|
|
return port
|
|
except OSError:
|
|
continue
|
|
raise RuntimeError("8765 至 8784 均被占用")
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(description="启动三笙AI情报局本地站点")
|
|
parser.add_argument("--port", type=int, default=8765)
|
|
args = parser.parse_args()
|
|
try:
|
|
if not (ROOT / "dist" / "index.html").is_file():
|
|
raise FileNotFoundError("dist/index.html 不存在,请先运行 update.bat")
|
|
port = available_port(args.port)
|
|
handler = partial(SimpleHTTPRequestHandler, directory=str(ROOT / "dist"))
|
|
server = ThreadingHTTPServer(("127.0.0.1", port), handler)
|
|
url = f"http://127.0.0.1:{port}/"
|
|
print(f"[启动成功] {url}")
|
|
webbrowser.open(url)
|
|
server.serve_forever()
|
|
except KeyboardInterrupt:
|
|
print("\n[已停止] 本地服务已关闭")
|
|
return 0
|
|
except Exception as exc:
|
|
print(f"[启动失败] {exc}", file=sys.stderr)
|
|
return 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|