add admin head.
This commit is contained in:
6
package-lock.json
generated
6
package-lock.json
generated
@@ -17,6 +17,7 @@
|
|||||||
"date-fns": "^2.29.3",
|
"date-fns": "^2.29.3",
|
||||||
"highlight.js": "^11.7.0",
|
"highlight.js": "^11.7.0",
|
||||||
"naive-ui": "^2.34.3",
|
"naive-ui": "^2.34.3",
|
||||||
|
"normalize.css": "^8.0.1",
|
||||||
"party-js": "^2.2.0",
|
"party-js": "^2.2.0",
|
||||||
"pinia": "^2.0.33",
|
"pinia": "^2.0.33",
|
||||||
"vue": "^3.2.47",
|
"vue": "^3.2.47",
|
||||||
@@ -2966,6 +2967,11 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/normalize.css": {
|
||||||
|
"version": "8.0.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/normalize.css/-/normalize.css-8.0.1.tgz",
|
||||||
|
"integrity": "sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg=="
|
||||||
|
},
|
||||||
"node_modules/npm-run-path": {
|
"node_modules/npm-run-path": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-4.0.1.tgz",
|
"resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-4.0.1.tgz",
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
"date-fns": "^2.29.3",
|
"date-fns": "^2.29.3",
|
||||||
"highlight.js": "^11.7.0",
|
"highlight.js": "^11.7.0",
|
||||||
"naive-ui": "^2.34.3",
|
"naive-ui": "^2.34.3",
|
||||||
|
"normalize.css": "^8.0.1",
|
||||||
"party-js": "^2.2.0",
|
"party-js": "^2.2.0",
|
||||||
"pinia": "^2.0.33",
|
"pinia": "^2.0.33",
|
||||||
"vue": "^3.2.47",
|
"vue": "^3.2.47",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import "normalize.css"
|
||||||
import { zhCN, dateZhCN, darkTheme } from "naive-ui"
|
import { zhCN, dateZhCN, darkTheme } from "naive-ui"
|
||||||
import { isDark } from "./shared/composables/dark"
|
import { isDark } from "./shared/composables/dark"
|
||||||
import hljs from "highlight.js/lib/core"
|
import hljs from "highlight.js/lib/core"
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script setup lang="ts"></script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>contest detail</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script setup lang="ts"></script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>contest list</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script setup lang="ts"></script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>contest problem list</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script setup lang="ts"></script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>problem detail</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script setup lang="ts"></script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>problem list</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
|
|||||||
7
src/admin/setting/announcement.vue
Normal file
7
src/admin/setting/announcement.vue
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<script setup lang="ts"></script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>announcement</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
7
src/admin/setting/config.vue
Normal file
7
src/admin/setting/config.vue
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<script setup lang="ts"></script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>conf</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
7
src/admin/user/import.vue
Normal file
7
src/admin/user/import.vue
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<script setup lang="ts"></script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>user import</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
7
src/admin/user/list.vue
Normal file
7
src/admin/user/list.vue
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<script setup lang="ts"></script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>user list</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
@@ -18,6 +18,7 @@ router.beforeEach((to, from, next) => {
|
|||||||
if (to.matched.some((record) => record.meta.requiresAuth)) {
|
if (to.matched.some((record) => record.meta.requiresAuth)) {
|
||||||
if (!storage.get(STORAGE_KEY.AUTHED)) {
|
if (!storage.get(STORAGE_KEY.AUTHED)) {
|
||||||
toggleLogin(true)
|
toggleLogin(true)
|
||||||
|
next("/")
|
||||||
} else {
|
} else {
|
||||||
next()
|
next()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { RouteRecordRaw } from "vue-router"
|
import { RouteRecordRaw } from "vue-router"
|
||||||
|
import { getProfile } from "./shared/api"
|
||||||
import { loadChart } from "./shared/composables/chart"
|
import { loadChart } from "./shared/composables/chart"
|
||||||
|
import { USER_TYPE } from "./utils/constants"
|
||||||
|
|
||||||
export const routes: RouteRecordRaw[] = [
|
export const routes: RouteRecordRaw[] = [
|
||||||
{
|
{
|
||||||
@@ -95,42 +97,80 @@ export const routes: RouteRecordRaw[] = [
|
|||||||
{
|
{
|
||||||
path: "/admin",
|
path: "/admin",
|
||||||
component: () => import("~/shared/layout/admin.vue"),
|
component: () => import("~/shared/layout/admin.vue"),
|
||||||
|
meta: { requiresAuth: true },
|
||||||
|
beforeEnter: async () => {
|
||||||
|
const res = await getProfile()
|
||||||
|
if (res.data.user.admin_type === USER_TYPE.REGULAR_USER) return "/"
|
||||||
|
},
|
||||||
children: [
|
children: [
|
||||||
{ path: "", component: () => import("admin/index.vue") },
|
{ path: "", name: "home", component: () => import("admin/index.vue") },
|
||||||
{ path: "user", component: () => import("admin/setting/user.vue") },
|
{
|
||||||
{ path: "conf", component: () => import("admin/setting/conf.vue") },
|
path: "config",
|
||||||
{ path: "problems", component: () => import("admin/problem/list.vue") },
|
name: "config",
|
||||||
|
component: () => import("admin/setting/config.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "announcement",
|
||||||
|
name: "announcement",
|
||||||
|
component: () => import("admin/setting/announcement.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "user/list",
|
||||||
|
name: "user list",
|
||||||
|
component: () => import("admin/user/list.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "user/import",
|
||||||
|
name: "user importing",
|
||||||
|
component: () => import("admin/user/import.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "problem/list",
|
||||||
|
name: "problem list",
|
||||||
|
component: () => import("admin/problem/list.vue"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "problem/create",
|
path: "problem/create",
|
||||||
|
name: "problem create",
|
||||||
component: () => import("admin/problem/detail.vue"),
|
component: () => import("admin/problem/detail.vue"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "problem/:problemID/edit",
|
path: "problem/:problemID/edit",
|
||||||
|
name: "problem edit",
|
||||||
component: () => import("admin/problem/detail.vue"),
|
component: () => import("admin/problem/detail.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
},
|
},
|
||||||
{ path: "contests", component: () => import("admin/contest/list.vue") },
|
{
|
||||||
|
path: "contest/list",
|
||||||
|
name: "contest list",
|
||||||
|
component: () => import("admin/contest/list.vue"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "contest/create",
|
path: "contest/create",
|
||||||
|
name: "contest create",
|
||||||
component: () => import("admin/contest/detail.vue"),
|
component: () => import("admin/contest/detail.vue"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "contest/:contestID/edit",
|
path: "contest/:contestID/edit",
|
||||||
|
name: "contest edit",
|
||||||
component: () => import("admin/contest/detail.vue"),
|
component: () => import("admin/contest/detail.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "contest/:contestID/problems",
|
path: "contest/:contestID/problems",
|
||||||
|
name: "contest problems",
|
||||||
component: () => import("admin/contest/detail.vue"),
|
component: () => import("admin/contest/detail.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "contest/:contestID/problem/create",
|
path: "contest/:contestID/problem/create",
|
||||||
|
name: "contest problem create",
|
||||||
component: () => import("admin/problem/detail.vue"),
|
component: () => import("admin/problem/detail.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "contest/:contestID/problem/:problemID/edit",
|
path: "contest/:contestID/problem/:problemID/edit",
|
||||||
|
name: "contest problem edit",
|
||||||
component: () => import("admin/problem/detail.vue"),
|
component: () => import("admin/problem/detail.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import http from "utils/http"
|
import http from "utils/http"
|
||||||
|
import { Profile } from "~/utils/types"
|
||||||
|
|
||||||
export function login(data: { username: string; password: string }) {
|
export function login(data: { username: string; password: string }) {
|
||||||
return http.post("login", data)
|
return http.post("login", data)
|
||||||
@@ -9,5 +10,5 @@ export function logout() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getProfile(username: string = "") {
|
export function getProfile(username: string = "") {
|
||||||
return http.get("profile", { params: { username } })
|
return http.get<Profile>("profile", { params: { username } })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +1,100 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { MenuOption } from "naive-ui"
|
import { MenuOption } from "naive-ui"
|
||||||
|
import { RouterLink } from "vue-router"
|
||||||
import Login from "../Login.vue"
|
import Login from "../Login.vue"
|
||||||
import Signup from "../Signup.vue"
|
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
const options: MenuOption[] = [
|
const options: MenuOption[] = [
|
||||||
{ label: "题目", key: "problem", disabled: true },
|
{
|
||||||
{ label: "题目列表", key: "problem list" },
|
label: () => h(RouterLink, { to: "/admin" }, { default: () => "首页" }),
|
||||||
{ label: "创建题目", key: "create problem" },
|
key: "home",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "题目",
|
||||||
|
key: "problem",
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: () =>
|
||||||
|
h(
|
||||||
|
RouterLink,
|
||||||
|
{ to: "/admin/problem/list" },
|
||||||
|
{ default: () => "题目列表" }
|
||||||
|
),
|
||||||
|
key: "problem list",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: () =>
|
||||||
|
h(
|
||||||
|
RouterLink,
|
||||||
|
{ to: "/admin/problem/create" },
|
||||||
|
{ default: () => "创建题目" }
|
||||||
|
),
|
||||||
|
key: "problem create",
|
||||||
|
},
|
||||||
{ label: "用户", key: "user", disabled: true },
|
{ label: "用户", key: "user", disabled: true },
|
||||||
{ label: "用户列表", key: "user list" },
|
{
|
||||||
{ label: "导入用户", key: "user import" },
|
label: () =>
|
||||||
|
h(RouterLink, { to: "/admin/user/list" }, { default: () => "用户列表" }),
|
||||||
|
key: "user list",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: () =>
|
||||||
|
h(
|
||||||
|
RouterLink,
|
||||||
|
{ to: "/admin/user/import" },
|
||||||
|
{ default: () => "导入用户" }
|
||||||
|
),
|
||||||
|
key: "user importing",
|
||||||
|
},
|
||||||
{ label: "比赛", key: "contest", disabled: true },
|
{ label: "比赛", key: "contest", disabled: true },
|
||||||
{ label: "比赛列表", key: "contest list" },
|
{
|
||||||
{ label: "创建比赛", key: "create contest" },
|
label: () =>
|
||||||
|
h(
|
||||||
|
RouterLink,
|
||||||
|
{ to: "/admin/contest/list" },
|
||||||
|
{ default: () => "比赛列表" }
|
||||||
|
),
|
||||||
|
key: "contest list",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: () =>
|
||||||
|
h(
|
||||||
|
RouterLink,
|
||||||
|
{ to: "/admin/contest/create" },
|
||||||
|
{ default: () => "创建比赛" }
|
||||||
|
),
|
||||||
|
key: "contest create",
|
||||||
|
},
|
||||||
{ label: "其他", key: "other", disabled: true },
|
{ label: "其他", key: "other", disabled: true },
|
||||||
{ label: "系统配置", key: "config" },
|
{
|
||||||
{ label: "公告配置", key: "announcement" },
|
label: () =>
|
||||||
|
h(RouterLink, { to: "/admin/config" }, { default: () => "系统配置" }),
|
||||||
|
key: "config",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: () =>
|
||||||
|
h(
|
||||||
|
RouterLink,
|
||||||
|
{ to: "/admin/announcement" },
|
||||||
|
{ default: () => "公告配置" }
|
||||||
|
),
|
||||||
|
key: "announcement",
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const active = computed(() => (route.name as string) || "")
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<n-layout has-sider position="absolute">
|
<n-layout has-sider position="absolute">
|
||||||
<n-layout-sider bordered :native-scrollbar="false">
|
<n-layout-sider bordered :native-scrollbar="false">
|
||||||
<n-menu :options="options" />
|
<n-menu :options="options" :value="active" />
|
||||||
</n-layout-sider>
|
</n-layout-sider>
|
||||||
<n-layout-content :native-scrollbar="false">
|
<n-layout-content :native-scrollbar="false">
|
||||||
<router-view></router-view>
|
<router-view></router-view>
|
||||||
</n-layout-content>
|
</n-layout-content>
|
||||||
<Login />
|
<Login />
|
||||||
<Signup />
|
|
||||||
</n-layout>
|
</n-layout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user