chore: update & fix

This commit is contained in:
xilesun 2025-04-15 10:20:47 +08:00
parent 3e69026d73
commit 1c0f83311f
10 changed files with 98 additions and 35 deletions

View File

@ -8,7 +8,7 @@
*/
import React from 'react';
import { Avatar, Divider } from 'antd';
import { Avatar, Divider, Typography } from 'antd';
import { useToken } from '@nocobase/client';
import { AIEmployee } from './types';
import { avatars } from './avatars';
@ -48,11 +48,20 @@ export const ProfileCard: React.FC<{
style={{
fontSize: token.fontSizeLG,
fontWeight: token.fontWeightStrong,
margin: '8px 0',
marginTop: '8px',
}}
>
{aiEmployee.nickname}
</div>
<div
style={{
fontSize: token.fontSize,
color: token.colorTextSecondary,
marginBottom: '8px',
}}
>
{aiEmployee.position}
</div>
</div>
<Divider
orientation="left"
@ -63,7 +72,7 @@ export const ProfileCard: React.FC<{
>
{t('Bio')}
</Divider>
<p>{aiEmployee.bio}</p>
<Typography.Paragraph>{aiEmployee.bio}</Typography.Paragraph>
{taskDesc && (
<>
<Divider
@ -75,7 +84,7 @@ export const ProfileCard: React.FC<{
>
{t('Task description')}
</Divider>
<p>{taskDesc}</p>
<Typography.Paragraph>{taskDesc}</Typography.Paragraph>
</>
)}
</>

View File

@ -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%' }}>
<Sider
width={!expanded ? '30%' : '15%'}

View File

@ -7,7 +7,7 @@
* 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 { useChatBoxContext } from './ChatBoxContext';
import { SenderPrefix } from './SenderPrefix';
@ -17,7 +17,7 @@ import { SenderFooter } from './SenderFooter';
import { useChatConversations } from './ChatConversationsProvider';
import { useChatMessages } from './ChatMessagesProvider';
export const Sender: React.FC = memo(() => {
export const Sender: React.FC = () => {
const t = useT();
const { currentConversation } = useChatConversations();
const { responseLoading, cancelRequest } = useChatMessages();
@ -28,12 +28,22 @@ export const Sender: React.FC = memo(() => {
const currentEmployee = useChatBoxContext('currentEmployee');
const showInfoForm = useChatBoxContext('showInfoForm');
const senderRef = useChatBoxContext('senderRef');
const [value, setValue] = useState(senderValue);
useEffect(() => {
setSenderValue(value);
}, [value]);
useEffect(() => {
setValue(senderValue);
}, [senderValue]);
return (
<AntSender
value={senderValue}
value={value}
ref={senderRef}
onChange={(value) => {
setSenderValue(value);
setValue(value);
}}
onSubmit={(content) =>
send({
@ -57,4 +67,4 @@ export const Sender: React.FC = memo(() => {
actions={false}
/>
);
});
};

View File

@ -77,6 +77,7 @@ export const AIEmployeeButton: React.FC<{
<SortableItem
style={{
position: 'relative',
display: 'flex',
}}
onClick={async () => {
let msg;
@ -99,11 +100,11 @@ export const AIEmployeeButton: React.FC<{
<Button
shape="circle"
style={{
width: '40px',
height: '40px',
width: '36px',
height: '36px',
}}
>
<Avatar src={avatars(aiEmployee.avatar)} size={40} />
<Avatar src={avatars(aiEmployee.avatar)} size={36} />
</Button>
</Popover>
{render()}

View File

@ -8,7 +8,7 @@
*/
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 {
CollectionRecordProvider,
SchemaComponent,
@ -29,6 +29,7 @@ import { avatars } from '../avatars';
import { ModelSettings } from './ModelSettings';
import { ProfileSettings } from './ProfileSettings';
import { ChatSettings } from './ChatSettings';
import { AIEmployee } from '../types';
const EmployeeContext = createContext(null);
@ -230,14 +231,7 @@ export const Employees: React.FC = () => {
const { message, modal } = App.useApp();
const { token } = useToken();
const api = useAPIClient();
const { data, loading, refresh } = useRequest<
{
username: string;
nickname: string;
bio: string;
avatar: string;
}[]
>(() =>
const { data, loading, refresh } = useRequest<AIEmployee[]>(() =>
api
.resource('aiEmployees')
.list()
@ -391,16 +385,27 @@ export const Employees: React.FC = () => {
]}
>
<Meta
avatar={employee.avatar ? <Avatar src={avatars(employee.avatar)} /> : null}
avatar={employee.avatar ? <Avatar size={40} src={avatars(employee.avatar)} /> : null}
title={employee.nickname}
description={
<Typography.Paragraph
style={{ height: token.fontSize * token.lineHeight * 3 }}
ellipsis={{ rows: 3 }}
type="secondary"
>
{employee.bio}
</Typography.Paragraph>
<>
{employee.position && (
<Tag
style={{
marginBottom: token.marginXS,
}}
>
{employee.position}
</Tag>
)}
<Typography.Paragraph
style={{ height: token.fontSize * token.lineHeight * 3 }}
ellipsis={{ rows: 3 }}
type="secondary"
>
{employee.bio}
</Typography.Paragraph>
</>
}
/>
</Card>

View File

@ -10,8 +10,10 @@
import { SchemaComponent } from '@nocobase/client';
import React from 'react';
import { AvatarSelect } from './AvatarSelect';
import { useT } from '../../locale';
export const ProfileSettings: React.FC = () => {
const t = useT();
return (
<SchemaComponent
components={{ AvatarSelect }}
@ -32,6 +34,16 @@ export const ProfileSettings: React.FC = () => {
'x-component': 'Input',
required: true,
},
position: {
type: 'string',
title: 'Position',
'x-decorator': 'FormItem',
'x-component': 'Input',
description: t('A short label indicating the AI employees responsibility.'),
'x-component-props': {
placeholder: t('e.g. Translator, etc.'),
},
},
avatar: {
type: 'string',
title: 'Avatar',

View File

@ -30,7 +30,7 @@ const useStyles = createStyles(({ token, css }) => {
background: rgba(0, 210, 255, 0.2);
opacity: 0;
transition: opacity 0.3s ease;
z-index: 1;
z-index: 100;
}
&:hover::after {

View File

@ -17,10 +17,11 @@ import {
useCollectionFilterOptions,
useCollectionRecordData,
useSchemaSettings,
useToken,
} from '@nocobase/client';
import { useT } from '../../locale';
import { avatars } from '../avatars';
import { Card, Avatar, Tooltip, Modal } from 'antd';
import { Card, Avatar, Tooltip, Modal, Tag, Typography } from 'antd';
const { Meta } = Card;
import { Schema } from '@formily/react';
import { createForm } from '@formily/core';
@ -61,6 +62,7 @@ const SettingsForm: React.FC<{
}> = memo(({ form, aiEmployee }) => {
const { dn } = useSchemaSettings();
const t = useT();
const { token } = useToken();
return (
<SchemaComponent
components={{ InfoForm }}
@ -88,7 +90,20 @@ const SettingsForm: React.FC<{
<Meta
avatar={aiEmployee.avatar ? <Avatar src={avatars(aiEmployee.avatar)} size={48} /> : null}
title={aiEmployee.nickname}
description={aiEmployee.bio}
description={
<>
{aiEmployee.position && (
<Tag
style={{
marginBottom: token.marginXS,
}}
>
{aiEmployee.position}
</Tag>
)}
{aiEmployee.bio}
</>
}
/>
</Card>
),
@ -199,10 +214,10 @@ export const aiEmployeeButtonSettings = new SchemaSettings({
<Modal
styles={{
mask: {
zIndex: selectable ? -1 : 1000,
zIndex: selectable ? -1 : 311,
},
wrapper: {
zIndex: selectable ? -1 : 1000,
zIndex: selectable ? -1 : 311,
},
}}
title={t('Edit')}

View File

@ -16,6 +16,7 @@ export type Selector = {
export type AIEmployee = {
username: string;
nickname?: string;
position?: string;
avatar?: string;
bio?: string;
greeting?: string;

View File

@ -20,6 +20,11 @@ export default {
type: 'string',
interface: 'input',
},
{
name: 'position',
type: 'string',
interface: 'input',
},
{
name: 'avatar',
type: 'string',