重修选课

This commit is contained in:
biss committed 2026-08-15 14:57:22 +08:00
1 parent be49a2586f
commit 57a60ff8d5
10 files changed
+7275 -30

No files matched your search

+1
View File
@@ -38,6 +38,7 @@ declare module 'vue' {
ElPagination: typeof import('element-plus/es')['ElPagination']
ElPopover: typeof import('element-plus/es')['ElPopover']
ElProgress: typeof import('element-plus/es')['ElProgress']
ElRadio: typeof import('element-plus/es')['ElRadio']
ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
ElResult: typeof import('element-plus/es')['ElResult']
+24 -4
View File
@@ -65,6 +65,10 @@ const statusLabels: Record<string, string> = {
Open: '开放中',
Closed: '已关闭',
}
const scopeLabels: Record<string, string> = {
All: '普通选课',
RetakeOnly: '仅限重修',
}
const patternLabels: Record<string, string> = {
All: '每周',
Odd: '单周',
@@ -209,6 +213,9 @@ const filteredOfferings = computed(() => {
if (offeringStatus.value === 'Waitlisted') {
return offering.enrollmentStatus === 'Waitlisted'
}
if (offeringStatus.value === 'Retake') {
return offering.isRetake && !['Enrolled', 'Waitlisted'].includes(offering.enrollmentStatus)
}
const blocked = Boolean(offeringEligibilityReason(offering))
if (offeringStatus.value === 'Selectable') {
return !['Enrolled', 'Waitlisted'].includes(offering.enrollmentStatus) && !blocked
@@ -422,6 +429,7 @@ function openRound(round?: any) {
: toPickerValue(withdrawal.toISOString()),
maxCredits: round?.maxCredits ?? 30,
maxCourseCount: round?.maxCourseCount ?? undefined,
scope: round?.scope ?? 'All',
eligibleGrades: [...(round?.eligibleGrades ?? [])],
notes: round?.notes ?? '',
})
@@ -865,6 +873,7 @@ onMounted(async () => {
<b>{{ round.name }}</b>
<small>{{ formatDateTime(round.startsAt) }} — {{ formatDateTime(round.endsAt) }}</small>
<small>{{ roundLimitLabel(round) }}</small>
<small>{{ scopeLabels[round.scope] ?? '普通选课' }}</small>
<i :class="round.status.toLowerCase()">{{ statusLabels[round.status] }}</i>
</button>
</section>
@@ -882,6 +891,7 @@ onMounted(async () => {
选课 {{ formatDateTime(selectedRound.startsAt) }}—{{ formatDateTime(selectedRound.endsAt) }}
<em>退课截止 {{ formatDateTime(selectedRound.withdrawalEndsAt) }}</em>
<em>{{ roundLimitLabel(selectedRound) }}</em>
<em>{{ scopeLabels[selectedRound.scope] ?? '普通选课' }}</em>
</p>
</div>
<div v-if="isStudent" class="credit-meter">
@@ -1090,7 +1100,7 @@ onMounted(async () => {
<div>
<span>AVAILABLE CLASSES</span>
<h3>本轮可选教学班</h3>
<p>先试排再选课;冲突、容量和学分限制会提前显示,提交时服务端会再次校验。</p>
<p>先试排再选课;可用“重修可选”仅查看历史成绩未通过、且尚未通过的课程。提交时服务端会再次校验。</p>
</div>
<b>{{ filteredOfferings.length }} / {{ offerings.length }}</b>
</div>
@@ -1106,6 +1116,7 @@ onMounted(async () => {
:options="[
{ label: '全部', value: 'All' },
{ label: '可选', value: 'Selectable' },
{ label: '重修可选', value: 'Retake' },
{ label: '候补', value: 'Waitlisted' },
{ label: '已选', value: 'Selected' },
{ label: '受限', value: 'Blocked' },
@@ -1135,7 +1146,7 @@ onMounted(async () => {
<h3>{{ offering.courseName }}</h3>
<p>
{{ offering.teacherNames.join('、') || '教师待定' }} · {{ offering.credits }} 学分
<el-tag v-if="offering.isRetake && offering.enrollmentStatus !== 'Enrolled'" size="small" type="warning" effect="plain" style="margin-left:6px">重修</el-tag>
<el-tag v-if="offering.isRetake && offering.enrollmentStatus !== 'Enrolled'" size="small" type="warning" effect="plain" style="margin-left:6px">重修可选</el-tag>
</p>
</div>
<i v-if="offering.enrollmentStatus === 'Enrolled'" class="selected-mark">
@@ -1201,13 +1212,15 @@ onMounted(async () => {
v-else-if="isOfferingFull(offering) && !offeringEligibilityReason(offering)"
type="warning"
@click="joinWaitlist(offering)"
>加入候补</el-button>
>{{ offering.isRetake ? '重修候补' : '加入候补' }}</el-button>
<el-button
v-else
type="primary"
:disabled="Boolean(offeringEligibilityReason(offering))"
@click="enroll(offering)"
>{{ offering.enrollmentStatus === 'Withdrawn' ? '重新选择' : '选择课程' }}</el-button>
>{{ offering.enrollmentStatus === 'Withdrawn'
? '重新选择'
: offering.isRetake ? '重修选课' : '选择课程' }}</el-button>
</footer>
</article>
<el-empty
@@ -1236,6 +1249,13 @@ onMounted(async () => {
<el-input v-model="roundForm.name" placeholder="如 第一轮选课" />
</el-form-item>
</div>
<el-form-item label="选课类型" required>
<el-radio-group v-model="roundForm.scope">
<el-radio value="All">普通选课</el-radio>
<el-radio value="RetakeOnly">仅限重修</el-radio>
</el-radio-group>
<div class="form-hint">仅限重修批次独立按本批次时间开放和关闭,只有历史成绩未通过且尚未通过的学生可见并办理。</div>
</el-form-item>
<div class="form-grid">
<el-form-item label="选课开始时间" required>
<el-date-picker v-model="roundForm.startsAt" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" />