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,