1
0
mirror of https://github.com/ZeroCatDev/Classworks.git synced 2025-07-01 16:49:22 +00:00

Add mode switching and number range settings to RandomPicker component. Introduce picker modes for name and number, allowing users to set a range for student IDs. Update settings management for new properties and enhance UI for better user experience.

This commit is contained in:
SunWuyuan 2025-05-24 21:21:20 +08:00
parent ab20d6cecb
commit 0f9ad4f81a
No known key found for this signature in database
GPG Key ID: A6A54CF66F56BB64
4 changed files with 205 additions and 14 deletions

View File

@ -43,6 +43,48 @@
/>
</div>
<!-- 添加模式切换 -->
<div class="mode-switch-container mt-6">
<v-btn-toggle
v-model="pickerMode"
color="primary"
rounded="pill"
mandatory
class="mode-toggle"
>
<v-btn value="name" prepend-icon="mdi-account">姓名模式</v-btn>
<v-btn value="number" prepend-icon="mdi-numeric">学号模式</v-btn>
</v-btn-toggle>
</div>
<!-- 学号范围设置 -->
<div v-if="pickerMode === 'number'" class="number-range-container mt-4">
<div class="text-subtitle-1 mb-2">学号范围设置</div>
<div class="d-flex justify-center align-center gap-4">
<v-text-field
v-model.number="minNumber"
label="最小值"
type="number"
min="1"
max="100"
hide-details
class="number-input"
density="compact"
/>
<span class="mx-2"></span>
<v-text-field
v-model.number="maxNumber"
label="最大值"
type="number"
min="1"
max="100"
hide-details
class="number-input"
density="compact"
/>
</div>
</div>
<div class="mt-4">
<v-btn
size="x-large"
@ -57,12 +99,17 @@
</div>
<div v-if="filteredStudents.length === 0" class="mt-4 text-error">
没有可抽取的学生请调整过滤选项
<template v-if="pickerMode === 'name'">
没有可抽取的学生请调整过滤选项
</template>
<template v-else>
请设置有效的学号范围
</template>
</div>
<div class="mt-4 text-caption">
当前可抽取学生: {{ filteredStudents.length }}
<v-tooltip location="bottom">
<v-tooltip v-if="pickerMode === 'name'" location="bottom">
<template v-slot:activator="{ props }">
<v-icon
v-bind="props"
@ -81,10 +128,11 @@
<div v-if="tempFilters.excludeExcluded">
已排除不参与学生 ({{ excludedCount }})
</div>
</div> </v-tooltip
><!-- 添加临时过滤选项 -->
</div>
</v-tooltip>
<div class="d-flex flex-wrap justify-center gap-2 mt-4">
<!-- 添加临时过滤选项 -->
<div v-if="pickerMode === 'name'" class="d-flex flex-wrap justify-center gap-2 mt-4">
<v-chip
:color="tempFilters.excludeLate ? 'warning' : 'default'"
:variant="tempFilters.excludeLate ? 'elevated' : 'text'"
@ -107,9 +155,7 @@
<v-chip
:color="tempFilters.excludeExcluded ? 'grey' : 'default'"
:variant="tempFilters.excludeExcluded ? 'elevated' : 'text'"
@click="
tempFilters.excludeExcluded = !tempFilters.excludeExcluded
"
@click="tempFilters.excludeExcluded = !tempFilters.excludeExcluded"
prepend-icon="mdi-account-cancel"
class="filter-chip"
>
@ -195,7 +241,7 @@
</template>
<script>
import { getSetting } from "@/utils/settings";
import { getSetting, setSetting } from "@/utils/settings";
export default {
name: "RandomPicker",
@ -227,6 +273,9 @@ export default {
excludeLate: getSetting("randomPicker.excludeLate"),
excludeExcluded: getSetting("randomPicker.excludeExcluded"),
},
pickerMode: getSetting("randomPicker.mode"),
minNumber: getSetting("randomPicker.minNumber"),
maxNumber: getSetting("randomPicker.maxNumber"),
};
},
computed: {
@ -241,12 +290,25 @@ export default {
return this.attendance.exclude ? this.attendance.exclude.length : 0;
},
// 使
//
numberModeStudents() {
if (this.pickerMode !== "number") return [];
const students = [];
for (let i = this.minNumber; i <= this.maxNumber; i++) {
students.push(i.toString().padStart(2, "0") + "号");
}
return students;
},
// filteredStudents
filteredStudents() {
if (this.pickerMode === "number") {
return this.numberModeStudents;
}
if (!this.studentList || !this.studentList.length) return [];
return this.studentList.filter((student) => {
//
if (
this.tempFilters.excludeAbsent &&
this.attendance.absent.includes(student)
@ -318,6 +380,35 @@ export default {
},
deep: true,
},
//
pickerMode: {
handler(newMode) {
setSetting("randomPicker.mode", newMode);
},
},
minNumber: {
handler(newValue) {
if (newValue > this.maxNumber) {
this.minNumber = this.maxNumber;
}
if (newValue < 1) {
this.minNumber = 1;
}
setSetting("randomPicker.minNumber", this.minNumber);
},
},
maxNumber: {
handler(newValue) {
if (newValue < this.minNumber) {
this.maxNumber = this.minNumber;
}
if (newValue > 100) {
this.maxNumber = 100;
}
setSetting("randomPicker.maxNumber", this.maxNumber);
},
},
},
methods: {
open() {
@ -616,4 +707,45 @@ export default {
font-size: 1rem;
}
}
//
.mode-switch-container {
.mode-toggle {
border: 1px solid rgba(var(--v-theme-primary), 0.2);
border-radius: 50px;
padding: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
.v-btn {
min-width: 120px;
height: 40px;
font-weight: 500;
letter-spacing: 0.5px;
&.v-btn--active {
transform: scale(1.02);
font-weight: 600;
}
}
}
}
//
.number-range-container {
max-width: 300px;
margin: 0 auto;
padding: 16px;
background: rgba(var(--v-theme-surface-variant), 0.1);
border-radius: 12px;
border: 1px solid rgba(var(--v-theme-primary), 0.1);
.number-input {
width: 100px;
:deep(.v-field) {
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
}
}
</style>

View File

@ -0,0 +1,30 @@
<template>
<settings-card title="编辑设置" icon="mdi-cog">
<v-list>
<setting-item setting-key="randomPicker.enabled" />
<v-divider class="my-2" />
<setting-item setting-key="randomPicker.mode" />
<v-divider class="my-2" />
<setting-item setting-key="randomPicker.minNumber" />
<v-divider class="my-2" />
<setting-item setting-key="randomPicker.maxNumber" />
<v-divider class="my-2" />
<setting-item setting-key="randomPicker.defaultCount" />
<v-divider class="my-2" />
<setting-item setting-key="randomPicker.animation" />
</v-list>
</settings-card>
</template>
<script>
import SettingsCard from '@/components/SettingsCard.vue';
import SettingItem from '../SettingItem.vue';
</script>

View File

@ -143,7 +143,9 @@
<v-tabs-window-item value="student">
<student-list-card border :is-mobile="isMobile" />
</v-tabs-window-item>
<v-tabs-window-item value="randomPicker">
<random-picker-card border :is-mobile="isMobile" />
</v-tabs-window-item>
<v-tabs-window-item value="developer"
><settings-card border title="开发者选项" icon="mdi-developer-board">
<v-list>
@ -222,7 +224,7 @@ import SettingsExplorer from "@/components/settings/SettingsExplorer.vue";
import SettingsLinkGenerator from "@/components/SettingsLinkGenerator.vue";
import dataProvider from "@/utils/dataProvider";
import NamespaceSettingsCard from "@/components/settings/cards/NamespaceSettingsCard.vue";
import RandomPickerCard from "@/components/settings/cards/RandomPickerCard.vue";
export default {
name: "Settings",
components: {
@ -240,6 +242,7 @@ export default {
SettingsExplorer,
SettingsLinkGenerator,
NamespaceSettingsCard,
RandomPickerCard,
},
setup() {
const { mobile } = useDisplay();
@ -372,6 +375,11 @@ export default {
icon: "mdi-account-group",
value: "student",
},
{
title: "随机点名",
icon: "mdi-dice-multiple",
value: "randomPicker",
},
{
title: "开发者",
icon: "mdi-developer-board",

View File

@ -360,7 +360,7 @@ const settingsDefinitions = {
"randomPicker.defaultCount": {
type: "number",
default: 1,
validate: (value) => value >= 1 && value <= 10,
validate: (value) => value >= 1 && value,
description: "默认抽取人数",
icon: "mdi-counter",
},
@ -382,6 +382,27 @@ const settingsDefinitions = {
description: "是否排除不参与学生",
icon: "mdi-account-cancel",
},
"randomPicker.mode": {
type: "string",
default: "name",
validate: (value) => ["name", "number"].includes(value),
description: "随机点名模式",
icon: "mdi-format-list-numbered",
},
"randomPicker.maxNumber": {
type: "number",
default: 60,
validate: (value) => value >= 1 && value,
description: "学号模式最大值",
icon: "mdi-numeric",
},
"randomPicker.minNumber": {
type: "number",
default: 1,
validate: (value) => value >= 1 && value,
description: "学号模式最小值",
icon: "mdi-numeric-negative-1",
},
};
/**