From f3e4329d1fda250fdada354f4884e0c4c2fa061d Mon Sep 17 00:00:00 2001 From: Hera Zhao Date: Fri, 10 Apr 2026 15:58:44 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=B4=A1=E7=8C=AE=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E5=92=8C=E5=85=B1=E4=BA=AB=E7=8A=B6=E6=80=81=E5=9F=BA=E4=BA=8E?= =?UTF-8?q?=E7=9C=9F=E5=AE=9E=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 后端返回 adopted_names 和 pending_names 列表 - 共享状态根据实际被采纳/待审核的配方名匹配 - 不再按公共库同名配方误判为已共享 - 共享后实时刷新统计 Co-Authored-By: Claude Opus 4.6 (1M context) --- backend/main.py | 30 ++++++++++++++++++---------- frontend/src/views/RecipeManager.vue | 17 +++++++++------- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/backend/main.py b/backend/main.py index 6dd3136..bac2082 100644 --- a/backend/main.py +++ b/backend/main.py @@ -1497,19 +1497,27 @@ def list_recipe_reviews(user=Depends(require_role("admin"))): @app.get("/api/me/contribution") def my_contribution(user=Depends(get_current_user)): if not user.get("id"): - return {"adopted_count": 0, "shared_count": 0} + return {"adopted_count": 0, "shared_count": 0, "adopted_names": [], "pending_names": []} conn = get_db() - # adopted_count: recipes adopted from this user (owner changed to admin) - adopted = conn.execute( - "SELECT COUNT(*) FROM audit_log WHERE action = 'adopt_recipe' AND detail LIKE ?", - (f'%"from_user": "{user.get("display_name") or user.get("username")}"%',) - ).fetchone()[0] - # pending: recipes still owned by user in public library (not yet adopted) - pending = conn.execute( - "SELECT COUNT(*) FROM recipes WHERE owner_id = ?", (user["id"],) - ).fetchone()[0] + display = user.get("display_name") or user.get("username") + # adopted: recipes adopted from this user + adopted_rows = conn.execute( + "SELECT target_name FROM audit_log WHERE action = 'adopt_recipe' AND detail LIKE ?", + (f'%"from_user": "{display}"%',) + ).fetchall() + adopted_names = [r["target_name"] for r in adopted_rows if r["target_name"]] + # pending: recipes still owned by user in public library + pending_rows = conn.execute( + "SELECT name FROM recipes WHERE owner_id = ?", (user["id"],) + ).fetchall() + pending_names = [r["name"] for r in pending_rows] conn.close() - return {"adopted_count": adopted, "shared_count": adopted + pending} + return { + "adopted_count": len(adopted_names), + "shared_count": len(adopted_names) + len(pending_names), + "adopted_names": adopted_names, + "pending_names": pending_names, + } # ── Notifications ────────────────────────────────────── diff --git a/frontend/src/views/RecipeManager.vue b/frontend/src/views/RecipeManager.vue index 328c859..f920396 100644 --- a/frontend/src/views/RecipeManager.vue +++ b/frontend/src/views/RecipeManager.vue @@ -1028,14 +1028,19 @@ async function saveAllParsed() { closeOverlay() } -const sharedCount = ref({ adopted: 0, total: 0 }) +const sharedCount = ref({ adopted: 0, total: 0, adoptedNames: [], pendingNames: [] }) async function loadContribution() { try { const res = await api('/api/me/contribution') if (res.ok) { const data = await res.json() - sharedCount.value = { adopted: data.adopted_count || 0, total: data.shared_count || 0 } + sharedCount.value = { + adopted: data.adopted_count || 0, + total: data.shared_count || 0, + adoptedNames: data.adopted_names || [], + pendingNames: data.pending_names || [], + } } } catch {} } @@ -1136,11 +1141,9 @@ function openRecipeDetail(recipe) { } function getDiaryShareStatus(d) { - // Check if a public recipe with same name exists, owned by current user or adopted by admin - const pub = recipeStore.recipes.find(r => r.name === d.name) - if (!pub) return null - if (pub._owner_id === auth.user?.id) return 'pending' - return 'shared' + if (sharedCount.value.adoptedNames.includes(d.name)) return 'shared' + if (sharedCount.value.pendingNames.includes(d.name)) return 'pending' + return null } async function shareDiaryToPublic(diary) {