This commit is contained in:
lz_db
2026-10-24 00:04:50 +08:00
parent 1d440b2916
commit 893dfed0ed
11 changed files with 388 additions and 85 deletions
+73 -1
View File
@@ -12,7 +12,8 @@ from fastapi import APIRouter, Depends, Query, Request
from pydantic import BaseModel, BaseModel as _BM, Field as _F, Field as _Field
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.response import ok
from app.core import errors
from app.core.response import ok, BizException
from app.database import get_db
from app.deps import AdminIdentity, require_roles
from app.redis_client import get_redis
@@ -620,6 +621,77 @@ class _VideoSeriesBind(BaseModel):
episode_no: int = _Field(ge=1)
# ---------- 批量操作(必须在 /series/{series_id} 路由之前注册,否则被参数路由抢先匹配)----------
class _SeriesRebuildResp(BaseModel):
total: int = 0
fixed: int = 0
@router.post("/series/rebuild-counts")
async def rebuild_series_counts(db: AsyncSession = Depends(get_db),
admin: AdminIdentity = Depends(require_super)):
"""重算所有系列的 total_episodes(按 status=2 的视频真实计数)"""
from app.models.video import Series, Video
from sqlalchemy import select, func
rows = (await db.execute(select(Series.id, Series.total_episodes))).all()
total = len(rows)
fixed = 0
for sid, old_cnt in rows:
new_cnt = (await db.execute(
select(func.count(Video.id)).where(Video.series_id == sid, Video.status == 2)
)).scalar_one()
if old_cnt != new_cnt:
s = await db.get(Series, sid)
s.total_episodes = new_cnt
fixed += 1
await db.commit()
return ok(_SeriesRebuildResp(total=total, fixed=fixed))
class _SeriesBatchUpdate(BaseModel):
series_ids: list[int] = _Field(min_length=1, max_length=200)
status: int | None = _Field(None, ge=0, le=1)
category_id: int | None = _Field(None, ge=0)
@router.put("/series/batch")
async def batch_update_series(req: _SeriesBatchUpdate, request: Request,
db: AsyncSession = Depends(get_db),
admin: AdminIdentity = Depends(require_super)):
"""批量编辑系列属性(当前支持 status / category_id)"""
from app.models.admin import AdminLog
from app.models.video import Series
from sqlalchemy import select
if req.status is None and req.category_id is None:
raise BizException(errors.PARAM_ERROR, "至少要传一个要修改的字段")
stmt = select(Series).where(Series.id.in_(req.series_ids))
rows = (await db.execute(stmt)).scalars().all()
affected = 0
for s in rows:
changed = False
if req.status is not None and s.status != req.status:
s.status = req.status
changed = True
if req.category_id is not None and s.category_id != req.category_id:
s.category_id = req.category_id
changed = True
if changed:
affected += 1
db.add(AdminLog(
admin_id=admin.admin_id, action="series_batch_update",
target=f"series:{','.join(str(i) for i in req.series_ids)}",
detail=f"status={req.status} category_id={req.category_id} affected={affected}",
ip=_ip(request),
))
await db.commit()
return ok({"affected": affected})
@router.post("/series")
async def create_series(req: _SeriesCreate, db: AsyncSession = Depends(get_db),
admin: AdminIdentity = Depends(require_super)):
Binary file not shown.
+1 -1
View File
@@ -28,7 +28,7 @@ from app.services import config_service, invite_service, membership_service, sen
logger = logging.getLogger(__name__)
REFRESH_TTL = 30 * 24 * 3600
REFRESH_TTL = settings.refresh_token_ttl # 与 .env 的 REFRESH_TOKEN_TTL 同步
DEACTIVATE_FREEZE_DAYS = 7