fix(抽奖): 数字输入改 text 类型(时长/概率/库存/领奖窗口/发放次数)+ 重建 dist.zip
PR Check / Lint, Check, Test and Build (push) Has been cancelled

避开 EnhancedInput 在 type=number 下 min/max 实时钳制导致的"输入0/改数字跳变",
用 formatOutput 转 number,后端仍收 int。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-17 06:26:14 -07:00
parent 0d79e9a6fd
commit a98c7ecb52
3 changed files with 40 additions and 17 deletions
Binary file not shown.
@@ -31,6 +31,16 @@ const grantSchema = z.object({
source_ref: z.string().trim().min(1),
});
// 数字输入统一用 type="text" + 该 formatOutput,避开 number 类型 input 的实时钳制问题。
const numberOutput = (v: string | number): number | undefined => {
const s = String(v ?? "").trim();
if (s === "") {
return;
}
const n = Number(s);
return Number.isNaN(n) ? undefined : n;
};
type GrantFormValues = z.infer<typeof grantSchema>;
const SOURCE_REF_RANDOM_LENGTH = 6;
@@ -123,10 +133,11 @@ export default function GrantDialog({
<FormLabel>{t("grant.userId", "User ID")}</FormLabel>
<FormControl>
<EnhancedInput
min={1}
formatOutput={numberOutput}
inputMode="numeric"
onValueChange={(value) => field.onChange(value)}
placeholder={t("grant.userIdPlaceholder", "e.g. 87433")}
type="number"
type="text"
value={field.value}
/>
</FormControl>
@@ -148,10 +159,11 @@ export default function GrantDialog({
<FormLabel>{t("grant.amount", "Amount")}</FormLabel>
<FormControl>
<EnhancedInput
min={1}
formatOutput={numberOutput}
inputMode="numeric"
onValueChange={(value) => field.onChange(value)}
placeholder="1"
type="number"
type="text"
value={field.value}
/>
</FormControl>
+24 -13
View File
@@ -46,6 +46,18 @@ const CENTS_PER_YUAN = 100;
// 概率单位约定:weight 1000 = 1%(支持 3 位小数概率,总权重 100000 = 100%)。
const WEIGHT_PER_PERCENT = 1000;
// numberOutput 把 text 输入转成数字(空/非法→undefined)。数字输入统一用 type="text"
// + 该 formatOutput,避开 EnhancedInput 在 type="number" 下 min/max 实时钳制导致的
// “输入 0 / 改中间位跳变”问题;提交仍是数字,后端收 int。
const numberOutput = (v: string | number): number | undefined => {
const s = String(v ?? "").trim();
if (s === "") {
return;
}
const n = Number(s);
return Number.isNaN(n) ? undefined : n;
};
type TranslateFn = (key: string, defaultValue: string) => string;
const PRIZE_TYPE_OPTIONS: {
@@ -442,9 +454,9 @@ export default function PrizeForm({
"duration_days",
t("prize.durationDays", "Duration (days)"),
{
type: "number",
min: 1,
step: 1,
type: "text",
inputMode: "numeric",
formatOutput: numberOutput,
placeholder: t("prize.durationDaysPlaceholder", "e.g. 1"),
suffix: t("prize.daysSuffix", "days"),
}
@@ -538,9 +550,9 @@ export default function PrizeForm({
"claim_ttl_hours",
t("prize.claimTtlHours", "Claim window (hours)"),
{
type: "number",
min: 1,
step: 1,
type: "text",
inputMode: "numeric",
formatOutput: numberOutput,
placeholder: "168",
suffix: t("prize.hoursSuffix", "hours"),
},
@@ -561,10 +573,9 @@ export default function PrizeForm({
"weight",
t("prize.weight", "Win probability (%)"),
{
type: "number",
min: 0,
max: 100,
step: 0.001,
type: "text",
inputMode: "decimal",
formatOutput: numberOutput,
suffix: "%",
disabled: isFallback,
},
@@ -587,9 +598,9 @@ export default function PrizeForm({
"total_stock",
t("prize.totalStock", "Total Stock"),
{
type: "number",
min: 1,
step: 1,
type: "text",
inputMode: "numeric",
formatOutput: numberOutput,
placeholder: t("prize.totalStockPlaceholder", "e.g. 100"),
}
)}