add class username
Some checks failed
Deploy / deploy (build, debian, 22, /root/OJDeploy/data/clientnext) (push) Has been cancelled
Deploy / deploy (build:staging, school, 8822, /root/OJ/data/dist) (push) Has been cancelled

This commit is contained in:
2026-01-19 17:11:43 +08:00
parent f86bee9879
commit 97d3dabf4f
4 changed files with 56 additions and 10 deletions

View File

@@ -357,7 +357,7 @@ const flowchartColumns: DataTableColumn<FlowchartSubmissionListItem>[] = [
<n-form-item> <n-form-item>
<n-input <n-input
:disabled="query.myself === '1'" :disabled="query.myself === '1'"
style="width: 140px;" style="width: 140px"
clearable clearable
v-model:value="query.username" v-model:value="query.username"
placeholder="用户" placeholder="用户"
@@ -365,7 +365,7 @@ const flowchartColumns: DataTableColumn<FlowchartSubmissionListItem>[] = [
</n-form-item> </n-form-item>
<n-form-item> <n-form-item>
<n-input <n-input
style="width: 120px;" style="width: 120px"
clearable clearable
v-model:value="query.problem" v-model:value="query.problem"
placeholder="题号" placeholder="题号"

View File

@@ -33,3 +33,7 @@ export function getCaptcha() {
export function getHitokoto() { export function getHitokoto() {
return http.get("hitokoto") return http.get("hitokoto")
} }
export function getClassUsernames(classroom: string) {
return http.get("class_usernames", { params: { classroom: classroom } })
}

View File

@@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { login } from "../api" import { getClassUsernames, login } from "../api"
import { storeToRefs } from "pinia" import { storeToRefs } from "pinia"
import { useAuthModalStore } from "../store/authModal" import { useAuthModalStore } from "../store/authModal"
import { useConfigStore } from "../store/config" import { useConfigStore } from "../store/config"
@@ -18,6 +18,8 @@ const {
loginError: msg, loginError: msg,
} = storeToRefs(authStore) } = storeToRefs(authStore)
const loginRef = ref() const loginRef = ref()
const classUserOptions = ref<SelectOption[]>([])
const classUserLoading = ref(false)
const classList = computed<SelectOption[]>(() => { const classList = computed<SelectOption[]>(() => {
const defaults = [{ label: "没有我所在的班级", value: "" }] const defaults = [{ label: "没有我所在的班级", value: "" }]
const configs = const configs =
@@ -28,7 +30,9 @@ const classList = computed<SelectOption[]>(() => {
return [...defaults, ...configs] return [...defaults, ...configs]
}) })
const rules: FormRules = { const rules: FormRules = {
username: [{ required: true, message: "用户名必填", trigger: "blur" }], username: [
{ required: true, message: "用户名必填", trigger: ["blur", "change"] },
],
password: [ password: [
{ required: true, message: "密码必填", trigger: "blur" }, { required: true, message: "密码必填", trigger: "blur" },
{ min: 6, max: 20, message: "长度在 6 到 20 位之间", trigger: "input" }, { min: 6, max: 20, message: "长度在 6 到 20 位之间", trigger: "input" },
@@ -73,6 +77,34 @@ function goSignup() {
authStore.switchToSignup() authStore.switchToSignup()
} }
async function loadClassUsernames(selectedClass: string) {
classUserLoading.value = true
try {
const res = await getClassUsernames(selectedClass)
classUserOptions.value = res.data.map((name: string) => ({
label: name,
value: name,
}))
} catch {
classUserOptions.value = []
} finally {
classUserLoading.value = false
}
}
watch(
() => form.value.class,
(selectedClass) => {
classUserOptions.value = []
form.value.username = ""
if (!selectedClass) {
classUserLoading.value = false
return
}
loadClassUsernames(selectedClass.slice(2))
},
)
onMounted(() => { onMounted(() => {
authStore.clearLoginError() authStore.clearLoginError()
}) })
@@ -107,7 +139,19 @@ onMounted(() => {
/> />
</n-form-item> </n-form-item>
<n-form-item label="用户名" path="username"> <n-form-item label="用户名" path="username">
<n-select
v-if="form.class"
v-model:value="form.username"
:options="classUserOptions"
:loading="classUserLoading"
clearable
filterable
name="username"
id="login-username"
placeholder="请选择姓名"
/>
<n-input <n-input
v-else
v-model:value="form.username" v-model:value="form.username"
autofocus autofocus
clearable clearable

View File

@@ -17,7 +17,6 @@ const lastLoginTime = computed(() => {
}) })
const hasAnalysis = computed(() => !!loginSummaryStore.analysis) const hasAnalysis = computed(() => !!loginSummaryStore.analysis)
</script> </script>
<template> <template>
@@ -58,7 +57,9 @@ const hasAnalysis = computed(() => !!loginSummaryStore.analysis)
<n-gi> <n-gi>
<n-statistic <n-statistic
label="流程图提交" label="流程图提交"
:value="loginSummaryStore.summary?.flowchart_submission_count ?? 0" :value="
loginSummaryStore.summary?.flowchart_submission_count ?? 0
"
/> />
</n-gi> </n-gi>
</n-grid> </n-grid>
@@ -75,10 +76,7 @@ const hasAnalysis = computed(() => !!loginSummaryStore.analysis)
v-if="hasAnalysis" v-if="hasAnalysis"
:model-value="loginSummaryStore.analysis" :model-value="loginSummaryStore.analysis"
/> />
<n-empty <n-empty v-else description="期间提交数少于 3 次,暂不生成 AI 分析" />
v-else
description="期间提交数少于 3 次,暂不生成 AI 分析"
/>
</n-flex> </n-flex>
</n-spin> </n-spin>
</n-modal> </n-modal>