feat: 新功能改进 #20

Merged
hera merged 57 commits from feat/next-improvements into main 2026-04-10 20:30:37 +00:00
2 changed files with 45 additions and 18 deletions
Showing only changes of commit 480e843316 - Show all commits

View File

@@ -799,9 +799,16 @@ def create_recipe(recipe: RecipeIn, user=Depends(get_current_user)):
c.execute("INSERT OR IGNORE INTO tags (name) VALUES (?)", (tag,))
c.execute("INSERT OR IGNORE INTO recipe_tags (recipe_id, tag_name) VALUES (?, ?)", (rid, tag))
log_audit(conn, user["id"], "create_recipe", "recipe", rid, recipe.name)
# Notify admin when non-admin/non-senior_editor creates a recipe (needs review)
if user["role"] not in ("admin", "senior_editor"):
who = user.get("display_name") or user["username"]
who = user.get("display_name") or user["username"]
if user["role"] == "senior_editor":
# Senior editor adds directly — just inform admin
conn.execute(
"INSERT INTO notifications (target_role, title, body) VALUES (?, ?, ?)",
("admin", "📋 新配方已添加",
f"{who} 将配方「{recipe.name}」添加到了公共配方库。\n[recipe_id:{rid}]")
)
elif user["role"] not in ("admin",):
# Other users need review
conn.execute(
"INSERT INTO notifications (target_role, title, body) VALUES (?, ?, ?)",
("admin", "📝 新配方待审核",

View File

@@ -1199,22 +1199,21 @@ function openRecipeDetail(recipe) {
if (idx >= 0) previewRecipeIndex.value = idx
}
function diaryMatchesPublic(d) {
const pub = recipeStore.recipes.find(r => r.name === d.name)
if (!pub) return false
const dIngs = (d.ingredients || []).filter(i => i.oil).sort((a, b) => a.oil.localeCompare(b.oil))
const pIngs = (pub.ingredients || []).filter(i => i.oil).sort((a, b) => a.oil.localeCompare(b.oil))
return dIngs.length === pIngs.length && dIngs.every((ing, i) => ing.oil === pIngs[i].oil && ing.drops === pIngs[i].drops)
}
function getDiaryShareStatus(d) {
// Check pending first (exact name match in public library owned by user)
// Check pending (owned by user in public library, not yet adopted)
if (sharedCount.value.pendingNames.includes(d.name)) return 'pending'
// Check adopted — but if diary content was modified, allow re-sharing
if (sharedCount.value.adoptedNames.includes(d.name)) {
// Compare with the public recipe to see if content changed
const pub = recipeStore.recipes.find(r => r.name === d.name)
if (pub) {
const dIngs = (d.ingredients || []).filter(i => i.oil).sort((a, b) => a.oil.localeCompare(b.oil))
const pIngs = (pub.ingredients || []).filter(i => i.oil).sort((a, b) => a.oil.localeCompare(b.oil))
const same = dIngs.length === pIngs.length && dIngs.every((ing, i) => ing.oil === pIngs[i].oil && ing.drops === pIngs[i].drops)
if (same) return 'shared'
}
// Content changed or public recipe not found — can re-share
return null
}
// Check if public library has same recipe with same content
if (diaryMatchesPublic(d)) return 'shared'
// Check adopted names from audit log
if (sharedCount.value.adoptedNames.includes(d.name) && diaryMatchesPublic(d)) return 'shared'
return null
}
@@ -1244,6 +1243,27 @@ async function recommendApprove(recipe) {
}
async function shareDiaryToPublic(diary) {
// Check for duplicates in public library
const dup = recipeStore.recipes.find(r => r.name === diary.name)
if (dup) {
const dIngs = (diary.ingredients || []).filter(i => i.oil).sort((a, b) => a.oil.localeCompare(b.oil))
const pIngs = (dup.ingredients || []).filter(i => i.oil).sort((a, b) => a.oil.localeCompare(b.oil))
const identical = dIngs.length === pIngs.length && dIngs.every((ing, i) => ing.oil === pIngs[i].oil && ing.drops === pIngs[i].drops)
if (identical) {
ui.showToast('公共配方库中已有一模一样的配方「' + diary.name + '」')
return
}
// Same name, different content
const action = await showConfirm(
`公共配方库中已有同名配方「${diary.name}」但内容不同,是否改名后共享?`,
{ okText: '改名', cancelText: '取消' }
)
if (!action) return
const newName = await showPrompt('请输入新名称:', diary.name)
if (!newName || !newName.trim()) return
diary = { ...diary, name: newName.trim() }
}
const ok = await showConfirm(`将「${diary.name}」共享到公共配方库?`)
if (!ok) return
try {
@@ -1257,7 +1277,7 @@ async function shareDiaryToPublic(diary) {
}),
})
if (res.ok) {
if (auth.isAdmin) {
if (auth.isAdmin || auth.canManage) {
ui.showToast('已共享到公共配方库')
} else {
ui.showToast('已提交,等待管理员审核')