fix: 贡献统计和共享状态基于真实数据
Some checks failed
PR Preview / teardown-preview (pull_request) Has been skipped
Test / unit-test (push) Successful in 5s
Test / build-check (push) Successful in 4s
PR Preview / test (pull_request) Successful in 4s
PR Preview / deploy-preview (pull_request) Successful in 13s
Test / e2e-test (push) Failing after 56s
Some checks failed
PR Preview / teardown-preview (pull_request) Has been skipped
Test / unit-test (push) Successful in 5s
Test / build-check (push) Successful in 4s
PR Preview / test (pull_request) Successful in 4s
PR Preview / deploy-preview (pull_request) Successful in 13s
Test / e2e-test (push) Failing after 56s
- 后端返回 adopted_names 和 pending_names 列表 - 共享状态根据实际被采纳/待审核的配方名匹配 - 不再按公共库同名配方误判为已共享 - 共享后实时刷新统计 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1497,19 +1497,27 @@ def list_recipe_reviews(user=Depends(require_role("admin"))):
|
|||||||
@app.get("/api/me/contribution")
|
@app.get("/api/me/contribution")
|
||||||
def my_contribution(user=Depends(get_current_user)):
|
def my_contribution(user=Depends(get_current_user)):
|
||||||
if not user.get("id"):
|
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()
|
conn = get_db()
|
||||||
# adopted_count: recipes adopted from this user (owner changed to admin)
|
display = user.get("display_name") or user.get("username")
|
||||||
adopted = conn.execute(
|
# adopted: recipes adopted from this user
|
||||||
"SELECT COUNT(*) FROM audit_log WHERE action = 'adopt_recipe' AND detail LIKE ?",
|
adopted_rows = conn.execute(
|
||||||
(f'%"from_user": "{user.get("display_name") or user.get("username")}"%',)
|
"SELECT target_name FROM audit_log WHERE action = 'adopt_recipe' AND detail LIKE ?",
|
||||||
).fetchone()[0]
|
(f'%"from_user": "{display}"%',)
|
||||||
# pending: recipes still owned by user in public library (not yet adopted)
|
).fetchall()
|
||||||
pending = conn.execute(
|
adopted_names = [r["target_name"] for r in adopted_rows if r["target_name"]]
|
||||||
"SELECT COUNT(*) FROM recipes WHERE owner_id = ?", (user["id"],)
|
# pending: recipes still owned by user in public library
|
||||||
).fetchone()[0]
|
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()
|
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 ──────────────────────────────────────
|
# ── Notifications ──────────────────────────────────────
|
||||||
|
|||||||
@@ -1028,14 +1028,19 @@ async function saveAllParsed() {
|
|||||||
closeOverlay()
|
closeOverlay()
|
||||||
}
|
}
|
||||||
|
|
||||||
const sharedCount = ref({ adopted: 0, total: 0 })
|
const sharedCount = ref({ adopted: 0, total: 0, adoptedNames: [], pendingNames: [] })
|
||||||
|
|
||||||
async function loadContribution() {
|
async function loadContribution() {
|
||||||
try {
|
try {
|
||||||
const res = await api('/api/me/contribution')
|
const res = await api('/api/me/contribution')
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
const data = await res.json()
|
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 {}
|
} catch {}
|
||||||
}
|
}
|
||||||
@@ -1136,11 +1141,9 @@ function openRecipeDetail(recipe) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getDiaryShareStatus(d) {
|
function getDiaryShareStatus(d) {
|
||||||
// Check if a public recipe with same name exists, owned by current user or adopted by admin
|
if (sharedCount.value.adoptedNames.includes(d.name)) return 'shared'
|
||||||
const pub = recipeStore.recipes.find(r => r.name === d.name)
|
if (sharedCount.value.pendingNames.includes(d.name)) return 'pending'
|
||||||
if (!pub) return null
|
return null
|
||||||
if (pub._owner_id === auth.user?.id) return 'pending'
|
|
||||||
return 'shared'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function shareDiaryToPublic(diary) {
|
async function shareDiaryToPublic(diary) {
|
||||||
|
|||||||
Reference in New Issue
Block a user