Files
SecScore/src/components/AutoScore/IntervalValueWidget.tsx
T
NanGua-QWQ eef6b703f7 feat: Enhance AutoScore functionality with interval triggers and JSON tree support
- Added support for trigger trees in AutoScoreRule interface.
- Implemented functions to convert query trees to JSON and vice versa.
- Updated IntervalValue to use days, hours, and minutes instead of a single amount and unit.
- Refactored IntervalValueWidget to allow separate input for days, hours, and minutes.
- Added validation to ensure at least one interval trigger is present.
- Enhanced user interface with informative alerts and tooltips for better user experience.
- Updated localization files to include new strings for interval triggers and UI elements.
2026-04-10 21:09:04 +08:00

90 lines
3.0 KiB
TypeScript

import React from "react"
import { InputNumber } from "antd"
import type { WidgetProps } from "@react-awesome-query-builder/antd"
import { useTranslation } from "react-i18next"
import {
getDefaultIntervalValue,
parseIntervalTriggerValue,
stringifyIntervalTriggerValue,
type IntervalValue,
} from "./IntervalValueCodec"
export { parseIntervalTriggerValue, stringifyIntervalTriggerValue } from "./IntervalValueCodec"
export type { IntervalValue, IntervalUnit } from "./IntervalValueCodec"
const buildNextIntervalValue = (
currentValue: IntervalValue | null,
patch: Partial<IntervalValue>
): IntervalValue => {
const base = currentValue ?? getDefaultIntervalValue()
return {
days: patch.days ?? base.days,
hours: patch.hours ?? base.hours,
minutes: patch.minutes ?? base.minutes,
}
}
const getDisplayValue = (value: number | undefined, fallback = 0) =>
typeof value === "number" && Number.isFinite(value) ? value : fallback
export const IntervalValueWidget: React.FC<WidgetProps> = ({
value,
setValue,
readonly,
}) => {
const { t } = useTranslation()
const parsedValue = parseIntervalTriggerValue(value)
const updateValue = (patch: Partial<IntervalValue>) => {
const nextValue = buildNextIntervalValue(parsedValue, patch)
const serialized = stringifyIntervalTriggerValue(nextValue)
setValue(serialized)
}
return (
<div style={{ display: "flex", gap: 12, minWidth: 360 }}>
<div style={{ display: "flex", flexDirection: "column", gap: 6, minWidth: 96 }}>
<span style={{ fontSize: 12, color: "var(--ss-text-secondary)" }}>
{t("autoScore.intervalPartDay")}
</span>
<InputNumber
min={0}
precision={0}
disabled={readonly}
value={getDisplayValue(parsedValue?.days)}
onChange={(next) => updateValue({ days: Math.max(0, Number(next ?? 0)) })}
style={{ width: "100%" }}
/>
</div>
<div style={{ display: "flex", flexDirection: "column", gap: 6, minWidth: 96 }}>
<span style={{ fontSize: 12, color: "var(--ss-text-secondary)" }}>
{t("autoScore.intervalPartHour")}
</span>
<InputNumber
min={0}
precision={0}
disabled={readonly}
value={getDisplayValue(parsedValue?.hours)}
onChange={(next) => updateValue({ hours: Math.max(0, Number(next ?? 0)) })}
style={{ width: "100%" }}
/>
</div>
<div style={{ display: "flex", flexDirection: "column", gap: 6, minWidth: 96 }}>
<span style={{ fontSize: 12, color: "var(--ss-text-secondary)" }}>
{t("autoScore.intervalPartMinute")}
</span>
<InputNumber
min={0}
precision={0}
disabled={readonly}
value={getDisplayValue(parsedValue?.minutes)}
onChange={(next) => updateValue({ minutes: Math.max(0, Number(next ?? 0)) })}
style={{ width: "100%" }}
/>
</div>
</div>
)
}
export default IntervalValueWidget