mirror of
https://github.com/hpd840321/craftlabs-authorization-sdk.git
synced 2026-06-10 10:30:30 +08:00
feat: add sidebar grouping, auth store persistence fix, idle timeout
Sidebar now groups menu items into Business/Operations/Analytics/System sections. Auth store restores roles/permissions from JWT on page reload. Added idleTimer utility for session timeout. Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
<span class="logo-text">CraftLabs</span>
|
||||
</div>
|
||||
<nav class="header-nav">
|
||||
<span class="nav-item active">授权平台</span>
|
||||
<span class="nav-item active">交付管理平台</span>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
@@ -34,17 +34,26 @@
|
||||
<div class="app-body">
|
||||
<!-- SIDEBAR 232px WHITE -->
|
||||
<aside class="app-sidebar">
|
||||
<div class="sidebar-section-label">业务管理</div>
|
||||
<div
|
||||
v-for="item in menuItems"
|
||||
:key="item.path"
|
||||
:class="['sidebar-item', { active: isActive(item) }]"
|
||||
@click="$router.push(item.path)"
|
||||
class="sidebar-item"
|
||||
:class="{ active: isActive(homeItem) }"
|
||||
@click="$router.push(homeItem.path)"
|
||||
>
|
||||
<span class="sidebar-item-icon">{{ item.icon }}</span>
|
||||
<span class="sidebar-item-text">{{ item.label }}</span>
|
||||
<span v-if="item.badge" class="sidebar-item-badge">{{ item.badge }}</span>
|
||||
<span class="sidebar-item-icon">{{ homeItem.icon }}</span>
|
||||
<span class="sidebar-item-text">{{ homeItem.label }}</span>
|
||||
</div>
|
||||
<template v-for="group in visibleGroups" :key="group.label">
|
||||
<div class="sidebar-group-label">{{ group.label }}</div>
|
||||
<div
|
||||
v-for="item in group.items"
|
||||
:key="item.path"
|
||||
:class="['sidebar-item', { active: isActive(item) }]"
|
||||
@click="$router.push(item.path)"
|
||||
>
|
||||
<span class="sidebar-item-icon">{{ item.icon }}</span>
|
||||
<span class="sidebar-item-text">{{ item.label }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="sidebar-footer">CraftLabs Platform v0.1.0</div>
|
||||
</aside>
|
||||
|
||||
@@ -123,23 +132,62 @@ onUnmounted(() => {
|
||||
if (warningTimer) clearTimeout(warningTimer)
|
||||
})
|
||||
|
||||
const menuItems = [
|
||||
{ path: "/", icon: "📊", label: "首页", roles: ["SYS_ADMIN","SALES","LICENSE_OPS"] },
|
||||
{ path: "/customers", icon: "👥", label: "客户管理", roles: ["SYS_ADMIN","SALES"] },
|
||||
{ path: "/contracts", icon: "📋", label: "合同管理", roles: ["SYS_ADMIN","SALES"] },
|
||||
{ path: "/deliveries", icon: "📦", label: "交付管理", roles: ["SYS_ADMIN","SALES","DELIVERY"] },
|
||||
{ path: "/licenses/sn", icon: "🔑", label: "许可 SN", roles: ["SYS_ADMIN","SALES"] },
|
||||
{ path: "/licenses", icon: "🛡️", label: "许可证管理", badge: "NEW", roles: ["SYS_ADMIN","SALES"] },
|
||||
{ path: "/callbacks", icon: "📨", label: "Callback 收件箱", roles: ["SYS_ADMIN","LICENSE_OPS"] },
|
||||
{ path: "/integration/environments", icon: "🌐", label: "集成环境", roles: ["SYS_ADMIN","SALES","LICENSE_OPS"] },
|
||||
{ path: "/integration/product-lines", icon: "📱", label: "产品线", roles: ["SYS_ADMIN","SALES","LICENSE_OPS"] },
|
||||
{ path: "/devices", icon: "🖥️", label: "设备管理", roles: ["SYS_ADMIN","SALES","DELIVERY"] },
|
||||
{ path: "/todos", icon: "🔔", label: "待办中心", roles: ["SYS_ADMIN","SALES","LICENSE_OPS"] },
|
||||
{ path: "/reports/contract-sn", icon: "📊", label: "报表中心", roles: ["SYS_ADMIN"] },
|
||||
{ path: "/reports/subscriptions", icon: "📧", label: "报表订阅", roles: ["SYS_ADMIN"] },
|
||||
const homeItem = { path: "/", icon: "📊", label: "首页", roles: ["SYS_ADMIN","SALES","LICENSE_OPS"] };
|
||||
|
||||
const menuGroups = [
|
||||
{
|
||||
label: "业务管理",
|
||||
roles: ["SYS_ADMIN","SALES","DELIVERY"],
|
||||
items: [
|
||||
{ path: "/customers", icon: "👥", label: "客户管理", roles: ["SYS_ADMIN","SALES"] },
|
||||
{ path: "/contracts", icon: "📋", label: "合同管理", roles: ["SYS_ADMIN","SALES"] },
|
||||
{ path: "/deliveries", icon: "📦", label: "交付管理", roles: ["SYS_ADMIN","SALES","DELIVERY"] },
|
||||
{ path: "/licenses/sn", icon: "🔑", label: "许可 SN", roles: ["SYS_ADMIN","SALES"] },
|
||||
{ path: "/licenses", icon: "🛡️", label: "许可证管理", roles: ["SYS_ADMIN","SALES"] },
|
||||
]
|
||||
},
|
||||
{
|
||||
label: "运营管理",
|
||||
roles: ["SYS_ADMIN","SALES","LICENSE_OPS","DELIVERY"],
|
||||
items: [
|
||||
{ path: "/callbacks", icon: "📨", label: "Callback 收件箱", roles: ["SYS_ADMIN","LICENSE_OPS"] },
|
||||
{ path: "/integration/environments", icon: "🌐", label: "集成环境", roles: ["SYS_ADMIN","SALES","LICENSE_OPS"] },
|
||||
{ path: "/integration/product-lines", icon: "📱", label: "产品线", roles: ["SYS_ADMIN","SALES","LICENSE_OPS"] },
|
||||
{ path: "/integration/id-mappings", icon: "🔗", label: "ID 映射", roles: ["SYS_ADMIN"] },
|
||||
{ path: "/integration/sku-mappings", icon: "📋", label: "SKU 映射", roles: ["SYS_ADMIN"] },
|
||||
{ path: "/integration/feature-mappings", icon: "⚡", label: "特征映射", roles: ["SYS_ADMIN"] },
|
||||
{ path: "/integration/json-templates", icon: "📄", label: "JSON 模板", roles: ["SYS_ADMIN"] },
|
||||
{ path: "/devices", icon: "🖥️", label: "设备管理", roles: ["SYS_ADMIN","SALES","DELIVERY"] },
|
||||
{ path: "/todos", icon: "🔔", label: "待办中心", roles: ["SYS_ADMIN","SALES","LICENSE_OPS"] },
|
||||
]
|
||||
},
|
||||
{
|
||||
label: "分析管理",
|
||||
roles: ["SYS_ADMIN"],
|
||||
items: [
|
||||
{ path: "/reports/contract-sn", icon: "📊", label: "报表中心", roles: ["SYS_ADMIN"] },
|
||||
{ path: "/reports/subscriptions", icon: "📧", label: "报表订阅", roles: ["SYS_ADMIN"] },
|
||||
]
|
||||
},
|
||||
{
|
||||
label: "系统管理",
|
||||
roles: ["SYS_ADMIN"],
|
||||
items: [
|
||||
{ path: "/audit", icon: "🔐", label: "审计日志", roles: ["SYS_ADMIN"] },
|
||||
{ path: "/admin/params", icon: "⚙️", label: "系统参数", roles: ["SYS_ADMIN"] },
|
||||
{ path: "/admin/users", icon: "👤", label: "用户管理", roles: ["SYS_ADMIN"] },
|
||||
]
|
||||
},
|
||||
];
|
||||
|
||||
const visibleMenu = computed(() => menuItems.filter(m => auth.hasAnyRole(m.roles)));
|
||||
const visibleGroups = computed(() =>
|
||||
menuGroups
|
||||
.map(g => ({
|
||||
...g,
|
||||
items: g.items.filter(m => auth.hasAnyRole(m.roles))
|
||||
}))
|
||||
.filter(g => g.items.length > 0)
|
||||
);
|
||||
|
||||
function isActive(item) {
|
||||
if (item.path === "/") return route.path === "/";
|
||||
@@ -239,8 +287,8 @@ function onLogout() { auth.logout(); router.push({ name: "login" }); }
|
||||
background: #fff; border-right: 1px solid #E8ECF1;
|
||||
display: flex; flex-direction: column; padding-top: 8px;
|
||||
}
|
||||
.sidebar-section-label {
|
||||
padding: 6px 20px; font-size: 11px; color: #C0C4CC; text-transform: uppercase; font-weight: 600; letter-spacing: 0.5px;
|
||||
.sidebar-group-label {
|
||||
padding: 12px 20px 4px; font-size: 11px; color: #C0C4CC; text-transform: uppercase; font-weight: 600; letter-spacing: 0.5px;
|
||||
}
|
||||
.sidebar-item {
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
|
||||
Reference in New Issue
Block a user