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
+30 -12
View File
@@ -1,6 +1,7 @@
"use client";
import { zodResolver } from "@hookform/resolvers/zod";
import { useQuery } from "@tanstack/react-query";
import { Button } from "@workspace/ui/components/button";
import { Checkbox } from "@workspace/ui/components/checkbox";
import {
@@ -25,8 +26,10 @@ import {
import { Combobox } from "@workspace/ui/composed/combobox";
import { EnhancedInput } from "@workspace/ui/composed/enhanced-input";
import TagInput from "@workspace/ui/composed/tag-input";
import { getGroupConfig, getNodeGroupList } from "@workspace/ui/services/admin/group";
import { useQuery } from "@tanstack/react-query";
import {
getGroupConfig,
getNodeGroupList,
} from "@workspace/ui/services/admin/group";
import type { TFunction } from "i18next";
import { useEffect, useMemo, useState } from "react";
import { useForm } from "react-hook-form";
@@ -150,7 +153,7 @@ export default function NodeForm(props: {
},
});
const isGroupEnabled = groupConfigData?.enabled || false;
const isGroupEnabled = groupConfigData?.enabled;
useEffect(() => {
if (initialValues) {
@@ -166,15 +169,21 @@ export default function NodeForm(props: {
// Copy only the values we need from initialValues
if (initialValues.name) resetValues.name = initialValues.name;
if (initialValues.server_id) resetValues.server_id = initialValues.server_id;
if (initialValues.server_id)
resetValues.server_id = initialValues.server_id;
if (initialValues.protocol) resetValues.protocol = initialValues.protocol;
if (initialValues.address) resetValues.address = initialValues.address;
if (initialValues.port) resetValues.port = initialValues.port;
if (initialValues.tags) resetValues.tags = initialValues.tags;
// Convert node_group_ids from number[] to string[], ensure it's always an array
if (initialValues.node_group_ids && Array.isArray(initialValues.node_group_ids)) {
resetValues.node_group_ids = initialValues.node_group_ids.map((id: string | number) => String(id));
if (
initialValues.node_group_ids &&
Array.isArray(initialValues.node_group_ids)
) {
resetValues.node_group_ids = initialValues.node_group_ids.map(
(id: string | number) => String(id)
);
} else {
resetValues.node_group_ids = [];
}
@@ -449,23 +458,32 @@ export default function NodeForm(props: {
<div className="grid grid-cols-2 gap-2">
{nodeGroupsData?.map((g) => (
<div
key={g.id}
className="flex items-center space-x-2"
key={g.id}
>
<Checkbox
checked={field.value?.includes(String(g.id))}
id={`node-group-${g.id}`}
checked={field.value?.includes(String(g.id)) || false}
onCheckedChange={(checked) => {
// Ensure field.value is always an array
const currentValue = Array.isArray(field.value) ? field.value : [];
const currentValue = Array.isArray(
field.value
)
? field.value
: [];
if (checked) {
const newValue = [...currentValue, String(g.id)];
const newValue = [
...currentValue,
String(g.id),
];
form.setValue(field.name, newValue, {
shouldValidate: true,
shouldDirty: true,
});
} else {
const newValue = currentValue.filter((v: string) => v !== String(g.id));
const newValue = currentValue.filter(
(v: string) => v !== String(g.id)
);
form.setValue(field.name, newValue, {
shouldValidate: true,
shouldDirty: true,
@@ -474,8 +492,8 @@ export default function NodeForm(props: {
}}
/>
<Label
htmlFor={`node-group-${g.id}`}
className="cursor-pointer"
htmlFor={`node-group-${g.id}`}
>
{g.name}
</Label>