From cc8a10376aa203378f9578ea5c717095fb33f68e Mon Sep 17 00:00:00 2001 From: balibabu Date: Mon, 5 Jan 2026 09:53:47 +0800 Subject: [PATCH] Refactor: Refactoring VolcEngine and Yiyan modal using shadcn. #10427 (#12426) ### What problem does this PR solve? Refactor: Refactoring VolcEngine and Yiyan modal using shadcn. #10427 ### Type of change - [x] New Feature (non-breaking change which adds functionality) --- web/src/interfaces/request/llm.ts | 2 +- web/src/pages/user-setting/hooks.ts | 19 -- .../modal/volcengine-modal/index.tsx | 207 +++++++++--------- .../setting-model/modal/yiyan-modal/index.tsx | 193 ++++++++-------- 4 files changed, 205 insertions(+), 216 deletions(-) delete mode 100644 web/src/pages/user-setting/hooks.ts diff --git a/web/src/interfaces/request/llm.ts b/web/src/interfaces/request/llm.ts index a5ca42fdc..687d13aca 100644 --- a/web/src/interfaces/request/llm.ts +++ b/web/src/interfaces/request/llm.ts @@ -3,7 +3,7 @@ export interface IAddLlmRequestBody { llm_name: string; model_type: string; api_base?: string; // chat|embedding|speech2text|image2text - api_key: string | Record; + api_key?: string | Record; max_tokens: number; } diff --git a/web/src/pages/user-setting/hooks.ts b/web/src/pages/user-setting/hooks.ts deleted file mode 100644 index 0da2243c3..000000000 --- a/web/src/pages/user-setting/hooks.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Form } from 'antd'; -import { useEffect, useState } from 'react'; - -export const useValidateSubmittable = () => { - const [form] = Form.useForm(); - const [submittable, setSubmittable] = useState(false); - - // Watch all values - const values = Form.useWatch([], form); - - useEffect(() => { - form - .validateFields({ validateOnly: true }) - .then(() => setSubmittable(true)) - .catch(() => setSubmittable(false)); - }, [form, values]); - - return { submittable, form }; -}; diff --git a/web/src/pages/user-setting/setting-model/modal/volcengine-modal/index.tsx b/web/src/pages/user-setting/setting-model/modal/volcengine-modal/index.tsx index 79b3e877d..388fbe5d6 100644 --- a/web/src/pages/user-setting/setting-model/modal/volcengine-modal/index.tsx +++ b/web/src/pages/user-setting/setting-model/modal/volcengine-modal/index.tsx @@ -1,20 +1,20 @@ -import { useTranslate } from '@/hooks/common-hooks'; +import { + DynamicForm, + FormFieldConfig, + FormFieldType, +} from '@/components/dynamic-form'; +import { Modal } from '@/components/ui/modal/modal'; +import { useCommonTranslation, useTranslate } from '@/hooks/common-hooks'; import { IModalProps } from '@/interfaces/common'; import { IAddLlmRequestBody } from '@/interfaces/request/llm'; -import { Flex, Form, Input, InputNumber, Modal, Select, Space } from 'antd'; -import omit from 'lodash/omit'; +import { FieldValues } from 'react-hook-form'; import { LLMHeader } from '../../components/llm-header'; -type FieldType = IAddLlmRequestBody & { - vision: boolean; - volc_ak: string; - volc_sk: string; +type VolcEngineLlmRequest = IAddLlmRequestBody & { endpoint_id: string; ark_api_key: string; }; -const { Option } = Select; - const VolcEngineModal = ({ visible, hideModal, @@ -22,115 +22,122 @@ const VolcEngineModal = ({ loading, llmFactory, }: IModalProps & { llmFactory: string }) => { - const [form] = Form.useForm(); - const { t } = useTranslate('setting'); + const { t: tc } = useCommonTranslation(); + + const fields: FormFieldConfig[] = [ + { + name: 'model_type', + label: t('modelType'), + type: FormFieldType.Select, + required: true, + options: [ + { label: 'chat', value: 'chat' }, + { label: 'embedding', value: 'embedding' }, + { label: 'image2text', value: 'image2text' }, + ], + defaultValue: 'chat', + }, + { + name: 'llm_name', + label: t('modelName'), + type: FormFieldType.Text, + required: true, + placeholder: t('volcModelNameMessage'), + }, + { + name: 'endpoint_id', + label: t('addEndpointID'), + type: FormFieldType.Text, + required: true, + placeholder: t('endpointIDMessage'), + }, + { + name: 'ark_api_key', + label: t('addArkApiKey'), + type: FormFieldType.Text, + required: true, + placeholder: t('ArkApiKeyMessage'), + }, + { + name: 'max_tokens', + label: t('maxTokens'), + type: FormFieldType.Number, + required: true, + placeholder: t('maxTokensTip'), + validation: { + min: 0, + }, + }, + ]; + + const handleOk = async (values?: FieldValues) => { + if (!values) return; - const handleOk = async () => { - const values = await form.validateFields(); const modelType = values.model_type === 'chat' && values.vision ? 'image2text' : values.model_type; - const data = { - ...omit(values, ['vision']), - model_type: modelType, + const data: VolcEngineLlmRequest = { llm_factory: llmFactory, - max_tokens: values.max_tokens, + llm_name: values.llm_name as string, + model_type: modelType, + endpoint_id: values.endpoint_id as string, + ark_api_key: values.ark_api_key as string, + max_tokens: values.max_tokens as number, }; + console.info(data); - onOk?.(data); + await onOk?.(data); }; return ( } - open={visible} - onOk={handleOk} - onCancel={hideModal} - okButtonProps={{ loading }} - footer={(originNode: React.ReactNode) => { - return ( - - - {t('ollamaLink', { name: llmFactory })} - - {originNode} - - ); - }} + open={visible || false} + onOpenChange={(open) => !open && hideModal?.()} + maskClosable={false} + footer={
} > -
{ + console.log(data); + }} + defaultValues={ + { + model_type: 'chat', + vision: false, + } as FieldValues + } + labelClassName="font-normal" > - - label={t('modelType')} - name="model_type" - initialValue={'chat'} - rules={[{ required: true, message: t('modelTypeMessage') }]} - > - - - - label={t('modelName')} - name="llm_name" - rules={[{ required: true, message: t('volcModelNameMessage') }]} - > - - - - label={t('addEndpointID')} - name="endpoint_id" - rules={[{ required: true, message: t('endpointIDMessage') }]} - > - - - - label={t('addArkApiKey')} - name="ark_api_key" - rules={[{ required: true, message: t('ArkApiKeyMessage') }]} - > - - - - label={t('maxTokens')} - name="max_tokens" - rules={[ - { required: true, message: t('maxTokensMessage') }, - { - type: 'number', - message: t('maxTokensInvalidMessage'), - }, - ({}) => ({ - validator(_, value) { - if (value < 0) { - return Promise.reject(new Error(t('maxTokensMinMessage'))); - } - return Promise.resolve(); - }, - }), - ]} - > - - - +
+ + {t('ollamaLink', { name: llmFactory })} + +
+ { + hideModal?.(); + }} + /> + { + handleOk(values); + }} + /> +
+
+
); }; diff --git a/web/src/pages/user-setting/setting-model/modal/yiyan-modal/index.tsx b/web/src/pages/user-setting/setting-model/modal/yiyan-modal/index.tsx index 6991b9a3c..511f96077 100644 --- a/web/src/pages/user-setting/setting-model/modal/yiyan-modal/index.tsx +++ b/web/src/pages/user-setting/setting-model/modal/yiyan-modal/index.tsx @@ -1,18 +1,15 @@ -import { useTranslate } from '@/hooks/common-hooks'; +import { + DynamicForm, + FormFieldConfig, + FormFieldType, +} from '@/components/dynamic-form'; +import { Modal } from '@/components/ui/modal/modal'; +import { useCommonTranslation, useTranslate } from '@/hooks/common-hooks'; import { IModalProps } from '@/interfaces/common'; import { IAddLlmRequestBody } from '@/interfaces/request/llm'; -import { Form, Input, InputNumber, Modal, Select } from 'antd'; -import omit from 'lodash/omit'; +import { FieldValues } from 'react-hook-form'; import { LLMHeader } from '../../components/llm-header'; -type FieldType = IAddLlmRequestBody & { - vision: boolean; - yiyan_ak: string; - yiyan_sk: string; -}; - -const { Option } = Select; - const YiyanModal = ({ visible, hideModal, @@ -20,111 +17,115 @@ const YiyanModal = ({ loading, llmFactory, }: IModalProps & { llmFactory: string }) => { - const [form] = Form.useForm(); - const { t } = useTranslate('setting'); + const { t: tc } = useCommonTranslation(); + + const fields: FormFieldConfig[] = [ + { + name: 'model_type', + label: t('modelType'), + type: FormFieldType.Select, + required: true, + options: [ + { label: 'chat', value: 'chat' }, + { label: 'embedding', value: 'embedding' }, + { label: 'rerank', value: 'rerank' }, + ], + defaultValue: 'chat', + }, + { + name: 'llm_name', + label: t('modelName'), + type: FormFieldType.Text, + required: true, + placeholder: t('yiyanModelNameMessage'), + }, + { + name: 'yiyan_ak', + label: t('addyiyanAK'), + type: FormFieldType.Text, + required: true, + placeholder: t('yiyanAKMessage'), + }, + { + name: 'yiyan_sk', + label: t('addyiyanSK'), + type: FormFieldType.Text, + required: true, + placeholder: t('yiyanSKMessage'), + }, + { + name: 'max_tokens', + label: t('maxTokens'), + type: FormFieldType.Number, + required: true, + placeholder: t('maxTokensTip'), + validation: { + min: 0, + }, + }, + ]; + + const handleOk = async (values?: FieldValues) => { + if (!values) return; - const handleOk = async () => { - const values = await form.validateFields(); const modelType = values.model_type === 'chat' && values.vision ? 'image2text' : values.model_type; - const data = { - ...omit(values, ['vision']), - model_type: modelType, + const data: IAddLlmRequestBody = { llm_factory: llmFactory, - max_tokens: values.max_tokens, + llm_name: values.llm_name as string, + model_type: modelType, + api_key: { + yiyan_ak: values.yiyan_ak, + yiyan_sk: values.yiyan_sk, + }, + max_tokens: values.max_tokens as number, }; + console.info(data); - onOk?.(data); - }; - - const handleKeyDown = async (e: React.KeyboardEvent) => { - if (e.key === 'Enter') { - await handleOk(); - } + await onOk?.(data); }; return ( } - open={visible} - onOk={handleOk} - onCancel={hideModal} - okButtonProps={{ loading }} - confirmLoading={loading} + open={visible || false} + onOpenChange={(open) => !open && hideModal?.()} + maskClosable={false} + footer={
} > -
{ + console.log(data); + }} + defaultValues={ + { + model_type: 'chat', + vision: false, + } as FieldValues + } + labelClassName="font-normal" > - - label={t('modelType')} - name="model_type" - initialValue={'chat'} - rules={[{ required: true, message: t('modelTypeMessage') }]} - > - - - - label={t('modelName')} - name="llm_name" - rules={[{ required: true, message: t('yiyanModelNameMessage') }]} - > - + { + hideModal?.(); + }} /> - - - label={t('addyiyanAK')} - name="yiyan_ak" - rules={[{ required: true, message: t('yiyanAKMessage') }]} - > - - - - label={t('addyiyanSK')} - name="yiyan_sk" - rules={[{ required: true, message: t('yiyanSKMessage') }]} - > - - - - label={t('maxTokens')} - name="max_tokens" - rules={[ - { required: true, message: t('maxTokensMessage') }, - { - type: 'number', - message: t('maxTokensInvalidMessage'), - }, - ({}) => ({ - validator(_, value) { - if (value < 0) { - return Promise.reject(new Error(t('maxTokensMinMessage'))); - } - return Promise.resolve(); - }, - }), - ]} - > - { + handleOk(values); + }} /> - - + +
); };