learn.
This commit is contained in:
1
src/components.d.ts
vendored
1
src/components.d.ts
vendored
@@ -9,6 +9,7 @@ export {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
export interface GlobalComponents {
|
||||
IEpArrowRightBold: typeof import('~icons/ep/arrow-right-bold')['default']
|
||||
IEpBell: typeof import('~icons/ep/bell')['default']
|
||||
IEpCaretRight: typeof import('~icons/ep/caret-right')['default']
|
||||
IEpLoading: typeof import('~icons/ep/loading')['default']
|
||||
|
||||
@@ -1,23 +1,17 @@
|
||||
<script setup lang="ts">
|
||||
import { isDesktop } from "~/shared/composables/breakpoints"
|
||||
import { code } from "~/shared/composables/learn"
|
||||
import { useLearnStore } from "./store"
|
||||
|
||||
const CodeEditor = defineAsyncComponent(() => import("~/shared/CodeEditor.vue"))
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const learnStore = useLearnStore()
|
||||
|
||||
const TOTAL = 3
|
||||
|
||||
const Mds = Array.from({ length: TOTAL }, (_, i) => i + 1).map((v) =>
|
||||
const Mds = Array.from({ length: learnStore.total }, (_, i) => i + 1).map((v) =>
|
||||
defineAsyncComponent(() => import(`./step-${v}/index.md`))
|
||||
)
|
||||
const step = computed(() => {
|
||||
if (!route.params.step || !route.params.step.length) return 1
|
||||
else {
|
||||
return parseInt(route.params.step[0].split("-")[1])
|
||||
}
|
||||
})
|
||||
|
||||
watch(
|
||||
() => route.params.step,
|
||||
@@ -32,45 +26,38 @@ watch(
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
function prev() {
|
||||
router.push(`/learn/step-${step.value - 1}`)
|
||||
}
|
||||
function next() {
|
||||
router.push(`/learn/step-${step.value + 1}`)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-grid v-if="isDesktop" :cols="24">
|
||||
<n-gi :span="10">
|
||||
<n-grid v-if="isDesktop" :cols="22">
|
||||
<n-gi :span="2">
|
||||
<n-scrollbar style="max-height: calc(100vh - 92px)">
|
||||
<component :is="Mds[step - 1]"></component>
|
||||
<n-space justify="space-around">
|
||||
<n-button v-if="step !== 1" text type="primary" @click="prev">
|
||||
上一步
|
||||
</n-button>
|
||||
<n-button v-if="step !== TOTAL" text type="primary" @click="next">
|
||||
下一步
|
||||
<n-space vertical>
|
||||
<span>目录</span>
|
||||
<n-button
|
||||
text
|
||||
:type="learnStore.current === title.key ? 'primary' : 'default'"
|
||||
v-for="title in learnStore.menu"
|
||||
:key="title.key"
|
||||
@click="title.props?.onClick"
|
||||
>
|
||||
{{ title.label }}
|
||||
</n-button>
|
||||
</n-space>
|
||||
</n-scrollbar>
|
||||
</n-gi>
|
||||
<n-gi :span="14">
|
||||
<CodeEditor v-model="code" />
|
||||
<n-gi :span="10">
|
||||
<n-scrollbar style="max-height: calc(100vh - 92px)">
|
||||
<component :is="Mds[learnStore.current - 1]"></component>
|
||||
</n-scrollbar>
|
||||
</n-gi>
|
||||
<n-gi :span="10">
|
||||
<CodeEditor v-model="code" height="calc(100vh - 92px)" />
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
<div v-else>
|
||||
<n-scrollbar style="height: calc(50vh - 42px)">
|
||||
<component :is="Mds[step - 1]"></component>
|
||||
<n-space justify="space-around">
|
||||
<n-button v-if="step !== 1" text type="primary" @click="prev">
|
||||
上一步
|
||||
</n-button>
|
||||
<n-button v-if="step !== TOTAL" text type="primary" @click="next">
|
||||
下一步
|
||||
</n-button>
|
||||
</n-space>
|
||||
<component :is="Mds[learnStore.current - 1]"></component>
|
||||
</n-scrollbar>
|
||||
<CodeEditor v-model="code" height="calc(50vh - 42px)" />
|
||||
</div>
|
||||
|
||||
24
src/learn/menu.md
Normal file
24
src/learn/menu.md
Normal file
@@ -0,0 +1,24 @@
|
||||
我是第一步
|
||||
我是第二步
|
||||
我是第三步
|
||||
我是第一步
|
||||
我是第二步
|
||||
我是第三步
|
||||
我是第一步
|
||||
我是第二步
|
||||
我是第三步
|
||||
我是第一步
|
||||
我是第二步
|
||||
我是第三步
|
||||
我是第一步
|
||||
我是第二步
|
||||
我是第三步
|
||||
我是第一步
|
||||
我是第二步
|
||||
我是第三步
|
||||
我是第一步
|
||||
我是第二步
|
||||
我是第三步
|
||||
我是第一步
|
||||
我是第二步
|
||||
我是第三步
|
||||
39
src/learn/store.ts
Normal file
39
src/learn/store.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import sidebar from "./menu.md?raw"
|
||||
|
||||
export const useLearnStore = defineStore("learn", () => {
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const current = computed(() => {
|
||||
if (!route.params.step || !route.params.step.length) return 1
|
||||
else {
|
||||
return parseInt(route.params.step[0].split("-")[1])
|
||||
}
|
||||
})
|
||||
|
||||
const menu: DropdownOption[] = sidebar
|
||||
.split("\n")
|
||||
.filter((title) => !!title)
|
||||
.map((title: string, index) => {
|
||||
return {
|
||||
key: index + 1,
|
||||
label: title,
|
||||
props: {
|
||||
onClick: () => {
|
||||
router.push(`/learn/step-${index + 1}`)
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
function go(step: number) {
|
||||
router.push(`/learn/step-${step}`)
|
||||
}
|
||||
|
||||
return {
|
||||
total: menu.length,
|
||||
current,
|
||||
menu,
|
||||
go,
|
||||
}
|
||||
})
|
||||
@@ -7,9 +7,11 @@ import { toggleLogin, toggleSignup } from "~/shared/composables/modal"
|
||||
import { RouterLink } from "vue-router"
|
||||
import { isDesktop, isMobile } from "~/shared/composables/breakpoints"
|
||||
import { code } from "~/shared/composables/learn"
|
||||
import { useLearnStore } from "~/learn/store"
|
||||
|
||||
const userStore = useUserStore()
|
||||
const configStore = useConfigStore()
|
||||
const learnStore = useLearnStore()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const active = computed(() => {
|
||||
@@ -96,7 +98,7 @@ function goHome() {
|
||||
<template>
|
||||
<n-space justify="space-between" align="center">
|
||||
<n-space align="center">
|
||||
<div class="websiteTitle" @click="goHome">
|
||||
<div v-if="isDesktop" class="websiteTitle" @click="goHome">
|
||||
{{ configStore.config?.website_name }}
|
||||
</div>
|
||||
<n-menu
|
||||
@@ -107,9 +109,23 @@ function goHome() {
|
||||
/>
|
||||
</n-space>
|
||||
<n-space align="center">
|
||||
<n-button v-if="$route.name === 'learn'" type="primary" @click="run">
|
||||
运行
|
||||
</n-button>
|
||||
<n-dropdown
|
||||
v-if="$route.name === 'learn' && isMobile"
|
||||
trigger="click"
|
||||
:options="learnStore.menu"
|
||||
>
|
||||
<n-button>目录</n-button>
|
||||
</n-dropdown>
|
||||
<div v-if="$route.name === 'learn'">
|
||||
<n-button v-if="isDesktop" type="primary" @click="run">
|
||||
运行代码
|
||||
</n-button>
|
||||
<n-button v-else circle @click="run">
|
||||
<n-icon>
|
||||
<i-ep-arrow-right-bold />
|
||||
</n-icon>
|
||||
</n-button>
|
||||
</div>
|
||||
<n-dropdown v-if="isMobile" :options="menus" trigger="click">
|
||||
<n-button>菜单</n-button>
|
||||
</n-dropdown>
|
||||
|
||||
@@ -17,13 +17,6 @@ export function filterEmptyValue(object: any) {
|
||||
return query
|
||||
}
|
||||
|
||||
export function buildProblemCodeKey(problemID: string, contestID = "") {
|
||||
if (contestID) {
|
||||
return `${STORAGE_KEY.PROBLEM_CODE}_${contestID}_${problemID}`
|
||||
}
|
||||
return `${STORAGE_KEY.PROBLEM_CODE}_NaN_${problemID}`
|
||||
}
|
||||
|
||||
export function getTagColor(
|
||||
tag: "Low" | "Mid" | "High" | "简单" | "中等" | "困难"
|
||||
) {
|
||||
|
||||
@@ -38,8 +38,6 @@ export default defineConfig({
|
||||
],
|
||||
"codemirror-lang": [
|
||||
"@codemirror/lang-cpp",
|
||||
"@codemirror/lang-javascript",
|
||||
"@codemirror/lang-java",
|
||||
"@codemirror/lang-python",
|
||||
],
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user