任务系统 v2/v3:状态机统一、v2 发布字段、接单/交付/验收/返工/结算/发票全链路
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""存量用户默认头像同步脚本。
|
||||
|
||||
给「头像为空」的存量用户随机分配一个默认头像(来自 avatar_pool.json 池)。
|
||||
已有真实头像(非空、非默认池前缀)的用户不会被覆盖。
|
||||
|
||||
用法:
|
||||
python scripts/sync_default_avatars.py # 实际执行
|
||||
python scripts/sync_default_avatars.py --dry-run # 只预览不写库
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv(Path(__file__).resolve().parent.parent / ".env")
|
||||
|
||||
from sqlalchemy import text # noqa: E402
|
||||
|
||||
from app.infrastructure.db import AsyncSessionLocal # noqa: E402
|
||||
from app.infrastructure.repositories import utcnow_iso # noqa: E402
|
||||
from app.services.avatar_pool import random_default_avatar # noqa: E402
|
||||
|
||||
DEFAULT_POOL_PREFIX = "/oss/avatar/images/images/"
|
||||
|
||||
|
||||
async def main(dry_run: bool) -> int:
|
||||
async with AsyncSessionLocal() as session:
|
||||
# 仅处理头像为空(或 NULL)的存量用户;已设置真实头像的不动
|
||||
rows = (
|
||||
await session.execute(
|
||||
text(
|
||||
"SELECT id, nickname, username FROM users "
|
||||
"WHERE avatar IS NULL OR avatar = ''"
|
||||
)
|
||||
)
|
||||
).all()
|
||||
total = len(rows)
|
||||
print(f"待同步用户数(头像为空): {total}")
|
||||
if total == 0:
|
||||
print("无需同步。")
|
||||
return 0
|
||||
|
||||
updated = 0
|
||||
for row in rows:
|
||||
avatar = random_default_avatar()
|
||||
if not avatar:
|
||||
print("警告:默认头像池为空,跳过(请检查 serverdata/avatar_pool.json)")
|
||||
return 1
|
||||
print(
|
||||
f" {'[DRY] ' if dry_run else '[set] '}{row.id} "
|
||||
f"({row.nickname or row.username or ''}) -> {avatar}"
|
||||
)
|
||||
if not dry_run:
|
||||
await session.execute(
|
||||
text("UPDATE users SET avatar = :av, updated_at = :now WHERE id = :uid"),
|
||||
{"av": avatar, "uid": row.id, "now": utcnow_iso()},
|
||||
)
|
||||
updated += 1
|
||||
|
||||
if not dry_run:
|
||||
await session.commit()
|
||||
print(f"完成:{'(dry-run 未写库)' if dry_run else ''}计划/已更新 {updated} 人。")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="存量用户默认头像同步")
|
||||
parser.add_argument("--dry-run", action="store_true", help="只预览不写库")
|
||||
args = parser.parse_args()
|
||||
raise SystemExit(asyncio.run(main(args.dry_run)))
|
||||
Reference in New Issue
Block a user