feature: V4.11.1 (#5350)

* perf: system toolset & mcp (#5200)

* feat: support system toolset

* fix: type

* fix: system tool config

* chore: mcptool config migrate

* refactor: mcp toolset

* fix: fe type error

* fix: type error

* fix: show version

* chore: support extract tool's secretInputConfig out of inputs

* chore: compatible with old version mcp

* chore: adjust

* deps: update dependency @fastgpt-skd/plugin

* fix: version

* fix: some bug (#5316)

* chore: compatible with old version mcp

* fix: version

* fix: compatible bug

* fix: mcp object params

* fix: type error

* chore: update test cases

* chore: remove log

* fix: toolset node name

* optimize app logs sort (#5310)

* log keys config modal

* multiple select

* api

* fontsize

* code

* chatid

* fix build

* fix

* fix component

* change name

* log keys config

* fix

* delete unused

* fix

* perf: log code

* perf: send auth code modal enter press

* fix log (#5328)

* perf: mcp toolset comment

* perf: log ui

* remove log (#5347)

* doc

* fix: action

* remove log

* fix: Table Optimization (#5319)

* feat: table test: 1

* feat: table test: 2

* feat: table test: 3

* feat: table test: 4

* feat: table test : 5 把maxSize改回chunkSize

* feat: table test : 6 都删了,只看maxSize

* feat: table test : 7 恢复初始,接下来删除标签功能

* feat: table test : 8 删除标签功能

* feat: table test : 9 删除标签功能成功

* feat: table test : 10 继续调试,修改trainingStates

* feat: table test : 11 修改第一步

* feat: table test : 12 修改第二步

* feat: table test : 13 修改了HtmlTable2Md

* feat: table test : 14 修改表头分块规则

* feat: table test : 15 前面表格分的太细了

* feat: table test : 16 改着改着表头又不加了

* feat: table test : 17 用CUSTOM_SPLIT_SIGN不行,重新改

* feat: table test : 18 表头仍然还会多加,但现在分块搞的合理了终于

* feat: table test : 19 还是需要搞好表头问题,先保存一下调试情况

* feat: table test : 20 调试结束,看一下replace有没有问题,没问题就pr

* feat: table test : 21 先把注释删了

* feat: table test : 21 注释replace都改了,下面切main分支看看情况

* feat: table test : 22 修改旧文件

* feat: table test : 23 修改测试文件

* feat: table test : 24 xlsx表格处理

* feat: table test : 25 刚才没保存先com了

* feat: table test : 26 fix

* feat: table test : 27 先com一版调试

* feat: table test : 28 试试放format2csv里

* feat: table test : 29 xlsx解决

* feat: table test : 30 tablesplit解决

* feat: table test : 31

* feat: table test : 32

* perf: table split

* perf: mcp old version compatibility (#5342)

* fix: system-tool secret inputs

* fix: rewrite runtime node i18n for system tool

* perf: mcp old version compatibility

* fix: splitPluginId

* fix: old mcp toolId

* fix: filter secret key

* feat: support system toolset activation

* chore: remove log

* perf: mcp update

* perf: rewrite toolset

* fix:delete variable id (#5335)

* perf: variable update

* fix: multiple select ui

* perf: model config move to plugin

* fix: var conflit

* perf: variable checker

* Avoid empty number

* update doc time

* fix: test

* fix: mcp object

* update count app

* update count app

---------

Co-authored-by: Finley Ge <32237950+FinleyGe@users.noreply.github.com>
Co-authored-by: heheer <heheer@sealos.io>
Co-authored-by: heheer <zhiyu44@qq.com>
Co-authored-by: colnii <1286949794@qq.com>
Co-authored-by: dreamer6680 <1468683855@qq.com>
This commit is contained in:
Archer
2025-08-01 16:08:20 +08:00
committed by GitHub
parent e0c21a949c
commit e25d7efb5b
143 changed files with 2596 additions and 4177 deletions

View File

@@ -1,5 +1,6 @@
import React, { useState, useMemo, useRef, useEffect } from 'react';
import { Box, Card, Flex, useTheme, useOutsideClick, Button } from '@chakra-ui/react';
import type { BoxProps } from '@chakra-ui/react';
import { Box, Card, Flex, useOutsideClick, Button } from '@chakra-ui/react';
import { addDays, format } from 'date-fns';
import { DayPicker } from 'react-day-picker';
import 'react-day-picker/dist/style.css';
@@ -15,21 +16,23 @@ export type DateRangeType = {
const DateRangePicker = ({
onChange,
onSuccess,
position = 'bottom',
popPosition = 'bottom',
defaultDate = {
from: addDays(new Date(), -30),
to: new Date()
},
dateRange
dateRange,
formLabel,
...props
}: {
onChange?: (date: DateRangeType) => void;
onSuccess?: (date: DateRangeType) => void;
position?: 'bottom' | 'top';
popPosition?: 'bottom' | 'top';
defaultDate?: DateRangeType;
dateRange?: DateRangeType;
}) => {
formLabel?: string;
} & BoxProps) => {
const { t } = useTranslation();
const theme = useTheme();
const OutRangeRef = useRef(null);
const [range, setRange] = useState<DateRangeType>(defaultDate);
const [showSelected, setShowSelected] = useState(false);
@@ -42,9 +45,9 @@ const DateRangePicker = ({
const formatSelected = useMemo(() => {
if (range?.from && range.to) {
return `${format(range.from, 'y-MM-dd')} ~ ${format(range.to, 'y-MM-dd')}`;
return `${format(range.from, 'y/MM/dd')} - ${format(range.to, 'y/MM/dd')}`;
}
return `${format(new Date(), 'y-MM-dd')} ~ ${format(new Date(), 'y-MM-dd')}`;
return `${format(new Date(), 'y/MM/dd')} - ${format(new Date(), 'y/MM/dd')}`;
}, [range]);
useOutsideClick({
@@ -57,19 +60,30 @@ const DateRangePicker = ({
return (
<Box position={'relative'} ref={OutRangeRef}>
<Flex
border={theme.borders.base}
border={'base'}
px={3}
pr={3}
py={1}
borderRadius={'sm'}
cursor={'pointer'}
bg={'myGray.50'}
fontSize={'sm'}
onClick={() => setShowSelected(true)}
alignItems={'center'}
{...props}
>
<Box color={'myGray.600'} fontWeight={'400'}>
{formLabel && (
<>
<Box fontSize={'sm'} color={'myGray.600'}>
{formLabel}
</Box>
<Box w={'1px'} h={'12px'} bg={'myGray.200'} mx={2} />
</>
)}
<Box color={'myGray.600'} fontWeight={'400'} flex={1}>
{formatSelected}
</Box>
<MyIcon ml={2} name={'date'} w={'16px'} color={'myGray.600'} />
{!formLabel && <MyIcon ml={2} name={'date'} w={'16px'} color={'myGray.600'} />}
</Flex>
{showSelected && (
<Card
@@ -77,9 +91,9 @@ const DateRangePicker = ({
zIndex={1}
css={{
'--rdp-background-color': '#d6e8ff',
' --rdp-accent-color': '#0000ff'
'--rdp-accent-color': '#0000ff'
}}
{...(position === 'top'
{...(popPosition === 'top'
? {
bottom: '40px'
}

View File

@@ -487,5 +487,6 @@ export const iconPaths = {
union: () => import('./icons/union.svg'),
user: () => import('./icons/user.svg'),
visible: () => import('./icons/visible.svg'),
invisible: () => import('./icons/invisible.svg'),
wx: () => import('./icons/wx.svg')
};

View File

@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 17" >
<path d="M3.09477 5.68345C2.49088 6.22956 1.97818 6.87496 1.58219 7.59384C1.46142 7.81308 1.40104 7.9227 1.35575 8.1445C1.32591 8.29065 1.32591 8.59337 1.35575 8.73952C1.40104 8.96131 1.46142 9.07094 1.58219 9.29018C2.82944 11.5544 5.23455 13.0897 8.00004 13.0897C8.7567 13.0897 9.48638 12.9748 10.1727 12.7614L9.15237 11.7411C8.77428 11.814 8.38849 11.8511 8.00004 11.8511C6.86129 11.8511 5.74538 11.5316 4.77917 10.929C4.1443 10.533 3.5908 10.0252 3.14375 9.43336C2.97848 9.21457 2.89585 9.10518 2.82105 8.82259C2.7747 8.64749 2.7747 8.23652 2.82105 8.06143C2.89585 7.77884 2.97848 7.66945 3.14375 7.45066C3.38856 7.12656 3.6653 6.82766 3.96984 6.55852L3.09477 5.68345Z" />
<path d="M6.16773 8.75641C6.23231 9.13279 6.41184 9.48294 6.68547 9.75658C6.95911 10.0302 7.30926 10.2097 7.68564 10.2743L6.16773 8.75641Z" />
<path d="M9.77417 8.99756L7.44449 6.66788C7.62269 6.61207 7.80986 6.58293 8.00004 6.58293C8.4931 6.58293 8.96596 6.7788 9.31461 7.12744C9.66325 7.47609 9.85912 7.94895 9.85912 8.44201C9.85912 8.63219 9.82998 8.81936 9.77417 8.99756Z" />
<path d="M11.5121 10.7355C12.026 10.3724 12.4791 9.93283 12.8563 9.43336C13.0216 9.21457 13.1042 9.10518 13.179 8.82259C13.2254 8.64749 13.2254 8.23652 13.179 8.06143C13.1042 7.77884 13.0216 7.66945 12.8563 7.45066C12.4093 6.85882 11.8558 6.35101 11.2209 5.95502C10.2547 5.35237 9.13879 5.03288 8.00004 5.03288C7.35512 5.03288 6.71753 5.13535 6.11031 5.3337L5.1481 4.37149C6.02445 3.99987 6.98812 3.79431 8.00004 3.79431C10.7655 3.79431 13.1706 5.32959 14.4179 7.59383C14.5387 7.81308 14.599 7.9227 14.6443 8.1445C14.6742 8.29065 14.6742 8.59337 14.6443 8.73952C14.599 8.96131 14.5387 9.07094 14.4179 9.29018C13.9151 10.203 13.224 10.9974 12.3971 11.6204L11.5121 10.7355Z" />
<path d="M2.3253 3.86234C2.61571 3.57193 3.08655 3.57193 3.37695 3.86234L12.6912 13.1766C12.9816 13.467 12.9816 13.9378 12.6912 14.2282C12.4008 14.5186 11.9299 14.5186 11.6395 14.2282L2.3253 4.91399C2.03489 4.62358 2.03489 4.15274 2.3253 3.86234Z" />
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -1,3 +1,3 @@
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.00011 6.3335C8.44214 6.3335 8.86606 6.50909 9.17863 6.82165C9.49119 7.13421 9.66678 7.55814 9.66678 8.00016C9.66678 8.44219 9.49119 8.86611 9.17863 9.17867C8.86606 9.49124 8.44214 9.66683 8.00011 9.66683C7.55809 9.66683 7.13416 9.49124 6.8216 9.17867C6.50904 8.86611 6.33345 8.44219 6.33345 8.00016C6.33345 7.55814 6.50904 7.13421 6.8216 6.82165C7.13416 6.50909 7.55809 6.3335 8.00011 6.3335ZM8.00011 3.8335C10.4794 3.8335 12.6356 5.20988 13.7537 7.23977C13.862 7.43633 13.9161 7.53461 13.9567 7.73345C13.9835 7.86447 13.9835 8.13586 13.9567 8.26688C13.9161 8.46572 13.862 8.564 13.7537 8.76055C12.6356 10.7905 10.4794 12.1668 8.00011 12.1668C5.52085 12.1668 3.36466 10.7905 2.2465 8.76055C2.13823 8.564 2.0841 8.46572 2.0435 8.26688C2.01675 8.13586 2.01675 7.86447 2.0435 7.73345C2.0841 7.53461 2.13823 7.43633 2.2465 7.23977C3.36466 5.20988 5.52085 3.8335 8.00011 3.8335ZM3.64644 7.11141C3.49828 7.30756 3.4242 7.40563 3.35714 7.65897C3.31559 7.81594 3.31559 8.18438 3.35714 8.34135C3.4242 8.5947 3.49828 8.69277 3.64644 8.88891C4.04722 9.41949 4.54344 9.87474 5.1126 10.2297C5.97881 10.77 6.97922 11.0565 8.00011 11.0565C9.021 11.0565 10.0214 10.77 10.8876 10.2297C11.4568 9.87474 11.953 9.41949 12.3538 8.88891C12.5019 8.69277 12.576 8.5947 12.6431 8.34135C12.6846 8.18438 12.6846 7.81594 12.6431 7.65897C12.576 7.40563 12.5019 7.30756 12.3538 7.11141C11.953 6.58083 11.4568 6.12558 10.8876 5.77058C10.0214 5.2303 9.021 4.94387 8.00011 4.94387C6.97922 4.94387 5.97881 5.2303 5.1126 5.77058C4.54344 6.12558 4.04722 6.58083 3.64644 7.11141Z" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" >
<path d="M8.00003 6.12221C8.49803 6.12221 8.97563 6.32004 9.32776 6.67217C9.6799 7.02431 9.87773 7.50191 9.87773 7.9999C9.87773 8.4979 9.6799 8.9755 9.32776 9.32764C8.97563 9.67977 8.49803 9.8776 8.00003 9.8776C7.50203 9.8776 7.02443 9.67977 6.6723 9.32764C6.32016 8.9755 6.12233 8.4979 6.12233 7.9999C6.12233 7.50191 6.32016 7.02431 6.6723 6.67217C7.02443 6.32004 7.50203 6.12221 8.00003 6.12221ZM8.00003 3.30566C10.7932 3.30566 13.2224 4.85632 14.4821 7.14324C14.6041 7.36468 14.6651 7.4754 14.7109 7.69942C14.741 7.84703 14.741 8.15278 14.7109 8.30039C14.6651 8.52441 14.6041 8.63513 14.4821 8.85657C13.2224 11.1435 10.7932 12.6941 8.00003 12.6941C5.20685 12.6941 2.77765 11.1435 1.51791 8.85657C1.39593 8.63513 1.33494 8.52441 1.2892 8.30039C1.25907 8.15278 1.25907 7.84703 1.2892 7.69942C1.33494 7.4754 1.39593 7.36468 1.51791 7.14324C2.77765 4.85632 5.20685 3.30566 8.00003 3.30566ZM3.0951 6.99862C2.92819 7.2196 2.84473 7.33009 2.76917 7.61551C2.72236 7.79236 2.72236 8.20745 2.76917 8.38429C2.84473 8.66971 2.92819 8.7802 3.09511 9.00118C3.54663 9.59895 4.10568 10.1118 4.74691 10.5118C5.72279 11.1205 6.84988 11.4432 8.00003 11.4432C9.15018 11.4432 10.2773 11.1205 11.2532 10.5118C11.8944 10.1118 12.4534 9.59895 12.905 9.00118C13.0719 8.7802 13.1553 8.66971 13.2309 8.38429C13.2777 8.20745 13.2777 7.79236 13.2309 7.61551C13.1553 7.33009 13.0719 7.2196 12.905 6.99862C12.4534 6.40086 11.8944 5.88797 11.2532 5.48801C10.2773 4.87932 9.15018 4.55664 8.00003 4.55664C6.84988 4.55664 5.72279 4.87932 4.74691 5.48801C4.10568 5.88797 3.54663 6.40086 3.0951 6.99862Z" />
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -1,9 +1,11 @@
import type { FlexProps } from '@chakra-ui/react';
import {
Box,
Button,
type ButtonProps,
Checkbox,
Flex,
Input,
Menu,
MenuButton,
MenuItem,
@@ -11,13 +13,27 @@ import {
MenuList,
useDisclosure
} from '@chakra-ui/react';
import React, { useCallback, useMemo, useRef, useState } from 'react';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import MyTag from '../Tag/index';
import MyIcon from '../Icon';
import MyAvatar from '../Avatar';
import { useTranslation } from 'next-i18next';
import type { useScrollPagination } from '../../../hooks/useScrollPagination';
import MyDivider from '../MyDivider';
import { shadowLight } from '../../../styles/theme';
const menuItemStyles: MenuItemProps = {
borderRadius: 'sm',
py: 2,
display: 'flex',
alignItems: 'center',
_hover: {
backgroundColor: 'myGray.100'
},
_notLast: {
mb: 2
}
};
export type SelectProps<T = any> = {
list: {
@@ -30,19 +46,25 @@ export type SelectProps<T = any> = {
setIsSelectAll?: React.Dispatch<React.SetStateAction<boolean>>;
placeholder?: string;
maxH?: number;
itemWrap?: boolean;
onSelect: (val: T[]) => void;
closeable?: boolean;
isDisabled?: boolean;
ScrollData?: ReturnType<typeof useScrollPagination>['ScrollData'];
formLabel?: string;
formLabelFontSize?: string;
inputValue?: string;
setInputValue?: (val: string) => void;
tagStyle?: FlexProps;
} & Omit<ButtonProps, 'onSelect'>;
const MultipleSelect = <T = any,>({
value = [],
placeholder,
list = [],
maxH = 400,
onSelect,
closeable = false,
itemWrap = true,
@@ -50,27 +72,92 @@ const MultipleSelect = <T = any,>({
isSelectAll,
setIsSelectAll,
isDisabled = false,
formLabel,
formLabelFontSize = 'sm',
inputValue,
setInputValue,
tagStyle,
...props
}: SelectProps<T>) => {
const ref = useRef<HTMLButtonElement>(null);
const SearchInputRef = useRef<HTMLInputElement>(null);
const tagsContainerRef = useRef<HTMLDivElement>(null);
const { t } = useTranslation();
const { isOpen, onOpen, onClose } = useDisclosure();
const menuItemStyles: MenuItemProps = {
borderRadius: 'sm',
py: 2,
display: 'flex',
alignItems: 'center',
_hover: {
backgroundColor: 'myGray.100'
},
_notLast: {
mb: 2
}
const canInput = setInputValue !== undefined;
type SelectedItemType = {
icon?: string;
label: string | React.ReactNode;
value: T;
};
const [visibleItems, setVisibleItems] = useState<SelectedItemType[]>([]);
const [overflowItems, setOverflowItems] = useState<SelectedItemType[]>([]);
const selectedItems = useMemo(() => {
return value.map((val) => {
const listItem = list.find((item) => item.value === val);
return listItem || { value: val, label: String(val) };
});
}, [value, list]);
const handleKeyDown = useCallback(
(e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Backspace' && (!inputValue || inputValue === '')) {
const newValue = [...value];
newValue.pop();
onSelect(newValue);
}
},
[inputValue, value, isSelectAll, onSelect]
);
useEffect(() => {
if (!isOpen) {
setInputValue?.('');
}
}, [isOpen]);
useEffect(() => {
const getWidth = (w: any) =>
typeof w === 'number' ? w : typeof w === 'string' ? parseInt(w) : 0;
const totalWidth = getWidth(props.w) || 200;
const tagWidth = getWidth(tagStyle?.w) || 60;
const formLabelWidth = formLabel ? formLabel.length * 8 + 20 : 0;
const availableWidth = totalWidth - formLabelWidth - 40;
const overflowWidth = 30;
if (availableWidth <= 0) {
setVisibleItems(selectedItems.length > 0 ? [selectedItems[0]] : []);
setOverflowItems(selectedItems.slice(1));
return;
}
const { count } = selectedItems.reduce(
(acc, item, i) => {
const remain = selectedItems.length - i - 1;
const needOverflow = remain > 0 ? overflowWidth : 0;
if (acc.used + tagWidth + needOverflow <= availableWidth) {
return {
used: acc.used + tagWidth,
count: i + 1
};
}
return acc;
},
{ used: 0, count: 0 }
);
setVisibleItems(selectedItems.slice(0, count));
setOverflowItems(selectedItems.slice(count));
}, [selectedItems, isOpen, props.w, tagStyle, formLabel]);
const onclickItem = useCallback(
(val: T) => {
// 全选状态下value 实际上上空。
if (isSelectAll) {
onSelect(list.map((item) => item.value).filter((i) => i !== val));
setIsSelectAll?.(false);
@@ -141,12 +228,11 @@ const MultipleSelect = <T = any,>({
>
<MenuButton
as={Flex}
h={'100%'}
alignItems={'center'}
ref={ref}
px={3}
alignItems={'center'}
borderRadius={'md'}
border={'base'}
border={'sm'}
userSelect={'none'}
cursor={isDisabled ? 'not-allowed' : 'pointer'}
_active={{
@@ -159,68 +245,108 @@ const MultipleSelect = <T = any,>({
{...props}
{...(isOpen && !isDisabled
? {
boxShadow: '0px 0px 4px #A8DBFF',
borderColor: 'primary.500',
boxShadow: shadowLight,
borderColor: 'primary.600 !important',
bg: 'white'
}
: {})}
>
{value.length === 0 && placeholder ? (
<Box color={'myGray.500'} fontSize={'sm'}>
{placeholder}
</Box>
) : (
<Flex alignItems={'center'} gap={2}>
<Flex alignItems={'center'} w={'100%'} h={'100%'} py={1.5}>
{formLabel && (
<Flex alignItems={'center'}>
<Box color={'myGray.600'} fontSize={formLabelFontSize} whiteSpace={'nowrap'}>
{formLabel}
</Box>
<Box w={'1px'} h={'12px'} bg={'myGray.200'} mx={2} />
</Flex>
)}
{value.length === 0 && placeholder ? (
<Box color={'myGray.500'} fontSize={formLabelFontSize} flex={1}>
{placeholder}
</Box>
) : (
<Flex
alignItems={'center'}
gap={2}
flexWrap={itemWrap ? 'wrap' : 'nowrap'}
ref={tagsContainerRef}
flex={'1 0 0'}
gap={1}
flexWrap={'nowrap'}
overflow={'hidden'}
flex={1}
alignItems={'center'}
>
{isSelectAll ? (
<Box fontSize={'mini'} color={'myGray.900'}>
{t('common:All')}
</Box>
) : (
list
.filter((item) => value.includes(item.value))
.map((item, i) => (
<MyTag
className="tag-icon"
key={i}
bg={'primary.100'}
color={'primary.700'}
type={'fill'}
borderRadius={'lg'}
px={2}
py={0.5}
flexShrink={0}
>
{item.label}
{closeable && (
<MyIcon
name={'common/closeLight'}
ml={1}
w="0.8rem"
cursor={'pointer'}
_hover={{
color: 'red.500'
}}
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
onclickItem(item.value);
}}
/>
)}
</MyTag>
))
{(!isOpen || !canInput) &&
(isSelectAll ? (
<Box fontSize={formLabelFontSize} color={'myGray.900'}>
{t('common:All')}
</Box>
) : (
<>
{visibleItems.map((item, i) => (
<MyTag
className="tag-icon"
key={i}
bg={'primary.100'}
color={'primary.700'}
type={'fill'}
borderRadius={'lg'}
px={2}
py={0.5}
flexShrink={0}
{...tagStyle}
>
{item.label}
{closeable && (
<MyIcon
name={'common/closeLight'}
ml={1}
w="0.8rem"
cursor={'pointer'}
_hover={{
color: 'red.500'
}}
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
onclickItem(item.value);
}}
/>
)}
</MyTag>
))}
{overflowItems.length > 0 && (
<Box
fontSize={formLabelFontSize}
px={2}
py={0.5}
flexShrink={0}
borderRadius={'lg'}
bg={'myGray.100'}
>
+{overflowItems.length}
</Box>
)}
</>
))}
{canInput && isOpen && (
<Input
value={inputValue}
onChange={(e) => setInputValue?.(e.target.value)}
onKeyDown={handleKeyDown}
ref={SearchInputRef}
autoFocus
onBlur={() => {
setTimeout(() => {
SearchInputRef?.current?.focus();
}, 0);
}}
h={6}
variant={'unstyled'}
border={'none'}
/>
)}
</Flex>
<MyIcon name={'core/chat/chevronDown'} color={'myGray.600'} w={4} h={4} />
</Flex>
)}
)}
<MyIcon name={'core/chat/chevronDown'} color={'myGray.600'} w={4} h={4} />
</Flex>
</MenuButton>
<MenuList
@@ -254,7 +380,7 @@ const MultipleSelect = <T = any,>({
<MyDivider my={1} />
{ScrollData ? <ScrollData>{ListRender}</ScrollData> : ListRender}
{ScrollData ? <ScrollData minH={20}>{ListRender}</ScrollData> : ListRender}
</MenuList>
</Menu>
</Box>

View File

@@ -1,7 +1,7 @@
import { useTranslation as useNextTranslation } from 'next-i18next';
import { I18N_NAMESPACES_MAP } from '../i18n/constants';
export function useTranslation() {
export function useSafeTranslation() {
const { t: originalT, ...rest } = useNextTranslation();
const t = (key: string | undefined, ...args: any[]): string => {

View File

@@ -90,10 +90,29 @@
"llm_use_vision": "Vision",
"llm_use_vision_tip": "After clicking on the model selection, you can see whether the model supports image recognition and the ability to control whether to start image recognition. \nAfter starting image recognition, the model will read the image content in the file link, and if the user question is less than 500 words, it will automatically parse the image in the user question.",
"logs_chat_user": "user",
"logs_date": "date",
"logs_empty": "No logs yet~",
"logs_error_count": "Error Count",
"logs_export_confirm_tip": "There are currently {{total}} conversation records, and each conversation can export up to 100 latest messages. \nConfirm export?",
"logs_export_title": "Time, source, user, contact, title, total number of messages, user good feedback, user bad feedback, custom feedback, labeled answers, conversation details",
"logs_key_config": "Field Configuration",
"logs_keys_annotatedCount": "Annotated Answer Count",
"logs_keys_createdTime": "Created Time",
"logs_keys_customFeedback": "Custom Feedback",
"logs_keys_errorCount": "Error Count",
"logs_keys_feedback": "User Feedback",
"logs_keys_lastConversationTime": "Last Conversation Time",
"logs_keys_messageCount": "Message Count",
"logs_keys_points": "Points Consumed",
"logs_keys_responseTime": "Average Response Time",
"logs_keys_sessionId": "Session ID",
"logs_keys_source": "Source",
"logs_keys_title": "Title",
"logs_keys_user": "User",
"logs_message_total": "Total Messages",
"logs_points": "Points Consumed",
"logs_response_time": "Average Response Time",
"logs_search_chat": "Search for session title or session ID",
"logs_source": "source",
"logs_title": "Title",
"look_ai_point_price": "View all model billing standards",
@@ -134,6 +153,7 @@
"question_guide_tip": "After the conversation, 3 guiding questions will be generated for you.",
"reasoning_response": "Output thinking",
"response_format": "Response format",
"save_team_app_log_keys": "Save as team configuration",
"saved_success": "Saved successfully! \nTo use this version externally, click Save and Publish",
"search_app": "Search apps",
"search_tool": "Search Tools",
@@ -147,7 +167,10 @@
"stop_sign_placeholder": "Multiple serial numbers are separated by |, for example: aaa|stop",
"stream_response": "Stream",
"stream_response_tip": "Turning this switch off forces the model to use non-streaming mode and will not output content directly. \nIn the output of the AI reply, the content output by this model can be obtained for secondary processing.",
"sync_log_keys_popover_text": "The current field configuration is only valid for individuals. Do you need to save it to the team configuration?",
"sync_team_app_log_keys": "Restore to team configuration",
"system_secret": "System secret",
"systemval_conflict_globalval": "The variable name conflicts with the system variable, please use other variable names",
"team_tags_set": "Team tags",
"temperature": "Temperature",
"temperature_tip": "Range 0~10. \nThe larger the value, the more divergent the models answer is; the smaller the value, the more rigorous the answer.",
@@ -229,6 +252,8 @@
"upload_file_max_amount_tip": "Maximum number of files uploaded in a single round of conversation",
"variable.select type_desc": "You can define a global variable that does not need to be filled in by the user.\n\nThe value of this variable can come from the API interface, the Query of the shared link, or assigned through the [Variable Update] module.",
"variable.textarea_type_desc": "Allows users to input up to 4000 characters in the dialogue box.",
"variable_name_required": "Required variable name",
"variable_repeat": "This variable name has been occupied and cannot be used",
"version.Revert success": "Revert Successful",
"version_back": "Revert to Original State",
"version_copy": "Duplicate",

View File

@@ -114,6 +114,8 @@
"can_copy_content_tip": "It is not possible to copy automatically using the browser, please manually copy the following content",
"chart_mode_cumulative": "Cumulative",
"chart_mode_incremental": "Incremental",
"chat": "Session",
"chat_chatId": "Session Id: {{chatId}}",
"choosable": "Choosable",
"chose_condition": "Choose Condition",
"chosen": "Chosen",
@@ -679,7 +681,6 @@
"core.module.variable.add option": "Add Option",
"core.module.variable.input type": "Text",
"core.module.variable.key": "Variable Key",
"core.module.variable.key already exists": "Key Already Exists",
"core.module.variable.key is required": "Variable Key is Required",
"core.module.variable.select type": "Dropdown Single Select",
"core.module.variable.text max length": "Max Length",
@@ -878,6 +879,7 @@
"max_quote_tokens": "Quote cap",
"max_quote_tokens_tips": "The maximum number of tokens in a single search, about 1 character in Chinese = 1.7 tokens, and about 1 character in English = 1 token",
"mcp_server": "MCP Services",
"member": "member",
"min_similarity": "lowest correlation",
"min_similarity_tip": "The relevance of different index models is different. Please select the appropriate value through search testing. \nWhen using Result Rearrange , use the rearranged results for filtering.",
"model.billing": "Billing",

View File

@@ -90,10 +90,29 @@
"llm_use_vision": "图片识别",
"llm_use_vision_tip": "点击模型选择后,可以看到模型是否支持图片识别以及控制是否启动图片识别的能力。启动图片识别后,模型会读取文件链接里图片内容,并且如果用户问题少于 500 字,会自动解析用户问题中的图片。",
"logs_chat_user": "使用者",
"logs_date": "日期",
"logs_empty": "还没有日志噢~",
"logs_error_count": "报错数量",
"logs_export_confirm_tip": "当前共有 {{total}} 条对话记录,每条对话最多可导出最新 100 条消息。确认导出?",
"logs_export_title": "时间,来源,使用者,联系方式,标题,消息总数,用户赞同反馈,用户反对反馈,自定义反馈,标注答案,对话详情",
"logs_key_config": "字段配置",
"logs_keys_annotatedCount": "标注答案数量",
"logs_keys_createdTime": "创建时间",
"logs_keys_customFeedback": "自定义反馈",
"logs_keys_errorCount": "报错数量",
"logs_keys_feedback": "用户反馈",
"logs_keys_lastConversationTime": "上次对话时间",
"logs_keys_messageCount": "消息总数",
"logs_keys_points": "积分消耗",
"logs_keys_responseTime": "平均响应时长",
"logs_keys_sessionId": "会话 ID",
"logs_keys_source": "来源",
"logs_keys_title": "标题",
"logs_keys_user": "使用者",
"logs_message_total": "消息总数",
"logs_points": "积分消耗",
"logs_response_time": "平均响应时长",
"logs_search_chat": "搜索会话标题或会话 ID",
"logs_source": "来源",
"logs_title": "标题",
"look_ai_point_price": "查看所有模型计费标准",
@@ -134,6 +153,7 @@
"question_guide_tip": "对话结束后,会为你生成 3 个引导性问题。",
"reasoning_response": "输出思考",
"response_format": "回复格式",
"save_team_app_log_keys": "保存为团队配置",
"saved_success": "保存成功!如需在外部使用该版本,请点击“保存并发布”",
"search_app": "搜索应用",
"search_tool": "搜索工具",
@@ -147,7 +167,10 @@
"stop_sign_placeholder": "多个序列号通过 | 隔开例如aaa|stop",
"stream_response": "流输出",
"stream_response_tip": "关闭该开关,可以强制模型使用非流模式,并且不会直接进行内容输出。可以在 AI 回复的输出中,获取本次模型输出的内容进行二次处理。",
"sync_log_keys_popover_text": "当前字段配置仅对个人生效,是否需要保存至团队配置?",
"sync_team_app_log_keys": "还原成团队配置",
"system_secret": "系统密钥",
"systemval_conflict_globalval": "变量名与系统变量有冲突,请使用其他变量名",
"team_tags_set": "团队标签",
"temperature": "温度",
"temperature_tip": "范围 010。值越大代表模型回答越发散值越小代表回答越严谨。",
@@ -229,6 +252,8 @@
"upload_file_max_amount_tip": "单轮对话中最大上传文件数量",
"variable.select type_desc": "可以为工作流定义全局变量,常用临时缓存。赋值的方式包括:\n1. 从对话页面的 query 参数获取。\n2. 通过 API 的 variables 对象传递。\n3. 通过【变量更新】节点进行赋值。",
"variable.textarea_type_desc": "允许用户最多输入4000字的对话框。",
"variable_name_required": "变量名必填",
"variable_repeat": "该变量名已被占用,无法使用",
"version.Revert success": "回滚成功",
"version_back": "回到初始状态",
"version_copy": "副本",

View File

@@ -114,6 +114,8 @@
"can_copy_content_tip": "无法使用浏览器自动复制,请手动复制下面内容",
"chart_mode_cumulative": "累积",
"chart_mode_incremental": "分时",
"chat": "会话",
"chat_chatId": "会话Id: {{chatId}}",
"choosable": "可选",
"chose_condition": "选择条件",
"chosen": "已选",
@@ -679,7 +681,6 @@
"core.module.variable.add option": "添加选项",
"core.module.variable.input type": "文本",
"core.module.variable.key": "变量 key",
"core.module.variable.key already exists": "Key 已经存在",
"core.module.variable.key is required": "变量 key 是必须的",
"core.module.variable.select type": "下拉单选",
"core.module.variable.text max length": "最大长度",
@@ -878,6 +879,7 @@
"max_quote_tokens": "引用上限",
"max_quote_tokens_tips": "单次搜索最大的 token 数量,中文约 1 字=1.7 tokens英文约 1 字=1 token",
"mcp_server": "MCP 服务",
"member": "成员",
"min_similarity": "最低相关度",
"min_similarity_tip": "不同索引模型的相关度有区别,请通过搜索测试来选择合适的数值。使用 结果重排 时,使用重排结果进行过滤。",
"model.billing": "模型计费",

View File

@@ -90,10 +90,29 @@
"llm_use_vision": "圖片辨識",
"llm_use_vision_tip": "點選模型選擇後,可以看到模型是否支援圖片辨識以及控制是否啟用圖片辨識的功能。啟用圖片辨識後,模型會讀取檔案連結中的圖片內容,並且如果使用者問題少於 500 字,會自動解析使用者問題中的圖片。",
"logs_chat_user": "使用者",
"logs_date": "日期",
"logs_empty": "還沒有紀錄喔~",
"logs_error_count": "錯誤數量",
"logs_export_confirm_tip": "當前共有 {{total}} 條對話記錄,每條對話最多可導出最新 100 條消息。\n確認導出",
"logs_export_title": "時間,來源,使用者,聯絡方式,標題,訊息總數,使用者贊同回饋,使用者反對回饋,自定義回饋,標註答案,對話詳細資訊",
"logs_key_config": "字段配置",
"logs_keys_annotatedCount": "標記答案數量",
"logs_keys_createdTime": "建立時間",
"logs_keys_customFeedback": "自訂回饋",
"logs_keys_errorCount": "錯誤數量",
"logs_keys_feedback": "使用者回饋",
"logs_keys_lastConversationTime": "上次對話時間",
"logs_keys_messageCount": "訊息總數",
"logs_keys_points": "積分消耗",
"logs_keys_responseTime": "平均回應時長",
"logs_keys_sessionId": "會話 ID",
"logs_keys_source": "來源",
"logs_keys_title": "標題",
"logs_keys_user": "使用者",
"logs_message_total": "訊息總數",
"logs_points": "積分消耗",
"logs_response_time": "平均回應時長",
"logs_search_chat": "搜索會話標題或會話 ID",
"logs_source": "來源",
"logs_title": "標題",
"look_ai_point_price": "檢視所有模型計費標準",
@@ -134,6 +153,7 @@
"question_guide_tip": "對話結束後,會為你產生 3 個引導性問題。",
"reasoning_response": "輸出思考",
"response_format": "回覆格式",
"save_team_app_log_keys": "保存為團隊配置",
"saved_success": "儲存成功!\n如需在外部使用該版本請點選“儲存並發布”",
"search_app": "搜尋應用程式",
"search_tool": "搜索工具",
@@ -147,7 +167,10 @@
"stop_sign_placeholder": "多個序列號透過 | 隔開例如aaa|stop",
"stream_response": "流輸出",
"stream_response_tip": "關閉該開關​​,可以強制模型使用非流模式,並且不會直接進行內容輸出。\n可在 AI 回覆的輸出中,取得本次模型輸出的內容進行二次處理。",
"sync_log_keys_popover_text": "當前字段配置僅對個人生效,是否需要保存至團隊配置?",
"sync_team_app_log_keys": "還原成團隊配置",
"system_secret": "系統密鑰",
"systemval_conflict_globalval": "變量名與系統變量有衝突,請使用其他變量名",
"team_tags_set": "團隊標籤",
"temperature": "溫度",
"temperature_tip": "範圍 010。\n值越大代表模型回答越發散值越小代表回答越嚴謹。",
@@ -229,6 +252,8 @@
"upload_file_max_amount_tip": "單輪對話中最大上傳檔案數量",
"variable.select type_desc": "可以為工作流程定義全域變數,常用於暫存。賦值的方式包括:\n1. 從對話頁面的 query 參數取得。\n2. 透過 API 的 variables 物件傳遞。\n3. 透過【變數更新】節點進行賦值。",
"variable.textarea_type_desc": "允許使用者最多輸入 4000 字的對話框。",
"variable_name_required": "變量名必填",
"variable_repeat": "該變量名已被佔用,無法使用",
"version.Revert success": "復原成功",
"version_back": "回到初始狀態",
"version_copy": "副本",

View File

@@ -114,6 +114,8 @@
"can_copy_content_tip": "無法使用瀏覽器自動複製,請手動複製下面內容",
"chart_mode_cumulative": "累積",
"chart_mode_incremental": "分時",
"chat": "會話",
"chat_chatId": "會話Id: {{chatId}}",
"choosable": "可選擇",
"chose_condition": "選擇條件",
"chosen": "已選擇",
@@ -679,7 +681,6 @@
"core.module.variable.add option": "新增選項",
"core.module.variable.input type": "文字",
"core.module.variable.key": "變數鍵值",
"core.module.variable.key already exists": "鍵值已存在",
"core.module.variable.key is required": "變數鍵值為必填",
"core.module.variable.select type": "下拉單選",
"core.module.variable.text max length": "最大長度",
@@ -878,6 +879,7 @@
"max_quote_tokens": "引用上限",
"max_quote_tokens_tips": "單次搜尋最大的 token 數量,中文約 1 字=1.7 tokens英文約 1 字=1 token",
"mcp_server": "MCP 服務",
"member": "成員",
"min_similarity": "最低相關度",
"min_similarity_tip": "不同索引模型的相關度有區別,請透過搜尋測試來選擇合適的數值。\n使用 結果重排 時,使用重排結果過濾。",
"model.billing": "模型計費",