add user/setting page.
This commit is contained in:
3
src/oj/user/index.vue
Normal file
3
src/oj/user/index.vue
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<script setup lang="ts"></script>
|
||||||
|
<template></template>
|
||||||
|
<style scoped></style>
|
||||||
3
src/oj/user/setting.vue
Normal file
3
src/oj/user/setting.vue
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<script setup lang="ts"></script>
|
||||||
|
<template></template>
|
||||||
|
<style scoped></style>
|
||||||
@@ -71,6 +71,16 @@ export const routes: RouteRecordRaw[] = [
|
|||||||
component: () => import("oj/rank/list.vue"),
|
component: () => import("oj/rank/list.vue"),
|
||||||
beforeEnter: loadChart,
|
beforeEnter: loadChart,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "user",
|
||||||
|
component: () => import("oj/user/index.vue"),
|
||||||
|
meta: { requiresAuth: true },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "setting",
|
||||||
|
component: () => import("oj/user/setting.vue"),
|
||||||
|
meta: { requiresAuth: true },
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "learn",
|
path: "learn",
|
||||||
redirect: "learn/step-1",
|
redirect: "learn/step-1",
|
||||||
|
|||||||
@@ -15,25 +15,19 @@ import { code } from "~/shared/composables/learn"
|
|||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const active = computed(() => {
|
||||||
|
const path = route.path.split("/")[1] || "problem"
|
||||||
|
return !["user", "setting"].includes(path) ? path : ""
|
||||||
|
})
|
||||||
|
|
||||||
async function handleLogout() {
|
async function handleLogout() {
|
||||||
await logout()
|
await logout()
|
||||||
userStore.clearMyProfile()
|
userStore.clearProfile()
|
||||||
router.replace("/")
|
router.replace("/")
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDropdown(key: string) {
|
|
||||||
switch (key) {
|
|
||||||
case "logout":
|
|
||||||
handleLogout()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(userStore.getMyProfile)
|
onMounted(userStore.getMyProfile)
|
||||||
|
|
||||||
const defaultValue = computed(() => route.path.split("/")[1] || "problem")
|
|
||||||
|
|
||||||
const menus: MenuOption[] = [
|
const menus: MenuOption[] = [
|
||||||
{
|
{
|
||||||
label: () =>
|
label: () =>
|
||||||
@@ -60,12 +54,30 @@ const menus: MenuOption[] = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
const options = computed<Array<DropdownOption | DropdownDividerOption>>(() => [
|
const options = computed<Array<DropdownOption | DropdownDividerOption>>(() => [
|
||||||
{ label: "我的主页", key: "home" },
|
{
|
||||||
{ label: "我的提交", key: "status" },
|
label: "我的主页",
|
||||||
{ label: "我的设置", key: "setting" },
|
key: "home",
|
||||||
|
props: {
|
||||||
|
onClick: () => router.push("/user"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "我的提交",
|
||||||
|
key: "status",
|
||||||
|
props: {
|
||||||
|
onClick: () => router.push("/submission?myself=1"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "我的设置",
|
||||||
|
key: "setting",
|
||||||
|
props: {
|
||||||
|
onClick: () => router.push("/setting"),
|
||||||
|
},
|
||||||
|
},
|
||||||
{ label: "后台管理", key: "admin", show: userStore.isAdminRole },
|
{ label: "后台管理", key: "admin", show: userStore.isAdminRole },
|
||||||
{ type: "divider" },
|
{ type: "divider" },
|
||||||
{ label: "退出", key: "logout" },
|
{ label: "退出", key: "logout", props: { onClick: handleLogout } },
|
||||||
])
|
])
|
||||||
|
|
||||||
function run() {
|
function run() {
|
||||||
@@ -75,7 +87,7 @@ function run() {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<n-space v-if="isDesktop" justify="space-between" align="center">
|
<n-space v-if="isDesktop" justify="space-between" align="center">
|
||||||
<n-menu mode="horizontal" :options="menus" :default-value="defaultValue" />
|
<n-menu mode="horizontal" :options="menus" :value="active" />
|
||||||
<n-space>
|
<n-space>
|
||||||
<n-button circle @click="toggleDark()">
|
<n-button circle @click="toggleDark()">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
@@ -88,7 +100,6 @@ function run() {
|
|||||||
v-if="userStore.isAuthed"
|
v-if="userStore.isAuthed"
|
||||||
:options="options"
|
:options="options"
|
||||||
trigger="click"
|
trigger="click"
|
||||||
@select="handleDropdown"
|
|
||||||
>
|
>
|
||||||
<n-button>{{ userStore.user.username }}</n-button>
|
<n-button>{{ userStore.user.username }}</n-button>
|
||||||
</n-dropdown>
|
</n-dropdown>
|
||||||
@@ -106,12 +117,7 @@ function run() {
|
|||||||
<n-button v-if="$route.name === 'learn'" type="primary" @click="run">
|
<n-button v-if="$route.name === 'learn'" type="primary" @click="run">
|
||||||
运行
|
运行
|
||||||
</n-button>
|
</n-button>
|
||||||
<n-dropdown
|
<n-dropdown v-if="userStore.isAuthed" :options="options" trigger="click">
|
||||||
v-if="userStore.isAuthed"
|
|
||||||
:options="options"
|
|
||||||
@select="handleDropdown"
|
|
||||||
trigger="click"
|
|
||||||
>
|
|
||||||
<n-button>{{ userStore.user.username }}</n-button>
|
<n-button>{{ userStore.user.username }}</n-button>
|
||||||
</n-dropdown>
|
</n-dropdown>
|
||||||
<n-space v-else>
|
<n-space v-else>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export const useUserStore = defineStore("user", () => {
|
|||||||
storage.set(STORAGE_KEY.AUTHED, !!user.value.email)
|
storage.set(STORAGE_KEY.AUTHED, !!user.value.email)
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearMyProfile() {
|
function clearProfile() {
|
||||||
profile.value = {}
|
profile.value = {}
|
||||||
storage.clear()
|
storage.clear()
|
||||||
}
|
}
|
||||||
@@ -40,6 +40,6 @@ export const useUserStore = defineStore("user", () => {
|
|||||||
hasProblemPermission,
|
hasProblemPermission,
|
||||||
isAuthed,
|
isAuthed,
|
||||||
getMyProfile,
|
getMyProfile,
|
||||||
clearMyProfile,
|
clearProfile,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user