add challenge author
Some checks failed
Deploy / deploy (build, debian, 22) (push) Has been cancelled
Deploy / deploy (build:staging, school, 8822) (push) Has been cancelled

This commit is contained in:
2026-05-06 06:28:49 -06:00
parent 9a8e5ad48e
commit 77aca640ac
4 changed files with 46 additions and 7 deletions

View File

@@ -25,6 +25,9 @@
> >
</n-flex> </n-flex>
</template> </template>
<n-text depth="3" class="challenge-author">
出题人{{ item.author_name || "未设置" }}
</n-text>
</n-card> </n-card>
</n-flex> </n-flex>
</div> </div>
@@ -72,4 +75,9 @@ onMounted(async () => {
.submitted-title { .submitted-title {
color: #888; color: #888;
} }
.challenge-author {
display: block;
font-size: 13px;
}
</style> </style>

View File

@@ -34,12 +34,19 @@
</n-flex> </n-flex>
</template> </template>
<n-tab-pane name="desc" tab="挑战描述" display-directive="show"> <n-tab-pane name="desc" tab="挑战描述" display-directive="show">
<div class="desc-pane">
<div class="challenge-meta">
<n-text depth="3">
出题人{{ challengeAuthor || "未设置" }}
</n-text>
</div>
<div <div
class="markdown-body content no-select" class="markdown-body content no-select"
v-html="challengeContent" v-html="challengeContent"
ref="$desc" ref="$desc"
@copy.prevent @copy.prevent
/> />
</div>
</n-tab-pane> </n-tab-pane>
<n-tab-pane name="chat" tab="AI 对话" display-directive="show"> <n-tab-pane name="chat" tab="AI 对话" display-directive="show">
<PromptPanel /> <PromptPanel />
@@ -156,6 +163,7 @@ function setupCodeCopy() {
const activeTab = ref("desc") const activeTab = ref("desc")
const challengeContent = ref("") const challengeContent = ref("")
const challengeAuthor = ref("")
const $desc = useTemplateRef<HTMLElement>("$desc") const $desc = useTemplateRef<HTMLElement>("$desc")
const showCode = ref(false) const showCode = ref(false)
const showStats = ref(false) const showStats = ref(false)
@@ -176,6 +184,7 @@ async function loadChallenge() {
challengeDisplay.value = display challengeDisplay.value = display
const data = await Challenge.get(display) const data = await Challenge.get(display)
taskId.value = data.task_ptr taskId.value = data.task_ptr
challengeAuthor.value = data.author_name ?? ""
challengeContent.value = await marked.parse(data.content, { challengeContent.value = await marked.parse(data.content, {
async: true, async: true,
renderer: challengeRenderer, renderer: challengeRenderer,
@@ -272,10 +281,23 @@ onUnmounted(disconnectPrompt)
.content { .content {
padding: 12px; padding: 12px;
overflow-y: auto; overflow-y: auto;
height: 100%; flex: 1;
min-height: 0;
box-sizing: border-box; box-sizing: border-box;
} }
.desc-pane {
height: 100%;
display: flex;
flex-direction: column;
}
.challenge-meta {
padding: 10px 12px;
border-bottom: 1px solid var(--n-border-color, #efeff5);
flex-shrink: 0;
}
.no-select { .no-select {
user-select: none; user-select: none;
} }

View File

@@ -29,6 +29,7 @@
</n-button> </n-button>
<span>{{ item.display }}{{ item.title }}</span> <span>{{ item.display }}{{ item.title }}</span>
<n-tag size="small" type="warning">{{ item.score }}</n-tag> <n-tag size="small" type="warning">{{ item.score }}</n-tag>
<n-tag size="small">出题人 {{ item.author_name || "未设置" }}</n-tag>
</n-flex> </n-flex>
</template> </template>
<template #header-extra> <template #header-extra>
@@ -66,6 +67,9 @@
<n-form-item label="公开" label-placement="left"> <n-form-item label="公开" label-placement="left">
<n-switch v-model:value="challenge.is_public" /> <n-switch v-model:value="challenge.is_public" />
</n-form-item> </n-form-item>
<n-form-item label="出题人" label-placement="left">
<n-text depth="3">{{ challenge.author_name || "未设置" }}</n-text>
</n-form-item>
<n-form-item label-placement="left"> <n-form-item label-placement="left">
<n-button type="primary" @click="submit" :disabled="!canSubmit"> <n-button type="primary" @click="submit" :disabled="!canSubmit">
提交 提交
@@ -107,6 +111,7 @@ const challenge = reactive({
content: "", content: "",
score: 0, score: 0,
is_public: false, is_public: false,
author_name: "",
}) })
const canSubmit = computed( const canSubmit = computed(
@@ -129,6 +134,7 @@ function createNew() {
challenge.content = "" challenge.content = ""
challenge.score = 0 challenge.score = 0
challenge.is_public = false challenge.is_public = false
challenge.author_name = ""
} }
async function submit() { async function submit() {
@@ -140,6 +146,7 @@ async function submit() {
challenge.content = "" challenge.content = ""
challenge.score = 0 challenge.score = 0
challenge.is_public = false challenge.is_public = false
challenge.author_name = ""
await getContent() await getContent()
} catch (error: any) { } catch (error: any) {
message.error(error.response.data.detail) message.error(error.response.data.detail)
@@ -168,6 +175,7 @@ async function show(display: number) {
challenge.content = item.content challenge.content = item.content
challenge.score = item.score challenge.score = item.score
challenge.is_public = item.is_public challenge.is_public = item.is_public
challenge.author_name = item.author_name ?? ""
} }
async function togglePublic(display: number) { async function togglePublic(display: number) {

View File

@@ -56,6 +56,7 @@ export interface ChallengeSlim {
pass_score: number | null pass_score: number | null
submitted: boolean submitted: boolean
is_public: boolean is_public: boolean
author_name: string | null
} }
export interface ChallengeIn { export interface ChallengeIn {