feat: header重排、共享配方、待审核、权限优化
Some checks failed
Test / unit-test (push) Successful in 5s
Test / build-check (push) Successful in 4s
PR Preview / teardown-preview (pull_request) Has been skipped
Test / e2e-test (push) Failing after 54s
PR Preview / test (pull_request) Successful in 5s
PR Preview / deploy-preview (pull_request) Successful in 15s

Header:
- 登录按钮固定右侧,flex布局自适应所有屏幕
- 登录后不显示版本号,用户名在右侧
- 商业认证用户显示🏢标识
- 手机端响应式适配

配方共享:
- 个人配方卡片加📤共享按钮
- 提交到公共库,非管理员需审核

管理配方:
- 待审核栏从recipes动态计算(不依赖不存在的API)
- 采纳用/adopt端点,拒绝=确认删除
- senior_editor可编辑精油和公共配方

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-09 08:24:28 +00:00
parent 3d95db6cae
commit 3a65cb7209
4 changed files with 133 additions and 51 deletions

View File

@@ -196,7 +196,7 @@
</template>
<script setup>
import { ref, computed, reactive, onMounted } from 'vue'
import { ref, computed, reactive, onMounted, watch } from 'vue'
import { useAuthStore } from '../stores/auth'
import { useOilsStore } from '../stores/oils'
import { useRecipesStore } from '../stores/recipes'
@@ -431,10 +431,8 @@ async function removeRecipe(recipe) {
async function approveRecipe(recipe) {
try {
await api('/api/recipes/' + recipe._id + '/approve', { method: 'POST' })
pendingRecipes.value = pendingRecipes.value.filter(r => r._id !== recipe._id)
pendingCount.value--
ui.showToast('已通过')
await api('/api/recipes/' + recipe._id + '/adopt', { method: 'POST' })
ui.showToast('已采纳')
await recipeStore.loadRecipes()
} catch {
ui.showToast('操作失败')
@@ -442,11 +440,11 @@ async function approveRecipe(recipe) {
}
async function rejectRecipe(recipe) {
const ok = await showConfirm(`确定删除「${recipe.name}」?`)
if (!ok) return
try {
await api('/api/recipes/' + recipe._id + '/reject', { method: 'POST' })
pendingRecipes.value = pendingRecipes.value.filter(r => r._id !== recipe._id)
pendingCount.value--
ui.showToast('已拒绝')
await recipeStore.deleteRecipe(recipe._id)
ui.showToast('已删除')
} catch {
ui.showToast('操作失败')
}
@@ -474,16 +472,13 @@ function onTagPickerSave(tags) {
showTagPicker.value = false
}
// Load pending if admin
if (auth.isAdmin) {
api('/api/recipes/pending').then(async res => {
if (res.ok) {
const data = await res.json()
pendingRecipes.value = data
pendingCount.value = data.length
}
}).catch(() => {})
}
watch(() => recipeStore.recipes, () => {
if (auth.isAdmin) {
const pending = recipeStore.recipes.filter(r => r._owner_id && r._owner_id !== auth.user.id)
pendingRecipes.value = pending
pendingCount.value = pending.length
}
}, { immediate: true })
</script>
<style scoped>