mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-17 19:24:19 +00:00
refactor: replace antd with shadcn/ui
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
flex-direction: row;
|
||||
gap: 0.8rem;
|
||||
user-select: none;
|
||||
/* background-color: aqua; */
|
||||
}
|
||||
|
||||
.iconImage {
|
||||
@@ -31,7 +32,7 @@
|
||||
.basicInfoContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.6rem;
|
||||
gap: 0.2rem;
|
||||
}
|
||||
|
||||
.basicInfoText {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import styles from './LLMCard.module.css';
|
||||
import { LLMCardVO } from '@/app/home/models/component/llm-card/LLMCardVO';
|
||||
import { Button } from '@/components/ui/button';
|
||||
|
||||
function checkAbilityBadges(abilities: string[]) {
|
||||
|
||||
|
||||
@@ -1,12 +1,69 @@
|
||||
import styles from '@/app/home/models/LLMConfig.module.css';
|
||||
import { Button, Form, Input, Select, SelectProps, Space, Modal } from 'antd';
|
||||
import { SelectProps } from 'antd';
|
||||
import { ICreateLLMField } from '@/app/home/models/ICreateLLMField';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { IChooseRequesterEntity } from '@/app/home/models/component/llm-form/ChooseAdapterEntity';
|
||||
import { IChooseRequesterEntity } from '@/app/home/models/component/llm-form/ChooseRequesterEntity';
|
||||
import { httpClient } from '@/app/infra/http/HttpClient';
|
||||
import { LLMModel } from '@/app/infra/api/api-types';
|
||||
import { UUID } from 'uuidjs';
|
||||
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { useForm } from "react-hook-form"
|
||||
import { z } from "zod"
|
||||
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
DialogFooter,
|
||||
} from "@/components/ui/dialog"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@/components/ui/form"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@/components/ui/select"
|
||||
import { Checkbox } from "@/components/ui/checkbox"
|
||||
|
||||
const extraArgSchema = z.object({
|
||||
key: z.string().min(1, { message: '键名不能为空' }),
|
||||
type: z.enum(['string', 'number', 'boolean']),
|
||||
value: z.string(),
|
||||
}).superRefine((data, ctx) => {
|
||||
if (data.type === 'number' && isNaN(Number(data.value))) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: "必须是有效的数字",
|
||||
path: ['value'],
|
||||
});
|
||||
}
|
||||
if (data.type === 'boolean' && data.value !== 'true' && data.value !== 'false') {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: "必须是 true 或 false",
|
||||
path: ['value'],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const formSchema = z.object({
|
||||
name: z.string().min(1, { message: '模型名称不能为空' }),
|
||||
model_provider: z.string().min(1, { message: '模型供应商不能为空' }),
|
||||
url: z.string().min(1, { message: '请求URL不能为空' }),
|
||||
api_key: z.string().min(1, { message: 'API Key不能为空' }),
|
||||
abilities: z.array(z.string()),
|
||||
extra_args: z.array(extraArgSchema).optional(),
|
||||
})
|
||||
|
||||
export default function LLMForm({
|
||||
editMode,
|
||||
initLLMId,
|
||||
@@ -16,40 +73,97 @@ export default function LLMForm({
|
||||
}: {
|
||||
editMode: boolean;
|
||||
initLLMId?: string;
|
||||
onFormSubmit: (value: ICreateLLMField) => void;
|
||||
onFormCancel: (value: ICreateLLMField) => void;
|
||||
onFormSubmit: (value: z.infer<typeof formSchema>) => void;
|
||||
onFormCancel: () => void;
|
||||
onLLMDeleted: () => void;
|
||||
}) {
|
||||
const [form] = Form.useForm<ICreateLLMField>();
|
||||
const extraOptions: SelectProps['options'] = [];
|
||||
const [initValue] = useState<ICreateLLMField>();
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
name: '',
|
||||
model_provider: '',
|
||||
url: '',
|
||||
api_key: '',
|
||||
abilities: [],
|
||||
extra_args: [],
|
||||
},
|
||||
});
|
||||
|
||||
const [extraArgs, setExtraArgs] = useState<{key: string, type: 'string' | 'number' | 'boolean', value: string}[]>([]);
|
||||
|
||||
const [showDeleteConfirmModal, setShowDeleteConfirmModal] = useState(false);
|
||||
const abilityOptions: SelectProps['options'] = [
|
||||
{
|
||||
label: '视觉能力',
|
||||
value: 'vision',
|
||||
},
|
||||
{
|
||||
label: '函数调用',
|
||||
value: 'func_call',
|
||||
},
|
||||
{
|
||||
label: '图像识别',
|
||||
value: 'vision',
|
||||
},
|
||||
];
|
||||
const [requesterNameList, setRequesterNameList] = useState<
|
||||
IChooseRequesterEntity[]
|
||||
>([]);
|
||||
const [requesterDefaultURLList, setRequesterDefaultURLList] = useState<
|
||||
string[]
|
||||
>([]);
|
||||
|
||||
useEffect(() => {
|
||||
initLLMModelFormComponent();
|
||||
if (editMode && initLLMId) {
|
||||
getLLMConfig(initLLMId).then((val) => {
|
||||
form.setFieldsValue(val);
|
||||
form.setValue('name', val.name);
|
||||
form.setValue('model_provider', val.model_provider);
|
||||
form.setValue('url', val.url);
|
||||
form.setValue('api_key', val.api_key);
|
||||
form.setValue('abilities', val.abilities as ("vision" | "func_call")[]);
|
||||
// 转换extra_args为新格式
|
||||
if(val.extra_args) {
|
||||
const args = val.extra_args.map(arg => {
|
||||
const [key, value] = arg.split(':');
|
||||
let type: 'string' | 'number' | 'boolean' = 'string';
|
||||
if(!isNaN(Number(value))) {
|
||||
type = 'number';
|
||||
} else if(value === 'true' || value === 'false') {
|
||||
type = 'boolean';
|
||||
}
|
||||
return {
|
||||
key,
|
||||
type,
|
||||
value
|
||||
};
|
||||
});
|
||||
setExtraArgs(args);
|
||||
form.setValue('extra_args', args);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
form.resetFields();
|
||||
form.reset();
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const addExtraArg = () => {
|
||||
setExtraArgs([...extraArgs, {key: '', type: 'string', value: ''}]);
|
||||
};
|
||||
|
||||
const updateExtraArg = (index: number, field: 'key' | 'type' | 'value', value: string) => {
|
||||
const newArgs = [...extraArgs];
|
||||
newArgs[index] = {
|
||||
...newArgs[index],
|
||||
[field]: value
|
||||
};
|
||||
setExtraArgs(newArgs);
|
||||
form.setValue('extra_args', newArgs);
|
||||
};
|
||||
|
||||
const removeExtraArg = (index: number) => {
|
||||
const newArgs = extraArgs.filter((_, i) => i !== index);
|
||||
setExtraArgs(newArgs);
|
||||
form.setValue('extra_args', newArgs);
|
||||
};
|
||||
|
||||
async function initLLMModelFormComponent() {
|
||||
const requesterNameList = await httpClient.getProviderRequesters();
|
||||
setRequesterNameList(
|
||||
@@ -60,6 +174,17 @@ export default function LLMForm({
|
||||
};
|
||||
}),
|
||||
);
|
||||
setRequesterDefaultURLList(
|
||||
requesterNameList.requesters.map((item) => {
|
||||
const config = item.spec.config;
|
||||
for (let i = 0; i < config.length; i++) {
|
||||
if (config[i].name == 'base_url') {
|
||||
return config[i].default;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
async function getLLMConfig(id: string): Promise<ICreateLLMField> {
|
||||
@@ -75,42 +200,35 @@ export default function LLMForm({
|
||||
model_provider: llmModel.model.requester,
|
||||
url: llmModel.model.requester_config?.base_url,
|
||||
api_key: llmModel.model.api_keys[0],
|
||||
abilities: llmModel.model.abilities,
|
||||
abilities: llmModel.model.abilities || [],
|
||||
extra_args: fakeExtraArgs,
|
||||
};
|
||||
}
|
||||
|
||||
function handleFormSubmit(value: ICreateLLMField) {
|
||||
function handleFormSubmit(value: z.infer<typeof formSchema>) {
|
||||
if (editMode) {
|
||||
// 暂不支持更改模型
|
||||
// onSaveEdit(value)
|
||||
} else {
|
||||
onCreateLLM(value);
|
||||
}
|
||||
form.resetFields();
|
||||
form.reset();
|
||||
}
|
||||
|
||||
// function onSaveEdit(value: ICreateLLMField) {
|
||||
// const requestParam: LLMModel = {
|
||||
// uuid: UUID.generate(),
|
||||
// name: value.name,
|
||||
// description: "",
|
||||
// requester: value.model_provider,
|
||||
// requester_config: {
|
||||
// "base_url": value.url,
|
||||
// "timeout": 120
|
||||
// },
|
||||
// extra_args: value.extra_args,
|
||||
// api_keys: [value.api_key],
|
||||
// abilities: value.abilities,
|
||||
// // created_at: 'Sun Apr 27 2025 21:56:35 GMT+0800',
|
||||
// // updated_at: 'Sun Apr 27 2025 21:56:35 GMT+0800',
|
||||
// };
|
||||
// httpClient.createProviderLLMModel(requestParam).then(r => console.log(r))
|
||||
// }
|
||||
|
||||
function onCreateLLM(value: ICreateLLMField) {
|
||||
function onCreateLLM(value: z.infer<typeof formSchema>) {
|
||||
console.log('create llm', value);
|
||||
// 转换extra_args为对象格式
|
||||
const extraArgsObj: Record<string, any> = {};
|
||||
value.extra_args?.forEach(arg => {
|
||||
if(arg.type === 'number') {
|
||||
extraArgsObj[arg.key] = Number(arg.value);
|
||||
} else if(arg.type === 'boolean') {
|
||||
extraArgsObj[arg.key] = arg.value === 'true';
|
||||
} else {
|
||||
extraArgsObj[arg.key] = arg.value;
|
||||
}
|
||||
});
|
||||
|
||||
const requestParam: LLMModel = {
|
||||
uuid: UUID.generate(),
|
||||
name: value.name,
|
||||
@@ -120,18 +238,16 @@ export default function LLMForm({
|
||||
base_url: value.url,
|
||||
timeout: 120,
|
||||
},
|
||||
extra_args: value.extra_args,
|
||||
extra_args: extraArgsObj,
|
||||
api_keys: [value.api_key],
|
||||
abilities: value.abilities,
|
||||
// created_at: 'Sun Apr 27 2025 21:56:35 GMT+0800',
|
||||
// updated_at: 'Sun Apr 27 2025 21:56:35 GMT+0800',
|
||||
};
|
||||
httpClient.createProviderLLMModel(requestParam).then(() => {
|
||||
onFormSubmit(value);
|
||||
});
|
||||
}
|
||||
|
||||
function handleAbilitiesChange() {}
|
||||
function handleAbilitiesChange() { }
|
||||
|
||||
function deleteModel() {
|
||||
if (initLLMId) {
|
||||
@@ -143,145 +259,221 @@ export default function LLMForm({
|
||||
|
||||
return (
|
||||
<div className={styles.modalContainer}>
|
||||
<Modal
|
||||
open={showDeleteConfirmModal}
|
||||
title={'删除确认'}
|
||||
onCancel={() => setShowDeleteConfirmModal(false)}
|
||||
footer={
|
||||
<div
|
||||
style={{
|
||||
width: '170px',
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
danger
|
||||
onClick={() => {
|
||||
deleteModel();
|
||||
setShowDeleteConfirmModal(false);
|
||||
}}
|
||||
>
|
||||
确认删除
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setShowDeleteConfirmModal(false);
|
||||
}}
|
||||
>
|
||||
|
||||
<Dialog open={showDeleteConfirmModal} onOpenChange={setShowDeleteConfirmModal}>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>删除确认</DialogTitle>
|
||||
</DialogHeader>
|
||||
<DialogDescription>
|
||||
你确定要删除这个模型吗?
|
||||
</DialogDescription>
|
||||
<DialogFooter>
|
||||
<Button variant="outline" onClick={() => setShowDeleteConfirmModal(false)}>
|
||||
取消
|
||||
</Button>
|
||||
<Button variant="destructive" onClick={() => {
|
||||
deleteModel();
|
||||
setShowDeleteConfirmModal(false);
|
||||
}}>
|
||||
确认删除
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(handleFormSubmit)} className="space-y-8">
|
||||
<div className="space-y-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="name"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>模型名称<span className="text-red-500">*</span></FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
<FormDescription>
|
||||
请填写供应商向您提供的模型名称
|
||||
</FormDescription>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="model_provider"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>模型供应商<span className="text-red-500">*</span></FormLabel>
|
||||
<FormControl>
|
||||
<Select onValueChange={(value) => {
|
||||
field.onChange(value);
|
||||
const index = requesterNameList.findIndex(item => item.value === value);
|
||||
if(index !== -1) {
|
||||
form.setValue('url', requesterDefaultURLList[index]);
|
||||
}
|
||||
}} value={field.value}>
|
||||
<SelectTrigger className="w-[180px]">
|
||||
<SelectValue placeholder="选择模型供应商" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
{requesterNameList.map((item) => (
|
||||
<SelectItem key={item.value} value={item.value}>
|
||||
{item.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="url"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>请求URL<span className="text-red-500">*</span></FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="api_key"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>API Key<span className="text-red-500">*</span></FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="abilities"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>能力</FormLabel>
|
||||
<div className="mb-0">
|
||||
<FormDescription>
|
||||
选择模型能力
|
||||
</FormDescription>
|
||||
</div>
|
||||
{abilityOptions.map((item) => (
|
||||
<FormField
|
||||
key={item.value}
|
||||
control={form.control}
|
||||
name="abilities"
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<FormItem
|
||||
key={item.value}
|
||||
className="flex flex-row items-start space-x-1 space-y-0"
|
||||
>
|
||||
<FormControl>
|
||||
<Checkbox
|
||||
checked={Array.isArray(field.value) && field.value?.includes(item.value)}
|
||||
onCheckedChange={(checked) => {
|
||||
return checked
|
||||
? field.onChange([...(field.value || []), item.value])
|
||||
: field.onChange(
|
||||
field.value?.filter(
|
||||
(value) => value !== item.value
|
||||
)
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormLabel className="font-normal">
|
||||
{item.label}
|
||||
</FormLabel>
|
||||
</FormItem>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormItem>
|
||||
<FormLabel>额外参数</FormLabel>
|
||||
<div className="space-y-2">
|
||||
{extraArgs.map((arg, index) => (
|
||||
<div key={index} className="flex gap-2">
|
||||
<Input
|
||||
placeholder="键名"
|
||||
value={arg.key}
|
||||
onChange={(e) => updateExtraArg(index, 'key', e.target.value)}
|
||||
/>
|
||||
<Select
|
||||
value={arg.type}
|
||||
onValueChange={(value) => updateExtraArg(index, 'type', value)}
|
||||
>
|
||||
<SelectTrigger className="w-[120px]">
|
||||
<SelectValue placeholder="类型" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="string">字符串</SelectItem>
|
||||
<SelectItem value="number">数字</SelectItem>
|
||||
<SelectItem value="boolean">布尔值</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Input
|
||||
placeholder="值"
|
||||
value={arg.value}
|
||||
onChange={(e) => updateExtraArg(index, 'value', e.target.value)}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
className="p-2 hover:bg-gray-100 rounded"
|
||||
onClick={() => removeExtraArg(index)}
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" className="w-5 h-5 text-red-500">
|
||||
<path d="M7 4V2H17V4H22V6H20V21C20 21.5523 19.5523 22 19 22H5C4.44772 22 4 21.5523 4 21V6H2V4H7ZM6 6V20H18V6H6ZM9 9H11V17H9V9ZM13 9H15V17H13V9Z"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
<Button type="button" variant="outline" onClick={addExtraArg}>
|
||||
添加参数
|
||||
</Button>
|
||||
</div>
|
||||
<FormDescription>
|
||||
将在请求时附加到请求体中,如 max_tokens, temperature, top_p 等
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
|
||||
</div>
|
||||
}
|
||||
>
|
||||
你确定要删除这个模型吗?
|
||||
</Modal>
|
||||
<Form
|
||||
form={form}
|
||||
labelCol={{ span: 4 }}
|
||||
wrapperCol={{ span: 14 }}
|
||||
layout="horizontal"
|
||||
initialValues={{
|
||||
...initValue,
|
||||
}}
|
||||
onFinish={handleFormSubmit}
|
||||
clearOnDestroy={true}
|
||||
disabled={editMode}
|
||||
>
|
||||
<Form.Item<ICreateLLMField>
|
||||
label={'模型名称'}
|
||||
name={'name'}
|
||||
rules={[{ required: true, message: '该项为必填项哦~' }]}
|
||||
>
|
||||
<Input
|
||||
placeholder={'为自己的大模型取个好听的名字~'}
|
||||
style={{ width: 260 }}
|
||||
></Input>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<ICreateLLMField>
|
||||
label={'模型供应商'}
|
||||
name={'model_provider'}
|
||||
rules={[{ required: true, message: '该项为必填项哦~' }]}
|
||||
>
|
||||
<Select
|
||||
style={{ width: 120 }}
|
||||
onChange={() => {}}
|
||||
options={requesterNameList}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<ICreateLLMField>
|
||||
label={'请求URL'}
|
||||
name={'url'}
|
||||
rules={[{ required: true, message: '该项为必填项哦~' }]}
|
||||
>
|
||||
<Input
|
||||
placeholder="请求地址,一般是API提供商提供的URL"
|
||||
style={{ width: 500 }}
|
||||
></Input>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<ICreateLLMField>
|
||||
label={'API Key'}
|
||||
name={'api_key'}
|
||||
rules={[{ required: true, message: '该项为必填项哦~' }]}
|
||||
>
|
||||
<Input placeholder="你的API Key" style={{ width: 500 }}></Input>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<ICreateLLMField> label={'开启能力'} name={'abilities'}>
|
||||
<Select
|
||||
mode="tags"
|
||||
style={{ width: 500 }}
|
||||
placeholder="选择模型能力,输入回车可自定义能力"
|
||||
onChange={handleAbilitiesChange}
|
||||
options={abilityOptions}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<ICreateLLMField> label={'其他参数'} name={'extra_args'}>
|
||||
<Select
|
||||
mode="tags"
|
||||
style={{ width: 500 }}
|
||||
placeholder="输入后回车可自定义其他参数,例 key:value"
|
||||
onChange={handleAbilitiesChange}
|
||||
options={extraOptions}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item wrapperCol={{ offset: 4, span: 14 }}>
|
||||
<Space>
|
||||
<DialogFooter>
|
||||
{!editMode && (
|
||||
<Button type="primary" htmlType="submit">
|
||||
提交
|
||||
</Button>
|
||||
<Button type="submit">提交</Button>
|
||||
)}
|
||||
{editMode && (
|
||||
<Button
|
||||
color="danger"
|
||||
variant="solid"
|
||||
onClick={() => {
|
||||
setShowDeleteConfirmModal(true);
|
||||
}}
|
||||
disabled={false}
|
||||
>
|
||||
<Button type="button" variant="destructive" onClick={() => setShowDeleteConfirmModal(true)}>
|
||||
删除
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
htmlType="button"
|
||||
onClick={() => {
|
||||
onFormCancel(form.getFieldsValue());
|
||||
}}
|
||||
disabled={false}
|
||||
>
|
||||
<Button type="button" onClick={() => onFormCancel()}>
|
||||
取消
|
||||
</Button>
|
||||
</Space>
|
||||
</Form.Item>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</Form>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user