feat: add week 3 audio and timeline enhancements
This commit is contained in:
@@ -10,7 +10,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.core.deps import require_user
|
||||
from app.db.database import get_db
|
||||
from app.db.models import ChildProfile, Story, StoryUniverse, User
|
||||
from app.db.models import ChildProfile, MemoryItem, ReadingEvent, Story, StoryUniverse, User
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@@ -67,7 +67,7 @@ class TimelineEvent(BaseModel):
|
||||
"""Timeline event item."""
|
||||
|
||||
date: str
|
||||
type: Literal["story", "achievement", "milestone"]
|
||||
type: Literal["story", "achievement", "milestone", "reading_event", "memory"]
|
||||
title: str
|
||||
description: str | None = None
|
||||
image_url: str | None = None
|
||||
@@ -241,7 +241,10 @@ async def get_profile_timeline(
|
||||
|
||||
# 2. Stories
|
||||
stories_result = await db.execute(
|
||||
select(Story).where(Story.child_profile_id == profile_id)
|
||||
select(Story).where(
|
||||
Story.child_profile_id == profile_id,
|
||||
Story.user_id == user.id,
|
||||
)
|
||||
)
|
||||
for s in stories_result.scalars():
|
||||
events.append(TimelineEvent(
|
||||
@@ -252,7 +255,89 @@ async def get_profile_timeline(
|
||||
metadata={"story_id": s.id, "mode": s.mode}
|
||||
))
|
||||
|
||||
# 3. Achievements (from Universe)
|
||||
# 3. Reading events
|
||||
reading_result = await db.execute(
|
||||
select(ReadingEvent, Story)
|
||||
.outerjoin(Story, ReadingEvent.story_id == Story.id)
|
||||
.where(ReadingEvent.child_profile_id == profile_id)
|
||||
.order_by(ReadingEvent.created_at.desc())
|
||||
)
|
||||
reading_labels = {
|
||||
"started": "开始阅读",
|
||||
"completed": "读完故事",
|
||||
"replayed": "再次阅读",
|
||||
"skipped": "暂时跳过",
|
||||
}
|
||||
for reading_event, story in reading_result.all():
|
||||
story_title = story.title if story else "未关联故事"
|
||||
duration = (
|
||||
f"阅读 {reading_event.reading_time} 秒"
|
||||
if reading_event.reading_time
|
||||
else "记录了一次阅读行为"
|
||||
)
|
||||
events.append(
|
||||
TimelineEvent(
|
||||
date=reading_event.created_at.isoformat(),
|
||||
type="reading_event",
|
||||
title=reading_labels.get(reading_event.event_type, "阅读记录"),
|
||||
description=f"{story_title} · {duration}",
|
||||
image_url=story.image_url if story else None,
|
||||
metadata={
|
||||
"story_id": reading_event.story_id,
|
||||
"mode": story.mode if story else None,
|
||||
"event_type": reading_event.event_type,
|
||||
"reading_time": reading_event.reading_time,
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
# 4. Memory items
|
||||
memories_result = await db.execute(
|
||||
select(MemoryItem)
|
||||
.where(MemoryItem.child_profile_id == profile_id)
|
||||
.order_by(MemoryItem.created_at.desc())
|
||||
.limit(20)
|
||||
)
|
||||
memory_labels = {
|
||||
"recent_story": "近期故事记忆",
|
||||
"favorite_character": "喜欢的角色",
|
||||
"scary_element": "回避元素",
|
||||
"vocabulary_growth": "词汇积累",
|
||||
"emotional_highlight": "情感高光",
|
||||
"reading_preference": "阅读偏好",
|
||||
"milestone": "成长里程碑",
|
||||
"skill_mastered": "掌握的技能",
|
||||
}
|
||||
for memory in memories_result.scalars():
|
||||
value = memory.value or {}
|
||||
title = str(
|
||||
value.get("title")
|
||||
or value.get("name")
|
||||
or value.get("keyword")
|
||||
or value.get("description")
|
||||
or memory_labels.get(memory.type, memory.type)
|
||||
)
|
||||
events.append(
|
||||
TimelineEvent(
|
||||
date=memory.created_at.isoformat(),
|
||||
type="memory",
|
||||
title=f"记忆沉淀:{memory_labels.get(memory.type, memory.type)}",
|
||||
description=title,
|
||||
image_url=(
|
||||
value.get("image_url")
|
||||
if isinstance(value.get("image_url"), str)
|
||||
else None
|
||||
),
|
||||
metadata={
|
||||
"memory_id": memory.id,
|
||||
"memory_type": memory.type,
|
||||
"story_id": value.get("story_id") or value.get("source_story_id"),
|
||||
"mode": value.get("mode"),
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
# 5. Achievements (from Universe)
|
||||
universes_result = await db.execute(
|
||||
select(StoryUniverse).where(StoryUniverse.child_profile_id == profile_id)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user