整合小程序、管理端与后端的最新本地改动,补齐用户管理与首页入口相关能力;提交前已完成敏感信息扫描,并移除本地 gitea 远程 URL 中的明文凭证,避免隐私信息进入远程仓库。 Made-with: Cursor
125 lines
3.5 KiB
Python
125 lines
3.5 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
将误挂在「第四篇 / 第9章」等下的 2026 派对场次,归位到「2026每日派对干货」篇章。
|
||
|
||
规则(与 content_upload.py 一致):
|
||
- id 为 10.xx 的节:只修正 part_id / chapter_id / part_title / chapter_title,不改 id。
|
||
- section_title 含「第102场」及以后、且不在 part-2026-daily:同上修正(含 id 非 10.xx 的遗留)。
|
||
|
||
用法:
|
||
python3 scripts/fix_2026_daily_part.py # 预览
|
||
python3 scripts/fix_2026_daily_part.py --execute # 执行 UPDATE
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
import argparse
|
||
import importlib.util
|
||
import re
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
ROOT = Path(__file__).resolve().parent.parent
|
||
|
||
|
||
def load_db_config() -> dict:
|
||
mig = ROOT / "scripts" / "migrate_2026_sections.py"
|
||
spec = importlib.util.spec_from_file_location("_mig", mig)
|
||
mod = importlib.util.module_from_spec(spec)
|
||
assert spec.loader is not None
|
||
spec.loader.exec_module(mod)
|
||
return mod.DB_CONFIG
|
||
|
||
|
||
PART_2026 = "part-2026-daily"
|
||
CHAPTER_2026 = "chapter-2026-daily"
|
||
TITLE_2026 = "2026每日派对干货"
|
||
|
||
|
||
def session_num(title: str) -> int | None:
|
||
m = re.search(r"第(\d+)场", title or "")
|
||
return int(m.group(1)) if m else None
|
||
|
||
|
||
def main():
|
||
p = argparse.ArgumentParser()
|
||
p.add_argument("--execute", action="store_true")
|
||
args = p.parse_args()
|
||
|
||
try:
|
||
import pymysql
|
||
except ImportError:
|
||
print("需要: pip install pymysql", file=sys.stderr)
|
||
sys.exit(1)
|
||
|
||
cfg = load_db_config()
|
||
conn = pymysql.connect(**cfg)
|
||
cur = conn.cursor()
|
||
|
||
cur.execute(
|
||
"""
|
||
SELECT id, section_title, part_id, chapter_id, part_title, chapter_title, sort_order
|
||
FROM chapters
|
||
ORDER BY sort_order, id
|
||
"""
|
||
)
|
||
rows = cur.fetchall()
|
||
to_fix: list[tuple] = []
|
||
|
||
def is_2026_daily_row(sid: str, title: str) -> bool:
|
||
"""与上传脚本一致:10.01~10.99(两位小数段)、2026.1;不含 10.1/10.2 单段 id。"""
|
||
s = str(sid)
|
||
if s == "2026.1":
|
||
return True
|
||
if re.match(r"^10\.\d{2}$", s):
|
||
return True
|
||
n = session_num(title or "")
|
||
if n is not None and n >= 102:
|
||
return True
|
||
return False
|
||
|
||
for r in rows:
|
||
sid, title, pid, cid, ptitle, ctitle, so = r
|
||
wrong_part = pid != PART_2026 or cid != CHAPTER_2026
|
||
if wrong_part and is_2026_daily_row(sid, title or ""):
|
||
to_fix.append(r)
|
||
|
||
if not to_fix:
|
||
print("没有需要归位的节(10.xx 或第102场及以后且已在 part-2026-daily)。")
|
||
conn.close()
|
||
return
|
||
|
||
print(f"待归位到「{TITLE_2026}」: {len(to_fix)} 节\n")
|
||
for r in to_fix:
|
||
sid, title, pid, cid, _, _, _ = r
|
||
print(f" {sid}\tpart={pid}\tch={cid}\t{title[:60] if title else ''}")
|
||
|
||
if not args.execute:
|
||
print("\n[预览] 未写入。确认无误后加 --execute")
|
||
conn.close()
|
||
return
|
||
|
||
n = 0
|
||
for r in to_fix:
|
||
sid = r[0]
|
||
cur.execute(
|
||
"""
|
||
UPDATE chapters SET
|
||
part_id = %s,
|
||
part_title = %s,
|
||
chapter_id = %s,
|
||
chapter_title = %s,
|
||
updated_at = NOW()
|
||
WHERE id = %s
|
||
""",
|
||
(PART_2026, TITLE_2026, CHAPTER_2026, TITLE_2026, sid),
|
||
)
|
||
n += cur.rowcount
|
||
conn.commit()
|
||
conn.close()
|
||
print(f"\n已更新 {n} 行,part/chapter 已归位 {PART_2026} / {CHAPTER_2026}。")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|