fix admin.

This commit is contained in:
2023-03-14 12:25:48 +08:00
parent b3ec4ef63e
commit 477cece1e7
9 changed files with 153 additions and 79 deletions

47
src/admin/api.ts Normal file
View File

@@ -0,0 +1,47 @@
import http from "utils/http"
import { DIFFICULTY } from "~/utils/constants"
import { getACRate } from "~/utils/functions"
import { Problem } from "~/utils/types"
function filterResult(result: Problem) {
const newResult = {
id: result.id,
_id: result._id,
title: result.title,
difficulty: DIFFICULTY[result.difficulty],
tags: result.tags,
submission: result.submission_number,
rate: getACRate(result.accepted_number, result.submission_number),
status: "",
}
if (result.my_status === null || result.my_status === undefined) {
newResult.status = "not_test"
} else if (result.my_status === 0) {
newResult.status = "passed"
} else {
newResult.status = "failed"
}
return newResult
}
export async function getProblemList(
offset = 0,
limit = 10,
searchParams: any = {}
) {
let params: any = {
paging: true,
offset,
limit,
}
Object.keys(searchParams).forEach((element) => {
if (searchParams[element]) {
params[element] = searchParams[element]
}
})
const res = await http.get("admin/problem", { params })
return {
results: res.data.results.map(filterResult),
total: res.data.total,
}
}

View File

@@ -1,11 +0,0 @@
<script setup lang="ts"></script>
<template>
<div class="container">1213</div>
</template>
<style scoped>
.container {
height: 200vh;
}
</style>

View File

@@ -1,7 +1,40 @@
<script setup lang="ts"></script> <script setup lang="ts">
import { getProblemList } from "../api"
import Pagination from "~/shared/Pagination.vue"
import { DataTableColumn } from "naive-ui"
import { ProblemFiltered } from "~/utils/types"
const total = ref(0)
const problems = ref([])
const query = reactive({
limit: 10,
page: 1,
keyword: "",
})
const columns: DataTableColumn<ProblemFiltered>[] = [
{ title: "编号", key: "_id", width: 100 },
]
async function listProblems() {
const offset = (query.page - 1) * query.limit
const res = await getProblemList(offset, query.limit, {
keyword: query.keyword,
})
total.value = res.total
problems.value = res.results
}
onMounted(listProblems)
</script>
<template> <template>
<div>problem list</div> <n-data-table :columns="columns" :data="problems" />
<Pagination
:total="total"
v-model:limit="query.limit"
v-model:page="query.page"
/>
</template> </template>
<style scoped></style> <style scoped></style>

View File

@@ -0,0 +1,7 @@
<script setup lang="ts"></script>
<template>
<div></div>
</template>
<style scoped></style>

92
src/components.d.ts vendored
View File

