NEW:Now can select many many students!

This commit is contained in:
NanGua-QWQ
2026-02-04 14:54:35 +08:00
parent 817c3e701c
commit bdd3ab3724
2 changed files with 90 additions and 43 deletions
@@ -13,6 +13,8 @@ import {
Switch,
Popconfirm,
Radio,
Select,
TooltipLite
} from 'tdesign-react'
interface AutoScoreRule {
@@ -36,6 +38,7 @@ interface AutoScoreRuleFormValues {
export const AutoScoreManager: React.FC = () => {
const [rules, setRules] = useState<AutoScoreRule[]>([])
const [students, setStudents] = useState<{ id: number; name: string }[]>([])
const [loading, setLoading] = useState(false)
const [form] = Form.useForm()
const [editingRuleId, setEditingRuleId] = useState<number | null>(null)
@@ -58,11 +61,17 @@ export const AutoScoreManager: React.FC = () => {
console.warn('Auth check failed', e)
}
const res = await (window as any).api.invoke('auto-score:getRules', {})
if (res.success) {
setRules(res.data)
const [rulesRes, studentsRes] = await Promise.all([
(window as any).api.invoke('auto-score:getRules', {}),
(window as any).api.queryStudents({})
])
if (rulesRes.success) {
setRules(rulesRes.data)
} else {
MessagePlugin.error(res.message || '获取规则失败')
MessagePlugin.error(rulesRes.message || '获取规则失败')
}
if (studentsRes.success) {
setStudents(studentsRes.data)
}
} catch (error) {
console.error('Failed to fetch auto score rules:', error)
@@ -77,29 +86,29 @@ export const AutoScoreManager: React.FC = () => {
}, [])
const handleSubmit = async () => {
if (!(window as any).api) return
// 修复类型转换错误,使用更安全的方式获取表单值
const values = form.getFieldsValue(true) as unknown as AutoScoreRuleFormValues
if (!(window as any).api) return;
const values = form.getFieldsValue(true) as unknown as AutoScoreRuleFormValues & { timeUnit: string };
if (!values.name || values.intervalMinutes == null || values.scoreValue == null) {
MessagePlugin.warning('请填写完整信息')
return
MessagePlugin.warning('请填写完整信息');
return;
}
// 解析学生姓名列表(以逗号分隔)
const studentNames = values.studentNames
? values.studentNames.split(',').map(name => name.trim()).filter(name => name)
: []
// 根据单位转换间隔时间
const intervalMinutes = values.timeUnit === 'days' ? values.intervalMinutes * 1440 : values.intervalMinutes;
// 确保 studentNames 是数组类型
const studentNames = Array.isArray(values.studentNames) ? values.studentNames : [];
const ruleData = {
enabled: true, // 默认启用新规则
enabled: true,
name: values.name,
intervalMinutes: values.intervalMinutes,
intervalMinutes,
studentNames,
scoreValue: values.scoreValue,
reason: values.reason || `自动化加分 - ${values.name}`
}
reason: values.reason || `自动化加分 - ${values.name}`,
};
// 权限检查:仅管理员可创建/更新规则
try {
@@ -133,7 +142,8 @@ export const AutoScoreManager: React.FC = () => {
intervalMinutes: undefined,
studentNames: '',
scoreValue: undefined,
reason: ''
reason: '',
timeUnit: 'minutes'
})
setEditingRuleId(null)
fetchRules() // 刷新规则列表
@@ -240,7 +250,12 @@ export const AutoScoreManager: React.FC = () => {
colKey: 'intervalMinutes',
title: '间隔',
width: 100,
cell: ({ row }) => `${row.intervalMinutes} 分钟`
cell: ({ row }) => {
const isDays = row.intervalMinutes >= 1440
const value = isDays ? row.intervalMinutes / 1440 : row.intervalMinutes
const unit = isDays ? '天' : '分钟'
return `${value} ${unit}`
}
},
{
colKey: 'scoreValue',
@@ -260,7 +275,17 @@ export const AutoScoreManager: React.FC = () => {
if (row.studentNames.length === 0) {
return <span></span>
}
return <span title={row.studentNames.join(', ')}>{row.studentNames.length} </span>
const studentList = row.studentNames.join(',\n')
return (
<TooltipLite
content={studentList}
showArrow
placement="mouse"
theme="default"
>
{row.studentNames.length}
</TooltipLite>
)
}
},
{ colKey: 'reason', title: '理由', ellipsis: true },
@@ -336,7 +361,7 @@ export const AutoScoreManager: React.FC = () => {
>
<InputNumber min={1} placeholder="例如:1(每隔1分钟/天执行一次)" />
</Form.FormItem>
<Form.FormItem name="timeUnit" style={{ marginBottom: 0 }}>
<Form.FormItem name="timeUnit" initialData="minutes" style={{ marginBottom: 0 }}>
<Radio.Group variant="default-filled">
<Radio.Button value="days"></Radio.Button>
<Radio.Button value="minutes"></Radio.Button>
@@ -357,7 +382,12 @@ export const AutoScoreManager: React.FC = () => {
label="适用学生"
name="studentNames"
>
<Input placeholder="留空表示所有学生,多个学生用逗号分隔" />
<Select
filterable
multiple
placeholder="请选择或搜索学生(留空表示所有学生)"
options={students.map((student) => ({ label: student.name, value: student.name }))}
/>
</Form.FormItem>
<Form.FormItem
+36 -19
View File
@@ -138,7 +138,10 @@ export const ScoreManager: React.FC<{ canEdit: boolean }> = ({ canEdit }) => {
return
}
const values = form.getFieldsValue(true) as any
if (!values.student_name || !values.reason_content) {
// 支持多选学生
const studentNames = Array.isArray(values.student_name) ? values.student_name : [values.student_name]
if (!studentNames || studentNames.length === 0 || !values.reason_content) {
MessagePlugin.warning('请填写完整信息')
return
}
@@ -161,26 +164,39 @@ export const ScoreManager: React.FC<{ canEdit: boolean }> = ({ canEdit }) => {
: Math.abs(deltaInput)
: Number(selectedReason?.delta ?? 0)
const res = await (window as any).api.createEvent({
student_name: values.student_name,
reason_content: values.reason_content,
delta: delta
})
// 为每个选中的学生创建事件
try {
let successCount = 0
for (const studentName of studentNames) {
const res = await (window as any).api.createEvent({
student_name: studentName,
reason_content: values.reason_content,
delta: delta
})
if (res.success) {
successCount++
}
}
if (res.success) {
MessagePlugin.success('积分提交成功')
form.setFieldsValue({
delta: undefined,
reason_content: '',
reason_id: undefined,
type: 'add'
})
fetchData()
emitDataUpdated('events')
} else {
MessagePlugin.error(res.message || '提交失败')
if (successCount === studentNames.length) {
MessagePlugin.success(`已为 ${successCount} 名学生提交积分`)
form.setFieldsValue({
student_name: [],
delta: undefined,
reason_content: '',
reason_id: undefined,
type: 'add'
})
fetchData()
emitDataUpdated('events')
} else {
MessagePlugin.warning(`成功提交 ${successCount}/${studentNames.length} 名学生的积分`)
fetchData()
emitDataUpdated('events')
}
} finally {
setSubmitLoading(false)
}
setSubmitLoading(false)
}
const handleUndo = async (uuid: string) => {
@@ -250,6 +266,7 @@ export const ScoreManager: React.FC<{ canEdit: boolean }> = ({ canEdit }) => {
<Form.FormItem label="姓名" name="student_name">
<Select
filterable
multiple
placeholder="请选择或搜索学生"
filter={(filterWords, option) =>
matchStudentName(getOptionLabel(option), filterWords)