Fix: Fixed the issue of retrieval operator text overlapping #3221 (#8652)

### What problem does this PR solve?

Fix: Fixed the issue of retrieval operator text overlapping #3221

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
balibabu
2025-07-03 19:04:06 +08:00
committed by GitHub
parent 9771b521cd
commit 3234a15aae
11 changed files with 113 additions and 62 deletions

View File

@ -1,3 +1,4 @@
import { FormLayout } from '@/constants/form';
import { useTranslate } from '@/hooks/common-hooks'; import { useTranslate } from '@/hooks/common-hooks';
import { SliderInputFormField } from './slider-input-form-field'; import { SliderInputFormField } from './slider-input-form-field';
@ -11,6 +12,7 @@ export function AutoKeywordsFormField() {
max={30} max={30}
min={0} min={0}
tooltip={t('autoKeywordsTip')} tooltip={t('autoKeywordsTip')}
layout={FormLayout.Horizontal}
></SliderInputFormField> ></SliderInputFormField>
); );
} }
@ -25,6 +27,7 @@ export function AutoQuestionsFormField() {
max={10} max={10}
min={0} min={0}
tooltip={t('autoQuestionsTip')} tooltip={t('autoQuestionsTip')}
layout={FormLayout.Horizontal}
></SliderInputFormField> ></SliderInputFormField>
); );
} }

View File

@ -1,3 +1,4 @@
import { FormLayout } from '@/constants/form';
import { useTranslate } from '@/hooks/common-hooks'; import { useTranslate } from '@/hooks/common-hooks';
import { SliderInputFormField } from './slider-input-form-field'; import { SliderInputFormField } from './slider-input-form-field';
@ -14,6 +15,7 @@ export function MaxTokenNumberFormField({ max = 2048 }: IProps) {
name={'parser_config.chunk_token_num'} name={'parser_config.chunk_token_num'}
label={t('chunkTokenNumber')} label={t('chunkTokenNumber')}
max={max} max={max}
layout={FormLayout.Horizontal}
></SliderInputFormField> ></SliderInputFormField>
); );
} }

View File

@ -1,3 +1,4 @@
import { FormLayout } from '@/constants/form';
import { useTranslate } from '@/hooks/common-hooks'; import { useTranslate } from '@/hooks/common-hooks';
import { SliderInputFormField } from './slider-input-form-field'; import { SliderInputFormField } from './slider-input-form-field';
@ -12,6 +13,7 @@ export function PageRankFormField() {
defaultValue={0} defaultValue={0}
max={100} max={100}
min={0} min={0}
layout={FormLayout.Horizontal}
></SliderInputFormField> ></SliderInputFormField>
); );
} }

View File

