diff --git a/frontend/packages/common/src/components/postcat/api/Codebox/index.tsx b/frontend/packages/common/src/components/postcat/api/Codebox/index.tsx index d5685e70..7cf4ec9c 100644 --- a/frontend/packages/common/src/components/postcat/api/Codebox/index.tsx +++ b/frontend/packages/common/src/components/postcat/api/Codebox/index.tsx @@ -1,12 +1,12 @@ -import { memo, useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react' -import type { RefObject } from 'react' -import { Box, useTheme } from '@mui/material' -import { Editor, useMonaco } from '@monaco-editor/react' -import { type editor as MonacoEditor } from 'monaco-editor' -import { IconButton } from '../IconButton' -import { message } from 'antd' -import { $t } from '@common/locales' import { RESPONSE_TIPS } from '@common/const/const' +import { $t } from '@common/locales' +import { Editor, useMonaco } from '@monaco-editor/react' +import { Box, useTheme } from '@mui/material' +import { message } from 'antd' +import { type editor as MonacoEditor } from 'monaco-editor' +import type { RefObject } from 'react' +import { memo, useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react' +import { IconButton } from '../IconButton' export interface CodeboxApiRef { insertCode: (value: string) => void diff --git a/frontend/packages/core/src/pages/aiSetting/AiSettingModal.tsx b/frontend/packages/core/src/pages/aiSetting/AiSettingModal.tsx index c824a23c..862a7d71 100644 --- a/frontend/packages/core/src/pages/aiSetting/AiSettingModal.tsx +++ b/frontend/packages/core/src/pages/aiSetting/AiSettingModal.tsx @@ -20,124 +20,118 @@ type AiSettingModalContentField = { defaultLlm: string } -const AiSettingModalContent = forwardRef( - (props, ref) => { - const [form] = Form.useForm() - const { message } = App.useApp() - const { entity, readOnly } = props - const { fetchData } = useFetch() - const [llmList, setLlmList] = useState() - const [loading, setLoading] = useState(false) +const AiSettingModalContent = forwardRef((props, ref) => { + const [form] = Form.useForm() + const { message } = App.useApp() + const { entity, readOnly } = props + const { fetchData } = useFetch() + const [llmList, setLlmList] = useState() + const [loading, setLoading] = useState(false) - const getLlmList = () => { - setLoading(true) - fetchData>(`ai/provider/llms`, { - method: 'GET', - eoParams: { provider: entity.id } + const getLlmList = () => { + setLoading(true) + fetchData>(`ai/provider/llms`, { + method: 'GET', + eoParams: { provider: entity.id } + }) + .then((response) => { + const { code, data, msg } = response + if (code === STATUS_CODE.SUCCESS) { + setLlmList(data.llms) + } else { + message.error(msg || $t(RESPONSE_TIPS.error)) + } }) - .then(response => { - const { code, data, msg } = response - if (code === STATUS_CODE.SUCCESS) { - setLlmList(data.llms) - } else { - message.error(msg || $t(RESPONSE_TIPS.error)) - } - }) - .finally(() => { - setLoading(false) - }) - } - - useEffect(() => { - getLlmList() - try { - form.setFieldsValue({ - defaultLlm: entity.defaultLlm, - config: entity!.config ? JSON.stringify(JSON.parse(entity!.config), null, 2) : '' - }) - } catch (e) { - form.setFieldsValue({ - defaultLlm: entity.defaultLlm, - config: '' - }) - } - }, []) - - const save: () => Promise = () => { - return new Promise((resolve, reject) => { - form - .validateFields() - .then(value => { - fetchData>('ai/provider/config', { - method: 'PUT', - eoParams: { provider: entity?.id }, - eoBody: value, - eoTransformKeys: ['defaultLlm'] - }) - .then(response => { - const { code, msg } = response - if (code === STATUS_CODE.SUCCESS) { - message.success(msg || $t(RESPONSE_TIPS.success)) - resolve(true) - } else { - message.error(msg || $t(RESPONSE_TIPS.error)) - reject(msg || $t(RESPONSE_TIPS.error)) - } - }) - .catch(errorInfo => reject(errorInfo)) - }) - .catch(errorInfo => reject(errorInfo)) + .finally(() => { + setLoading(false) }) - } - - useImperativeHandle(ref, () => ({ - save - })) - - return ( -
- - label={$t('模型')} - name="defaultLlm" - rules={[{ required: true }]} - > - - - - label={$t('参数')} name="config"> - - - - ) } -) + + useEffect(() => { + getLlmList() + try { + form.setFieldsValue({ + defaultLlm: entity.defaultLlm, + config: entity!.config ? JSON.stringify(JSON.parse(entity!.config), null, 2) : '' + }) + } catch (e) { + form.setFieldsValue({ + defaultLlm: entity.defaultLlm, + config: '' + }) + } + }, []) + + const save: () => Promise = () => { + return new Promise((resolve, reject) => { + form + .validateFields() + .then((value) => { + fetchData>('ai/provider/config', { + method: 'PUT', + eoParams: { provider: entity?.id }, + eoBody: value, + eoTransformKeys: ['defaultLlm'] + }) + .then((response) => { + const { code, msg } = response + if (code === STATUS_CODE.SUCCESS) { + message.success(msg || $t(RESPONSE_TIPS.success)) + resolve(true) + } else { + message.error(msg || $t(RESPONSE_TIPS.error)) + reject(msg || $t(RESPONSE_TIPS.error)) + } + }) + .catch((errorInfo) => reject(errorInfo)) + }) + .catch((errorInfo) => reject(errorInfo)) + }) + } + + useImperativeHandle(ref, () => ({ + save + })) + + return ( +
+ label={$t('模型')} name="defaultLlm" rules={[{ required: true }]}> + + + + label={$t('参数')} name="config"> + + + + ) +}) export default AiSettingModalContent diff --git a/frontend/packages/core/src/pages/keySettings/components/ApiKeyContent.tsx b/frontend/packages/core/src/pages/keySettings/components/ApiKeyContent.tsx index d04e83e2..54eec8e8 100644 --- a/frontend/packages/core/src/pages/keySettings/components/ApiKeyContent.tsx +++ b/frontend/packages/core/src/pages/keySettings/components/ApiKeyContent.tsx @@ -1,9 +1,11 @@ import { Codebox } from '@common/components/postcat/api/Codebox' +import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const' +import { useFetch } from '@common/hooks/http' import { $t } from '@common/locales' import { AIProvider } from '@core/components/AIProviderSelect' -import { DatePicker, Form, Input, Switch } from 'antd' +import { App, DatePicker, Form, Input, Switch } from 'antd' import dayjs from 'dayjs' -import React, { useEffect, useState } from 'react' +import React, { forwardRef, useEffect, useImperativeHandle, useState } from 'react' import { EditAPIKey } from '../types' interface ApiKeyContentProps { @@ -11,15 +13,19 @@ interface ApiKeyContentProps { entity: EditAPIKey } -const ApiKeyContent: React.FC = ({ provider, entity }) => { +const ApiKeyContent: React.FC = forwardRef(({ provider, entity }, ref) => { const [form] = Form.useForm() const [neverExpire, setNeverExpire] = useState(true) + const { fetchData } = useFetch() + const { message } = App.useApp() useEffect(() => { try { + const isNeverExpire = entity.expire_time === '0' + setNeverExpire(isNeverExpire) form.setFieldsValue({ name: entity.name, - expire_time: entity.expire_time === '0' ? 0 : dayjs(entity.expire_time), + expire_time: isNeverExpire ? undefined : dayjs(entity.expire_time), config: entity.config }) } catch (e) { @@ -29,23 +35,43 @@ const ApiKeyContent: React.FC = ({ provider, entity }) => { config: '' }) } - // setNeverExpire(entity.expire_time === '0') }, []) const handleOk = async () => { try { const values = await form.validateFields() - // onSave({ - // ...values, - // expire_time: neverExpire ? null : values.expire_time.format('YYYY-MM-DD HH:mm:ss') - // }) + const { expire_time, ...restValues } = values + const expireTime = neverExpire ? '0' : expire_time?.format('YYYY-MM-DD HH:mm:ss') + + const [response, error] = await fetchData>('ai/resource/key', { + method: 'POST', + eoParams: { provider: provider?.id }, + eoBody: { ...restValues, expire_time: expireTime }, + eoTransformKeys: ['config'] + }) + + if (error) { + console.error('API request failed:', error) + message.error($t(RESPONSE_TIPS.error)) + throw error + } + + const { code, msg } = response + if (code === STATUS_CODE.SUCCESS) { + message.success(msg || $t(RESPONSE_TIPS.success)) + return true + } else { + message.error(msg || $t(RESPONSE_TIPS.error)) + throw new Error(msg || $t(RESPONSE_TIPS.error)) + } } catch (error) { console.error('Validation failed:', error) } } - + useImperativeHandle(ref, () => ({ + handleOk + })) const handleNeverExpireChange = (checked: boolean) => { - console.log(checked) setNeverExpire(checked) if (!checked) { form.setFieldsValue({ @@ -64,18 +90,17 @@ const ApiKeyContent: React.FC = ({ provider, entity }) => { editorTheme="vs-dark" readOnly={false} width="100%" - height="300px" + height="150px" language="json" enableToolbar={false} />
- + {neverExpire ? $t('永不过期') : $t('设置过期时间')}
- neverExpire:{neverExpire} {!neverExpire && ( = ({ provider, entity }) => { )} ) -} +}) export default ApiKeyContent diff --git a/frontend/packages/core/src/pages/keySettings/index.tsx b/frontend/packages/core/src/pages/keySettings/index.tsx index 6fa9fc46..f131a8ee 100644 --- a/frontend/packages/core/src/pages/keySettings/index.tsx +++ b/frontend/packages/core/src/pages/keySettings/index.tsx @@ -4,8 +4,10 @@ import InsidePage from '@common/components/aoplatform/InsidePage' import PageList, { PageProColumns } from '@common/components/aoplatform/PageList' import TableBtnWithPermission from '@common/components/aoplatform/TableBtnWithPermission' import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const' +import { useGlobalContext } from '@common/contexts/GlobalStateContext' import { useFetch } from '@common/hooks/http' import { $t } from '@common/locales' +import { checkAccess } from '@common/utils/permission' import AIProviderSelect, { AIProvider } from '@core/components/AIProviderSelect' import { App, Divider, Space, Typography } from 'antd' import React, { useEffect, useRef, useState } from 'react' @@ -22,6 +24,8 @@ const KeySettings: React.FC = () => { const [searchWord, setSearchWord] = useState('') const [total, setTotal] = useState(0) const modalRef = useRef() + const { accessData } = useGlobalContext() + useEffect(() => { pageListRef.current?.reload() }, [selectedProvider]) @@ -63,9 +67,10 @@ const KeySettings: React.FC = () => { title: mode === 'add' ? $t(`添加 ${provider?.name} APIKey`) : $t('编辑 APIKey'), content: , onOk: () => { - return modalRef.current?.save().then((res) => { - // if (res === true) setAiConfigFlushed(true) - // getAiSettingList() + return modalRef.current?.handleOk().then((res) => { + if (res === true) { + pageListRef.current?.reload() + } }) }, width: 600, @@ -84,7 +89,7 @@ const KeySettings: React.FC = () => {
- {/* {checkAccess('system.devops.ai_provider.edit', accessData) ? : null} */} + {checkAccess('system.settings.ai_key_resource.manager', accessData) ? : null}
)