UI: 管理配方界面按角色调整
Some checks failed
PR Preview / teardown-preview (pull_request) Has been skipped
Test / unit-test (push) Successful in 4s
Test / build-check (push) Successful in 4s
PR Preview / test (pull_request) Successful in 5s
PR Preview / deploy-preview (pull_request) Successful in 12s
Test / e2e-test (push) Has been cancelled
Some checks failed
PR Preview / teardown-preview (pull_request) Has been skipped
Test / unit-test (push) Successful in 4s
Test / build-check (push) Successful in 4s
PR Preview / test (pull_request) Successful in 5s
PR Preview / deploy-preview (pull_request) Successful in 12s
Test / e2e-test (push) Has been cancelled
- 管理员: 搜索 + 导出Excel | 添加 + 全选 + 标签 + 批量 - 编辑者: 搜索 | 添加 + 全选 + 标签 + 批量(无导出) - 普通用户: 全选 + 标签(无添加无导出) - 批量操作改为下拉选择,内联在工具栏 - 我的配方和公共配方库默认折叠 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -14,35 +14,39 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Search & Actions Bar (editor+) -->
|
<!-- Row 1: Search (editor+) + Export (admin only) -->
|
||||||
<template v-if="auth.canEdit">
|
<template v-if="auth.canEdit">
|
||||||
<div class="manage-toolbar">
|
<div class="manage-toolbar">
|
||||||
<div class="search-box">
|
<div class="search-box">
|
||||||
<input
|
<input class="search-input" v-model="manageSearch" placeholder="搜索配方..." />
|
||||||
class="search-input"
|
|
||||||
v-model="manageSearch"
|
|
||||||
placeholder="搜索配方..."
|
|
||||||
/>
|
|
||||||
<button v-if="manageSearch" class="search-clear-btn" @click="manageSearch = ''">✕</button>
|
<button v-if="manageSearch" class="search-clear-btn" @click="manageSearch = ''">✕</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="toolbar-actions">
|
<button v-if="auth.isAdmin" class="btn-outline btn-sm" @click="exportExcel">📥 导出Excel</button>
|
||||||
<button class="btn-outline btn-sm" @click="exportExcel">📥 导出Excel</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- Tag Filter & Select All (visible to all) -->
|
<!-- Row 2: Add + Select + Tags + Batch -->
|
||||||
<div class="tag-filter-bar">
|
<div class="tag-filter-bar">
|
||||||
|
<button v-if="auth.canEdit" class="btn-outline btn-sm" @click="showAddOverlay = true">+ 添加配方</button>
|
||||||
<button
|
<button
|
||||||
class="btn-sm"
|
class="btn-sm"
|
||||||
:class="selectedDiaryIds.size > 0 ? 'btn-select-active' : 'btn-outline'"
|
:class="selectedDiaryIds.size > 0 ? 'btn-select-active' : 'btn-outline'"
|
||||||
@click="toggleSelectAllDiary"
|
@click="toggleSelectAllDiary"
|
||||||
>全选</button>
|
>全选</button>
|
||||||
<button class="btn-outline btn-sm" @click="showAddOverlay = true">+ 添加配方</button>
|
|
||||||
<button class="tag-toggle-btn" @click="showTagFilter = !showTagFilter">
|
<button class="tag-toggle-btn" @click="showTagFilter = !showTagFilter">
|
||||||
🏷️ 标签筛选 {{ showTagFilter ? '▾' : '▸' }}
|
🏷️ 标签筛选 {{ showTagFilter ? '▾' : '▸' }}
|
||||||
</button>
|
</button>
|
||||||
|
<!-- Batch (inline when selected) -->
|
||||||
|
<template v-if="selectedIds.size > 0 || selectedDiaryIds.size > 0">
|
||||||
|
<span class="batch-count">{{ selectedIds.size + selectedDiaryIds.size }}项</span>
|
||||||
|
<select v-model="batchAction" class="batch-select" @change="onBatchSelect">
|
||||||
|
<option value="">批量操作...</option>
|
||||||
|
<option value="tag">打标签</option>
|
||||||
|
<option v-if="selectedDiaryIds.size > 0" value="share_public">分享到公共库</option>
|
||||||
|
<option value="delete">删除</option>
|
||||||
|
</select>
|
||||||
|
<button class="btn-sm btn-outline" @click="clearSelection">取消</button>
|
||||||
|
</template>
|
||||||
<div v-if="showTagFilter" class="tag-list">
|
<div v-if="showTagFilter" class="tag-list">
|
||||||
<span
|
<span
|
||||||
v-for="tag in recipeStore.allTags"
|
v-for="tag in recipeStore.allTags"
|
||||||
@@ -54,16 +58,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Batch Operations -->
|
|
||||||
<div v-if="selectedIds.size > 0 || selectedDiaryIds.size > 0" class="batch-bar">
|
|
||||||
<span>已选 {{ selectedIds.size + selectedDiaryIds.size }} 项</span>
|
|
||||||
<button class="btn-sm btn-outline" @click="executeBatchAction('tag')">🏷 打标签</button>
|
|
||||||
<button class="btn-sm btn-outline" @click="executeBatchAction('share_public')" v-if="selectedDiaryIds.size > 0">📤 分享到公共库</button>
|
|
||||||
<button class="btn-sm btn-outline" @click="executeBatchAction('export')">📷 导出卡片</button>
|
|
||||||
<button class="btn-sm btn-danger-outline" @click="executeBatchAction('delete')">🗑 删除</button>
|
|
||||||
<button class="btn-sm btn-outline" @click="clearSelection">取消</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- My Recipes Section (from diary) -->
|
<!-- My Recipes Section (from diary) -->
|
||||||
<div class="recipe-section">
|
<div class="recipe-section">
|
||||||
<h3 class="section-title clickable" @click="showMyRecipes = !showMyRecipes">
|
<h3 class="section-title clickable" @click="showMyRecipes = !showMyRecipes">
|
||||||
@@ -452,6 +446,14 @@ function toggleDiarySelect(id) {
|
|||||||
function clearSelection() {
|
function clearSelection() {
|
||||||
selectedIds.clear()
|
selectedIds.clear()
|
||||||
selectedDiaryIds.clear()
|
selectedDiaryIds.clear()
|
||||||
|
batchAction.value = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
function onBatchSelect() {
|
||||||
|
if (batchAction.value) {
|
||||||
|
executeBatchAction(batchAction.value)
|
||||||
|
batchAction.value = ''
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleSelectAllDiary() {
|
function toggleSelectAllDiary() {
|
||||||
@@ -797,7 +799,8 @@ async function saveAllParsed() {
|
|||||||
|
|
||||||
const sharedCount = ref({ adopted: 0, total: 0 })
|
const sharedCount = ref({ adopted: 0, total: 0 })
|
||||||
const previewRecipeIndex = ref(null)
|
const previewRecipeIndex = ref(null)
|
||||||
const showMyRecipes = ref(true)
|
const batchAction = ref('')
|
||||||
|
const showMyRecipes = ref(false)
|
||||||
const showPublicRecipes = ref(false)
|
const showPublicRecipes = ref(false)
|
||||||
const showReviewHistory = ref(false)
|
const showReviewHistory = ref(false)
|
||||||
const reviewHistory = ref([])
|
const reviewHistory = ref([])
|
||||||
@@ -1399,6 +1402,8 @@ watch(() => recipeStore.recipes, () => {
|
|||||||
.drops-sm:focus { border-color: #7ec6a4; }
|
.drops-sm:focus { border-color: #7ec6a4; }
|
||||||
.select-sm { padding: 4px 6px; border: 1.5px solid #d4cfc7; border-radius: 6px; font-size: 12px; font-family: inherit; background: #fff; width: auto; }
|
.select-sm { padding: 4px 6px; border: 1.5px solid #d4cfc7; border-radius: 6px; font-size: 12px; font-family: inherit; background: #fff; width: auto; }
|
||||||
.btn-select-active { background: #e8f5e9; color: #2e7d5a; border: 1.5px solid #7ec6a4; border-radius: 10px; padding: 7px 14px; font-size: 13px; cursor: pointer; font-family: inherit; font-weight: 600; }
|
.btn-select-active { background: #e8f5e9; color: #2e7d5a; border: 1.5px solid #7ec6a4; border-radius: 10px; padding: 7px 14px; font-size: 13px; cursor: pointer; font-family: inherit; font-weight: 600; }
|
||||||
|
.batch-count { font-size: 12px; color: #4a9d7e; font-weight: 600; white-space: nowrap; }
|
||||||
|
.batch-select { padding: 5px 8px; border: 1.5px solid #d4cfc7; border-radius: 8px; font-size: 12px; font-family: inherit; background: #fff; }
|
||||||
|
|
||||||
.divider-text {
|
.divider-text {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|||||||
Reference in New Issue
Block a user