教程的标题
This commit is contained in:
@@ -114,14 +114,11 @@ async function markAllAsChecked() {
|
||||
// 过滤后的提交列表
|
||||
const filteredSubmissions = computed(() => {
|
||||
return submissions.value.filter((item) => {
|
||||
if (query.username && !item.username.includes(query.username))
|
||||
return false
|
||||
if (query.username && !item.username.includes(query.username)) return false
|
||||
if (query.problemId && !item.problem_display_id.includes(query.problemId))
|
||||
return false
|
||||
if (query.checked === "checked" && !item.checked)
|
||||
return false
|
||||
if (query.checked === "unchecked" && item.checked)
|
||||
return false
|
||||
if (query.checked === "checked" && !item.checked) return false
|
||||
if (query.checked === "unchecked" && item.checked) return false
|
||||
return true
|
||||
})
|
||||
})
|
||||
@@ -254,12 +251,8 @@ onMounted(loadData)
|
||||
<n-flex justify="space-between" align="center">
|
||||
<n-flex align="center">
|
||||
<h2 style="margin: 0">比赛辅助检查</h2>
|
||||
<n-tag type="info" size="large">
|
||||
总计: {{ stats.total }}
|
||||
</n-tag>
|
||||
<n-tag type="success" size="large">
|
||||
已检查: {{ stats.checked }}
|
||||
</n-tag>
|
||||
<n-tag type="info" size="large"> 总计: {{ stats.total }} </n-tag>
|
||||
<n-tag type="success" size="large"> 已检查: {{ stats.checked }} </n-tag>
|
||||
<n-tag type="warning" size="large">
|
||||
未检查: {{ stats.unchecked }}
|
||||
</n-tag>
|
||||
@@ -328,4 +321,3 @@ onMounted(loadData)
|
||||
margin-top: 16px;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -1,71 +1,49 @@
|
||||
<template>
|
||||
<n-grid :cols="2" :x-gap="24" v-if="!!tutorial.id">
|
||||
<n-grid :cols="5" :x-gap="16" v-if="tutorial.id">
|
||||
<n-gi :span="1">
|
||||
<n-flex vertical>
|
||||
<n-flex align="center">
|
||||
<n-button text :disabled="step == 1" @click="prev">
|
||||
<Icon :width="30" icon="pepicons-pencil:arrow-left"></Icon>
|
||||
</n-button>
|
||||
<n-dropdown size="large" :options="menu" trigger="click">
|
||||
<n-button tertiary style="flex: 1" size="large">
|
||||
<n-flex align="center">
|
||||
<span style="font-weight: bold">
|
||||
{{ title }}
|
||||
</span>
|
||||
<Icon :width="24" icon="proicons:chevron-down"></Icon>
|
||||
</n-flex>
|
||||
</n-button>
|
||||
</n-dropdown>
|
||||
<n-button text :disabled="step == titles.length" @click="next">
|
||||
<Icon :width="30" icon="pepicons-pencil:arrow-right"></Icon>
|
||||
</n-button>
|
||||
</n-flex>
|
||||
<n-flex vertical size="large">
|
||||
<MdPreview
|
||||
preview-theme="vuepress"
|
||||
:theme="isDark ? 'dark' : 'light'"
|
||||
:model-value="tutorial.content"
|
||||
/>
|
||||
<n-flex justify="space-between">
|
||||
<div style="flex: 1">
|
||||
<n-button
|
||||
block
|
||||
style="height: 40px"
|
||||
v-if="step !== 1"
|
||||
@click="prev"
|
||||
<n-card title="目录" :bordered="false" size="small">
|
||||
<n-scrollbar :style="{ maxHeight: 'calc(100vh - 180px)' }">
|
||||
<n-list hoverable clickable>
|
||||
<n-list-item
|
||||
v-for="(item, index) in titles"
|
||||
:key="item.id"
|
||||
@click="goToLesson(index + 1)"
|
||||
>
|
||||
<n-text
|
||||
:type="step === index + 1 ? 'primary' : undefined"
|
||||
:strong="step === index + 1"
|
||||
>
|
||||
上一课时
|
||||
</n-button>
|
||||
</div>
|
||||
<div style="flex: 1">
|
||||
<n-button
|
||||
block
|
||||
style="height: 40px"
|
||||
v-if="step !== titles.length"
|
||||
@click="next"
|
||||
>
|
||||
下一课时
|
||||
</n-button>
|
||||
</div>
|
||||
</n-flex>
|
||||
</n-flex>
|
||||
</n-flex>
|
||||
{{ index + 1 }}. {{ item.title }}
|
||||
</n-text>
|
||||
</n-list-item>
|
||||
</n-list>
|
||||
</n-scrollbar>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
<n-gi :span="1">
|
||||
<n-flex vertical>
|
||||
<CodeEditor
|
||||
v-show="!!tutorial.code"
|
||||
language="Python3"
|
||||
v-model="tutorial.code"
|
||||
|
||||
<n-gi :span="tutorial.code ? 2 : 4">
|
||||
<n-card
|
||||
:title="`第 ${step} 课:${titles[step - 1]?.title}`"
|
||||
:bordered="false"
|
||||
size="small"
|
||||
>
|
||||
<MdPreview
|
||||
preview-theme="vuepress"
|
||||
:theme="isDark ? 'dark' : 'light'"
|
||||
:model-value="tutorial.content"
|
||||
/>
|
||||
</n-flex>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
|
||||
<n-gi :span="2" v-if="tutorial.code">
|
||||
<n-card title="示例代码" :bordered="false" size="small">
|
||||
<CodeEditor language="Python3" v-model="tutorial.code" />
|
||||
</n-card>
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Icon } from "@iconify/vue"
|
||||
|
||||
import { MdPreview } from "md-editor-v3"
|
||||
import "md-editor-v3/lib/preview.css"
|
||||
import { Tutorial } from "utils/types"
|
||||
@@ -94,23 +72,11 @@ const tutorial = ref<Partial<Tutorial>>({
|
||||
})
|
||||
|
||||
const titles = ref<{ id: number; title: string }[]>([])
|
||||
const title = computed(
|
||||
() => `第 ${step.value} 课:${titles.value[step.value - 1].title}`,
|
||||
)
|
||||
|
||||
const menu = computed<DropdownOption[]>(() => {
|
||||
return titles.value.map((item, index) => {
|
||||
const id = (index + 1).toString().padStart(2, "0")
|
||||
const prefix = `第 ${index + 1} 课:`
|
||||
return {
|
||||
key: id,
|
||||
label: prefix + item.title,
|
||||
props: {
|
||||
onClick: () => router.push(`/learn/${id}`),
|
||||
},
|
||||
}
|
||||
})
|
||||
})
|
||||
function goToLesson(lessonNumber: number) {
|
||||
const dest = lessonNumber.toString().padStart(2, "0")
|
||||
router.push("/learn/" + dest)
|
||||
}
|
||||
|
||||
async function init() {
|
||||
const res1 = await getTutorials()
|
||||
@@ -121,18 +87,6 @@ async function init() {
|
||||
tutorial.value = res2.data
|
||||
}
|
||||
|
||||
function next() {
|
||||
if (step.value === titles.value.length) return
|
||||
const dest = (step.value + 1).toString().padStart(2, "0")
|
||||
router.push("/learn/" + dest)
|
||||
}
|
||||
|
||||
function prev() {
|
||||
if (step.value === 1) return
|
||||
const dest = (step.value - 1).toString().padStart(2, "0")
|
||||
router.push("/learn/" + dest)
|
||||
}
|
||||
|
||||
watch(
|
||||
() => route.params.step,
|
||||
async () => {
|
||||
@@ -143,8 +97,8 @@ watch(
|
||||
)
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.md-editor-preview .md-editor-code .md-editor-code-head {
|
||||
<style scoped>
|
||||
:deep(.md-editor-preview .md-editor-code .md-editor-code-head) {
|
||||
z-index: 100;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -86,9 +86,7 @@ const languageOptions: DropdownOption[] = problem.value!.languages.map(
|
||||
:options="languageOptions"
|
||||
@update:value="changeLanguage"
|
||||
/>
|
||||
<n-button @click="copy">
|
||||
复制代码
|
||||
</n-button>
|
||||
<n-button @click="copy">复制代码</n-button>
|
||||
<n-button @click="reset">重置代码</n-button>
|
||||
<n-button type="primary" secondary @click="runCode">
|
||||
运行代码
|
||||
|
||||
@@ -204,116 +204,138 @@ function type(status: ProblemStatus) {
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.problemContent .problemTitle {
|
||||
<style scoped>
|
||||
.problemContent {
|
||||
--border-color-light: rgb(239, 239, 245);
|
||||
--bg-code-light: rgb(250, 250, 252);
|
||||
--bg-code-dark: rgb(24, 24, 28);
|
||||
--bg-table-light: rgba(250, 250, 252, 1);
|
||||
--bg-table-dark: rgba(38, 38, 42, 1);
|
||||
--border-color-dark: rgba(255, 255, 255, 0.09);
|
||||
--blockquote-color: #7b7b7b;
|
||||
--blockquote-border: #bbbec4;
|
||||
--link-color: #18a058;
|
||||
--transition: 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.problemTitle {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.problemContent .title {
|
||||
.title {
|
||||
font-size: 20px;
|
||||
margin: 12px 0;
|
||||
}
|
||||
|
||||
.problemContent .content {
|
||||
.testcase {
|
||||
font-size: 14px;
|
||||
white-space: pre;
|
||||
font-family: "Monaco", monospace;
|
||||
}
|
||||
|
||||
.status-alert {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.content {
|
||||
font-size: 16px;
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
.problemContent .testcase {
|
||||
font-size: 14px;
|
||||
white-space: pre;
|
||||
font-family: "Monaco";
|
||||
}
|
||||
|
||||
.problemContent .status-alert {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.problemContent .content > p {
|
||||
/* 针对 v-html 渲染内容的深度样式 */
|
||||
.content :deep(p) {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.problemContent .content > blockquote {
|
||||
border-left: 3px solid #bbbec4;
|
||||
.content :deep(blockquote) {
|
||||
border-left: 3px solid var(--blockquote-border);
|
||||
padding-left: 10px;
|
||||
margin: 10px 0;
|
||||
color: #7b7b7b;
|
||||
color: var(--blockquote-color);
|
||||
}
|
||||
|
||||
.problemContent .content > pre {
|
||||
.content :deep(pre) {
|
||||
width: 100%;
|
||||
background-color: rgb(250, 250, 252);
|
||||
border: 1px solid rgb(239, 239, 245);
|
||||
background-color: var(--bg-code-light);
|
||||
border: 1px solid var(--border-color-light);
|
||||
word-break: break-word;
|
||||
box-sizing: border-box;
|
||||
transition:
|
||||
background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||
border-color 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
background-color var(--transition),
|
||||
border-color var(--transition);
|
||||
}
|
||||
|
||||
.problemContent .content > pre > code {
|
||||
font-family: "Monaco";
|
||||
.content :deep(pre code) {
|
||||
font-family: "Monaco", monospace;
|
||||
}
|
||||
|
||||
.dark .problemContent .content > pre {
|
||||
background-color: rgb(24, 24, 28);
|
||||
border-color: rgba(255, 255, 255, 0.09);
|
||||
.dark .content :deep(pre) {
|
||||
background-color: var(--bg-code-dark);
|
||||
border-color: var(--border-color-dark);
|
||||
}
|
||||
|
||||
.problemContent .content > table {
|
||||
.content :deep(table) {
|
||||
width: 100%;
|
||||
border-spacing: 0;
|
||||
border: 1px solid rgba(239, 239, 245, 1);
|
||||
border: 1px solid var(--border-color-light);
|
||||
transition:
|
||||
background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||
border-color 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
background-color var(--transition),
|
||||
border-color var(--transition);
|
||||
}
|
||||
|
||||
.problemContent .content > table th {
|
||||
background-color: rgba(250, 250, 252, 1);
|
||||
.content :deep(table th) {
|
||||
background-color: var(--bg-table-light);
|
||||
padding: 8px;
|
||||
transition:
|
||||
background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||
border-color 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
background-color var(--transition),
|
||||
border-color var(--transition);
|
||||
}
|
||||
|
||||
.dark .problemContent .content > table th {
|
||||
background-color: rgba(38, 38, 42, 1);
|
||||
.dark .content :deep(table th) {
|
||||
background-color: var(--bg-table-dark);
|
||||
}
|
||||
|
||||
.problemContent .content > table td {
|
||||
.content :deep(table td) {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.problemContent .content > table td,
|
||||
.problemContent .content > table th {
|
||||
border-right: 1px solid rgba(239, 239, 245, 1);
|
||||
border-bottom: 1px solid rgba(239, 239, 245, 1);
|
||||
.content :deep(table td),
|
||||
.content :deep(table th) {
|
||||
border-right: 1px solid var(--border-color-light);
|
||||
border-bottom: 1px solid var(--border-color-light);
|
||||
}
|
||||
|
||||
.problemContent .content > table th:last-child,
|
||||
.problemContent .content > table td:last-child {
|
||||
border-right: 0px solid rgba(239, 239, 245, 1);
|
||||
.content :deep(table th:last-child),
|
||||
.content :deep(table td:last-child) {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.problemContent .content > table tr:last-child td {
|
||||
border-bottom: 0px solid rgba(239, 239, 245, 1);
|
||||
.content :deep(table tr:last-child td) {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.problemContent .content > p > code {
|
||||
.content :deep(p code) {
|
||||
font-size: 90%;
|
||||
padding: 2px 5px;
|
||||
margin: 0px 4px;
|
||||
margin: 0 4px;
|
||||
background-color: rgba(27, 31, 35, 0.05);
|
||||
border-radius: 3px;
|
||||
line-height: 1.5;
|
||||
font-family: "Monaco", monospace;
|
||||
}
|
||||
|
||||
.problemContent .content img {
|
||||
max-width: 100% !important;
|
||||
height: 100% !important;
|
||||
.content :deep(img) {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.problemContent .content a {
|
||||
color: #18a058;
|
||||
.content :deep(a) {
|
||||
color: var(--link-color);
|
||||
text-decoration: none;
|
||||
transition: opacity var(--transition);
|
||||
}
|
||||
|
||||
.content :deep(a:hover) {
|
||||
opacity: 0.8;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -8,7 +8,7 @@ export const useConfigStore = defineStore("config", () => {
|
||||
website_name_shortcut: "",
|
||||
website_footer: "",
|
||||
submission_list_show_all: true,
|
||||
allow_register: true,
|
||||
allow_register: false,
|
||||
class_list: [],
|
||||
})
|
||||
async function getConfig() {
|
||||
|
||||
Reference in New Issue
Block a user