mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-02 03:55:55 +00:00
feat: bot enable and pipeline binding
This commit is contained in:
30
web/package-lock.json
generated
30
web/package-lock.json
generated
@@ -15,6 +15,7 @@
|
||||
"@radix-ui/react-label": "^2.1.6",
|
||||
"@radix-ui/react-select": "^2.2.4",
|
||||
"@radix-ui/react-slot": "^1.2.2",
|
||||
"@radix-ui/react-switch": "^1.2.4",
|
||||
"@radix-ui/react-toggle": "^1.1.8",
|
||||
"@radix-ui/react-toggle-group": "^1.1.9",
|
||||
"@tailwindcss/postcss": "^4.1.5",
|
||||
@@ -1473,6 +1474,35 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-switch": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.4.tgz",
|
||||
"integrity": "sha512-yZCky6XZFnR7pcGonJkr9VyNRu46KcYAbyg1v/gVVCZUr8UJ4x+RpncC27hHtiZ15jC+3WS8Yg/JSgyIHnYYsQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/primitive": "1.1.2",
|
||||
"@radix-ui/react-compose-refs": "1.1.2",
|
||||
"@radix-ui/react-context": "1.1.2",
|
||||
"@radix-ui/react-primitive": "2.1.2",
|
||||
"@radix-ui/react-use-controllable-state": "1.2.2",
|
||||
"@radix-ui/react-use-previous": "1.1.1",
|
||||
"@radix-ui/react-use-size": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-toggle": {
|
||||
"version": "1.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-toggle/-/react-toggle-1.1.8.tgz",
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"@radix-ui/react-label": "^2.1.6",
|
||||
"@radix-ui/react-select": "^2.2.4",
|
||||
"@radix-ui/react-slot": "^1.2.2",
|
||||
"@radix-ui/react-switch": "^1.2.4",
|
||||
"@radix-ui/react-toggle": "^1.1.8",
|
||||
"@radix-ui/react-toggle-group": "^1.1.9",
|
||||
"@tailwindcss/postcss": "^4.1.5",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { IChooseAdapterEntity } from '@/app/home/bots/components/bot-form/ChooseAdapterEntity';
|
||||
import { IChooseAdapterEntity, IPipelineEntity } from '@/app/home/bots/components/bot-form/ChooseEntity';
|
||||
import {
|
||||
DynamicFormItemConfig,
|
||||
IDynamicFormItemConfig,
|
||||
@@ -37,12 +37,15 @@ import {
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@/components/ui/select"
|
||||
import { Checkbox } from "@/components/ui/checkbox"
|
||||
import { Switch } from "@/components/ui/switch"
|
||||
|
||||
const formSchema = z.object({
|
||||
name: z.string().min(1, { message: '机器人名称不能为空' }),
|
||||
description: z.string().min(1, { message: '机器人描述不能为空' }),
|
||||
adapter: z.string().min(1, { message: '适配器不能为空' }),
|
||||
adapter_config: z.record(z.string(), z.any()),
|
||||
enable: z.boolean(),
|
||||
use_pipeline_uuid: z.string().min(1, { message: '流水线不能为空' }),
|
||||
});
|
||||
|
||||
export default function BotForm({
|
||||
@@ -64,6 +67,8 @@ export default function BotForm({
|
||||
description: '一个机器人',
|
||||
adapter: '',
|
||||
adapter_config: {},
|
||||
enable: true,
|
||||
use_pipeline_uuid: '',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -85,6 +90,10 @@ export default function BotForm({
|
||||
Record<string, string>
|
||||
>({});
|
||||
|
||||
const [pipelineNameList, setPipelineNameList] = useState<
|
||||
IPipelineEntity[]
|
||||
>([]);
|
||||
|
||||
const [dynamicFormConfigList, setDynamicFormConfigList] = useState<
|
||||
IDynamicFormItemConfig[]
|
||||
>([]);
|
||||
@@ -100,6 +109,9 @@ export default function BotForm({
|
||||
form.setValue('description', val.description);
|
||||
form.setValue('adapter', val.adapter);
|
||||
form.setValue('adapter_config', val.adapter_config);
|
||||
form.setValue('enable', val.enable);
|
||||
form.setValue('use_pipeline_uuid', val.use_pipeline_uuid || '');
|
||||
console.log('form', form.getValues());
|
||||
handleAdapterSelect(val.adapter);
|
||||
// dynamicForm.setFieldsValue(val.adapter_config);
|
||||
});
|
||||
@@ -138,6 +150,19 @@ export default function BotForm({
|
||||
}, {} as Record<string, string>),
|
||||
);
|
||||
|
||||
if (initBotId) {
|
||||
// 初始化流水线列表
|
||||
const rawPipelineList = await httpClient.getPipelines();
|
||||
setPipelineNameList(
|
||||
rawPipelineList.pipelines.map((item) => {
|
||||
return {
|
||||
label: item.name,
|
||||
value: item.uuid,
|
||||
};
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
// 初始化适配器表单map
|
||||
rawAdapterList.adapters.forEach((rawAdapter) => {
|
||||
adapterNameToDynamicConfigMap.set(
|
||||
@@ -172,6 +197,8 @@ export default function BotForm({
|
||||
description: bot.description,
|
||||
name: bot.name,
|
||||
adapter_config: bot.adapter_config,
|
||||
enable: bot.enable ?? true,
|
||||
use_pipeline_uuid: bot.use_pipeline_uuid,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -214,6 +241,8 @@ export default function BotForm({
|
||||
description: form.getValues().description,
|
||||
adapter: form.getValues().adapter,
|
||||
adapter_config: form.getValues().adapter_config,
|
||||
enable: form.getValues().enable,
|
||||
use_pipeline_uuid: form.getValues().use_pipeline_uuid,
|
||||
};
|
||||
httpClient
|
||||
.updateBot(initBotId, updateBot)
|
||||
@@ -316,6 +345,54 @@ export default function BotForm({
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onDynamicFormSubmit)} className="space-y-8">
|
||||
<div className="space-y-4">
|
||||
{/* 是否启用 & 绑定流水线 仅在编辑模式 */}
|
||||
{initBotId && (
|
||||
<div className="flex items-center gap-6">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="enable"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex flex-col justify-start gap-[0.8rem] h-[3.8rem]">
|
||||
<FormLabel>是否启用</FormLabel>
|
||||
<FormControl>
|
||||
<Switch checked={field.value} onCheckedChange={field.onChange} />
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="use_pipeline_uuid"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex flex-col justify-start gap-[0.8rem] h-[3.8rem]">
|
||||
<FormLabel>绑定流水线</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
onValueChange={field.onChange}
|
||||
{...field}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="选择流水线" />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="fixed z-[1000]">
|
||||
<SelectGroup>
|
||||
{pipelineNameList.map((item) => (
|
||||
<SelectItem key={item.value} value={item.value}>
|
||||
{item.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
)}
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="name"
|
||||
|
||||
@@ -2,3 +2,8 @@ export interface IChooseAdapterEntity {
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface IPipelineEntity {
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
31
web/src/components/ui/switch.tsx
Normal file
31
web/src/components/ui/switch.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import * as SwitchPrimitive from "@radix-ui/react-switch"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function Switch({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof SwitchPrimitive.Root>) {
|
||||
return (
|
||||
<SwitchPrimitive.Root
|
||||
data-slot="switch"
|
||||
className={cn(
|
||||
"peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<SwitchPrimitive.Thumb
|
||||
data-slot="switch-thumb"
|
||||
className={cn(
|
||||
"bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block size-4 rounded-full ring-0 transition-transform data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0"
|
||||
)}
|
||||
/>
|
||||
</SwitchPrimitive.Root>
|
||||
)
|
||||
}
|
||||
|
||||
export { Switch }
|
||||
Reference in New Issue
Block a user