H5 支持 ?mp=1 嵌入微信 WebView;user-h5/admin-h5 底部展示蜀ICP备2025140386号-2 并链至工信部;补充小程序+H5 部署说明。 Co-authored-by: Cursor <cursoragent@cursor.com>
110 lines
3.5 KiB
Vue
110 lines
3.5 KiB
Vue
<script setup lang="ts">
|
|
import { onMounted } from 'vue'
|
|
import { RouterLink, RouterView, useRouter } from 'vue-router'
|
|
import BrandLogo from '@/components/BrandLogo.vue'
|
|
import IcpFooter from '@/components/IcpFooter.vue'
|
|
import { useAuthStore } from '@/stores/auth'
|
|
|
|
const auth = useAuthStore()
|
|
const router = useRouter()
|
|
|
|
onMounted(() => {
|
|
void auth.hydrate()
|
|
})
|
|
|
|
async function onLogout() {
|
|
await auth.logout()
|
|
await router.push({ name: 'login' })
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="shell">
|
|
<aside class="nav">
|
|
<RouterLink class="brand" to="/">
|
|
<BrandLogo size="nav" />
|
|
</RouterLink>
|
|
<nav>
|
|
<RouterLink to="/">概览</RouterLink>
|
|
<RouterLink to="/analytics">数据</RouterLink>
|
|
<RouterLink to="/content">内容</RouterLink>
|
|
<RouterLink to="/users">用户</RouterLink>
|
|
<RouterLink to="/plans">套餐</RouterLink>
|
|
<RouterLink to="/codes">兑换码</RouterLink>
|
|
<RouterLink to="/ask">问答</RouterLink>
|
|
<RouterLink to="/safety">安全</RouterLink>
|
|
<RouterLink to="/ai">AI</RouterLink>
|
|
<RouterLink to="/crisis">危机</RouterLink>
|
|
<RouterLink to="/cms">CMS</RouterLink>
|
|
<RouterLink to="/star-configs">星座配置</RouterLink>
|
|
<RouterLink to="/rhythm-configs">节律配置</RouterLink>
|
|
<RouterLink to="/image-card-decks">意象牌组</RouterLink>
|
|
<RouterLink to="/scale-definitions">量表元数据</RouterLink>
|
|
<RouterLink to="/funnel-definitions">漏斗定义</RouterLink>
|
|
<RouterLink to="/report-templates">报告模板</RouterLink>
|
|
<RouterLink to="/catalogs">目录仓</RouterLink>
|
|
<RouterLink to="/orders">订单</RouterLink>
|
|
<RouterLink v-if="auth.can('admin.membership.plans.read')" to="/pricing">定价</RouterLink>
|
|
<RouterLink to="/push">推送</RouterLink>
|
|
<RouterLink v-if="auth.isSuper" to="/admins">管理员</RouterLink>
|
|
<RouterLink to="/audit">审计</RouterLink>
|
|
</nav>
|
|
<div class="foot">
|
|
<span class="muted">{{ auth.username || '管理员' }}</span>
|
|
<span v-if="auth.role" class="role">{{ auth.role }} · {{ auth.permissions.length }} 权</span>
|
|
<button class="btn ghost" type="button" @click="onLogout">退出</button>
|
|
</div>
|
|
</aside>
|
|
<main class="main">
|
|
<div class="main-body">
|
|
<RouterView />
|
|
</div>
|
|
<IcpFooter />
|
|
</main>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.shell { display: grid; grid-template-columns: 220px 1fr; min-height: 100vh; }
|
|
.nav {
|
|
padding: 1.15rem 1rem;
|
|
border-right: 1px solid rgba(240, 230, 226, 0.9);
|
|
background: rgba(255, 253, 251, 0.88);
|
|
backdrop-filter: blur(12px);
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 1.25rem;
|
|
}
|
|
.brand {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 0.15rem 0.25rem;
|
|
}
|
|
nav { display: flex; flex-direction: column; gap: 0.35rem; }
|
|
nav a {
|
|
padding: 0.5rem 0.7rem;
|
|
border-radius: 12px;
|
|
color: var(--muted);
|
|
font-weight: 550;
|
|
}
|
|
nav a.router-link-active {
|
|
background: linear-gradient(135deg, #fff0ec, #ffe4e0);
|
|
color: var(--accent);
|
|
font-weight: 700;
|
|
box-shadow: 0 4px 12px rgba(229, 77, 66, 0.08);
|
|
}
|
|
.foot { margin-top: auto; display: flex; flex-direction: column; gap: 0.5rem; }
|
|
.role { font-size: 0.75rem; color: var(--muted); }
|
|
.main {
|
|
padding: 1.5rem 1.75rem;
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-height: 100vh;
|
|
}
|
|
.main-body { flex: 1; min-width: 0; }
|
|
@media (max-width: 800px) {
|
|
.shell { grid-template-columns: 1fr; }
|
|
.nav { border-right: 0; border-bottom: 1px solid var(--line); }
|
|
}
|
|
</style>
|