feat:添加前端页面
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
/* 应用外壳:左侧菜单 + 顶栏 + 内容区,最后加载并挂载
|
||||
(ref / computed / createApp 等已在 util.js 里解构到全局) */
|
||||
|
||||
const App = {
|
||||
template: `
|
||||
<div class="layout">
|
||||
<aside class="sidebar">
|
||||
<div class="brand">
|
||||
<div class="brand-mark">沃</div>
|
||||
<div class="brand-text">
|
||||
<div class="brand-title">沃林学生管理系统</div>
|
||||
<div class="brand-sub">Student Manager</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav class="nav">
|
||||
<template v-for="g in groups" :key="g.name">
|
||||
<div class="nav-group">{{ g.name }}</div>
|
||||
<div v-for="p in g.items" :key="p.key"
|
||||
class="nav-item" :class="{ active: p.key === currentKey }"
|
||||
@click="go(p.key)">
|
||||
<span v-html="icon(p.icon)"></span>
|
||||
<span>{{ p.title }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</nav>
|
||||
|
||||
<div class="sidebar-foot">
|
||||
接口文档:<a :href="docsUrl" target="_blank" style="color:#4F46E5">/docs</a><br>
|
||||
后端 127.0.0.1:8001
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<div class="main">
|
||||
<header class="topbar">
|
||||
<div>
|
||||
<div class="topbar-title">{{ current.title }}</div>
|
||||
<div class="topbar-sub">{{ current.sub }}</div>
|
||||
</div>
|
||||
<div class="topbar-actions">
|
||||
<el-button @click="reload">
|
||||
<span style="margin-right:4px">↻</span>刷新本页
|
||||
</el-button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="content">
|
||||
<component :is="current.component" :key="currentKey + '#' + reloadTick" />
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
|
||||
setup() {
|
||||
const pages = window.PAGES;
|
||||
|
||||
// 分组:按注册顺序把页面归到各自的分组里(总览 / 数据管理 / 统计分析)
|
||||
const groups = [];
|
||||
pages.forEach(p => {
|
||||
const name = p.group || '其他';
|
||||
let g = groups.find(x => x.name === name);
|
||||
if (!g) { g = { name, items: [] }; groups.push(g); }
|
||||
g.items.push(p);
|
||||
});
|
||||
|
||||
const fallback = (pages[0] && pages[0].key) || '';
|
||||
const currentKey = ref(location.hash.replace(/^#\/?/, '') || fallback);
|
||||
|
||||
// 刷新本页:改 key 让组件重新挂载,页面自己会重新拉数据
|
||||
const reloadTick = ref(0);
|
||||
const reload = () => { reloadTick.value++; };
|
||||
|
||||
const current = computed(() =>
|
||||
pages.find(p => p.key === currentKey.value) || pages[0] || { title: '', sub: '', component: null });
|
||||
|
||||
const go = (key) => {
|
||||
if (key === currentKey.value) { reload(); return; }
|
||||
location.hash = '#/' + key;
|
||||
};
|
||||
|
||||
// 地址栏直接改 hash / 浏览器前进后退也能切页
|
||||
const onHash = () => {
|
||||
const k = location.hash.replace(/^#\/?/, '');
|
||||
if (k && k !== currentKey.value) currentKey.value = k;
|
||||
};
|
||||
onMounted(() => window.addEventListener('hashchange', onHash));
|
||||
onUnmounted(() => window.removeEventListener('hashchange', onHash));
|
||||
|
||||
// 把地址栏补齐,刷新页面能停在当前页
|
||||
if (!location.hash) location.hash = '#/' + currentKey.value;
|
||||
|
||||
// 前后端不同源了,/docs 这种站内相对路径会指到前端服务器上,必须用后端地址
|
||||
const docsUrl = API_BASE + '/docs';
|
||||
|
||||
return { groups, currentKey, current, go, reload, reloadTick, icon, docsUrl };
|
||||
},
|
||||
};
|
||||
|
||||
const app = createApp(App);
|
||||
|
||||
// 模板里写错组件名之类的错误,直接在界面上弹出来,比只看控制台快
|
||||
app.config.errorHandler = (err) => {
|
||||
console.error(err);
|
||||
toastErr(err && err.message ? err.message : '页面出错了,请按 F12 看控制台');
|
||||
};
|
||||
|
||||
app.use(ElementPlus, { locale: ElementPlusLocaleZhCn });
|
||||
app.mount('#app');
|
||||
Reference in New Issue
Block a user