Files
SecScore/src/components/AutoScoreManagerPage/ActionEditor.tsx
T
NanGua-QWQ e4d9ee0c85 feat: 间隔时间加分可以按照多少天、月、分钟后加分
fix: 修复若干问题
下雨了好害怕我靠
2026-03-29 18:17:54 +08:00

129 lines
4.0 KiB
TypeScript

import React, { useMemo } from "react"
import { Button, Card, InputNumber, Select, Space } from "antd"
import { DeleteOutlined, PlusOutlined } from "@ant-design/icons"
import { useTranslation } from "react-i18next"
import type { ActionDraft, ActionEvent, AutoScoreTagOption } from "./AutoScoreUtils"
import { createDefaultActionDraft } from "./AutoScoreUtils"
interface ActionEditorProps {
value: ActionDraft[]
tagOptions: AutoScoreTagOption[]
canEdit: boolean
onChange: (nextDrafts: ActionDraft[]) => void
}
export const ActionEditor: React.FC<ActionEditorProps> = ({
value,
tagOptions,
canEdit,
onChange,
}) => {
const { t } = useTranslation()
const actionOptions = useMemo(
() => [
{ value: "add_score", label: t("autoScore.actionAddScore") },
{ value: "add_tag", label: t("autoScore.actionAddTag") },
],
[t]
)
const mergedTagOptions = useMemo(() => {
const optionMap = new Map(tagOptions.map((option) => [option.value, option]))
for (const action of value) {
if (action.event !== "add_tag") continue
const tagValues = Array.isArray(action.value)
? action.value
: action.value
? [action.value]
: []
for (const tagValue of tagValues) {
if (!optionMap.has(tagValue)) {
optionMap.set(tagValue, { label: tagValue, value: tagValue })
}
}
}
return Array.from(optionMap.values())
}, [tagOptions, value])
const updateAction = (id: string, patch: Partial<Omit<ActionDraft, "id">>) => {
onChange(value.map((item) => (item.id === id ? { ...item, ...patch } : item)))
}
const handleAddAction = () => {
onChange([...value, createDefaultActionDraft()])
}
const handleRemoveAction = (id: string) => {
if (value.length <= 1) return
onChange(value.filter((item) => item.id !== id))
}
return (
<Card
style={{ marginBottom: "24px", backgroundColor: "var(--ss-card-bg)" }}
title={t("autoScore.triggeredActions")}
>
<Space direction="vertical" style={{ width: "100%" }} size={12}>
{value.map((action) => (
<div key={action.id} style={{ display: "flex", gap: "8px", alignItems: "center" }}>
<Select
style={{ minWidth: 180 }}
value={action.event}
disabled={!canEdit}
options={actionOptions}
onChange={(event: ActionEvent) =>
updateAction(action.id, {
event,
value: event === "add_score" ? "1" : [],
})
}
/>
{action.event === "add_score" ? (
<InputNumber
style={{ width: 180 }}
placeholder={t("autoScore.scorePlaceholder")}
value={action.value ? Number(action.value) : undefined}
disabled={!canEdit}
onChange={(nextValue) =>
updateAction(action.id, { value: nextValue === null ? "" : String(nextValue) })
}
/>
) : (
<Select
mode="multiple"
showSearch
allowClear
style={{ minWidth: 260 }}
placeholder={t("autoScore.tagNamePlaceholder")}
value={Array.isArray(action.value) ? action.value : action.value ? [action.value] : []}
disabled={!canEdit}
options={mergedTagOptions}
onChange={(nextValue) => updateAction(action.id, { value: nextValue })}
/>
)}
<Button
danger
icon={<DeleteOutlined />}
disabled={!canEdit || value.length <= 1}
onClick={() => handleRemoveAction(action.id)}
/>
</div>
))}
<Button
type="dashed"
icon={<PlusOutlined />}
disabled={!canEdit}
onClick={handleAddAction}
style={{ fontWeight: "bolder", fontSize: 15 }}
>
{t("autoScore.addAction")}
</Button>
</Space>
</Card>
)
}