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
@@ -15,8 +15,9 @@ import { useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { z } from "zod";
import { useGlobalStore } from "@/stores/global";
import CloudFlareTurnstile, { type TurnstileRef } from "../turnstile";
import LocalCaptcha, { type LocalCaptchaRef } from "../local-captcha";
import SliderCaptcha, { type SliderCaptchaRef } from "../slider-captcha";
import CloudFlareTurnstile, { type TurnstileRef } from "../turnstile";
export default function LoginForm({
loading,
@@ -38,6 +39,7 @@ export default function LoginForm({
const isTurnstile = verify.captcha_type === "turnstile";
const isLocal = verify.captcha_type === "local";
const isSlider = verify.captcha_type === "slider";
const captchaEnabled = verify.enable_admin_login_captcha;
const formSchema = z.object({
@@ -53,14 +55,26 @@ export default function LoginForm({
captchaEnabled && isLocal
? z.string().min(1, t("captcha.required", "Please enter captcha code"))
: z.string().optional(),
slider_token:
captchaEnabled && isSlider
? z
.string()
.min(1, t("captcha.sliderRequired", "Please complete the slider"))
: z.string().optional(),
});
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: initialValues,
defaultValues: {
cf_token: "",
captcha_code: "",
slider_token: "",
...initialValues,
},
});
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
@@ -71,6 +85,7 @@ export default function LoginForm({
} catch (_error) {
turnstile.current?.reset();
localCaptcha.current?.reset();
sliderCaptcha.current?.reset();
}
});
@@ -143,8 +158,8 @@ export default function LoginForm({
<FormControl>
<LocalCaptcha
{...field}
ref={localCaptcha}
onCaptchaIdChange={setCaptchaId}
ref={localCaptcha}
/>
</FormControl>
<FormMessage />
@@ -152,6 +167,20 @@ export default function LoginForm({
)}
/>
)}
{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("login.title", "Login")}