2837500bc0
对齐云客员工聊天窗口朋友圈tab:帖子 create_time desc 分页 + wechat_account 头部(昵称/头像/别名);员工不存在不404(header全None 前端兜底)。头像提取抽共享 helper account_avatar 放 organization.py, accounts 列表与 moments 头部复用。 Co-Authored-By: Claude <noreply@anthropic.com>
86 lines
2.8 KiB
Python
86 lines
2.8 KiB
Python
"""GET /api/moments — 员工朋友圈帖子列表(create_time desc)+账号头部。全本地。
|
|
|
|
对齐云客员工聊天窗口「朋友圈」tab:顶部账号资料卡(昵称/头像/别名)+
|
|
帖子流(新→旧)。读镜像 ``moments_post`` 表(WeChat-only,所属员工由
|
|
``wechat_id`` 标识),头部信息查 ``wechat_account``。
|
|
|
|
员工微信号不存在时不 404——返回 ``header`` 全 ``None`` + 空 ``items``,
|
|
前端资料卡自行兜底(云客侧同一员工必定有账号行,本地镜像可能滞后)。
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from typing import Annotated
|
|
|
|
import sqlalchemy as sa
|
|
from fastapi import APIRouter, Depends, Query
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.api.deps import get_session
|
|
from app.api.routers.organization import account_avatar
|
|
from app.api.schemas import MomentsHeaderOut, MomentsListOut, MomentsPostOut
|
|
from app.db.models import MomentsPost, WechatAccount
|
|
|
|
router = APIRouter(prefix="/api", tags=["moments"])
|
|
|
|
SessionDep = Annotated[AsyncSession, Depends(get_session)]
|
|
PageParam = Annotated[int, Query(ge=1)]
|
|
PageSizeParam = Annotated[int, Query(ge=1, le=100)]
|
|
|
|
|
|
@router.get("/moments")
|
|
async def list_moments(
|
|
session: SessionDep,
|
|
wechat_id: Annotated[str, Query(min_length=1)],
|
|
page: PageParam = 1,
|
|
page_size: PageSizeParam = 20,
|
|
) -> MomentsListOut:
|
|
"""员工朋友圈帖子列表(``create_time`` desc,分页)+ 账号头部。
|
|
|
|
排序 ``nullslast(create_time desc)`` + ``id`` 稳定断尾(MySQL 下 compat
|
|
补丁剥掉 NULLS LAST,但 DESC 语义本就把 NULL 排后,等价——项目已有验证)。
|
|
"""
|
|
account = (
|
|
await session.execute(
|
|
sa.select(
|
|
WechatAccount.nick_name,
|
|
WechatAccount.alias,
|
|
WechatAccount.raw_json,
|
|
).where(WechatAccount.wx_id == wechat_id)
|
|
)
|
|
).first()
|
|
header = MomentsHeaderOut(
|
|
nickname=account.nick_name if account else None,
|
|
avatar=account_avatar(account.raw_json) if account else None,
|
|
alias=account.alias if account else None,
|
|
)
|
|
|
|
total = (
|
|
await session.execute(
|
|
sa.select(sa.func.count())
|
|
.select_from(MomentsPost)
|
|
.where(MomentsPost.wechat_id == wechat_id)
|
|
)
|
|
).scalar_one()
|
|
|
|
rows = (
|
|
await session.execute(
|
|
sa.select(MomentsPost)
|
|
.where(MomentsPost.wechat_id == wechat_id)
|
|
.order_by(
|
|
sa.nullslast(MomentsPost.create_time.desc()),
|
|
MomentsPost.id.asc(),
|
|
)
|
|
.offset((page - 1) * page_size)
|
|
.limit(page_size)
|
|
)
|
|
).scalars().all()
|
|
|
|
return MomentsListOut(
|
|
wechat_id=wechat_id,
|
|
header=header,
|
|
total=total,
|
|
page=page,
|
|
page_size=page_size,
|
|
items=[MomentsPostOut.model_validate(r) for r in rows],
|
|
)
|