|
|
@@ -275,6 +275,75 @@ class EnergyStoneService:
|
|
|
logger.warning("获取能量石数量失败: user=%s error=%s", user_id, exc)
|
|
|
return {"mission_count": 0, "conversation_count": 0}
|
|
|
|
|
|
+ async def get_active_stones(self, user_id: str) -> List[Dict[str, Any]]:
|
|
|
+ """获取用户未过期的能量石(用于页面恢复)"""
|
|
|
+ if not user_id:
|
|
|
+ return []
|
|
|
+
|
|
|
+ try:
|
|
|
+ async with self.db.get_session() as session:
|
|
|
+ now = datetime.utcnow()
|
|
|
+ active_stones: List[Dict[str, Any]] = []
|
|
|
+
|
|
|
+ # 查询未过期的任务能量石
|
|
|
+ # 条件:clicked_at IS NULL 且 appear_at + ttl_seconds > now
|
|
|
+ mission_result = await session.execute(
|
|
|
+ select(MissionEnergyStone).where(
|
|
|
+ MissionEnergyStone.user_id == user_id,
|
|
|
+ MissionEnergyStone.clicked_at.is_(None),
|
|
|
+ )
|
|
|
+ )
|
|
|
+ for stone in mission_result.scalars().all():
|
|
|
+ appear_at = stone.appear_at or stone.created_at
|
|
|
+ if appear_at:
|
|
|
+ expire_at = appear_at.timestamp() + self.ttl_seconds
|
|
|
+ if expire_at > now.timestamp():
|
|
|
+ # 计算剩余 TTL(秒)
|
|
|
+ remaining_ttl = int(expire_at - now.timestamp())
|
|
|
+ payload = self._to_spawn_payload(
|
|
|
+ stone=stone,
|
|
|
+ stone_type="mission",
|
|
|
+ extra={
|
|
|
+ "appear_reason": stone.appear_reason,
|
|
|
+ "mission_type": stone.mission_type,
|
|
|
+ },
|
|
|
+ )
|
|
|
+ # 更新 TTL 为剩余时间
|
|
|
+ payload["ttl_seconds"] = remaining_ttl
|
|
|
+ active_stones.append(payload)
|
|
|
+
|
|
|
+ # 查询未过期的对话能量石
|
|
|
+ conversation_result = await session.execute(
|
|
|
+ select(ConversationEnergyStone).where(
|
|
|
+ ConversationEnergyStone.user_id == user_id,
|
|
|
+ ConversationEnergyStone.clicked_at.is_(None),
|
|
|
+ )
|
|
|
+ )
|
|
|
+ for stone in conversation_result.scalars().all():
|
|
|
+ appear_at = stone.appear_at or stone.created_at
|
|
|
+ if appear_at:
|
|
|
+ expire_at = appear_at.timestamp() + self.ttl_seconds
|
|
|
+ if expire_at > now.timestamp():
|
|
|
+ # 计算剩余 TTL(秒)
|
|
|
+ remaining_ttl = int(expire_at - now.timestamp())
|
|
|
+ payload = self._to_spawn_payload(
|
|
|
+ stone=stone,
|
|
|
+ stone_type="conversation",
|
|
|
+ extra={
|
|
|
+ "threshold_index": stone.threshold_index,
|
|
|
+ "total_duration_ms": stone.total_duration_ms,
|
|
|
+ "duration_increment_ms": stone.duration_increment_ms,
|
|
|
+ },
|
|
|
+ )
|
|
|
+ # 更新 TTL 为剩余时间
|
|
|
+ payload["ttl_seconds"] = remaining_ttl
|
|
|
+ active_stones.append(payload)
|
|
|
+
|
|
|
+ return active_stones
|
|
|
+ except Exception as exc:
|
|
|
+ logger.warning("获取未过期能量石失败: user=%s error=%s", user_id, exc)
|
|
|
+ return []
|
|
|
+
|
|
|
async def _get_mission_type_config(
|
|
|
self, session, mission_type_key: str
|
|
|
) -> Optional[MissionType]:
|