重构主题切换和题目页面的切换

This commit is contained in:
2024-07-05 13:05:02 +08:00
parent fdf0de9db1
commit 2e260db9e5
4 changed files with 91 additions and 84 deletions

View File

@@ -2,7 +2,11 @@
import { getProblem } from "oj/api"
import { ScreenMode } from "utils/constants"
import { isDesktop, isMobile } from "~/shared/composables/breakpoints"
import { screenMode } from "~/shared/composables/switchScreen"
import {
bothAndProblem,
resetScreenMode,
screenMode,
} from "~/shared/composables/switchScreen"
import { problem } from "../composables/problem"
const Editor = defineAsyncComponent(() => import("./components/Editor.vue"))
@@ -33,14 +37,8 @@ const props = withDefaults(defineProps<Props>(), {
const errMsg = ref("无数据")
const bothAndProblem = computed(
() =>
screenMode.value === ScreenMode.both ||
screenMode.value === ScreenMode.problem,
)
async function init() {
screenMode.value = ScreenMode.both
resetScreenMode()
try {
const res = await getProblem(props.problemID, props.contestID)
problem.value = res.data
@@ -55,13 +53,11 @@ onMounted(init)
onBeforeUnmount(() => {
problem.value = null
errMsg.value = "无数据"
screenMode.value = ScreenMode.both
resetScreenMode()
})
watch(isMobile, (value) => {
if (value) {
screenMode.value = ScreenMode.both
}
if (value) resetScreenMode()
})
</script>

View File

@@ -3,10 +3,8 @@ import { Icon } from "@iconify/vue"
import { RouterLink } from "vue-router"
import { isDesktop, isMobile } from "~/shared/composables/breakpoints"
import { toggleLogin, toggleSignup } from "~/shared/composables/modal"
import {
screenSwitchLabel,
switchScreenMode,
} from "~/shared/composables/switchScreen"
import { screenMode, switchScreenMode } from "~/shared/composables/switchScreen"
import { avatar, getRandomAvatar } from "~/utils/constants"
import { logout } from "../api"
import { useConfigStore } from "../store/config"
import { useUserStore } from "../store/user"
@@ -32,35 +30,6 @@ function renderIcon(icon: string) {
return () => h(Icon, { icon, width: 24, height: 24 })
}
const avatars = [
"streamline-emojis:man-with-chinese-cap-1",
"streamline-emojis:cat-face",
"streamline-emojis:china",
"streamline-emojis:chicken",
"streamline-emojis:eyes",
"streamline-emojis:elephant",
"streamline-emojis:hear-no-evil-monkey",
"streamline-emojis:panda-face",
"streamline-emojis:penguin-1",
"streamline-emojis:rooster",
"streamline-emojis:star-struck-1",
"streamline-emojis:tomato",
"streamline-emojis:rocket",
"streamline-emojis:sparkles",
"streamline-emojis:money-bag",
"streamline-emojis:ghost",
"streamline-emojis:game-dice",
"streamline-emojis:ewe-1",
"streamline-emojis:artist-palette",
"streamline-emojis:baby-bottle",
]
const avatar = ref(avatars[Math.floor(Math.random() * avatars.length)])
function getRandomAvatar() {
avatar.value = avatars[Math.floor(Math.random() * avatars.length)]
}
onMounted(() => {
userStore.getMyProfile()
configStore.getConfig()
@@ -102,7 +71,7 @@ const menus = computed<MenuOption[]>(() => [
},
])
const options: Array<DropdownOption | DropdownDividerOption> = [
const options = computed<Array<DropdownOption | DropdownDividerOption>>(() => [
{
label: "我的主页",
key: "home",
@@ -135,6 +104,18 @@ const options: Array<DropdownOption | DropdownDividerOption> = [
onClick: () => router.push("/setting"),
},
},
{
label: isDark.value ? "浅色主题" : "深色主题",
key: "theme",
icon: renderIcon(
isDark.value
? "twemoji:sun-behind-small-cloud"
: "twemoji:cloud-with-lightning-and-rain",
),
props: {
onClick: () => toggleDark(),
},
},
{ type: "divider" },
{
label: "退出",
@@ -142,7 +123,7 @@ const options: Array<DropdownOption | DropdownDividerOption> = [
icon: renderIcon("streamline-emojis:hot-beverage-2"),
props: { onClick: handleLogout },
},
]
])
function goHome() {
router.push("/")
@@ -150,20 +131,22 @@ function goHome() {
</script>
<template>
<n-space justify="space-between" align="center">
<n-space align="center">
<n-flex justify="space-between" align="center">
<n-flex align="center">
<n-flex align="center" class="title" @click="goHome">
<Icon icon="streamline-emojis:dog" :width="30" :height="30"></Icon>
<div v-if="isDesktop">{{ configStore.config?.website_name }}</div>
</n-flex>
<div>
<n-menu
v-if="isDesktop"
mode="horizontal"
:options="menus"
:value="active"
/>
</n-space>
<n-space align="center">
</div>
</n-flex>
<n-flex align="center">
<n-dropdown v-if="isMobile" :options="menus" size="large">
<n-button>菜单</n-button>
</n-dropdown>
@@ -172,9 +155,9 @@ function goHome() {
isDesktop &&
(route.name === 'problem' || route.name === 'contest problem')
"
@click="switchScreenMode"
@click="() => switchScreenMode()"
>
{{ screenSwitchLabel }}
{{ screenMode }}
</n-button>
<div v-if="userStore.isFinished">
<n-dropdown v-if="userStore.isAuthed" :options="options" size="large">
@@ -186,8 +169,11 @@ function goHome() {
</n-button>
</n-dropdown>
<n-flex align="center" v-else>
<n-button @click="toggleLogin(true)">登录</n-button>
<n-button secondary type="primary" @click="toggleLogin(true)">
登录
</n-button>
<n-button
tertiary
v-if="configStore.config?.allow_register"
@click="toggleSignup(true)"
>
@@ -195,14 +181,8 @@ function goHome() {
</n-button>
</n-flex>
</div>
<n-button circle @click="toggleDark()">
<template #icon>
<Icon v-if="isDark" icon="ph:sun"></Icon>
<Icon v-else icon="ph:moon"></Icon>
</template>
</n-button>
</n-space>
</n-space>
</n-flex>
</n-flex>
</template>
<style scoped>

View File

@@ -1,17 +1,19 @@
import { ScreenMode } from "~/utils/constants"
export const screenMode = ref(ScreenMode.both)
export const { state: screenMode, next: switchScreenMode } = useCycleList(
Object.values(ScreenMode),
{
initialValue: ScreenMode.both,
},
)
export const screenSwitchLabel = computed(() => {
if (screenMode.value === ScreenMode.both) return "题目 | 自测"
else if (screenMode.value === ScreenMode.problem) return "仅题目"
return "仅自测"
})
export function switchScreenMode() {
if (screenMode.value === ScreenMode.both) {
screenMode.value = ScreenMode.problem
return
}
screenMode.value += 1
export function resetScreenMode() {
screenMode.value = ScreenMode.both
}
export const bothAndProblem = computed(
() =>
screenMode.value === ScreenMode.both ||
screenMode.value === ScreenMode.problem,
)

View File

@@ -271,7 +271,36 @@ export const CODE_TEMPLATES = {
}
export enum ScreenMode {
problem,
code,
both,
both = "题目 | 自测",
code = "仅自测",
problem = "仅题目",
}
const AVATARS = [
"streamline-emojis:man-with-chinese-cap-1",
"streamline-emojis:cat-face",
"streamline-emojis:china",
"streamline-emojis:chicken",
"streamline-emojis:eyes",
"streamline-emojis:elephant",
"streamline-emojis:hear-no-evil-monkey",
"streamline-emojis:panda-face",
"streamline-emojis:penguin-1",
"streamline-emojis:rooster",
"streamline-emojis:star-struck-1",
"streamline-emojis:tomato",
"streamline-emojis:rocket",
"streamline-emojis:sparkles",
"streamline-emojis:money-bag",
"streamline-emojis:ghost",
"streamline-emojis:game-dice",
"streamline-emojis:ewe-1",
"streamline-emojis:artist-palette",
"streamline-emojis:baby-bottle",
]
export const avatar = ref(AVATARS[Math.floor(Math.random() * AVATARS.length)])
export function getRandomAvatar() {
avatar.value = AVATARS[Math.floor(Math.random() * AVATARS.length)]
}