feat(后台): 侧栏分组带图标、可收起,加顶栏;所有后台页面统一页头
Deploy / deploy (push) Canceled after 0s

- 侧栏按 概览 / 教学内容 / 学情分析 / 站点管理 分组,去掉超管菜单里的重复项;
  菜单项的角色与路由守卫一一对应,没有题目权限的教师不再看到点了就被踢回首页的「题目」
- 顶栏:面包屑、回到前台、明暗切换、用户菜单(退出登录);窄屏侧栏自动收起
- 新增 PageHeader:标题 + 右侧主操作 + 下方筛选栏,编辑页带返回按钮
- 卡点分析 / 年度趋势 / 标签管理从题目列表的按钮挪进侧栏
- 首页改成统计卡片 + 班级排名卡片;设置页按钮移到卡片右上角
- 题目、比赛、题单、用户列表的「选项」列固定在右侧,不再被挤出屏幕

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-09-27 19:54:42 +08:00
1 parent d25b5dbe6d
commit d3823430f9
25 files changed
+764 -587

No files matched your search

+5 -7
View File
@@ -1,4 +1,5 @@
<script lang="ts" setup>
import PageHeader from "admin/components/PageHeader.vue"
import { errorMessage } from "utils/api"
import CodeEditor from "shared/components/CodeEditor.vue"
import MarkdownEditor from "shared/components/MarkdownEditor.vue"
@@ -72,9 +73,10 @@ async function submit() {
onMounted(init)
</script>
<template>
<h2 class="title">
{{ route.name === "admin tutorial create" ? "新建教程" : "编辑教程" }}
</h2>
<PageHeader
:title="route.name === 'admin tutorial create' ? '新建教程' : '编辑教程'"
:back="{ name: 'admin tutorial list' }"
/>
<n-form inline>
<n-form-item label="标题">
<n-input class="contestTitle" v-model:value="tutorial.title" />
@@ -111,10 +113,6 @@ onMounted(init)
</n-tabs>
</template>
<style scoped>
.title {
margin-top: 0;
}
.select {
width: 100px;
}
+8 -16
View File
@@ -1,4 +1,5 @@
<script setup lang="ts">
import PageHeader from "admin/components/PageHeader.vue"
import { errorMessage } from "utils/api"
import { NSwitch } from "naive-ui"
import { parseTime } from "utils/functions"
@@ -77,12 +78,13 @@ onMounted(listTutorials)
</script>
<template>
<n-flex align="center" class="titleWrapper">
<h2 class="title">教程列表</h2>
<n-button type="primary" @click="$router.push({ name: 'admin tutorial create' })">
新建
</n-button>
</n-flex>
<PageHeader title="教程列表">
<template #actions>
<n-button type="primary" @click="$router.push({ name: 'admin tutorial create' })">
新建教程
</n-button>
</template>
</PageHeader>
<n-tabs v-model:value="activeTab" type="line" animated>
<n-tab-pane name="python" tab="Python">
<n-data-table striped :columns="columns" :data="tutorials.python" />
@@ -92,13 +94,3 @@ onMounted(listTutorials)
</n-tab-pane>
</n-tabs>
</template>
<style scoped>
.titleWrapper {
margin-bottom: 16px;
}
.title {
margin: 0;
}
</style>