Merge pull request 'feat:优化演示' (#15) from feat/0.3.0 into main
my-v0-server / deploy (push) Successful in 49s
my-v0-server / deploy (push) Successful in 49s
Reviewed-on: #15
This commit was merged in pull request #15.
This commit is contained in:
+111
-2
@@ -1,14 +1,24 @@
|
||||
"""匿名接口,统一放在 /api/public 下,一眼能看出哪些不鉴权"""
|
||||
|
||||
from typing import Annotated, Any
|
||||
from typing import Annotated, Any, Literal
|
||||
|
||||
from fastapi import APIRouter, Query, Response
|
||||
from fastapi import APIRouter, Depends, Query, Request, Response
|
||||
from fastapi.responses import FileResponse
|
||||
|
||||
from app.api.files import MAX_OFFSET, MAX_PAGE_ROWS, _detail, _public, _service
|
||||
from app.api.screens import Service, thumbnail_url
|
||||
from app.common.response import ApiResponse, success_response
|
||||
from app.config import settings
|
||||
from app.core.exceptions import BizException
|
||||
from app.schemas.conversation import ConversationDetail, ConversationList
|
||||
from app.schemas.data_file import (
|
||||
AggregateRequest,
|
||||
AggregateResult,
|
||||
DataFileDetail,
|
||||
DataFileInfo,
|
||||
DataFileList,
|
||||
DataTableRows,
|
||||
)
|
||||
from app.schemas.saved_screen import (
|
||||
DemoScreen,
|
||||
DemoScreenList,
|
||||
@@ -56,6 +66,105 @@ async def list_demo_screens(
|
||||
)
|
||||
|
||||
|
||||
def demo_owner() -> int:
|
||||
"""演示账号的用户 ID;没配置时没有演示数据,按不存在处理"""
|
||||
owner_id = settings.demo_owner_id
|
||||
if owner_id is None:
|
||||
raise BizException(404, "没有演示数据")
|
||||
return owner_id
|
||||
|
||||
|
||||
DemoOwner = Annotated[int, Depends(demo_owner)]
|
||||
|
||||
|
||||
# 以下是演示账号的对话和数据文件,只读:形状与登录后的 /conversations、/files 一致,
|
||||
# 前端未登录时换个前缀就能复用;归属一律按演示账号校验,别人的会话和文件与不存在同样是 404
|
||||
@router.get("/demo/conversations")
|
||||
async def list_demo_conversations(
|
||||
request: Request,
|
||||
screen_id: Annotated[str, Query(min_length=1)],
|
||||
limit: Annotated[int, Query(ge=1, le=20)] = 1,
|
||||
) -> ApiResponse[ConversationList]:
|
||||
"""演示大屏下的会话,最近更新的在前;没配演示账号时为空"""
|
||||
owner_id = settings.demo_owner_id
|
||||
if owner_id is None:
|
||||
return success_response(ConversationList(conversations=[], total=0))
|
||||
store = request.app.state.conversation_store
|
||||
return success_response(
|
||||
ConversationList(
|
||||
conversations=await store.list_by_user(owner_id, limit, 0, screen_id),
|
||||
total=await store.count_by_user(owner_id, screen_id),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@router.get("/demo/conversations/{conversation_id}")
|
||||
async def get_demo_conversation(
|
||||
conversation_id: str, request: Request, owner_id: DemoOwner
|
||||
) -> ApiResponse[ConversationDetail]:
|
||||
store = request.app.state.conversation_store
|
||||
if not await store.exists(conversation_id, owner_id):
|
||||
raise BizException(404, "会话不存在或已过期")
|
||||
turns = await store.load_turns(conversation_id, None)
|
||||
return success_response(
|
||||
ConversationDetail(conversation_id=conversation_id, turns=turns)
|
||||
)
|
||||
|
||||
|
||||
@router.get("/demo/files")
|
||||
async def list_demo_files(
|
||||
request: Request,
|
||||
conversation_id: Annotated[str, Query(min_length=1)],
|
||||
owner_id: DemoOwner,
|
||||
) -> ApiResponse[DataFileList]:
|
||||
# 不带上传任务:那是演示账号自己正在进行的,访客不该看到
|
||||
records = await _service(request).list_files(owner_id, conversation_id)
|
||||
return success_response(
|
||||
DataFileList(
|
||||
files=[DataFileInfo.model_validate(_public(record)) for record in records]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@router.get("/demo/files/{file_id}")
|
||||
async def get_demo_file(
|
||||
file_id: str, request: Request, owner_id: DemoOwner
|
||||
) -> ApiResponse[DataFileDetail]:
|
||||
return success_response(_detail(await _service(request).get_file(owner_id, file_id)))
|
||||
|
||||
|
||||
@router.get("/demo/files/{file_id}/tables/{table}/rows")
|
||||
async def get_demo_table_rows(
|
||||
file_id: str,
|
||||
table: str,
|
||||
request: Request,
|
||||
owner_id: DemoOwner,
|
||||
offset: Annotated[int, Query(ge=0, le=MAX_OFFSET)] = 0,
|
||||
limit: Annotated[int, Query(ge=1, le=MAX_PAGE_ROWS)] = 100,
|
||||
sort_by: Annotated[str | None, Query(min_length=1)] = None,
|
||||
order: Annotated[Literal["asc", "desc"], Query()] = "asc",
|
||||
) -> ApiResponse[DataTableRows]:
|
||||
return success_response(
|
||||
await _service(request).get_rows(
|
||||
owner_id, file_id, table, offset, limit, sort_by, order == "desc"
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@router.post("/demo/files/{file_id}/tables/{table}/aggregate")
|
||||
async def aggregate_demo_table(
|
||||
file_id: str,
|
||||
table: str,
|
||||
body: AggregateRequest,
|
||||
request: Request,
|
||||
owner_id: DemoOwner,
|
||||
) -> ApiResponse[AggregateResult]:
|
||||
"""POST 但只读:汇总结果算好就返回,不改任何数据"""
|
||||
return success_response(
|
||||
await _service(request).aggregate(owner_id, file_id, table, body)
|
||||
)
|
||||
|
||||
|
||||
@router.get("/screens/{share_id}")
|
||||
async def get_public_screen(
|
||||
share_id: str, service: Service
|
||||
|
||||
Reference in New Issue
Block a user