修你妈的

This commit is contained in:
Fox_block
2026-03-08 20:54:44 +08:00
parent 7100a30f1b
commit f47b6d483c
18 changed files with 124 additions and 190 deletions
@@ -42,10 +42,6 @@ interface ActionItem {
value: string
reason: string
}
interface TagItem {
id: number
name: string
}
interface AutoScoreRuleFormValues {
name: string
@@ -65,7 +61,6 @@ const ACTION_DEFINITIONS = [
export const AutoScoreManager: React.FC = () => {
const { t } = useTranslation()
const [rules, setRules] = useState<AutoScoreRule[]>([])
const [allTags, setAllTags] = useState<TagItem[]>([])
const [students, setStudents] = useState<{ id: number; name: string }[]>([])
const [loading, setLoading] = useState(false)
const [currentPage, setCurrentPage] = useState(1)
@@ -85,19 +80,6 @@ export const AutoScoreManager: React.FC = () => {
return def ? t(def.labelKey) : eventName
}
async function fetchAllTags() {
if (!(window as any).api) return
try {
const res = await (window as any).api.tagsGetAll()
if (res.success && res.data) {
setAllTags(res.data)
}
} catch (e) {
console.error('Failed to fetch tags:', e)
messageApi.error(t('tags.fetchFailed'))
}
}
const fetchRules = async () => {
if (!(window as any).api) return
@@ -333,20 +315,6 @@ export const AutoScoreManager: React.FC = () => {
])
}
const handleRemoveTrigger = (id: number) => {
setTriggerList((prev) => prev.filter((t) => t.id !== id))
}
const handleTriggerChange = (
id: number,
field: keyof TriggerItem,
value: string | number | 'AND' | 'OR'
) => {
setTriggerList((prev) =>
prev.map((t) => (t.id === id ? { ...t, [field]: value } : t))
)
}
const handleAddAction = () => {
const nextId = actionList.length ? Math.max(...actionList.map((a) => a.id)) + 1 : 1
const defaultAction = ACTION_DEFINITIONS[0]
@@ -369,14 +337,8 @@ export const AutoScoreManager: React.FC = () => {
setActionList((prev) => prev.filter((a) => a.id !== id))
}
const handleActionChange = (
id: number,
field: keyof ActionItem,
value: string | number
) => {
setActionList((prev) =>
prev.map((a) => (a.id === id ? { ...a, [field]: value } : a))
)
const handleActionChange = (id: number, field: keyof ActionItem, value: string | number) => {
setActionList((prev) => prev.map((a) => (a.id === id ? { ...a, [field]: value } : a)))
}
const columns: ColumnsType<AutoScoreRule> = [
@@ -481,72 +443,6 @@ export const AutoScoreManager: React.FC = () => {
}
]
const renderTriggerItem = (trigger: TriggerItem, index: number) => (
<div
key={trigger.id}
style={{
padding: '12px',
border: '1px solid #d9d9d9',
borderRadius: '6px',
backgroundColor: 'var(--ss-card-bg)',
marginBottom: '8px'
}}
>
<Space wrap>
{index > 0 && (
<Select
value={trigger.relation}
onChange={(value) => handleTriggerChange(trigger.id, 'relation', value)}
style={{ width: 80 }}
options={[
{ label: 'AND', value: 'AND' },
{ label: 'OR', value: 'OR' }
]}
/>
)}
<Select
value={trigger.eventName}
onChange={(value) => handleTriggerChange(trigger.id, 'eventName', value)}
style={{ width: 150 }}
options={TRIGGER_DEFINITIONS.map((d) => ({
label: t(d.labelKey),
value: d.eventName
}))}
/>
{trigger.eventName === 'interval_time_passed' && (
<InputNumber
value={trigger.value ? parseInt(trigger.value) : undefined}
onChange={(value) => handleTriggerChange(trigger.id, 'value', String(value || 0))}
placeholder={t('autoScore.minutesPlaceholder')}
min={1}
style={{ width: 120 }}
addonAfter={t('autoScore.minutes')}
/>
)}
{trigger.eventName === 'student_has_tag' && (
<Select
mode="multiple"
allowClear
value={trigger.value}
onChange={(value) => handleTriggerChange(trigger.id, 'value', value)}
onClick={fetchAllTags}
style={{ width: 380 }}
options={allTags.map((tag) => ({
label: tag.name,
value: tag.name
}))}
/>
)}
<Button
type="text"
danger
icon={<DeleteOutlined />}
onClick={() => handleRemoveTrigger(trigger.id)}
/>
</Space>
</div>
)
const renderActionItem = (action: ActionItem) => (
<div
key={action.id}
@@ -635,9 +531,10 @@ export const AutoScoreManager: React.FC = () => {
title={t('autoScore.whenTriggered')}
>
<Space orientation="vertical" style={{ width: '100%' }}>
{/* {triggerList.map((trigger, index) => renderTriggerItem(trigger, index))}
*/} <RuleComponent />
<Button
{/* {triggerList.map((trigger, index) => renderTriggerItem(trigger, index))}
*/}{' '}
<RuleComponent />
<Button
type="dashed"
icon={<PlusOutlined />}
onClick={handleAddTrigger}
@@ -652,7 +549,7 @@ export const AutoScoreManager: React.FC = () => {
style={{ marginBottom: '24px', backgroundColor: 'var(--ss-card-bg)' }}
title={t('autoScore.triggeredActions')}
>
<Space direction="vertical" style={{ width: '100%' }}>
<Space orientation="vertical" style={{ width: '100%' }}>
{actionList.map((action) => renderActionItem(action))}
<Button
type="dashed"
@@ -667,9 +564,7 @@ export const AutoScoreManager: React.FC = () => {
<div style={{ marginBottom: '24px', display: 'flex', gap: '12px' }}>
<Button type="primary" onClick={handleSubmit}>
{editingRuleId !== null
? t('autoScore.updateAutomation')
: t('autoScore.addAutomation')}
{editingRuleId !== null ? t('autoScore.updateAutomation') : t('autoScore.addAutomation')}
</Button>
<Button onClick={handleResetForm}>
{editingRuleId !== null ? t('autoScore.cancelEdit') : t('autoScore.resetForm')}
@@ -701,4 +596,4 @@ export const AutoScoreManager: React.FC = () => {
</Card>
</div>
)
}
}
+5 -12
View File
@@ -1,5 +1,5 @@
import React, { Suspense, lazy } from 'react'
import { Layout, Space, Button, Tag } from 'antd'
import { Layout, Space, Button, Tag, Spin } from 'antd'
import { Routes, Route, Navigate } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
@@ -104,19 +104,12 @@ export function ContentArea({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
height: '100%'
height: '100%',
flexDirection: 'column',
gap: 16
}}
>
<div
style={{
width: '40px',
height: '40px',
border: '3px solid var(--ss-border-color)',
borderTopColor: 'var(--ant-color-primary)',
borderRadius: '50%',
animation: 'spin 1s linear infinite'
}}
/>
<Spin size="large" />
</div>
}
>
+12 -4
View File
@@ -598,7 +598,9 @@ export const OOBE: React.FC<oobeProps> = ({ visible, onComplete }) => {
}}
>
<span style={{ color: '#52c41a' }}></span>
<span>{t('oobe.steps.start.features.score')}</span>
<span style={{ color: isDark ? '#fff' : 'rgba(0, 0, 0, 0.88)' }}>
{t('oobe.steps.start.features.score')}
</span>
</div>
<div
style={{
@@ -611,7 +613,9 @@ export const OOBE: React.FC<oobeProps> = ({ visible, onComplete }) => {
}}
>
<span style={{ color: '#52c41a' }}></span>
<span>{t('oobe.steps.start.features.history')}</span>
<span style={{ color: isDark ? '#fff' : 'rgba(0, 0, 0, 0.88)' }}>
{t('oobe.steps.start.features.history')}
</span>
</div>
<div
style={{
@@ -624,7 +628,9 @@ export const OOBE: React.FC<oobeProps> = ({ visible, onComplete }) => {
}}
>
<span style={{ color: '#52c41a' }}></span>
<span>{t('oobe.steps.start.features.settlement')}</span>
<span style={{ color: isDark ? '#fff' : 'rgba(0, 0, 0, 0.88)' }}>
{t('oobe.steps.start.features.settlement')}
</span>
</div>
</div>
</div>
@@ -659,7 +665,9 @@ export const OOBE: React.FC<oobeProps> = ({ visible, onComplete }) => {
width: 480,
maxWidth: '90vw',
boxShadow: isDark ? '0 8px 32px rgba(0, 0, 0, 0.3)' : '0 8px 32px rgba(0, 0, 0, 0.1)',
border: isDark ? '1px solid rgba(255, 255, 255, 0.08)' : '1px solid rgba(0, 0, 0, 0.06)'
border: isDark ? '1px solid rgba(255, 255, 255, 0.08)' : '1px solid rgba(0, 0, 0, 0.06)',
fontFamily:
'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", sans-serif, "Apple Color Emoji", "Segoe UI Emoji"'
}}
>
{contextHolder}
+1 -1
View File
@@ -226,7 +226,7 @@ export function Sidebar({ activeMenu, permission, onMenuChange }: SidebarProps):
backgroundColor: 'var(--ss-card-bg)',
border: '1px solid var(--ss-border-color)'
}}
bodyStyle={{ padding: '12px' }}
styles={{ body: { padding: '12px' } }}
>
{contextHolder}
<Space orientation="vertical" size={4} style={{ width: '100%' }}>
@@ -477,7 +477,7 @@ export const StudentManager: React.FC<{ canEdit: boolean }> = ({ canEdit }) => {
footer={null}
destroyOnHidden
>
<Space direction="vertical" style={{ width: '100%' }}>
<Space orientation="vertical" style={{ width: '100%' }}>
<Button
loading={xlsxLoading}
disabled={!canEdit}
@@ -96,4 +96,4 @@ export const ActionComponent: React.FC<ActionComponentProps> = ({
)
}
export default ActionComponent
export default ActionComponent
@@ -1,5 +1,7 @@
.queryBuilder {
--querybuilder-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif;
--querybuilder-font-family:
-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans',
sans-serif;
--querybuilder-background: var(--ss-card-bg, #ffffff);
--querybuilder-color: var(--ss-text-main, rgba(0, 0, 0, 0.85));
--querybuilder-border-radius: 6px;
@@ -42,15 +42,15 @@ export const ACTION_TYPE_KEYS = {
// Function to get fields with i18n support
export const getFields = (t: (key: string) => string): Field[] => [
{
name: 'interval_time_passed',
label: t('autoScore.triggerIntervalTime'),
placeholder: t('autoScore.intervalMinutesPlaceholder')
{
name: 'interval_time_passed',
label: t('autoScore.triggerIntervalTime'),
placeholder: t('autoScore.intervalMinutesPlaceholder')
},
{
name: 'student_has_tag',
label: t('autoScore.triggerStudentTag'),
placeholder: t('autoScore.tagNamesPlaceholder')
{
name: 'student_has_tag',
label: t('autoScore.triggerStudentTag'),
placeholder: t('autoScore.tagNamesPlaceholder')
}
]
@@ -116,4 +116,4 @@ export function autoScoreRuleToQuery(ruleData: AutoScoreRuleData): RuleGroupType
combinator: currentCombinator,
rules: rules.length > 0 ? rules : defaultQuery.rules
}
}
}
@@ -81,4 +81,4 @@ export const RuleComponent: React.FC<RuleComponentProps> = ({ initialData, onCha
)
}
export default RuleComponent
export default RuleComponent