feat(douyu): 精英宝典导入支持按多行账户名筛选
对齐 Cookie 自定义 CK 的粘贴导入方式,按账户名精确匹配并保持粘贴顺序。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -17,7 +17,7 @@ from fastapi import (
|
||||
WebSocketDisconnect,
|
||||
)
|
||||
from loguru import logger
|
||||
from sqlalchemy import func, or_, select
|
||||
from sqlalchemy import case, func, or_, select
|
||||
from sqlalchemy.orm import Session, joinedload
|
||||
|
||||
from core.douyu import (
|
||||
@@ -243,6 +243,67 @@ def _require_batch_owner(db: Session, current: User, batch_id: str) -> None:
|
||||
raise HTTPException(status_code=403, detail="无权操作该斗鱼任务批次")
|
||||
|
||||
|
||||
def _parse_account_names(raw_names: str) -> list[str]:
|
||||
"""解析前端粘贴的 Excel 账号名,每行一个并去重。"""
|
||||
names: list[str] = []
|
||||
seen: set[str] = set()
|
||||
for value in (
|
||||
(raw_names or "").replace("\r\n", "\n").replace("\r", "\n").split("\n")
|
||||
):
|
||||
name = value.strip()
|
||||
if name and name not in seen:
|
||||
names.append(name)
|
||||
seen.add(name)
|
||||
return names
|
||||
|
||||
|
||||
def _apply_task_account_filters(
|
||||
query,
|
||||
*,
|
||||
search: str = "",
|
||||
tag: str = "",
|
||||
account_names: str = "",
|
||||
ids: str = "",
|
||||
):
|
||||
"""按工作台导入弹窗的搜索、标签、多行账号名筛选任务账号。"""
|
||||
id_list = [int(item) for item in ids.split(",") if item.strip().isdigit()]
|
||||
if id_list:
|
||||
query = query.filter(Account.id.in_(id_list))
|
||||
tag_text = (tag or "").strip()
|
||||
if tag_text:
|
||||
query = query.filter(Account.tag == tag_text)
|
||||
selected_names = _parse_account_names(account_names)
|
||||
if selected_names:
|
||||
query = query.filter(Account.username.in_(selected_names))
|
||||
search_text = (search or "").strip()
|
||||
if search_text:
|
||||
pattern = f"%{search_text}%"
|
||||
query = query.filter(
|
||||
or_(
|
||||
Account.username.ilike(pattern),
|
||||
Account.uid.ilike(pattern),
|
||||
Account.nickname.ilike(pattern),
|
||||
Account.tag.ilike(pattern),
|
||||
Account.game_name.ilike(pattern),
|
||||
Account.esports_game_name.ilike(pattern),
|
||||
Account.xpd_game_name.ilike(pattern),
|
||||
)
|
||||
)
|
||||
return query, selected_names
|
||||
|
||||
|
||||
def _order_task_accounts(query, selected_names: list[str]):
|
||||
"""自定义账号名按粘贴顺序排序,未指定时保持最新账号优先。"""
|
||||
if selected_names:
|
||||
input_order = case(
|
||||
{name: index for index, name in enumerate(selected_names)},
|
||||
value=Account.username,
|
||||
else_=len(selected_names),
|
||||
)
|
||||
return query.order_by(input_order, Account.id.desc())
|
||||
return query.order_by(Account.id.desc())
|
||||
|
||||
|
||||
def _account_out(account: Account) -> DouyuTaskAccountOut:
|
||||
return DouyuTaskAccountOut(
|
||||
id=account.id,
|
||||
@@ -324,6 +385,7 @@ def list_task_accounts(
|
||||
search: str = Query(""),
|
||||
tag: str = Query(""),
|
||||
ids: str = Query(""),
|
||||
account_names: str = Query(""),
|
||||
page: int | None = Query(None, ge=1),
|
||||
page_size: int = Query(50, ge=1, le=200),
|
||||
db: Session = Depends(get_db),
|
||||
@@ -331,33 +393,20 @@ def list_task_accounts(
|
||||
):
|
||||
"""查看可执行斗鱼任务的账号(必须有成功 Cookie)。
|
||||
|
||||
tag 按账号标签精确筛选;ids 为逗号分隔的账号 ID,用于工作台按已导入账号过滤;为空时返回全部。
|
||||
tag 按账号标签精确筛选;ids 为逗号分隔的账号 ID,用于工作台按已导入账号过滤;
|
||||
account_names 为多行斗鱼账户名(每行一个),按粘贴顺序精确匹配;为空时返回全部。
|
||||
"""
|
||||
query = _visible_task_accounts_query(db, current)
|
||||
id_list = [int(x) for x in ids.split(",") if x.strip().isdigit()]
|
||||
if id_list:
|
||||
query = query.filter(Account.id.in_(id_list))
|
||||
tag_text = (tag or "").strip()
|
||||
if tag_text:
|
||||
query = query.filter(Account.tag == tag_text)
|
||||
search_text = (search or "").strip()
|
||||
if search_text:
|
||||
pattern = f"%{search_text}%"
|
||||
query = query.filter(
|
||||
or_(
|
||||
Account.username.ilike(pattern),
|
||||
Account.uid.ilike(pattern),
|
||||
Account.nickname.ilike(pattern),
|
||||
Account.tag.ilike(pattern),
|
||||
Account.game_name.ilike(pattern),
|
||||
Account.esports_game_name.ilike(pattern),
|
||||
Account.xpd_game_name.ilike(pattern),
|
||||
)
|
||||
)
|
||||
query, selected_names = _apply_task_account_filters(
|
||||
_visible_task_accounts_query(db, current),
|
||||
search=search,
|
||||
tag=tag,
|
||||
account_names=account_names,
|
||||
ids=ids,
|
||||
)
|
||||
total = None
|
||||
if page is not None:
|
||||
total = query.order_by(None).count()
|
||||
query = query.order_by(Account.id.desc())
|
||||
query = _order_task_accounts(query, selected_names)
|
||||
if page is not None:
|
||||
query = query.offset((page - 1) * page_size).limit(page_size)
|
||||
else:
|
||||
@@ -377,34 +426,23 @@ def list_task_accounts(
|
||||
def list_task_account_ids(
|
||||
search: str = Query(""),
|
||||
tag: str = Query(""),
|
||||
account_names: str = Query(""),
|
||||
db: Session = Depends(get_db),
|
||||
current: User = Depends(get_current_user),
|
||||
):
|
||||
"""返回当前用户可导入工作台的全部账号 ID,不受列表分页限制。"""
|
||||
query = _visible_task_accounts_query(db, current)
|
||||
tag_text = (tag or "").strip()
|
||||
if tag_text:
|
||||
query = query.filter(Account.tag == tag_text)
|
||||
search_text = (search or "").strip()
|
||||
if search_text:
|
||||
pattern = f"%{search_text}%"
|
||||
query = query.filter(
|
||||
or_(
|
||||
Account.username.ilike(pattern),
|
||||
Account.uid.ilike(pattern),
|
||||
Account.nickname.ilike(pattern),
|
||||
Account.tag.ilike(pattern),
|
||||
Account.game_name.ilike(pattern),
|
||||
Account.esports_game_name.ilike(pattern),
|
||||
Account.xpd_game_name.ilike(pattern),
|
||||
)
|
||||
)
|
||||
query, selected_names = _apply_task_account_filters(
|
||||
_visible_task_accounts_query(db, current),
|
||||
search=search,
|
||||
tag=tag,
|
||||
account_names=account_names,
|
||||
)
|
||||
account_ids = [
|
||||
account_id
|
||||
for (account_id,) in query.enable_eagerloads(False)
|
||||
.order_by(Account.id.desc())
|
||||
.with_entities(Account.id)
|
||||
.all()
|
||||
for (account_id,) in _order_task_accounts(
|
||||
query.enable_eagerloads(False).with_entities(Account.id),
|
||||
selected_names,
|
||||
).all()
|
||||
]
|
||||
return {"account_ids": account_ids, "total": len(account_ids)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user