|
|
@@ -0,0 +1,157 @@
|
|
|
+<template>
|
|
|
+ <aside class="sidebar">
|
|
|
+ <div v-for="group in groups" :key="group.label" class="sb-section">
|
|
|
+ <div class="sb-label">{{ group.label }}</div>
|
|
|
+ <div
|
|
|
+ v-for="item in group.items"
|
|
|
+ :key="item.key"
|
|
|
+ :class="['sb-item', { active: isActive(item) }]"
|
|
|
+ @click="onClick(item)"
|
|
|
+ >
|
|
|
+ <span class="ico">{{ item.icon }}</span>
|
|
|
+ <span class="label">{{ item.label }}</span>
|
|
|
+ <span v-if="item.badge" class="num">{{ item.badge }}</span>
|
|
|
+ </div>
|
|
|
+ <div v-if="group.divider" class="sb-divider"></div>
|
|
|
+ </div>
|
|
|
+ </aside>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { useRouter, useRoute } from 'vue-router'
|
|
|
+
|
|
|
+const router = useRouter()
|
|
|
+const route = useRoute()
|
|
|
+
|
|
|
+const groups = [
|
|
|
+ {
|
|
|
+ label: '主导航',
|
|
|
+ divider: true,
|
|
|
+ items: [
|
|
|
+ { key: 'dashboard', label: '工作台', icon: '◉', to: '/' },
|
|
|
+ { key: 'board', label: '看板广场', icon: '▦' },
|
|
|
+ { key: 'watch', label: '自选股', icon: '★', badge: 12 },
|
|
|
+ { key: 'alert', label: '预警中心', icon: '⏰', badge: 3 },
|
|
|
+ { key: 'download', label: '数据下载', icon: '⬇' },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '基本面 · 7 大板块',
|
|
|
+ divider: true,
|
|
|
+ items: [
|
|
|
+ { key: 'macro', label: '宏观总览', icon: '●', to: '/fundamentals', match: 'fundamentals' },
|
|
|
+ { key: 'gdp', label: 'GDP 与增长', icon: '●' },
|
|
|
+ { key: 'invest', label: '投资分析', icon: '●' },
|
|
|
+ { key: 'trade', label: '进出口贸易', icon: '●' },
|
|
|
+ { key: 'consume', label: '消费与就业', icon: '●' },
|
|
|
+ { key: 'cpi', label: '通胀 (CPI/PPI)', icon: '●' },
|
|
|
+ { key: 'supply', label: '工业与供给', icon: '●' },
|
|
|
+ { key: 'pmi', label: '景气度 (PMI/BCI)', icon: '●' },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '模型工具',
|
|
|
+ divider: false,
|
|
|
+ items: [
|
|
|
+ { key: 'gdp-now', label: 'GDP 周频预测', icon: '⚙' },
|
|
|
+ { key: 'cpi-fcst', label: '通胀预测模型', icon: '⚙' },
|
|
|
+ { key: 'pmi-mix', label: 'PMI 合成', icon: '⚙' },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+]
|
|
|
+
|
|
|
+function isActive(item) {
|
|
|
+ if (item.to) return route.path === item.to
|
|
|
+ if (item.match) return route.path.startsWith(`/${item.match}`)
|
|
|
+ return false
|
|
|
+}
|
|
|
+
|
|
|
+function onClick(item) {
|
|
|
+ if (item.to) {
|
|
|
+ router.push(item.to)
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.sidebar {
|
|
|
+ width: 208px;
|
|
|
+ flex: none;
|
|
|
+ background: #0c2b5e;
|
|
|
+ color: rgba(255, 255, 255, 0.78);
|
|
|
+ padding: 14px 0;
|
|
|
+ overflow-y: auto;
|
|
|
+}
|
|
|
+
|
|
|
+.sb-section {
|
|
|
+ padding: 0 12px;
|
|
|
+ margin-bottom: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.sb-label {
|
|
|
+ font-size: 10.5px;
|
|
|
+ color: rgba(255, 255, 255, 0.4);
|
|
|
+ padding: 6px 14px;
|
|
|
+ margin-bottom: 6px;
|
|
|
+ letter-spacing: 1px;
|
|
|
+}
|
|
|
+
|
|
|
+.sb-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 11px;
|
|
|
+ padding: 9px 14px;
|
|
|
+ border-radius: 6px;
|
|
|
+ font-size: 12.5px;
|
|
|
+ cursor: pointer;
|
|
|
+ color: rgba(255, 255, 255, 0.78);
|
|
|
+ margin-bottom: 2px;
|
|
|
+ transition: 0.15s;
|
|
|
+}
|
|
|
+
|
|
|
+.sb-item:hover {
|
|
|
+ background: #143a80;
|
|
|
+ color: #fff;
|
|
|
+}
|
|
|
+
|
|
|
+.sb-item.active {
|
|
|
+ background: #fff;
|
|
|
+ color: #0c2b5e;
|
|
|
+ font-weight: 600;
|
|
|
+}
|
|
|
+
|
|
|
+.sb-item.active .ico {
|
|
|
+ color: #1552d0;
|
|
|
+}
|
|
|
+
|
|
|
+.sb-item .ico {
|
|
|
+ width: 14px;
|
|
|
+ height: 14px;
|
|
|
+ font-size: 14px;
|
|
|
+ display: inline-grid;
|
|
|
+ place-items: center;
|
|
|
+ color: rgba(255, 255, 255, 0.6);
|
|
|
+}
|
|
|
+
|
|
|
+.sb-item .label {
|
|
|
+ flex: 1;
|
|
|
+ white-space: nowrap;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+}
|
|
|
+
|
|
|
+.sb-item .num {
|
|
|
+ font-size: 10px;
|
|
|
+ color: #fff;
|
|
|
+ background: #e13b3b;
|
|
|
+ padding: 1px 5px;
|
|
|
+ border-radius: 8px;
|
|
|
+ font-weight: 600;
|
|
|
+}
|
|
|
+
|
|
|
+.sb-divider {
|
|
|
+ height: 1px;
|
|
|
+ background: rgba(255, 255, 255, 0.1);
|
|
|
+ margin: 8px 14px;
|
|
|
+}
|
|
|
+</style>
|