mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-05 21:49:25 +08:00
chore: update & fix
This commit is contained in:
parent
3e69026d73
commit
1c0f83311f
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Avatar, Divider } from 'antd';
|
import { Avatar, Divider, Typography } from 'antd';
|
||||||
import { useToken } from '@nocobase/client';
|
import { useToken } from '@nocobase/client';
|
||||||
import { AIEmployee } from './types';
|
import { AIEmployee } from './types';
|
||||||
import { avatars } from './avatars';
|
import { avatars } from './avatars';
|
||||||
@ -48,11 +48,20 @@ export const ProfileCard: React.FC<{
|
|||||||
style={{
|
style={{
|
||||||
fontSize: token.fontSizeLG,
|
fontSize: token.fontSizeLG,
|
||||||
fontWeight: token.fontWeightStrong,
|
fontWeight: token.fontWeightStrong,
|
||||||
margin: '8px 0',
|
marginTop: '8px',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{aiEmployee.nickname}
|
{aiEmployee.nickname}
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: token.fontSize,
|
||||||
|
color: token.colorTextSecondary,
|
||||||
|
marginBottom: '8px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{aiEmployee.position}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Divider
|
<Divider
|
||||||
orientation="left"
|
orientation="left"
|
||||||
@ -63,7 +72,7 @@ export const ProfileCard: React.FC<{
|
|||||||
>
|
>
|
||||||
{t('Bio')}
|
{t('Bio')}
|
||||||
</Divider>
|
</Divider>
|
||||||
<p>{aiEmployee.bio}</p>
|
<Typography.Paragraph>{aiEmployee.bio}</Typography.Paragraph>
|
||||||
{taskDesc && (
|
{taskDesc && (
|
||||||
<>
|
<>
|
||||||
<Divider
|
<Divider
|
||||||
@ -75,7 +84,7 @@ export const ProfileCard: React.FC<{
|
|||||||
>
|
>
|
||||||
{t('Task description')}
|
{t('Task description')}
|
||||||
</Divider>
|
</Divider>
|
||||||
<p>{taskDesc}</p>
|
<Typography.Paragraph>{taskDesc}</Typography.Paragraph>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
@ -51,7 +51,12 @@ export const ChatBox: React.FC = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Card style={{ height: '100%' }} styles={{ body: { height: '100%', paddingTop: 0 } }}>
|
<Card
|
||||||
|
style={{ height: '100%' }}
|
||||||
|
styles={{
|
||||||
|
body: { height: '100%', paddingTop: 0, boxShadow: token.boxShadow },
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Layout style={{ height: '100%' }}>
|
<Layout style={{ height: '100%' }}>
|
||||||
<Sider
|
<Sider
|
||||||
width={!expanded ? '30%' : '15%'}
|
width={!expanded ? '30%' : '15%'}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { memo } from 'react';
|
import React, { memo, useEffect, useRef, useState } from 'react';
|
||||||
import { Sender as AntSender } from '@ant-design/x';
|
import { Sender as AntSender } from '@ant-design/x';
|
||||||
import { useChatBoxContext } from './ChatBoxContext';
|
import { useChatBoxContext } from './ChatBoxContext';
|
||||||
import { SenderPrefix } from './SenderPrefix';
|
import { SenderPrefix } from './SenderPrefix';
|
||||||
@ -17,7 +17,7 @@ import { SenderFooter } from './SenderFooter';
|
|||||||
import { useChatConversations } from './ChatConversationsProvider';
|
import { useChatConversations } from './ChatConversationsProvider';
|
||||||
import { useChatMessages } from './ChatMessagesProvider';
|
import { useChatMessages } from './ChatMessagesProvider';
|
||||||
|
|
||||||
export const Sender: React.FC = memo(() => {
|
export const Sender: React.FC = () => {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
const { currentConversation } = useChatConversations();
|
const { currentConversation } = useChatConversations();
|
||||||
const { responseLoading, cancelRequest } = useChatMessages();
|
const { responseLoading, cancelRequest } = useChatMessages();
|
||||||
@ -28,12 +28,22 @@ export const Sender: React.FC = memo(() => {
|
|||||||
const currentEmployee = useChatBoxContext('currentEmployee');
|
const currentEmployee = useChatBoxContext('currentEmployee');
|
||||||
const showInfoForm = useChatBoxContext('showInfoForm');
|
const showInfoForm = useChatBoxContext('showInfoForm');
|
||||||
const senderRef = useChatBoxContext('senderRef');
|
const senderRef = useChatBoxContext('senderRef');
|
||||||
|
const [value, setValue] = useState(senderValue);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setSenderValue(value);
|
||||||
|
}, [value]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setValue(senderValue);
|
||||||
|
}, [senderValue]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AntSender
|
<AntSender
|
||||||
value={senderValue}
|
value={value}
|
||||||
ref={senderRef}
|
ref={senderRef}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
setSenderValue(value);
|
setValue(value);
|
||||||
}}
|
}}
|
||||||
onSubmit={(content) =>
|
onSubmit={(content) =>
|
||||||
send({
|
send({
|
||||||
@ -57,4 +67,4 @@ export const Sender: React.FC = memo(() => {
|
|||||||
actions={false}
|
actions={false}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
};
|
||||||
|
@ -77,6 +77,7 @@ export const AIEmployeeButton: React.FC<{
|
|||||||
<SortableItem
|
<SortableItem
|
||||||
style={{
|
style={{
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
|
display: 'flex',
|
||||||
}}
|
}}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
let msg;
|
let msg;
|
||||||
@ -99,11 +100,11 @@ export const AIEmployeeButton: React.FC<{
|
|||||||
<Button
|
<Button
|
||||||
shape="circle"
|
shape="circle"
|
||||||
style={{
|
style={{
|
||||||
width: '40px',
|
width: '36px',
|
||||||
height: '40px',
|
height: '36px',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Avatar src={avatars(aiEmployee.avatar)} size={40} />
|
<Avatar src={avatars(aiEmployee.avatar)} size={36} />
|
||||||
</Button>
|
</Button>
|
||||||
</Popover>
|
</Popover>
|
||||||
{render()}
|
{render()}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { createContext, useContext, useMemo } from 'react';
|
import React, { createContext, useContext, useMemo } from 'react';
|
||||||
import { Card, Row, Col, Avatar, Input, Space, Button, Tabs, App, Spin, Empty, Typography } from 'antd';
|
import { Card, Row, Col, Avatar, Input, Space, Button, Tabs, App, Spin, Empty, Typography, Tag } from 'antd';
|
||||||
import {
|
import {
|
||||||
CollectionRecordProvider,
|
CollectionRecordProvider,
|
||||||
SchemaComponent,
|
SchemaComponent,
|
||||||
@ -29,6 +29,7 @@ import { avatars } from '../avatars';
|
|||||||
import { ModelSettings } from './ModelSettings';
|
import { ModelSettings } from './ModelSettings';
|
||||||
import { ProfileSettings } from './ProfileSettings';
|
import { ProfileSettings } from './ProfileSettings';
|
||||||
import { ChatSettings } from './ChatSettings';
|
import { ChatSettings } from './ChatSettings';
|
||||||
|
import { AIEmployee } from '../types';
|
||||||
|
|
||||||
const EmployeeContext = createContext(null);
|
const EmployeeContext = createContext(null);
|
||||||
|
|
||||||
@ -230,14 +231,7 @@ export const Employees: React.FC = () => {
|
|||||||
const { message, modal } = App.useApp();
|
const { message, modal } = App.useApp();
|
||||||
const { token } = useToken();
|
const { token } = useToken();
|
||||||
const api = useAPIClient();
|
const api = useAPIClient();
|
||||||
const { data, loading, refresh } = useRequest<
|
const { data, loading, refresh } = useRequest<AIEmployee[]>(() =>
|
||||||
{
|
|
||||||
username: string;
|
|
||||||
nickname: string;
|
|
||||||
bio: string;
|
|
||||||
avatar: string;
|
|
||||||
}[]
|
|
||||||
>(() =>
|
|
||||||
api
|
api
|
||||||
.resource('aiEmployees')
|
.resource('aiEmployees')
|
||||||
.list()
|
.list()
|
||||||
@ -391,9 +385,19 @@ export const Employees: React.FC = () => {
|
|||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Meta
|
<Meta
|
||||||
avatar={employee.avatar ? <Avatar src={avatars(employee.avatar)} /> : null}
|
avatar={employee.avatar ? <Avatar size={40} src={avatars(employee.avatar)} /> : null}
|
||||||
title={employee.nickname}
|
title={employee.nickname}
|
||||||
description={
|
description={
|
||||||
|
<>
|
||||||
|
{employee.position && (
|
||||||
|
<Tag
|
||||||
|
style={{
|
||||||
|
marginBottom: token.marginXS,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{employee.position}
|
||||||
|
</Tag>
|
||||||
|
)}
|
||||||
<Typography.Paragraph
|
<Typography.Paragraph
|
||||||
style={{ height: token.fontSize * token.lineHeight * 3 }}
|
style={{ height: token.fontSize * token.lineHeight * 3 }}
|
||||||
ellipsis={{ rows: 3 }}
|
ellipsis={{ rows: 3 }}
|
||||||
@ -401,6 +405,7 @@ export const Employees: React.FC = () => {
|
|||||||
>
|
>
|
||||||
{employee.bio}
|
{employee.bio}
|
||||||
</Typography.Paragraph>
|
</Typography.Paragraph>
|
||||||
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
|
@ -10,8 +10,10 @@
|
|||||||
import { SchemaComponent } from '@nocobase/client';
|
import { SchemaComponent } from '@nocobase/client';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { AvatarSelect } from './AvatarSelect';
|
import { AvatarSelect } from './AvatarSelect';
|
||||||
|
import { useT } from '../../locale';
|
||||||
|
|
||||||
export const ProfileSettings: React.FC = () => {
|
export const ProfileSettings: React.FC = () => {
|
||||||
|
const t = useT();
|
||||||
return (
|
return (
|
||||||
<SchemaComponent
|
<SchemaComponent
|
||||||
components={{ AvatarSelect }}
|
components={{ AvatarSelect }}
|
||||||
@ -32,6 +34,16 @@ export const ProfileSettings: React.FC = () => {
|
|||||||
'x-component': 'Input',
|
'x-component': 'Input',
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
position: {
|
||||||
|
type: 'string',
|
||||||
|
title: 'Position',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-component': 'Input',
|
||||||
|
description: t('A short label indicating the AI employee’s responsibility.'),
|
||||||
|
'x-component-props': {
|
||||||
|
placeholder: t('e.g. Translator, etc.'),
|
||||||
|
},
|
||||||
|
},
|
||||||
avatar: {
|
avatar: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
title: 'Avatar',
|
title: 'Avatar',
|
||||||
|
@ -30,7 +30,7 @@ const useStyles = createStyles(({ token, css }) => {
|
|||||||
background: rgba(0, 210, 255, 0.2);
|
background: rgba(0, 210, 255, 0.2);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity 0.3s ease;
|
transition: opacity 0.3s ease;
|
||||||
z-index: 1;
|
z-index: 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover::after {
|
&:hover::after {
|
||||||
|
@ -17,10 +17,11 @@ import {
|
|||||||
useCollectionFilterOptions,
|
useCollectionFilterOptions,
|
||||||
useCollectionRecordData,
|
useCollectionRecordData,
|
||||||
useSchemaSettings,
|
useSchemaSettings,
|
||||||
|
useToken,
|
||||||
} from '@nocobase/client';
|
} from '@nocobase/client';
|
||||||
import { useT } from '../../locale';
|
import { useT } from '../../locale';
|
||||||
import { avatars } from '../avatars';
|
import { avatars } from '../avatars';
|
||||||
import { Card, Avatar, Tooltip, Modal } from 'antd';
|
import { Card, Avatar, Tooltip, Modal, Tag, Typography } from 'antd';
|
||||||
const { Meta } = Card;
|
const { Meta } = Card;
|
||||||
import { Schema } from '@formily/react';
|
import { Schema } from '@formily/react';
|
||||||
import { createForm } from '@formily/core';
|
import { createForm } from '@formily/core';
|
||||||
@ -61,6 +62,7 @@ const SettingsForm: React.FC<{
|
|||||||
}> = memo(({ form, aiEmployee }) => {
|
}> = memo(({ form, aiEmployee }) => {
|
||||||
const { dn } = useSchemaSettings();
|
const { dn } = useSchemaSettings();
|
||||||
const t = useT();
|
const t = useT();
|
||||||
|
const { token } = useToken();
|
||||||
return (
|
return (
|
||||||
<SchemaComponent
|
<SchemaComponent
|
||||||
components={{ InfoForm }}
|
components={{ InfoForm }}
|
||||||
@ -88,7 +90,20 @@ const SettingsForm: React.FC<{
|
|||||||
<Meta
|
<Meta
|
||||||
avatar={aiEmployee.avatar ? <Avatar src={avatars(aiEmployee.avatar)} size={48} /> : null}
|
avatar={aiEmployee.avatar ? <Avatar src={avatars(aiEmployee.avatar)} size={48} /> : null}
|
||||||
title={aiEmployee.nickname}
|
title={aiEmployee.nickname}
|
||||||
description={aiEmployee.bio}
|
description={
|
||||||
|
<>
|
||||||
|
{aiEmployee.position && (
|
||||||
|
<Tag
|
||||||
|
style={{
|
||||||
|
marginBottom: token.marginXS,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{aiEmployee.position}
|
||||||
|
</Tag>
|
||||||
|
)}
|
||||||
|
{aiEmployee.bio}
|
||||||
|
</>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
),
|
),
|
||||||
@ -199,10 +214,10 @@ export const aiEmployeeButtonSettings = new SchemaSettings({
|
|||||||
<Modal
|
<Modal
|
||||||
styles={{
|
styles={{
|
||||||
mask: {
|
mask: {
|
||||||
zIndex: selectable ? -1 : 1000,
|
zIndex: selectable ? -1 : 311,
|
||||||
},
|
},
|
||||||
wrapper: {
|
wrapper: {
|
||||||
zIndex: selectable ? -1 : 1000,
|
zIndex: selectable ? -1 : 311,
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
title={t('Edit')}
|
title={t('Edit')}
|
||||||
|
@ -16,6 +16,7 @@ export type Selector = {
|
|||||||
export type AIEmployee = {
|
export type AIEmployee = {
|
||||||
username: string;
|
username: string;
|
||||||
nickname?: string;
|
nickname?: string;
|
||||||
|
position?: string;
|
||||||
avatar?: string;
|
avatar?: string;
|
||||||
bio?: string;
|
bio?: string;
|
||||||
greeting?: string;
|
greeting?: string;
|
||||||
|
@ -20,6 +20,11 @@ export default {
|
|||||||
type: 'string',
|
type: 'string',
|
||||||
interface: 'input',
|
interface: 'input',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'position',
|
||||||
|
type: 'string',
|
||||||
|
interface: 'input',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'avatar',
|
name: 'avatar',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user