feat: 权限细化、商业认证跳转、UI改进
All checks were successful
Test / unit-test (push) Successful in 4s
Test / build-check (push) Successful in 3s
Test / e2e-test (push) Successful in 58s
PR Preview / teardown-preview (pull_request) Has been skipped
PR Preview / test (pull_request) Successful in 4s
PR Preview / deploy-preview (pull_request) Successful in 14s

权限:
- viewer 管理配方页只显示我的配方,隐藏公共配方库和工具栏
- 高级编辑者可看到精油价目信息不全的红色提示
- 商业核算删除按钮仅管理员可见
- 搜索未收录通知只发管理员和高级编辑者

Tab 可见性:
- 所有用户可见:配方查询、管理配方、个人库存、精油价目、商业核算
- 需登录的 tab 点击弹登录框,登录后跳转
- 操作日志/Bug/用户管理仅管理员可见

商业核算:
- 未认证用户可看项目列表,点详情提示去认证
- 跳转到我的账户页商业认证区域并自动滚动

其他:
- 我的配方和收藏配方默认折叠

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-09 21:49:37 +00:00
parent 4696ece139
commit f3279ac348
6 changed files with 63 additions and 32 deletions

View File

@@ -32,7 +32,7 @@
<div v-for="tab in visibleTabs" :key="tab.key"
class="nav-tab"
:class="{ active: ui.currentSection === tab.key }"
@click="goSection(tab.key)"
@click="handleTabClick(tab)"
>{{ tab.icon }} {{ tab.label }}</div>
</div>
@@ -72,29 +72,24 @@ const route = useRoute()
const showUserMenu = ref(false)
const navTabsRef = ref(null)
// Tab 定义,顺序固定:配方查询 → 管理配方 → 个人库存 → 精油价目 → 商业核算 → 操作日志 → Bug → 用户管理
// require: 'login' = 需要登录, 'business' = 需要商业认证, 'admin' = 需要管理员
// Tab 定义,顺序固定
// require: 点击时需要的条件,不满足则提示
// hide: 完全隐藏(只有满足条件才显示)
const allTabs = [
{ key: 'search', icon: '🔍', label: '配方查询' },
{ key: 'manage', icon: '📋', label: '管理配方', require: 'login' },
{ key: 'inventory', icon: '📦', label: '个人库存', require: 'login' },
{ key: 'oils', icon: '💧', label: '精油价目' },
{ key: 'projects', icon: '💼', label: '商业核算', require: 'business' },
{ key: 'audit', icon: '📜', label: '操作日志', require: 'admin' },
{ key: 'bugs', icon: '🐛', label: 'Bug', require: 'admin' },
{ key: 'users', icon: '👥', label: '用户管理', require: 'admin' },
{ key: 'projects', icon: '💼', label: '商业核算', require: 'login' },
{ key: 'audit', icon: '📜', label: '操作日志', hide: 'admin' },
{ key: 'bugs', icon: '🐛', label: 'Bug', hide: 'admin' },
{ key: 'users', icon: '👥', label: '用户管理', hide: 'admin' },
]
// 根据当前用户角色,过滤出可见的 tab
// 未登录: 配方查询, 精油价目
// 普通登录: 配方查询, 管理配方, 个人库存, 精油价目
// 商业用户: + 商业核算
// 管理员: + 操作日志, Bug, 用户管理
// 所有人都能看到大部分 tabbug 和用户管理只有 admin 可见
const visibleTabs = computed(() => allTabs.filter(t => {
if (!t.require) return true
if (t.require === 'login') return auth.isLoggedIn
if (t.require === 'business') return auth.isBusiness
if (t.require === 'admin') return auth.isAdmin
if (!t.hide) return true
if (t.hide === 'admin') return auth.isAdmin
return true
}))
const unreadNotifCount = ref(0)
@@ -124,6 +119,22 @@ const prMatch = hostname.match(/^pr-(\d+)\./)
const isPreview = !!prMatch
const prId = prMatch ? prMatch[1] : ''
function handleTabClick(tab) {
if (tab.require === 'login' && !auth.isLoggedIn) {
ui.openLogin(() => goSection(tab.key))
return
}
if (tab.require === 'business' && !auth.isBusiness) {
if (!auth.isLoggedIn) {
ui.openLogin(() => goSection(tab.key))
} else {
ui.showToast('需要商业认证才能使用此功能')
}
return
}
goSection(tab.key)
}
function goSection(name) {
ui.showSection(name)
router.push('/' + (name === 'search' ? '' : name))
@@ -178,12 +189,12 @@ function onSwipeEnd(e) {
const currentIdx = tabs.indexOf(ui.currentSection)
if (currentIdx < 0) return
if (dx < 0 && currentIdx < tabs.length - 1) {
// 左滑 → 下一个 tab
goSection(tabs[currentIdx + 1])
} else if (dx > 0 && currentIdx > 0) {
// 右滑 → 上一个 tab
goSection(tabs[currentIdx - 1])
let nextIdx = -1
if (dx < 0 && currentIdx < tabs.length - 1) nextIdx = currentIdx + 1
else if (dx > 0 && currentIdx > 0) nextIdx = currentIdx - 1
if (nextIdx >= 0) {
const tab = visibleTabs.value[nextIdx]
handleTabClick(tab)
}
}