@@ -7,52 +7,52 @@ import '@vue/runtime-core'
export {} export {}
declare module '@vue/runtime-core' { declare module "@vue/runtime-core" {
export interface GlobalComponents { export interface GlobalComponents {
IEpBell: typeof import('~icons/ep/bell')['default'] IEpBell: typeof import("~icons/ep/bell")["default"]
IEpCaretRight: typeof import('~icons/ep/caret-right')['default'] IEpCaretRight: typeof import("~icons/ep/caret-right")["default"]
IEpLoading: typeof import('~icons/ep/loading')['default'] IEpLoading: typeof import("~icons/ep/loading")["default"]
IEpLock: typeof import('~icons/ep/lock')['default'] IEpLock: typeof import("~icons/ep/lock")["default"]
IEpMenu: typeof import('~icons/ep/menu')['default'] IEpMenu: typeof import("~icons/ep/menu")["default"]
IEpMoon: typeof import('~icons/ep/moon')['default'] IEpMoon: typeof import("~icons/ep/moon")["default"]
IEpMoreFilled: typeof import('~icons/ep/more-filled')['default'] IEpMoreFilled: typeof import("~icons/ep/more-filled")["default"]
IEpSunny: typeof import('~icons/ep/sunny')['default'] IEpSunny: typeof import("~icons/ep/sunny")["default"]
NAlert: typeof import('naive-ui')['NAlert'] NAlert: typeof import("naive-ui")["NAlert"]
NAvatar: typeof import('naive-ui')['NAvatar'] NAvatar: typeof import("naive-ui")["NAvatar"]
NButton: typeof import('naive-ui')['NButton'] NButton: typeof import("naive-ui")["NButton"]
NCard: typeof import('naive-ui')['NCard'] NCard: typeof import("naive-ui")["NCard"]
NCode: typeof import('naive-ui')['NCode'] NCode: typeof import("naive-ui")["NCode"]
NConfigProvider: typeof import('naive-ui')['NConfigProvider'] NConfigProvider: typeof import("naive-ui")["NConfigProvider"]
NDataTable: typeof import('naive-ui')['NDataTable'] NDataTable: typeof import("naive-ui")["NDataTable"]
NDescriptions: typeof import('naive-ui')['NDescriptions'] NDescriptions: typeof import("naive-ui")["NDescriptions"]
NDescriptionsItem: typeof import('naive-ui')['NDescriptionsItem'] NDescriptionsItem: typeof import("naive-ui")["NDescriptionsItem"]
NDropdown: typeof import('naive-ui')['NDropdown'] NDropdown: typeof import("naive-ui")["NDropdown"]
NEmpty: typeof import('naive-ui')['NEmpty'] NEmpty: typeof import("naive-ui")["NEmpty"]
NForm: typeof import('naive-ui')['NForm'] NForm: typeof import("naive-ui")["NForm"]
NFormItem: typeof import('naive-ui')['NFormItem'] NFormItem: typeof import("naive-ui")["NFormItem"]
NGi: typeof import('naive-ui')['NGi'] NGi: typeof import("naive-ui")["NGi"]
NGrid: typeof import('naive-ui')['NGrid'] NGrid: typeof import("naive-ui")["NGrid"]
NIcon: typeof import('naive-ui')['NIcon'] NIcon: typeof import("naive-ui")["NIcon"]
NInput: typeof import('naive-ui')['NInput'] NInput: typeof import("naive-ui")["NInput"]
NLayout: typeof import('naive-ui')['NLayout'] NLayout: typeof import("naive-ui")["NLayout"]
NLayoutContent: typeof import('naive-ui')['NLayoutContent'] NLayoutContent: typeof import("naive-ui")["NLayoutContent"]
NLayoutHeader: typeof import('naive-ui')['NLayoutHeader'] NLayoutHeader: typeof import("naive-ui")["NLayoutHeader"]
NLayoutSider: typeof import('naive-ui')['NLayoutSider'] NLayoutSider: typeof import("naive-ui")["NLayoutSider"]
NMenu: typeof import('naive-ui')['NMenu'] NMenu: typeof import("naive-ui")["NMenu"]
NMessageProvider: typeof import('naive-ui')['NMessageProvider'] NMessageProvider: typeof import("naive-ui")["NMessageProvider"]
NModal: typeof import('naive-ui')['NModal'] NModal: typeof import("naive-ui")["NModal"]
NPagination: typeof import('naive-ui')['NPagination'] NPagination: typeof import("naive-ui")["NPagination"]
NPopover: typeof import('naive-ui')['NPopover'] NPopover: typeof import("naive-ui")["NPopover"]
NScrollbar: typeof import('naive-ui')['NScrollbar'] NScrollbar: typeof import("naive-ui")["NScrollbar"]
NSelect: typeof import('naive-ui')['NSelect'] NSelect: typeof import("naive-ui")["NSelect"]
NSpace: typeof import('naive-ui')['NSpace'] NSpace: typeof import("naive-ui")["NSpace"]
NSwitch: typeof import('naive-ui')['NSwitch'] NSwitch: typeof import("naive-ui")["NSwitch"]
NTabPane: typeof import('naive-ui')['NTabPane'] NTabPane: typeof import("naive-ui")["NTabPane"]
NTabs: typeof import('naive-ui')['NTabs'] NTabs: typeof import("naive-ui")["NTabs"]
NTag: typeof import('naive-ui')['NTag'] NTag: typeof import("naive-ui")["NTag"]
NTooltip: typeof import('naive-ui')['NTooltip'] NTooltip: typeof import("naive-ui")["NTooltip"]
NUpload: typeof import('naive-ui')['NUpload'] NUpload: typeof import("naive-ui")["NUpload"]
RouterLink: typeof import('vue-router')['RouterLink'] RouterLink: typeof import("vue-router")["RouterLink"]
RouterView: typeof import('vue-router')['RouterView'] RouterView: typeof import("vue-router")["RouterView"]
} }
} }