@ -1,3 +1,4 @@
import { FormLayout } from '@/constants/form';
import { DocumentParserType } from '@/constants/knowledge'; import { DocumentParserType } from '@/constants/knowledge';
import { useTranslate } from '@/hooks/common-hooks'; import { useTranslate } from '@/hooks/common-hooks';
import random from 'lodash/random'; import random from 'lodash/random';
@ -130,6 +131,7 @@ const RaptorFormFields = () => {
defaultValue={256} defaultValue={256}
max={2048} max={2048}
min={0} min={0}
layout={FormLayout.Horizontal}
></SliderInputFormField> ></SliderInputFormField>
<SliderInputFormField <SliderInputFormField
name={'parser_config.raptor.threshold'} name={'parser_config.raptor.threshold'}
@ -139,6 +141,7 @@ const RaptorFormFields = () => {
step={0.01} step={0.01}
max={1} max={1}
min={0} min={0}
layout={FormLayout.Horizontal}
></SliderInputFormField> ></SliderInputFormField>
<SliderInputFormField <SliderInputFormField
name={'parser_config.raptor.max_cluster'} name={'parser_config.raptor.max_cluster'}
@ -147,6 +150,7 @@ const RaptorFormFields = () => {
defaultValue={64} defaultValue={64}
max={1024} max={1024}
min={1} min={1}
layout={FormLayout.Horizontal}
></SliderInputFormField> ></SliderInputFormField>
<FormField <FormField
control={form.control} control={form.control}

View File

@ -1,3 +1,4 @@
import { FormLayout } from '@/constants/form';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { useFormContext } from 'react-hook-form'; import { useFormContext } from 'react-hook-form';
@ -11,6 +12,10 @@ import {
} from './ui/form'; } from './ui/form';
import { Input } from './ui/input'; import { Input } from './ui/input';
export type FormLayoutType = {
layout?: FormLayout;
};
type SliderInputFormFieldProps = { type SliderInputFormFieldProps = {
max?: number; max?: number;
min?: number; min?: number;
@ -20,7 +25,7 @@ type SliderInputFormFieldProps = {
tooltip?: ReactNode; tooltip?: ReactNode;
defaultValue?: number; defaultValue?: number;
className?: string; className?: string;
}; } & FormLayoutType;
export function SliderInputFormField({ export function SliderInputFormField({
max, max,
@ -31,57 +36,63 @@ export function SliderInputFormField({
tooltip, tooltip,
defaultValue, defaultValue,
className, className,
layout = FormLayout.Vertical,
}: SliderInputFormFieldProps) { }: SliderInputFormFieldProps) {
const form = useFormContext(); const form = useFormContext();
const isHorizontal = layout === FormLayout.Horizontal;
return ( return (
<FormField <FormField
control={form.control} control={form.control}
name={name} name={name}
defaultValue={defaultValue || 0} defaultValue={defaultValue || 0}
render={({ field }) => ( render={({ field }) => (
<FormItem className=" items-center space-y-0 "> <FormItem
<div className="flex items-center"> className={cn({ 'flex items-center space-y-0': isHorizontal })}
<FormLabel >
tooltip={tooltip} <FormLabel
className="text-sm text-muted-foreground whitespace-nowrap w-1/4" tooltip={tooltip}
> className={cn({
{label} 'text-sm text-muted-foreground whitespace-nowrap w-1/4':
</FormLabel> isHorizontal,
<div })}
className={cn( >
'flex items-center gap-14 justify-between', {label}
'w-3/4', </FormLabel>
className, <div
)} className={cn(
> 'flex items-center gap-14 justify-between',
<FormControl> { 'w-3/4': isHorizontal },
<SingleFormSlider className,
{...field} )}
max={max} >
min={min} <FormControl>
step={step} <SingleFormSlider
// defaultValue={ {...field}
// typeof defaultValue === 'number' ? [defaultValue] : undefined max={max}
// } min={min}
></SingleFormSlider> step={step}
</FormControl> // defaultValue={
<FormControl> // typeof defaultValue === 'number' ? [defaultValue] : undefined
<Input // }
type={'number'} ></SingleFormSlider>
className="h-7 w-20" </FormControl>
max={max} <FormControl>
min={min} <Input
step={step} type={'number'}
{...field} className="h-7 w-20"
onChange={(ev) => { max={max}
const value = ev.target.value; min={min}
field.onChange(value === '' ? 0 : Number(value)); // convert to number step={step}
}} {...field}
// defaultValue={defaultValue} onChange={(ev) => {
></Input> const value = ev.target.value;
</FormControl> field.onChange(value === '' ? 0 : Number(value)); // convert to number
</div> }}
// defaultValue={defaultValue}
></Input>
</FormControl>
</div> </div>
<FormMessage /> <FormMessage />
</FormItem> </FormItem>

View File

@ -0,0 +1,5 @@
export enum FormLayout {
Horizontal = 'horizontal',
Vertical = 'vertical',
Inline = 'inline',
}

View File

@ -1275,7 +1275,7 @@ This delimiter is used to split the input text into several text pieces echo of
inputVariables: 'Input variables', inputVariables: 'Input variables',
runningHintText: 'is running...🕞', runningHintText: 'is running...🕞',
openingSwitch: 'Opening switch', openingSwitch: 'Opening switch',
openingCopy: 'Opening copy', openingCopy: 'Opening greeting',
openingSwitchTip: openingSwitchTip:
'Your users will see this welcome message at the beginning.', 'Your users will see this welcome message at the beginning.',
modeTip: 'The mode defines how the workflow is initiated.', modeTip: 'The mode defines how the workflow is initiated.',

View File

@ -1,9 +1,9 @@
import { IconFont } from '@/components/icon-font';
import { Card, CardContent } from '@/components/ui/card'; import { Card, CardContent } from '@/components/ui/card';
import { ISwitchCondition, ISwitchNode } from '@/interfaces/database/flow'; import { ISwitchCondition, ISwitchNode } from '@/interfaces/database/flow';
import { NodeProps, Position } from '@xyflow/react'; import { NodeProps, Position } from '@xyflow/react';
import { memo, useCallback } from 'react'; import { memo, useCallback } from 'react';
import { NodeHandleId, SwitchOperatorOptions } from '../../constant'; import { NodeHandleId, SwitchOperatorOptions } from '../../constant';
import { LogicalOperatorIcon } from '../../form/switch-form';
import { useGetVariableLabelByValue } from '../../hooks/use-get-begin-query'; import { useGetVariableLabelByValue } from '../../hooks/use-get-begin-query';
import { CommonHandle } from './handle'; import { CommonHandle } from './handle';
import { RightHandleStyle } from './handle-icon'; import { RightHandleStyle } from './handle-icon';
@ -30,8 +30,16 @@ const ConditionBlock = ({
const getLabel = useGetVariableLabelByValue(nodeId); const getLabel = useGetVariableLabelByValue(nodeId);
const renderOperatorIcon = useCallback((operator?: string) => { const renderOperatorIcon = useCallback((operator?: string) => {
const name = SwitchOperatorOptions.find((x) => x.value === operator)?.icon; const item = SwitchOperatorOptions.find((x) => x.value === operator);
return <IconFont name={name!}></IconFont>; if (item) {
return (
<LogicalOperatorIcon
icon={item?.icon}
value={item?.value}
></LogicalOperatorIcon>
);
}
return <></>;
}, []); }, []);
return ( return (

View File

@ -34,6 +34,8 @@ export enum PromptRole {
} }
import { import {
Circle,
CircleSlash2,
CloudUpload, CloudUpload,
ListOrdered, ListOrdered,
OptionIcon, OptionIcon,
@ -378,8 +380,16 @@ export const SwitchOperatorOptions = [
{ value: 'not contains', label: 'notContains', icon: 'not-contains' }, { value: 'not contains', label: 'notContains', icon: 'not-contains' },
{ value: 'start with', label: 'startWith', icon: 'list-start' }, { value: 'start with', label: 'startWith', icon: 'list-start' },
{ value: 'end with', label: 'endWith', icon: 'list-end' }, { value: 'end with', label: 'endWith', icon: 'list-end' },
{ value: 'empty', label: 'empty', icon: 'circle' }, {
{ value: 'not empty', label: 'notEmpty', icon: 'circle-slash-2' }, value: 'empty',
label: 'empty',
icon: <Circle className="size-4" />,
},
{
value: 'not empty',
label: 'notEmpty',
icon: <CircleSlash2 className="size-4" />,
},
]; ];
export const SwitchElseTo = 'end_cpn_ids'; export const SwitchElseTo = 'end_cpn_ids';

View File

@ -8,9 +8,7 @@ import { FormSchemaType } from './schema';
function convertToObject(list: FormSchemaType['arguments'] = []) { function convertToObject(list: FormSchemaType['arguments'] = []) {
return list.reduce<Record<string, string>>((pre, cur) => { return list.reduce<Record<string, string>>((pre, cur) => {
if (cur.name && cur.type) { pre[cur.name] = cur.type;
pre[cur.name] = cur.type;
}
return pre; return pre;
}, {}); }, {});

View File

@ -41,18 +41,21 @@ type ConditionCardsProps = {
parentLength: number; parentLength: number;
} & IOperatorForm; } & IOperatorForm;
const OperatorIcon = function OperatorIcon({ export const LogicalOperatorIcon = function OperatorIcon({
icon, icon,
value, value,
}: Omit<(typeof SwitchOperatorOptions)[0], 'label'>) { }: Omit<(typeof SwitchOperatorOptions)[0], 'label'>) {
return ( if (typeof icon === 'string') {
<IconFont return (
name={icon} <IconFont
className={cn('size-4', { name={icon}
'rotate-180': value === '>', className={cn('size-4', {
})} 'rotate-180': value === '>',
></IconFont> })}
); ></IconFont>
);
}
return icon;
}; };
function useBuildSwitchOperatorOptions() { function useBuildSwitchOperatorOptions() {
@ -61,7 +64,12 @@ function useBuildSwitchOperatorOptions() {
const switchOperatorOptions = useMemo(() => { const switchOperatorOptions = useMemo(() => {
return SwitchOperatorOptions.map((x) => ({ return SwitchOperatorOptions.map((x) => ({
value: x.value, value: x.value,
icon: <OperatorIcon icon={x.icon} value={x.value}></OperatorIcon>, icon: (
<LogicalOperatorIcon
icon={x.icon}
value={x.value}
></LogicalOperatorIcon>
),
label: t(`flow.switchOperatorOptions.${x.label}`), label: t(`flow.switchOperatorOptions.${x.label}`),
})); }));
}, [t]); }, [t]);