fix(ai): enabled employees & model configure & chat button (#8650)

* fix(ai): enabled employees & model configure & chat button

* fix: permission table
This commit is contained in:
YANG QIA
2026-02-14 17:53:49 +08:00
committed by GitHub
parent 8361a336ad
commit f0ce659569
8 changed files with 36 additions and 25 deletions
@@ -13,12 +13,14 @@ import { useField } from '@formily/react';
import { Field } from '@formily/core';
import { useCollectionRecordData, useDataBlockRequest, useDataBlockResource } from '@nocobase/client';
import { useT } from '../../locale';
import { useAIEmployeesData } from '../hooks/useAIEmployeesData';
export const EnableSwitch: React.FC = () => {
const field = useField<Field>();
const record = useCollectionRecordData();
const resource = useDataBlockResource();
const { refresh } = useDataBlockRequest();
const { refresh: refreshAIEmployees } = useAIEmployeesData();
const { message } = App.useApp();
const t = useT();
const [loading, setLoading] = useState(false);
@@ -32,6 +34,7 @@ export const EnableSwitch: React.FC = () => {
});
message.success(t('Saved successfully'));
refresh();
refreshAIEmployees();
} catch (error) {
message.error(t('Failed to update'));
} finally {
@@ -23,7 +23,7 @@ import { useChatConversationsStore } from './stores/chat-conversations';
export const ChatButton: React.FC = observer(() => {
const ctx = useFlowContext<FlowRuntimeContext>();
const { isMobileLayout } = useMobileLayout();
const isV2Page = ctx.pageInfo.version === 'v2';
const isV1Page = ctx?.pageInfo?.version === 'v1';
const { token } = useToken();
const { aiEmployees } = useAIEmployeesData();
@@ -56,15 +56,14 @@ export const ChatButton: React.FC = observer(() => {
}));
}, [aiEmployees]);
if (open || !aiEmployees?.length) {
if (open || !aiEmployees?.length || isV1Page) {
return null;
}
const buttonShadow = token.boxShadowSecondary || token.boxShadow;
return (
!isMobileLayout &&
isV2Page && (
!isMobileLayout && (
<Dropdown
menu={{ items }}
placement="topRight"
@@ -128,11 +128,6 @@ export const Permissions: React.FC<{
dataIndex: 'position',
title: t('Position'),
},
{
dataIndex: 'modelSettings',
title: t('Model'),
render: (value) => value?.model && <Tag>{value?.model}</Tag>,
},
{
dataIndex: 'available',
title: (
@@ -112,6 +112,7 @@ export const EnabledModelsSelect: React.FC<any> = observer((props) => {
// Use provider-specific formatModelLabel if available, otherwise default
const providerOptions = provider ? plugin.aiManager.llmProviders.get(provider) : null;
const labelFormatter = providerOptions?.formatModelLabel || formatModelLabel;
const hasRecommended = !!provider && getRecommendedModels(provider).length > 0;
// Access deep properties to establish observer tracking
const optionsKey = JSON.stringify(formOptions);
@@ -136,6 +137,17 @@ export const EnabledModelsSelect: React.FC<any> = observer((props) => {
modelsCache.current[normalized.mode] = normalized.models;
}, []);
// If there are no recommended models, default to provider mode.
useEffect(() => {
if (!provider) {
return;
}
if (!hasRecommended && config.mode === 'recommended') {
modelsCache.current.recommended = config.models;
updateFieldValue({ mode: 'provider', models: modelsCache.current.provider || [] });
}
}, [provider, hasRecommended, config.mode]);
// Reset options when provider or options change so stale data is cleared
const prevKeyRef = useRef<string>('');
useEffect(() => {
@@ -226,17 +238,19 @@ export const EnabledModelsSelect: React.FC<any> = observer((props) => {
<div style={{ width: '100%' }}>
<Radio.Group value={config.mode} onChange={(e) => handleModeChange(e.target.value)} style={{ width: '100%' }}>
<Space direction="vertical" style={{ width: '100%' }}>
<Radio value="recommended">{t('Recommended models')}</Radio>
{config.mode === 'recommended' && (
<Text type="secondary" style={{ paddingLeft: 24 }}>
{t('Use recommended models:')}
{provider &&
getRecommendedModels(provider).length > 0 &&
' ' +
getRecommendedModels(provider)
.map((m) => m.label)
.join(', ')}
</Text>
{hasRecommended && (
<>
<Radio value="recommended">{t('Recommended models')}</Radio>
{config.mode === 'recommended' && (
<Text type="secondary" style={{ paddingLeft: 24 }}>
{t('Use recommended models:') +
' ' +
getRecommendedModels(provider)
.map((m) => m.label)
.join(', ')}
</Text>
)}
</>
)}
<Radio value="provider">{t('Select models')}</Radio>
@@ -38,14 +38,14 @@ export const LLMTestFlight: React.FC = observer(() => {
if (config.mode === 'recommended') {
const recommended = getRecommendedModels(provider);
if (recommended.length === 0) {
message.warning(t('Please set up Enabled Models first'));
message.warning(t('Please configure enabled models first'));
return;
}
model = recommended[0].value;
} else {
// provider or custom mode
if (config.models.length === 0) {
message.warning(t('Please set up Enabled Models first'));
message.warning(t('Please configure enabled models first'));
return;
}
model = config.models[0].value;
@@ -259,7 +259,7 @@
"Recommended": "Recommended",
"Select models to enable": "Select models to enable",
"Please fill in the API Key first": "Please fill in the API Key first",
"Please set up Enabled Models first": "Please set up Enabled Models first",
"Please configure enabled models first": "Please configure enabled models first",
"Test connection with the configured API Key": "Test connection with the configured API Key",
"Successful": "Successful",
"Failure": "Failure",
@@ -260,7 +260,7 @@
"Recommended": "推荐",
"Select models to enable": "选择要启用的模型",
"Please fill in the API Key first": "请先填写 API Key",
"Please set up Enabled Models first": "请先设置 Enabled Models",
"Please configure enabled models first": "请先配置启用的模型",
"Test connection with the configured API Key": "测试配置的 API Key 连接",
"Successful": "成功",
"Failure": "失败",
@@ -108,7 +108,7 @@ export class BuiltInManager {
enableKnowledgeBase: false,
knowledgeBase: DEFAULT_KNOWLEDGE_BASE,
knowledgeBasePrompt: DEFAULT_KNOWLEDGE_BASE_PROMPT,
enabled: false,
enabled: true,
builtIn: true,
},
});