merge: 同步 upstream/main 新功能到定制版本

- feat: Add slider verification code (bd67997)
- fix bug: Inventory cannot be zero (1f7a6ee)
- fix: resolve merge conflicts and lint errors
This commit is contained in:
2026-03-23 21:50:10 -07:00
parent 3806264343
commit d6616c5859
63 changed files with 3111 additions and 1130 deletions
@@ -17,10 +17,11 @@ import { useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { z } from "zod";
import { useGlobalStore } from "@/stores/global";
import LocalCaptcha, { type LocalCaptchaRef } from "../local-captcha";
import SendCode from "../send-code";
import SliderCaptcha, { type SliderCaptchaRef } from "../slider-captcha";
import type { TurnstileRef } from "../turnstile";
import CloudFlareTurnstile from "../turnstile";
import LocalCaptcha, { type LocalCaptchaRef } from "../local-captcha";
export default function RegisterForm({
loading,
@@ -41,6 +42,7 @@ export default function RegisterForm({
const isTurnstile = verify.captcha_type === "turnstile";
const isLocal = verify.captcha_type === "local";
const isSlider = verify.captcha_type === "slider";
const captchaEnabled = verify.enable_user_register_captcha;
const formSchema = z
@@ -57,8 +59,16 @@ export default function RegisterForm({
: z.string().nullish(),
captcha_code:
captchaEnabled && isLocal
? z.string().min(1, t("captcha.required", "Please enter captcha code"))
? z
.string()
.min(1, t("captcha.required", "Please enter captcha code"))
: z.string().nullish(),
slider_token:
captchaEnabled && isSlider
? z
.string()
.min(1, t("captcha.sliderRequired", "Please complete the slider"))
: z.string().optional(),
})
.superRefine(({ password, repeat_password }, ctx) => {
if (password !== repeat_password) {
@@ -73,6 +83,9 @@ export default function RegisterForm({
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
cf_token: "",
captcha_code: "",
slider_token: "",
...initialValues,
telephone_area_code: initialValues?.telephone_area_code || "1",
invite: localStorage.getItem("invite") || "",
@@ -81,6 +94,7 @@ export default function RegisterForm({
const turnstile = useRef<TurnstileRef>(null);
const localCaptcha = useRef<LocalCaptchaRef>(null);
const sliderCaptcha = useRef<SliderCaptchaRef>(null);
const handleSubmit = form.handleSubmit((data) => {
try {
// Add captcha_id for local captcha
@@ -91,6 +105,7 @@ export default function RegisterForm({
} catch (_error) {
turnstile.current?.reset();
localCaptcha.current?.reset();
sliderCaptcha.current?.reset();
}
});
@@ -126,7 +141,10 @@ export default function RegisterForm({
);
}
}}
placeholder={t("register.areaCodePlaceholder", "Area code...")}
placeholder={t(
"register.areaCodePlaceholder",
"Area code..."
)}
simple
value={field.value}
whitelist={enable_whitelist ? whitelist : []}
@@ -138,7 +156,10 @@ export default function RegisterForm({
/>
<Input
className="rounded-l-none"
placeholder={t("register.telephonePlaceholder", "Enter your telephone...")}
placeholder={t(
"register.telephonePlaceholder",
"Enter your telephone..."
)}
type="tel"
{...field}
/>
@@ -155,7 +176,10 @@ export default function RegisterForm({
<FormItem>
<FormControl>
<Input
placeholder={t("register.passwordPlaceholder", "Enter your password...")}
placeholder={t(
"register.passwordPlaceholder",
"Enter your password..."
)}
type="password"
{...field}
/>
@@ -172,7 +196,10 @@ export default function RegisterForm({
<FormControl>
<Input
disabled={loading}
placeholder={t("register.repeatPasswordPlaceholder", "Enter password again...")}
placeholder={t(
"register.repeatPasswordPlaceholder",
"Enter password again..."
)}
type="password"
{...field}
/>
@@ -190,7 +217,10 @@ export default function RegisterForm({
<div className="flex items-center gap-2">
<Input
disabled={loading}
placeholder={t("register.codePlaceholder", "Enter code...")}
placeholder={t(
"register.codePlaceholder",
"Enter code..."
)}
type="text"
{...field}
value={field.value as string}
@@ -259,8 +289,8 @@ export default function RegisterForm({
<FormControl>
<LocalCaptcha
{...field}
ref={localCaptcha}
onCaptchaIdChange={setCaptchaId}
ref={localCaptcha}
/>
</FormControl>
<FormMessage />
@@ -268,6 +298,20 @@ export default function RegisterForm({
)}
/>
)}
{captchaEnabled && isSlider && (
<FormField
control={form.control}
name="slider_token"
render={({ field }) => (
<FormItem>
<FormControl>
<SliderCaptcha {...field} ref={sliderCaptcha} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
)}
<Button disabled={loading} type="submit">
{loading && <Icon className="animate-spin" icon="mdi:loading" />}
{t("register.title", "Register")}