feat: 调整新建/重建账号命名格式为 {上游网站名}-{上游分组名/ID}-{KeyID}

This commit is contained in:
liumangmang
2026-07-01 21:11:37 +08:00
parent ebf7def177
commit 94d9550f77
4 changed files with 130 additions and 22 deletions
+62 -19
View File
@@ -49,6 +49,7 @@ from app.services.website_sync import (
reconcile_upstream_keys_full,
sync_account_priorities_for_upstream,
latest_rate_map,
build_imported_account_name,
)
from app.utils.auth import get_current_user
from app.utils.number import fixed_decimal_number
@@ -630,15 +631,11 @@ def import_upstream_keys_as_accounts(
)
for kid in missing_ids
]
# 查出来源上游的 Base URL
upstream_base_url = ""
if body.upstream_key_ids:
first_row = rows[0] if rows else None
if first_row:
from app.models.upstream import Upstream as _Up
_u = db.query(_Up).filter(_Up.id == first_row.upstream_id).first()
if _u:
upstream_base_url = _u.base_url
# 预载上游以方便获取名称和 base_url
from app.models.upstream import Upstream as _Up
upstream_ids = {row.upstream_id for row in rows}
upstreams_db = db.query(_Up).filter(_Up.id.in_(upstream_ids)).all()
upstreams_map = {u.id: u for u in upstreams_db}
# 按倍率自动分配优先级
rate_priority_map: dict[tuple[str, int, str], int] = {}
@@ -665,6 +662,21 @@ def import_upstream_keys_as_accounts(
except Exception as e:
logger.warning("failed to fetch groups for website %s at import: %s", wid, e)
# 预先拉取远端账号列表以避免循环请求,并能拿到已存在账号 of 远端名称
remote_accounts_map: dict[str, dict[str, Any]] = {}
remote_accounts_list = None
has_list_accounts = hasattr(c, "list_accounts")
if has_list_accounts:
try:
remote_accounts_list = c.list_accounts(endpoint=website.accounts_endpoint)
if remote_accounts_list is not None:
for acc in remote_accounts_list:
aid = c.extract_id(acc)
if aid:
remote_accounts_map[aid] = acc
except Exception as e:
logger.warning("failed to fetch remote accounts at import: %s", e)
for row in rows:
# 跳过远端已不存在或导入失败的 Key(对账后标记为 orphaned / import_failed
if row.status in ("orphaned", "failed", "import_failed"):
@@ -687,10 +699,34 @@ def import_upstream_keys_as_accounts(
else:
platform = body.default_platform
upstream = upstreams_map.get(row.upstream_id)
upstream_name = upstream.name if upstream else "Unknown"
upstream_base_url = upstream.base_url if upstream else ""
# 构建新格式的预期账号名称
expected_new_name = build_imported_account_name(
upstream_name=upstream_name,
group_name=row.group_name,
group_id=row.group_id,
key_id=row.id,
)
# 幂等校验:已导入过则检查远端账号是否仍存在
if row.imported_website_id == wid and row.imported_account_id:
old_account_id = row.imported_account_id
exists = c.account_exists(row.imported_account_id)
if has_list_accounts:
if remote_accounts_list is None:
# 接口获取失败,保守判定为校验失败
exists = None
else:
exists = old_account_id in remote_accounts_map
else:
# 如果 client 没有 list_accounts,则 fallback 回原先的 account_exists 检测以兼容旧 Mock 测试
try:
exists = c.account_exists(row.imported_account_id)
except Exception:
exists = None
if exists is True:
# 顺手回填 imported_target_group_id(老数据升级后可通过重导自动补齐)
new_tgid = body.target_group_map.get(row.group_id) or None
@@ -700,13 +736,17 @@ def import_upstream_keys_as_accounts(
row.imported_target_group_id = new_tgid
row.imported_target_group_name = tg_name
db.commit()
remote_name = ""
if old_account_id in remote_accounts_map:
remote_name = remote_accounts_map[old_account_id].get("name") or ""
items.append(ImportAccountItem(
upstream_key_id=row.id,
source_group_id=row.group_id,
source_group_name=row.group_name,
target_group_id=body.target_group_map.get(row.group_id),
account_id=old_account_id,
account_name=f"{body.account_name_prefix}-{row.group_name or row.group_id}-{row.id}",
account_name=remote_name or expected_new_name,
platform=platform,
upstream_base_url=upstream_base_url,
status="exists",
@@ -750,7 +790,7 @@ def import_upstream_keys_as_accounts(
numeric_target = _numeric_group_id(target_group_id)
if numeric_target is not None:
group_ids.append(numeric_target)
account_name = f"{body.account_name_prefix}-{row.group_name or row.group_id}-{row.id}"
account_name = expected_new_name
account_body = {
"name": account_name,
"platform": platform,
@@ -921,7 +961,8 @@ def organize_website_groups(
if not uid or not gid:
continue
upstream_name = db.query(Upstream.name).filter(Upstream.id == uid).scalar() or f"#{uid}"
_u = db.query(Upstream).filter(Upstream.id == uid).first()
upstream_name = _u.name if _u else f"#{uid}"
# 来源名称优先取 src.group_name,再 fallback 快照,再 fallback ID
source_group_name = src.get("group_name") or ""
@@ -966,11 +1007,8 @@ def organize_website_groups(
)
continue
# 查询来源上游的 Base URL 用于账号创建
upstream_base_url = ""
_u = db.query(Upstream).filter(Upstream.id == uid).first()
if _u:
upstream_base_url = _u.base_url
# 获取来源上游的 Base URL 用于账号创建
upstream_base_url = _u.base_url if _u else ""
for row in keys:
# 跳过状态为 failed 的 Key
@@ -1115,7 +1153,12 @@ def organize_website_groups(
else:
group_ids.append(target_group_id)
account_name = f"SmartUp-{row.group_name or row.group_id}-{row.id}"
account_name = build_imported_account_name(
upstream_name=upstream_name,
group_name=row.group_name,
group_id=row.group_id,
key_id=row.id,
)
priority_val = rate_priority_map.get((str(target_group_id), row.upstream_id, row.group_id), 1)
account_body = {
"name": account_name,