From 8c3cca6fdef6b694436e2df3832238b9d2171b36 Mon Sep 17 00:00:00 2001
From: kronecker <2026692687@qq.com>
Date: Mon, 5 Oct 2026 01:50:07 +0800
Subject: [PATCH] feat(frontend): isolate admin app with sidebar navigation
Build a separate admin entrypoint with its own router and sidebar layout.
Add preview sections for problems, contests, users, judge nodes and site settings.
Configure Vite to emit both public and admin HTML entries.
---
frontend/admin/index.html | 12 ++
frontend/src/admin/AdminApp.vue | 39 +++++
frontend/src/admin/AdminView.vue | 272 +++++++++++++++++++++++++++++++
frontend/src/admin/main.ts | 10 ++
frontend/src/admin/navigation.ts | 8 +
frontend/src/admin/router.ts | 12 ++
frontend/vite.config.ts | 9 +
7 files changed, 362 insertions(+)
create mode 100644 frontend/admin/index.html
create mode 100644 frontend/src/admin/AdminApp.vue
create mode 100644 frontend/src/admin/AdminView.vue
create mode 100644 frontend/src/admin/main.ts
create mode 100644 frontend/src/admin/navigation.ts
create mode 100644 frontend/src/admin/router.ts
diff --git a/frontend/admin/index.html b/frontend/admin/index.html
new file mode 100644
index 0000000..ad457f0
--- /dev/null
+++ b/frontend/admin/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ KF 管理控制台
+
+
+
+
+
+
diff --git a/frontend/src/admin/AdminApp.vue b/frontend/src/admin/AdminApp.vue
new file mode 100644
index 0000000..3c81b9f
--- /dev/null
+++ b/frontend/src/admin/AdminApp.vue
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/admin/AdminView.vue b/frontend/src/admin/AdminView.vue
new file mode 100644
index 0000000..c6535b7
--- /dev/null
+++ b/frontend/src/admin/AdminView.vue
@@ -0,0 +1,272 @@
+
+
+ 返回站点
+
+
+
+ 前端预览待接入待接入待接入
+
新建题目草稿
+
+
+
+ 编辑预览查看
+
创建比赛
+
+
+
+ 查看
+
+
+
+ 用户查看主页修改角色
+
实际节点、负载、心跳和任务状态将在协调器接口接入后展示。
+ {{
+ row.status
+ }}暂停接单
+
+
+
+ 保存设置当前编辑只在本页面预览
+
+
+
+
+ 公开草稿
+ 题面编辑、测试数据和版本发布将在题库接口接入后启用。
关闭预览保存题目
+
diff --git a/frontend/src/admin/main.ts b/frontend/src/admin/main.ts
new file mode 100644
index 0000000..49dfc10
--- /dev/null
+++ b/frontend/src/admin/main.ts
@@ -0,0 +1,10 @@
+import { createApp } from 'vue'
+import { registerUi } from '../plugins/ui'
+import { adminRouter } from './router'
+import AdminApp from './AdminApp.vue'
+import '../styles/base.css'
+import '../styles/blueprint.css'
+
+const app = createApp(AdminApp)
+registerUi(app)
+app.use(adminRouter).mount('#admin-app')
diff --git a/frontend/src/admin/navigation.ts b/frontend/src/admin/navigation.ts
new file mode 100644
index 0000000..9d70ebf
--- /dev/null
+++ b/frontend/src/admin/navigation.ts
@@ -0,0 +1,8 @@
+export const adminSections = [
+ { id: 'overview', title: '概览', icon: 'monitor' },
+ { id: 'problems', title: '题目管理', icon: 'problems' },
+ { id: 'contests', title: '比赛管理', icon: 'contests' },
+ { id: 'users', title: '用户管理', icon: 'teams' },
+ { id: 'judges', title: '判题节点', icon: 'connection' },
+ { id: 'settings', title: '站点设置', icon: 'settings' },
+]
diff --git a/frontend/src/admin/router.ts b/frontend/src/admin/router.ts
new file mode 100644
index 0000000..eac06de
--- /dev/null
+++ b/frontend/src/admin/router.ts
@@ -0,0 +1,12 @@
+import { createRouter, createWebHashHistory } from 'vue-router'
+import { adminSections } from './navigation'
+
+export const adminRouter = createRouter({
+ history: createWebHashHistory('/admin/index.html'),
+ scrollBehavior: () => ({ top: 0 }),
+ routes: [{ path: '/:section?', component: () => import('./AdminView.vue') }],
+})
+adminRouter.afterEach((to) => {
+ const section = adminSections.find((item) => item.id === (to.params.section || 'overview'))
+ document.title = `${section?.title ?? '页面不存在'} · KF 管理控制台`
+})
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts
index cacb854..a5b61e3 100644
--- a/frontend/vite.config.ts
+++ b/frontend/vite.config.ts
@@ -1,10 +1,19 @@
import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
+import { fileURLToPath, URL } from 'node:url'
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), '')
return {
plugins: [vue()],
+ build: {
+ rollupOptions: {
+ input: {
+ main: fileURLToPath(new URL('./index.html', import.meta.url)),
+ admin: fileURLToPath(new URL('./admin/index.html', import.meta.url)),
+ },
+ },
+ },
server: {
port: 5173,
strictPort: true,