View File

@@ -44,9 +44,7 @@ export async function getProblemList(
params[element] = searchParams[element] params[element] = searchParams[element]
} }
}) })
const res = await http.get("problem", { const res = await http.get("problem", { params })
params,
})
return { return {
results: res.data.results.map(filterResult), results: res.data.results.map(filterResult),
total: res.data.total, total: res.data.total,

View File

@@ -1,7 +1,8 @@
import { RouteRecordRaw } from "vue-router" import { RouteRecordRaw } from "vue-router"
import { getProfile } from "./shared/api" import { getProfile } from "./shared/api"
import { loadChart } from "./shared/composables/chart" import { loadChart } from "./shared/composables/chart"
import { USER_TYPE } from "./utils/constants" import { STORAGE_KEY, USER_TYPE } from "./utils/constants"
import storage from "./utils/storage"
export const routes: RouteRecordRaw[] = [ export const routes: RouteRecordRaw[] = [
{ {
@@ -97,13 +98,17 @@ 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 () => { beforeEnter: async () => {
if (!storage.get(STORAGE_KEY.AUTHED)) return "/"
const res = await getProfile() const res = await getProfile()
if (res.data.user.admin_type === USER_TYPE.REGULAR_USER) return "/" if (res.data.user.admin_type === USER_TYPE.REGULAR_USER) return "/"
}, },
children: [ children: [
{ path: "", name: "home", component: () => import("admin/index.vue") }, {
path: "",
name: "home",
component: () => import("~/admin/setting/home.vue"),
},
{ {
path: "config", path: "config",
name: "config", name: "config",
@@ -120,7 +125,7 @@ export const routes: RouteRecordRaw[] = [
component: () => import("admin/user/list.vue"), component: () => import("admin/user/list.vue"),
}, },
{ {
path: "user/import", path: "user/importing",
name: "user importing", name: "user importing",
component: () => import("admin/user/import.vue"), component: () => import("admin/user/import.vue"),
}, },

View File

@@ -1,10 +1,13 @@
<script setup lang="ts"> <script setup lang="ts">
import { MenuOption } from "naive-ui" import { MenuOption } from "naive-ui"
import { RouterLink } from "vue-router" import { RouterLink } from "vue-router"
import Login from "../Login.vue"
const route = useRoute() const route = useRoute()
const options: MenuOption[] = [ const options: MenuOption[] = [
{
label: () => h(RouterLink, { to: "/" }, { default: () => "返回 OJ" }),
key: "return to OJ",
},
{ {
label: () => h(RouterLink, { to: "/admin" }, { default: () => "首页" }), label: () => h(RouterLink, { to: "/admin" }, { default: () => "首页" }),
key: "home", key: "home",
@@ -42,7 +45,7 @@ const options: MenuOption[] = [
label: () => label: () =>
h( h(
RouterLink, RouterLink,
{ to: "/admin/user/import" }, { to: "/admin/user/importing" },
{ default: () => "导入用户" } { default: () => "导入用户" }
), ),
key: "user importing", key: "user importing",
@@ -91,15 +94,10 @@ const active = computed(() => (route.name as string) || "home")
<n-layout-sider bordered :native-scrollbar="false"> <n-layout-sider bordered :native-scrollbar="false">
<n-menu :options="options" :value="active" /> <n-menu :options="options" :value="active" />
</n-layout-sider> </n-layout-sider>
<n-layout-content :native-scrollbar="false"> <n-layout-content :native-scrollbar="false" content-style="padding: 16px">
<router-view></router-view> <router-view></router-view>
</n-layout-content> </n-layout-content>
<Login />
</n-layout> </n-layout>
</template> </template>
<style scoped> <style scoped></style>
.content {
padding: 16px;
}
</style>

View File

@@ -9,7 +9,7 @@ import Header from "../Header.vue"
<n-layout-header bordered class="header"> <n-layout-header bordered class="header">
<Header /> <Header />
</n-layout-header> </n-layout-header>
<n-layout-content class="content"> <n-layout-content content-style="padding: 16px">
<router-view></router-view> <router-view></router-view>
</n-layout-content> </n-layout-content>
<Login /> <Login />
@@ -21,7 +21,4 @@ import Header from "../Header.vue"
.header { .header {
padding: 8px; padding: 8px;
} }
.content {
padding: 16px;
}
</style> </style>