Spaces:
Running
Running
Upload router_items.py
Browse files- router_items.py +67 -21
router_items.py
CHANGED
|
@@ -76,15 +76,42 @@ async def get_items(type: str = "tool", sort: str = "time", limit: int = 50): #
|
|
| 76 |
|
| 77 |
return {"status": "success", "data": filtered_items[:limit]}
|
| 78 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
@router.get("/api/creators")
|
| 80 |
async def get_creators(sort: str = "downloads", limit: int = 100):
|
| 81 |
"""
|
| 82 |
获取创作者列表
|
| 83 |
🚀 P1性能优化:预构建 author->items 索引,避免 N+1 查询
|
|
|
|
| 84 |
"""
|
| 85 |
users_db = db.load_data("users.json", default_data={})
|
| 86 |
items_db = db.load_data("items.json", default_data=[])
|
| 87 |
-
comments_db = db.load_data("comments.json", default_data={})
|
| 88 |
|
| 89 |
# 🚀 P1性能优化:预构建 author->items 索引,复杂度从 O(n*m) 降到 O(n+m)
|
| 90 |
author_items_index = {}
|
|
@@ -102,23 +129,15 @@ async def get_creators(sort: str = "downloads", limit: int = 100):
|
|
| 102 |
# 🚀 P1性能优化:直接从索引获取,而非遍历全表
|
| 103 |
u_items = author_items_index.get(account, [])
|
| 104 |
|
| 105 |
-
trend_tools = {m: 0 for m in months}
|
| 106 |
-
trend_apps = {m: 0 for m in months}
|
| 107 |
-
trend_recommends = {m: 0 for m in months}
|
| 108 |
tools_count = 0
|
| 109 |
apps_count = 0
|
| 110 |
|
| 111 |
for i in u_items:
|
| 112 |
itype = i.get("type", "")
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
elif itype == "app" or itype == "recommend_app":
|
| 118 |
-
if itype == "app": apps_count += 1
|
| 119 |
-
for m in months: trend_apps[m] += history.get(m, 0)
|
| 120 |
-
elif itype.startswith("recommend"):
|
| 121 |
-
for m in months: trend_recommends[m] += history.get(m, 0)
|
| 122 |
|
| 123 |
creators.append({
|
| 124 |
"account": account, "name": u.get("name", account), "avatar": u.get("avatarDataUrl", ""),
|
|
@@ -130,14 +149,6 @@ async def get_creators(sort: str = "downloads", limit: int = 100):
|
|
| 130 |
"daily_views": sum(i.get("daily_views", 0) for i in u_items),
|
| 131 |
"toolsCount": tools_count, "appsCount": apps_count, "followers": len(u.get("followers", [])), "created_at": u.get("created_at", 0),
|
| 132 |
"recent_tips": u.get("tip_history", {}).get(datetime.date.today().strftime("%Y-%m"), 0), # 🚀 新增:本月收益统计
|
| 133 |
-
"commentsData": comments_db.get(account, []),
|
| 134 |
-
"tip_board": u.get("tip_board", []), # 🎁 打赏榜数据
|
| 135 |
-
"trendData": {
|
| 136 |
-
"months": months,
|
| 137 |
-
"tools": [trend_tools[m] for m in months],
|
| 138 |
-
"apps": [trend_apps[m] for m in months],
|
| 139 |
-
"recommends": [trend_recommends[m] for m in months]
|
| 140 |
-
}
|
| 141 |
})
|
| 142 |
|
| 143 |
if sort == "likes": creators.sort(key=lambda x: x.get("likes", 0), reverse=True)
|
|
@@ -150,6 +161,41 @@ async def get_creators(sort: str = "downloads", limit: int = 100):
|
|
| 150 |
|
| 151 |
return {"status": "success", "data": creators[:limit]}
|
| 152 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 153 |
@router.post("/api/items")
|
| 154 |
async def create_item(item: ItemCreate):
|
| 155 |
item.price = int(item.price)
|
|
|
|
| 76 |
|
| 77 |
return {"status": "success", "data": filtered_items[:limit]}
|
| 78 |
|
| 79 |
+
def _build_creator_trend_data(account: str, u_items: list, months: list) -> dict:
|
| 80 |
+
"""
|
| 81 |
+
构建创作者趋势数据
|
| 82 |
+
提取为独立函数供列表接口和详情接口复用
|
| 83 |
+
"""
|
| 84 |
+
trend_tools = {m: 0 for m in months}
|
| 85 |
+
trend_apps = {m: 0 for m in months}
|
| 86 |
+
trend_recommends = {m: 0 for m in months}
|
| 87 |
+
|
| 88 |
+
for i in u_items:
|
| 89 |
+
itype = i.get("type", "")
|
| 90 |
+
history = i.get("use_history", {})
|
| 91 |
+
if itype == "tool" or itype == "recommend_tool":
|
| 92 |
+
for m in months: trend_tools[m] += history.get(m, 0)
|
| 93 |
+
elif itype == "app" or itype == "recommend_app":
|
| 94 |
+
for m in months: trend_apps[m] += history.get(m, 0)
|
| 95 |
+
elif itype.startswith("recommend"):
|
| 96 |
+
for m in months: trend_recommends[m] += history.get(m, 0)
|
| 97 |
+
|
| 98 |
+
return {
|
| 99 |
+
"months": months,
|
| 100 |
+
"tools": [trend_tools[m] for m in months],
|
| 101 |
+
"apps": [trend_apps[m] for m in months],
|
| 102 |
+
"recommends": [trend_recommends[m] for m in months]
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
|
| 106 |
@router.get("/api/creators")
|
| 107 |
async def get_creators(sort: str = "downloads", limit: int = 100):
|
| 108 |
"""
|
| 109 |
获取创作者列表
|
| 110 |
🚀 P1性能优化:预构建 author->items 索引,避免 N+1 查询
|
| 111 |
+
⚡ P2性能优化:移除大字段(trendData、commentsData、tip_board),移至详情接口按需加载
|
| 112 |
"""
|
| 113 |
users_db = db.load_data("users.json", default_data={})
|
| 114 |
items_db = db.load_data("items.json", default_data=[])
|
|
|
|
| 115 |
|
| 116 |
# 🚀 P1性能优化:预构建 author->items 索引,复杂度从 O(n*m) 降到 O(n+m)
|
| 117 |
author_items_index = {}
|
|
|
|
| 129 |
# 🚀 P1性能优化:直接从索引获取,而非遍历全表
|
| 130 |
u_items = author_items_index.get(account, [])
|
| 131 |
|
|
|
|
|
|
|
|
|
|
| 132 |
tools_count = 0
|
| 133 |
apps_count = 0
|
| 134 |
|
| 135 |
for i in u_items:
|
| 136 |
itype = i.get("type", "")
|
| 137 |
+
if itype == "tool":
|
| 138 |
+
tools_count += 1
|
| 139 |
+
elif itype == "app":
|
| 140 |
+
apps_count += 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 141 |
|
| 142 |
creators.append({
|
| 143 |
"account": account, "name": u.get("name", account), "avatar": u.get("avatarDataUrl", ""),
|
|
|
|
| 149 |
"daily_views": sum(i.get("daily_views", 0) for i in u_items),
|
| 150 |
"toolsCount": tools_count, "appsCount": apps_count, "followers": len(u.get("followers", [])), "created_at": u.get("created_at", 0),
|
| 151 |
"recent_tips": u.get("tip_history", {}).get(datetime.date.today().strftime("%Y-%m"), 0), # 🚀 新增:本月收益统计
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 152 |
})
|
| 153 |
|
| 154 |
if sort == "likes": creators.sort(key=lambda x: x.get("likes", 0), reverse=True)
|
|
|
|
| 161 |
|
| 162 |
return {"status": "success", "data": creators[:limit]}
|
| 163 |
|
| 164 |
+
|
| 165 |
+
@router.get("/api/creators/{account}/details")
|
| 166 |
+
async def get_creator_details(account: str):
|
| 167 |
+
"""
|
| 168 |
+
获取单个创作者的详细数据
|
| 169 |
+
供前端展开卡片时按需加载
|
| 170 |
+
包含:trendData、commentsData、tip_board
|
| 171 |
+
"""
|
| 172 |
+
users_db = db.load_data("users.json", default_data={})
|
| 173 |
+
items_db = db.load_data("items.json", default_data=[])
|
| 174 |
+
comments_db = db.load_data("comments.json", default_data={})
|
| 175 |
+
|
| 176 |
+
# 检查用户是否存在
|
| 177 |
+
if account not in users_db:
|
| 178 |
+
raise HTTPException(status_code=404, detail="创作者不存在")
|
| 179 |
+
|
| 180 |
+
u = users_db[account]
|
| 181 |
+
|
| 182 |
+
# 获取该用户的所有作品
|
| 183 |
+
u_items = [item for item in items_db if item.get("author") == account]
|
| 184 |
+
|
| 185 |
+
# 构建趋势数据
|
| 186 |
+
months = get_last_6_months()
|
| 187 |
+
trend_data = _build_creator_trend_data(account, u_items, months)
|
| 188 |
+
|
| 189 |
+
return {
|
| 190 |
+
"status": "success",
|
| 191 |
+
"data": {
|
| 192 |
+
"account": account,
|
| 193 |
+
"trendData": trend_data,
|
| 194 |
+
"commentsData": comments_db.get(account, []),
|
| 195 |
+
"tip_board": u.get("tip_board", [])
|
| 196 |
+
}
|
| 197 |
+
}
|
| 198 |
+
|
| 199 |
@router.post("/api/items")
|
| 200 |
async def create_item(item: ItemCreate):
|
| 201 |
item.price = int(item.price)
|