feat: 修复 H5 底部导航覆盖 + 更新项目进度文档
## H5 底部导航修复 (Bug #10) - 精简 App.vue,移除重复 tabbar,仅保留全局样式 - uni-page 设置 height: calc(100% - 50px) + overflow-y: auto - 内容区域精确停在底部导航上方,独立滚动不再叠加 - 恢复 custom-tab-bar 组件 ## 项目进度文档 - PROGRESS.md 更新至 10 个 Bug 修复 - 新增 H5 底部导航修复记录 - 新增历史变更条目
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
from typing import Dict, Any, Optional, List
|
||||
from datetime import datetime, timedelta
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import select, func, and_
|
||||
from app.models.preference import MarketingEffect
|
||||
import hashlib
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class MarketingEffectService:
|
||||
def __init__(self, db: AsyncSession):
|
||||
self.db = db
|
||||
|
||||
async def track_event(
|
||||
self,
|
||||
user_id: str,
|
||||
content: str,
|
||||
product_id: Optional[str] = None,
|
||||
product_name: Optional[str] = None,
|
||||
channel: str = "copy",
|
||||
event_type: str = "copy",
|
||||
target_audience: str = "",
|
||||
metadata: Optional[Dict] = None,
|
||||
) -> Dict[str, Any]:
|
||||
content_hash = hashlib.sha256(content.encode()).hexdigest()
|
||||
|
||||
event = MarketingEffect(
|
||||
user_id=user_id,
|
||||
content_hash=content_hash,
|
||||
product_id=product_id,
|
||||
product_name=product_name,
|
||||
channel=channel,
|
||||
event_type=event_type,
|
||||
target_audience=target_audience,
|
||||
metadata=metadata or {},
|
||||
)
|
||||
self.db.add(event)
|
||||
await self.db.flush()
|
||||
|
||||
return {
|
||||
"id": str(event.id),
|
||||
"event_type": event_type,
|
||||
"content_hash": content_hash,
|
||||
}
|
||||
|
||||
async def get_effects(
|
||||
self, user_id: str, page: int = 1, size: int = 20
|
||||
) -> Dict[str, Any]:
|
||||
query = (
|
||||
select(MarketingEffect)
|
||||
.where(MarketingEffect.user_id == user_id)
|
||||
.order_by(MarketingEffect.created_at.desc())
|
||||
.offset((page - 1) * size)
|
||||
.limit(size)
|
||||
)
|
||||
count_query = select(func.count(MarketingEffect.id)).where(
|
||||
MarketingEffect.user_id == user_id
|
||||
)
|
||||
|
||||
total = await self.db.execute(count_query)
|
||||
result = await self.db.execute(query)
|
||||
events = result.scalars().all()
|
||||
|
||||
return {
|
||||
"items": [
|
||||
{
|
||||
"id": str(e.id),
|
||||
"product_name": e.product_name,
|
||||
"channel": e.channel,
|
||||
"event_type": e.event_type,
|
||||
"target_audience": e.target_audience,
|
||||
"created_at": e.created_at.isoformat() if e.created_at else None,
|
||||
}
|
||||
for e in events
|
||||
],
|
||||
"total": total.scalar() or 0,
|
||||
"page": page,
|
||||
"size": size,
|
||||
}
|
||||
|
||||
async def get_stats(self, user_id: str) -> Dict[str, Any]:
|
||||
today = datetime.utcnow().date()
|
||||
week_ago = today - timedelta(days=7)
|
||||
|
||||
total_query = select(func.count(MarketingEffect.id)).where(
|
||||
MarketingEffect.user_id == user_id
|
||||
)
|
||||
today_query = select(func.count(MarketingEffect.id)).where(
|
||||
and_(
|
||||
MarketingEffect.user_id == user_id,
|
||||
func.date(MarketingEffect.created_at) == today,
|
||||
)
|
||||
)
|
||||
week_query = select(func.count(MarketingEffect.id)).where(
|
||||
and_(
|
||||
MarketingEffect.user_id == user_id,
|
||||
func.date(MarketingEffect.created_at) >= week_ago,
|
||||
)
|
||||
)
|
||||
copy_query = select(func.count(MarketingEffect.id)).where(
|
||||
and_(
|
||||
MarketingEffect.user_id == user_id,
|
||||
MarketingEffect.event_type == "copy",
|
||||
)
|
||||
)
|
||||
send_query = select(func.count(MarketingEffect.id)).where(
|
||||
and_(
|
||||
MarketingEffect.user_id == user_id,
|
||||
MarketingEffect.event_type == "send",
|
||||
)
|
||||
)
|
||||
|
||||
totals = await self.db.execute(total_query)
|
||||
todays = await self.db.execute(today_query)
|
||||
weeks = await self.db.execute(week_query)
|
||||
copies = await self.db.execute(copy_query)
|
||||
sends = await self.db.execute(send_query)
|
||||
|
||||
return {
|
||||
"total_events": totals.scalar() or 0,
|
||||
"today": todays.scalar() or 0,
|
||||
"this_week": weeks.scalar() or 0,
|
||||
"copy_count": copies.scalar() or 0,
|
||||
"send_count": sends.scalar() or 0,
|
||||
}
|
||||
Reference in New Issue
Block a user