mirror of
https://github.com/lobehub/lobehub.git
synced 2026-03-27 13:29:15 +07:00
✨ feat: 支持选择 Emoji
This commit is contained in:
@@ -61,6 +61,8 @@
|
||||
"@ant-design/colors": "^7",
|
||||
"@ant-design/icons": "^5",
|
||||
"@commitlint/cli": "^17",
|
||||
"@emoji-mart/data": "^1",
|
||||
"@emoji-mart/react": "^1",
|
||||
"@lobehub/ui": "^1",
|
||||
"@vercel/analytics": "^1",
|
||||
"ahooks": "^3",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Collapse, InputNumber, Segmented, Slider } from 'antd';
|
||||
import { Collapse, ConfigProvider, InputNumber, Segmented, Slider } from 'antd';
|
||||
import isEqual from 'fast-deep-equal';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Flexbox } from 'react-layout-kit';
|
||||
@@ -21,7 +21,15 @@ const AgentConfig = () => {
|
||||
const [updateAgentConfig] = useSessionStore((s) => [s.updateAgentConfig], shallow);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ConfigProvider
|
||||
theme={{
|
||||
components: {
|
||||
Segmented: {
|
||||
colorBgLayout: theme.isDarkMode ? '#111' : '#f1f1f1',
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Flexbox
|
||||
align={'center'}
|
||||
distribution={'space-between'}
|
||||
@@ -87,8 +95,8 @@ const AgentConfig = () => {
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Flexbox>
|
||||
</>
|
||||
</Flexbox>{' '}
|
||||
</ConfigProvider>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
74
src/pages/chat/[id]/edit/AgentMeta/EmojiPicker.tsx
Normal file
74
src/pages/chat/[id]/edit/AgentMeta/EmojiPicker.tsx
Normal file
@@ -0,0 +1,74 @@
|
||||
import data from '@emoji-mart/data';
|
||||
import i18n from '@emoji-mart/data/i18n/zh.json';
|
||||
import Picker from '@emoji-mart/react';
|
||||
import { Avatar } from '@lobehub/ui';
|
||||
import { Popover } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
import chroma from 'chroma-js';
|
||||
import { memo } from 'react';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
|
||||
import { useSessionStore } from '@/store/session';
|
||||
import { agentSelectors } from '@/store/session/selectors';
|
||||
|
||||
const useStyles = createStyles(({ css, token, prefixCls }) => ({
|
||||
avatar: css`
|
||||
border-radius: 50%;
|
||||
transition: scale 400ms ${token.motionEaseOut}, box-shadow 100ms ${token.motionEaseOut};
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 0 0 3px ${token.colorText};
|
||||
}
|
||||
|
||||
&:active {
|
||||
scale: 0.8;
|
||||
}
|
||||
`,
|
||||
picker: css`
|
||||
em-emoji-picker {
|
||||
--rgb-accent: ${chroma(token.colorPrimary) .rgb() .join(',')};
|
||||
--shadow: none;
|
||||
}
|
||||
`,
|
||||
popover: css`
|
||||
.${prefixCls}-popover-inner {
|
||||
padding: 0;
|
||||
}
|
||||
`,
|
||||
}));
|
||||
|
||||
const EmojiPicker = () => {
|
||||
const { styles } = useStyles();
|
||||
const [avatar, updateAgentMeta] = useSessionStore(
|
||||
(s) => [agentSelectors.currentAgentAvatar(s), s.updateAgentMeta],
|
||||
shallow,
|
||||
);
|
||||
|
||||
return (
|
||||
<Popover
|
||||
content={
|
||||
<div className={styles.picker}>
|
||||
<Picker
|
||||
data={data}
|
||||
i18n={i18n}
|
||||
locale={'zh'}
|
||||
onEmojiSelect={(e: any) => {
|
||||
updateAgentMeta({ avatar: e.native });
|
||||
}}
|
||||
skinTonePosition={'none'}
|
||||
theme={'auto'}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
placement={'left'}
|
||||
rootClassName={styles.popover}
|
||||
trigger={'click'}
|
||||
>
|
||||
<div className={styles.avatar} style={{ width: 'fit-content' }}>
|
||||
<Avatar avatar={avatar} size={200} />
|
||||
</div>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(EmojiPicker);
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ActionIcon, Avatar, Input, Tooltip } from '@lobehub/ui';
|
||||
import { ActionIcon, Input, Tooltip } from '@lobehub/ui';
|
||||
import { Button, Collapse } from 'antd';
|
||||
import isEqual from 'fast-deep-equal';
|
||||
import { LucideSparkles } from 'lucide-react';
|
||||
@@ -10,6 +10,7 @@ import { agentSelectors, useSessionStore } from '@/store/session';
|
||||
|
||||
import { FormItem } from '../FormItem';
|
||||
import { useStyles } from '../style';
|
||||
import EmojiPicker from './EmojiPicker';
|
||||
|
||||
const AgentMeta = () => {
|
||||
const { t } = useTranslation('common');
|
||||
@@ -83,7 +84,7 @@ const AgentMeta = () => {
|
||||
))}
|
||||
</Flexbox>
|
||||
<FormItem label={t('agentAvatar')}>
|
||||
<Avatar avatar={metaData.avatar} size={200} />
|
||||
<EmojiPicker />
|
||||
</FormItem>
|
||||
</Flexbox>
|
||||
),
|
||||
|
||||
@@ -35,15 +35,25 @@ export const promptSummaryAgentName = (content: string): Partial<OpenAIStreamPay
|
||||
export const promptPickEmoji = (content: string): Partial<OpenAIStreamPayload> => ({
|
||||
messages: [
|
||||
{
|
||||
content: `你是一名非常懂设计与时尚的设计师,你需要从用户的描述中匹配一个合适的 emoji。
|
||||
输入:你是一名精通体验设计的设计系统设计师,设计系统存在诸多类别的 token,比如品牌色、成功色等,你需要为各个类别的 token 提供说明文案。
|
||||
输出: 💅
|
||||
|
||||
输入:用户会输入一串 ts 代码,为了确保所有功能和分支的 100% 的覆盖率,你需要给出需要考虑哪些数据场景。
|
||||
输出: 🧪
|
||||
`,
|
||||
content: '你是一名非常懂设计与时尚的设计师,你需要从用户的描述中匹配一个合适的 emoji。',
|
||||
role: 'system',
|
||||
},
|
||||
{
|
||||
content: `输入:你是一名精通体验设计的设计系统设计师,设计系统存在诸多类别的 token,比如品牌色、成功色等,你需要为各个类别的 token 提供说明文案。`,
|
||||
role: 'user',
|
||||
},
|
||||
{
|
||||
content: `💅`,
|
||||
role: 'assistant',
|
||||
},
|
||||
{
|
||||
content: `输入:用户会输入一串 ts 代码,为了确保所有功能和分支的 100% 的覆盖率,你需要给出需要考虑哪些数据场景。`,
|
||||
role: 'user',
|
||||
},
|
||||
{
|
||||
content: `🧪`,
|
||||
role: 'assistant',
|
||||
},
|
||||
{
|
||||
content: `输入:${content}`,
|
||||
role: 'user',
|
||||
@@ -54,11 +64,12 @@ export const promptPickEmoji = (content: string): Partial<OpenAIStreamPayload> =
|
||||
export const promptSummaryDescription = (content: string): Partial<OpenAIStreamPayload> => ({
|
||||
messages: [
|
||||
{
|
||||
content: '你是一名擅长会话的助理,你需要将用户的提示词做一个3句话以内的总结。',
|
||||
content:
|
||||
'你是一名擅长会话的助理,你需要将用户的输入的内容总结为一个专家的简介,不超过 20 个字',
|
||||
role: 'system',
|
||||
},
|
||||
{
|
||||
content: `输入:${content}`,
|
||||
content: `${content}`,
|
||||
role: 'user',
|
||||
},
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user