fix: fix style problem by fengqian
parent
4d2bc459ca
commit
b013fff224
|
|
@ -176,7 +176,7 @@ export default function ChatPreview({ agent, agentId }: Props) {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="p-4 bg-white border-t">
|
<div className="p-4 bg-white">
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<Input.TextArea
|
<Input.TextArea
|
||||||
value={input}
|
value={input}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ interface CapabilitySettingsProps {
|
||||||
beforeUploadKnowledge: (file: any) => Promise<boolean>;
|
beforeUploadKnowledge: (file: any) => Promise<boolean>;
|
||||||
onDeleteKnowledge: (fileId: string) => Promise<void>;
|
onDeleteKnowledge: (fileId: string) => Promise<void>;
|
||||||
markDirty: () => void;
|
markDirty: () => void;
|
||||||
|
isMobile?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function CapabilitySettings({
|
export default function CapabilitySettings({
|
||||||
|
|
@ -32,6 +33,7 @@ export default function CapabilitySettings({
|
||||||
beforeUploadKnowledge,
|
beforeUploadKnowledge,
|
||||||
onDeleteKnowledge,
|
onDeleteKnowledge,
|
||||||
markDirty,
|
markDirty,
|
||||||
|
isMobile = false,
|
||||||
}: CapabilitySettingsProps) {
|
}: CapabilitySettingsProps) {
|
||||||
return (
|
return (
|
||||||
<div className="flex-1 agent-editor-pane">
|
<div className="flex-1 agent-editor-pane">
|
||||||
|
|
@ -55,7 +57,7 @@ export default function CapabilitySettings({
|
||||||
setAvatarSelectorOpen={setAvatarSelectorOpen}
|
setAvatarSelectorOpen={setAvatarSelectorOpen}
|
||||||
/>
|
/>
|
||||||
<BasicSettingsPanel teams={teams} />
|
<BasicSettingsPanel teams={teams} />
|
||||||
<ModelSettingsCard models={models} />
|
<ModelSettingsCard models={models} isMobile={isMobile} />
|
||||||
<KnowledgeSettingsPanel
|
<KnowledgeSettingsPanel
|
||||||
agent={agent}
|
agent={agent}
|
||||||
beforeUploadKnowledge={beforeUploadKnowledge}
|
beforeUploadKnowledge={beforeUploadKnowledge}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ export default function InitModal({
|
||||||
open={open}
|
open={open}
|
||||||
onCancel={onCancel}
|
onCancel={onCancel}
|
||||||
footer={null}
|
footer={null}
|
||||||
width={720}
|
width={isMobile ? 360 : 720}
|
||||||
centered
|
centered
|
||||||
maskClosable={false}
|
maskClosable={false}
|
||||||
destroyOnHidden
|
destroyOnHidden
|
||||||
|
|
@ -84,7 +84,7 @@ export default function InitModal({
|
||||||
onValuesChange={(changed) => {
|
onValuesChange={(changed) => {
|
||||||
if (changed.name !== undefined) setAgentName(changed.name);
|
if (changed.name !== undefined) setAgentName(changed.name);
|
||||||
}}
|
}}
|
||||||
className="agent-editor-modal-card agent-editor-init-form"
|
className="agent-editor-init-form"
|
||||||
>
|
>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="name"
|
name="name"
|
||||||
|
|
@ -93,7 +93,7 @@ export default function InitModal({
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
placeholder="给你的智能体起个名字"
|
placeholder="给你的智能体起个名字"
|
||||||
size="large"
|
size={isMobile ? 'middle' : 'large'}
|
||||||
autoFocus
|
autoFocus
|
||||||
className="agent-editor-form-input"
|
className="agent-editor-form-input"
|
||||||
/>
|
/>
|
||||||
|
|
@ -105,7 +105,7 @@ export default function InitModal({
|
||||||
>
|
>
|
||||||
<Input.TextArea
|
<Input.TextArea
|
||||||
placeholder="介绍一下这个智能体是做什么的..."
|
placeholder="介绍一下这个智能体是做什么的..."
|
||||||
rows={3}
|
rows={isMobile ? 2 : 3}
|
||||||
className="agent-editor-form-textarea"
|
className="agent-editor-form-textarea"
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
@ -140,21 +140,24 @@ export default function InitModal({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="agent-editor-avatar-section">
|
<div className="agent-editor-avatar-section">
|
||||||
<div className="agent-editor-avatar-heading">选择你的智能体形象</div>
|
{!isMobile && <div className="agent-editor-avatar-heading">选择你的智能体形象</div>}
|
||||||
<div className="agent-editor-avatar-toolbar">
|
<div className="agent-editor-avatar-toolbar">
|
||||||
<div className="agent-editor-avatar-hint">
|
<div className="agent-editor-avatar-hint">
|
||||||
默认会使用系统头像,你也可以上传自己的图片替换。
|
默认会使用系统头像,你也可以上传自己的图片替换。
|
||||||
</div>
|
</div>
|
||||||
|
<div className="agent-editor-avatar-upload-container">
|
||||||
|
{isMobile && <div className="agent-editor-avatar-heading">选择你的智能体形象</div>}
|
||||||
<Upload
|
<Upload
|
||||||
accept="image/png,image/jpeg,image/webp,image/gif"
|
accept="image/png,image/jpeg,image/webp,image/gif"
|
||||||
showUploadList={false}
|
showUploadList={false}
|
||||||
beforeUpload={beforeUploadInitAvatar}
|
beforeUpload={beforeUploadInitAvatar}
|
||||||
>
|
>
|
||||||
<Button icon={<UploadOutlined />} loading={avatarUploading} className="agent-editor-upload-button">
|
<Button icon={<UploadOutlined />} size={isMobile ? 'small' : 'middle'} loading={avatarUploading} className="agent-editor-upload-button">
|
||||||
上传图片
|
上传图片
|
||||||
</Button>
|
</Button>
|
||||||
</Upload>
|
</Upload>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div className="agent-editor-avatar-grid monica-scrollbar">
|
<div className="agent-editor-avatar-grid monica-scrollbar">
|
||||||
{[DEFAULT_AVATAR, ...PRESET_AVATARS].map((url) => {
|
{[DEFAULT_AVATAR, ...PRESET_AVATARS].map((url) => {
|
||||||
const isSelected = selectedAvatar === url;
|
const isSelected = selectedAvatar === url;
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,10 @@ interface ModelCheckboxDropdownProps {
|
||||||
value?: string[];
|
value?: string[];
|
||||||
onChange?: (value: string[]) => void;
|
onChange?: (value: string[]) => void;
|
||||||
models: AiModel[];
|
models: AiModel[];
|
||||||
|
isMobile?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ModelCheckboxDropdown({ value = [], onChange, models }: ModelCheckboxDropdownProps) {
|
export default function ModelCheckboxDropdown({ value = [], onChange, models, isMobile = false }: ModelCheckboxDropdownProps) {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const summary = value.length ? `${value.length} 个已选` : '选择模型';
|
const summary = value.length ? `${value.length} 个已选` : '选择模型';
|
||||||
|
|
||||||
|
|
@ -20,7 +21,7 @@ export default function ModelCheckboxDropdown({ value = [], onChange, models }:
|
||||||
open={open}
|
open={open}
|
||||||
onOpenChange={setOpen}
|
onOpenChange={setOpen}
|
||||||
popupRender={() => (
|
popupRender={() => (
|
||||||
<div className="agent-model-dropdown-panel" onClick={(e) => e.stopPropagation()}>
|
<div className={`agent-model-dropdown-panel${isMobile ? ' is-h5-panel' : ''}`} onClick={(e) => e.stopPropagation()}>
|
||||||
<Checkbox.Group
|
<Checkbox.Group
|
||||||
value={value}
|
value={value}
|
||||||
onChange={(checked) => onChange?.(checked.map((item) => String(item)))}
|
onChange={(checked) => onChange?.(checked.map((item) => String(item)))}
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,10 @@ import { FileTextOutlined } from '@ant-design/icons';
|
||||||
interface PromptEditorProps {
|
interface PromptEditorProps {
|
||||||
form: any;
|
form: any;
|
||||||
markDirty: () => void;
|
markDirty: () => void;
|
||||||
|
isMobile?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function PromptEditor({ form, markDirty }: PromptEditorProps) {
|
export default function PromptEditor({ form, markDirty, isMobile }: PromptEditorProps) {
|
||||||
return (
|
return (
|
||||||
<div className="flex-1 agent-editor-pane">
|
<div className="flex-1 agent-editor-pane">
|
||||||
<div className="agent-editor-pane-body">
|
<div className="agent-editor-pane-body">
|
||||||
|
|
@ -42,7 +43,7 @@ export default function PromptEditor({ form, markDirty }: PromptEditorProps) {
|
||||||
<div className="agent-editor-prompt">
|
<div className="agent-editor-prompt">
|
||||||
<Form.Item name="prompt" noStyle>
|
<Form.Item name="prompt" noStyle>
|
||||||
<Input.TextArea
|
<Input.TextArea
|
||||||
rows={30}
|
rows={isMobile ? 10 : 30}
|
||||||
placeholder="在这里输入智能体的人设、技能、风格和输出规范..."
|
placeholder="在这里输入智能体的人设、技能、风格和输出规范..."
|
||||||
className="agent-editor-prompt-textarea border-none focus:ring-0 bg-transparent p-4 font-mono text-sm leading-relaxed"
|
className="agent-editor-prompt-textarea border-none focus:ring-0 bg-transparent p-4 font-mono text-sm leading-relaxed"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -29,10 +29,10 @@ export default function BasicSettingsPanel({ teams }: BasicSettingsPanelProps) {
|
||||||
<span className="text-[11px] text-gray-400">名称、描述和可见性决定了这个智能体如何被理解和管理。</span>
|
<span className="text-[11px] text-gray-400">名称、描述和可见性决定了这个智能体如何被理解和管理。</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Form.Item name="name" label="名称" rules={[{ required: true }]} className="mb-3">
|
<Form.Item name="name" label="名称" rules={[{ required: true }]} className="mb-2">
|
||||||
<Input placeholder="智能体名称" className="agent-editor-field-input" />
|
<Input placeholder="智能体名称" className="agent-editor-field-input" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="description" label="描述" className="mb-3">
|
<Form.Item name="description" label="描述" className="mb-2">
|
||||||
<Input.TextArea rows={3} placeholder="简短描述这个智能体是做什么的..." className="agent-editor-field-textarea" />
|
<Input.TextArea rows={3} placeholder="简短描述这个智能体是做什么的..." className="agent-editor-field-textarea" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,10 @@ import ModelCheckboxDropdown from '../ModelCheckboxDropdown';
|
||||||
|
|
||||||
interface ModelSettingsCardProps {
|
interface ModelSettingsCardProps {
|
||||||
models: any[];
|
models: any[];
|
||||||
|
isMobile?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ModelSettingsCard({ models }: ModelSettingsCardProps) {
|
export default function ModelSettingsCard({ models, isMobile = false }: ModelSettingsCardProps) {
|
||||||
return (
|
return (
|
||||||
<div className="monica-card agent-editor-section-card">
|
<div className="monica-card agent-editor-section-card">
|
||||||
<div className="agent-editor-section-title">
|
<div className="agent-editor-section-title">
|
||||||
|
|
@ -31,7 +32,7 @@ export default function ModelSettingsCard({ models }: ModelSettingsCardProps) {
|
||||||
className="mb-0"
|
className="mb-0"
|
||||||
getValueProps={(value) => ({ value: parseModelSelections(value) })}
|
getValueProps={(value) => ({ value: parseModelSelections(value) })}
|
||||||
>
|
>
|
||||||
<ModelCheckboxDropdown models={models} />
|
<ModelCheckboxDropdown models={models} isMobile={isMobile} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="temperature" label="Temperature" className="mb-0" hidden>
|
<Form.Item name="temperature" label="Temperature" className="mb-0" hidden>
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,7 @@ export default function AgentEditor() {
|
||||||
beforeUploadKnowledge={beforeUploadKnowledge}
|
beforeUploadKnowledge={beforeUploadKnowledge}
|
||||||
onDeleteKnowledge={handleDeleteKnowledge}
|
onDeleteKnowledge={handleDeleteKnowledge}
|
||||||
markDirty={markDirty}
|
markDirty={markDirty}
|
||||||
|
isMobile={isMobile}
|
||||||
/>
|
/>
|
||||||
<PreviewPane liveAgent={liveAgent} agentId={id} />
|
<PreviewPane liveAgent={liveAgent} agentId={id} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@
|
||||||
|
|
||||||
.agent-editor-init-modal .agent-editor-avatar-grid,
|
.agent-editor-init-modal .agent-editor-avatar-grid,
|
||||||
.agent-editor-avatar-modal .agent-editor-avatar-grid {
|
.agent-editor-avatar-modal .agent-editor-avatar-grid {
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
|
|
||||||
.agent-editor-avatar-toolbar,
|
.agent-editor-avatar-toolbar,
|
||||||
|
|
|
||||||
|
|
@ -8,14 +8,14 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.agent-editor-init-header {
|
.agent-editor-init-header {
|
||||||
margin-bottom: 1.125rem;
|
margin-bottom: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.agent-editor-init-badge {
|
.agent-editor-init-badge {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
margin-bottom: 0.875rem;
|
margin-bottom: 12px;
|
||||||
padding: 0.375rem 0.75rem;
|
padding: 0.375rem 0.75rem;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: rgba(0, 97, 255, 0.08);
|
background: rgba(0, 97, 255, 0.08);
|
||||||
|
|
@ -24,6 +24,13 @@
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.agent-editor-avatar-upload-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.agent-editor-init-title {
|
.agent-editor-init-title {
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
|
|
@ -31,6 +38,50 @@
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.is-h5-modal {
|
||||||
|
.agent-editor-init-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
.agent-editor-init-subtitle {
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
.agent-editor-avatar-preview {
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
}
|
||||||
|
.agent-editor-preview-text {
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
.agent-editor-preview-name {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-editor-modal-hero {
|
||||||
|
gap: 12px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-form-item {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-editor-avatar-heading {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-editor-avatar-option {
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-editor-preview-card {
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.agent-editor-init-subtitle {
|
.agent-editor-init-subtitle {
|
||||||
color: var(--color-text-secondary);
|
color: var(--color-text-secondary);
|
||||||
font-size: 0.90625rem;
|
font-size: 0.90625rem;
|
||||||
|
|
@ -44,10 +95,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.agent-editor-modal-card {
|
.agent-editor-modal-card {
|
||||||
border: 1px solid rgba(150, 177, 217, 0.32);
|
|
||||||
border-radius: 1.25rem;
|
|
||||||
background: var(--color-surface);
|
|
||||||
box-shadow: 0 18px 42px rgba(10, 28, 72, 0.08);
|
box-shadow: 0 18px 42px rgba(10, 28, 72, 0.08);
|
||||||
|
border-radius: 12px;
|
||||||
|
border: 1px solid rgba(148, 163, 184, 0.14);
|
||||||
|
background: linear-gradient(180deg, rgba(255,255,255,0.96) 0%, rgba(248,250,252,0.88) 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.agent-editor-preview-card {
|
.agent-editor-preview-card {
|
||||||
|
|
@ -97,13 +148,7 @@
|
||||||
line-height: 1.7;
|
line-height: 1.7;
|
||||||
}
|
}
|
||||||
|
|
||||||
.agent-editor-init-form {
|
.agent-editor-init-form {}
|
||||||
padding: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.is-h5-modal .ant-form-item {
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.agent-editor-form-label {
|
.agent-editor-form-label {
|
||||||
color: var(--color-text-secondary);
|
color: var(--color-text-secondary);
|
||||||
|
|
@ -166,7 +211,6 @@
|
||||||
|
|
||||||
.agent-editor-avatar-heading {
|
.agent-editor-avatar-heading {
|
||||||
margin-bottom: 0.75rem;
|
margin-bottom: 0.75rem;
|
||||||
padding: 0 0.25rem;
|
|
||||||
color: #8a9ab8;
|
color: #8a9ab8;
|
||||||
font-size: 0.6875rem;
|
font-size: 0.6875rem;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
|
|
@ -210,7 +254,6 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 5rem;
|
width: 5rem;
|
||||||
height: 5rem;
|
height: 5rem;
|
||||||
min-width: 5rem;
|
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border: 2px solid transparent;
|
border: 2px solid transparent;
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 8px;
|
gap: 4px;
|
||||||
position: relative; /* 为右上角标签提供定位参考 */
|
position: relative; /* 为右上角标签提供定位参考 */
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
@ -166,7 +166,7 @@
|
||||||
|
|
||||||
.h5-agent-name {
|
.h5-agent-name {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 13px;
|
font-size: 12px;
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
/* 支持最多展示两行 */
|
/* 支持最多展示两行 */
|
||||||
|
|
@ -175,7 +175,7 @@
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
line-height: 1.4;
|
line-height: 1.3;
|
||||||
min-height: 1.4em; /* 调整为单行高度占位,因为下面加了描述 */
|
min-height: 1.4em; /* 调整为单行高度占位,因为下面加了描述 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -242,7 +242,6 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
margin-top: auto;
|
margin-top: auto;
|
||||||
padding-top: 8px;
|
|
||||||
border-top: 1px solid var(--color-border);
|
border-top: 1px solid var(--color-border);
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
.chat-side.is-full {
|
||||||
|
width: 100%;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-agent-sidebar-header {
|
||||||
|
padding: 16px;
|
||||||
|
border-bottom: 1px solid var(--color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-agent-sidebar-list {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-agent-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 10px 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
background: transparent;
|
||||||
|
border-left: 3px solid transparent;
|
||||||
|
transition: background 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-agent-item:hover {
|
||||||
|
background: var(--color-surface-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-agent-item.active {
|
||||||
|
background: var(--color-surface-2);
|
||||||
|
border-left: 3px solid var(--color-brand);
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-agent-avatar-wrap {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border-radius: 50%;
|
||||||
|
color: #fff;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 14px;
|
||||||
|
overflow: hidden;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-agent-avatar-img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-agent-info {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-agent-name {
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--color-text);
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-agent-item.active .chat-agent-name {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-agent-sidebar-status {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 200px;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-agent-empty-text,
|
||||||
|
.chat-agent-loading-text {
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--color-text-tertiary);
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-agent-loading-text {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
import { Button } from 'antd';
|
import { Button, Spin, Empty } from 'antd';
|
||||||
|
import { MessageOutlined } from '@ant-design/icons';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
import type { Agent } from '../../../api';
|
import type { Agent } from '../../../api';
|
||||||
|
import './AgentSidebar.css';
|
||||||
|
|
||||||
const isImageUrl = (url: string) => url?.startsWith('http') || url?.startsWith('/');
|
const isImageUrl = (url: string) => url?.startsWith('http') || url?.startsWith('/');
|
||||||
|
|
||||||
|
|
@ -8,68 +11,75 @@ export default function AgentSidebar(props: {
|
||||||
activeAgentId?: string;
|
activeAgentId?: string;
|
||||||
onCreate: () => void;
|
onCreate: () => void;
|
||||||
onSelect: (agentId: string) => void;
|
onSelect: (agentId: string) => void;
|
||||||
|
isSidebar?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const { agentList, activeAgentId, onCreate, onSelect } = props;
|
const { agentList, activeAgentId, onCreate, onSelect, isSidebar = true } = props;
|
||||||
|
const [loadingTimeout, setLoadingTimeout] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (agentList.length > 0) return;
|
||||||
|
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
setLoadingTimeout(true);
|
||||||
|
}, 5000);
|
||||||
|
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, [agentList.length]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<aside className="chat-side">
|
<aside className={`chat-side${isSidebar ? '' : ' is-full'}`}>
|
||||||
<div style={{ padding: '16px', borderBottom: '1px solid var(--color-border)' }}>
|
<div className="chat-agent-sidebar-header">
|
||||||
<Button block type="dashed" onClick={onCreate}>
|
<Button block type="dashed" onClick={onCreate}>
|
||||||
+ 创建智能体
|
+ 创建智能体
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ flex: 1, overflowY: 'auto', padding: '8px 0' }}>
|
<div className="chat-agent-sidebar-list">
|
||||||
{agentList.map((a) => {
|
{agentList.length > 0 ? (
|
||||||
|
agentList.map((a) => {
|
||||||
const isActive = a.id === activeAgentId;
|
const isActive = a.id === activeAgentId;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={a.id}
|
key={a.id}
|
||||||
onClick={() => onSelect(a.id)}
|
onClick={() => onSelect(a.id)}
|
||||||
style={{
|
className={`chat-agent-item ${isActive ? 'active' : ''}`}
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
gap: 12,
|
|
||||||
padding: '10px 16px',
|
|
||||||
cursor: 'pointer',
|
|
||||||
background: isActive ? 'var(--color-surface-2)' : 'transparent',
|
|
||||||
borderLeft: `3px solid ${isActive ? 'var(--color-brand)' : 'transparent'}`,
|
|
||||||
transition: 'background 0.2s'
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
style={{
|
className="chat-agent-avatar-wrap"
|
||||||
width: 32,
|
style={{ background: a.avatar || 'var(--gradient-brand)' }}
|
||||||
height: 32,
|
|
||||||
borderRadius: '50%',
|
|
||||||
background: a.avatar || 'var(--gradient-brand)',
|
|
||||||
color: '#fff',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
fontWeight: 700,
|
|
||||||
fontSize: 14,
|
|
||||||
overflow: 'hidden'
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{isImageUrl(a.avatar) ? <img src={a.avatar} className="w-full h-full object-cover" alt="avatar" /> : (a.name?.charAt(0) || '?').toUpperCase()}
|
{isImageUrl(a.avatar) ? (
|
||||||
|
<img src={a.avatar} className="chat-agent-avatar-img" alt="avatar" />
|
||||||
|
) : (
|
||||||
|
(a.name?.charAt(0) || '?').toUpperCase()
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div style={{ flex: 1, minWidth: 0 }}>
|
<div className="chat-agent-info">
|
||||||
<div
|
<div className="chat-agent-name">
|
||||||
style={{
|
|
||||||
fontWeight: isActive ? 600 : 500,
|
|
||||||
fontSize: 14,
|
|
||||||
color: 'var(--color-text)',
|
|
||||||
overflow: 'hidden',
|
|
||||||
textOverflow: 'ellipsis',
|
|
||||||
whiteSpace: 'nowrap'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{a.name}
|
{a.name}
|
||||||
|
{!isSidebar && <MessageOutlined style={{marginLeft: 12}} />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})
|
||||||
|
) : !loadingTimeout ? (
|
||||||
|
<div className="chat-agent-sidebar-status">
|
||||||
|
<Spin />
|
||||||
|
<div className="chat-agent-loading-text">正在加载智能体...</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="chat-agent-sidebar-status">
|
||||||
|
<Empty
|
||||||
|
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
||||||
|
description={
|
||||||
|
<span className="chat-agent-empty-text">
|
||||||
|
暂无智能体<br />
|
||||||
|
点击上方按钮开始创建
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -293,7 +293,7 @@ export default function ChatInput(props: {
|
||||||
|
|
||||||
<div className="chat-input-toolbar">
|
<div className="chat-input-toolbar">
|
||||||
<div className="chat-input-toolbar-left">
|
<div className="chat-input-toolbar-left">
|
||||||
<Select
|
{/* <Select
|
||||||
value={activeModelValue || undefined}
|
value={activeModelValue || undefined}
|
||||||
className="chat-model-select"
|
className="chat-model-select"
|
||||||
popupMatchSelectWidth={false}
|
popupMatchSelectWidth={false}
|
||||||
|
|
@ -301,7 +301,7 @@ export default function ChatInput(props: {
|
||||||
suffixIcon={<DownOutlined className="chat-model-select-arrow" />}
|
suffixIcon={<DownOutlined className="chat-model-select-arrow" />}
|
||||||
placeholder="选择模型"
|
placeholder="选择模型"
|
||||||
onChange={onChangeModel}
|
onChange={onChangeModel}
|
||||||
/>
|
/> */}
|
||||||
|
|
||||||
<Upload
|
<Upload
|
||||||
className="chat-upload"
|
className="chat-upload"
|
||||||
|
|
|
||||||
|
|
@ -166,6 +166,7 @@ export default function ChatInputH5(props: {
|
||||||
return (
|
return (
|
||||||
<div className="chat-input-h5-container">
|
<div className="chat-input-h5-container">
|
||||||
{/* 顶部附件展示 */}
|
{/* 顶部附件展示 */}
|
||||||
|
{(attachments.length > 0 || imageUrls.length > 0) && (
|
||||||
<div className="chat-input-h5-attachments">
|
<div className="chat-input-h5-attachments">
|
||||||
{attachments.map((a, i) => (
|
{attachments.map((a, i) => (
|
||||||
<Tag key={i} color="blue" closable className="chat-input-h5-attachment-tag" onClose={() => setAttachments((arr) => arr.filter((_, j) => j !== i))}>
|
<Tag key={i} color="blue" closable className="chat-input-h5-attachment-tag" onClose={() => setAttachments((arr) => arr.filter((_, j) => j !== i))}>
|
||||||
|
|
@ -185,12 +186,12 @@ export default function ChatInputH5(props: {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>)}
|
||||||
|
|
||||||
{/* 模型切换与工具栏 */}
|
{/* 模型切换与工具栏 */}
|
||||||
<div className="chat-input-h5-toolbar">
|
<div className="chat-input-h5-toolbar">
|
||||||
<div className="chat-input-h5-toolbar-scroll">
|
<div className="chat-input-h5-toolbar-scroll">
|
||||||
<Select
|
{/* <Select
|
||||||
value={activeModelValue || undefined}
|
value={activeModelValue || undefined}
|
||||||
size="small"
|
size="small"
|
||||||
className="chat-input-h5-model-select"
|
className="chat-input-h5-model-select"
|
||||||
|
|
@ -201,21 +202,16 @@ export default function ChatInputH5(props: {
|
||||||
onChange={onChangeModel}
|
onChange={onChangeModel}
|
||||||
dropdownStyle={{ minWidth: 160 }}
|
dropdownStyle={{ minWidth: 160 }}
|
||||||
/>
|
/>
|
||||||
<div className="chat-input-h5-toolbar-divider" />
|
<div className="chat-input-h5-toolbar-divider" /> */}
|
||||||
<Button size="small" className="chat-input-h5-action-icon" icon={<UserOutlined />} onClick={onOpenAgents}>
|
<Button size="small" title="智能体" className="chat-input-h5-action-icon" icon={<UserOutlined />} onClick={onOpenAgents}>
|
||||||
智能体
|
|
||||||
</Button>
|
</Button>
|
||||||
<Button size="small" className="chat-input-h5-action-icon" disabled={!hasAgent} icon={<UnorderedListOutlined />} onClick={onOpenOutline}>
|
<Button size="small" title="大纲" className="chat-input-h5-action-icon" disabled={!hasAgent} icon={<UnorderedListOutlined />} onClick={onOpenOutline}>
|
||||||
大纲
|
|
||||||
</Button>
|
</Button>
|
||||||
<Button size="small" className="chat-input-h5-action-icon" disabled={!hasId} icon={<HistoryIcon />} onClick={onOpenHistory}>
|
<Button size="small" title="历史" className="chat-input-h5-action-icon" disabled={!hasId} icon={<HistoryIcon />} onClick={onOpenHistory}>
|
||||||
历史
|
|
||||||
</Button>
|
</Button>
|
||||||
<Button size="small" className="chat-input-h5-action-icon" disabled={!hasId} icon={<NewChatIcon />} onClick={onNewSession}>
|
<Button size="small" title="新建" className="chat-input-h5-action-icon" disabled={!hasId} icon={<NewChatIcon />} onClick={onNewSession}>
|
||||||
新建
|
|
||||||
</Button>
|
</Button>
|
||||||
<Button size="small" className="chat-input-h5-action-icon" icon={<BookOutlined />} onClick={onOpenTpl}>
|
<Button size="small" title="模板" className="chat-input-h5-action-icon" icon={<BookOutlined />} onClick={onOpenTpl}>
|
||||||
模板
|
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -88,9 +88,13 @@ export default function ChatPageH5({ logic }: { logic: ChatPageLogicOutput }) {
|
||||||
|
|
||||||
<section className="chat-main h5-chat-main">
|
<section className="chat-main h5-chat-main">
|
||||||
{!agent ? (
|
{!agent ? (
|
||||||
<div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
<AgentSidebar
|
||||||
<Empty description="请选择一个智能体开始对话" />
|
isSidebar={false}
|
||||||
</div>
|
agentList={agentList}
|
||||||
|
activeAgentId={id}
|
||||||
|
onCreate={() => navigate('/agents/new')}
|
||||||
|
onSelect={(aid) => navigate(`/chat/${aid}`)}
|
||||||
|
/>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<ChatHeader
|
<ChatHeader
|
||||||
|
|
@ -126,8 +130,6 @@ export default function ChatPageH5({ logic }: { logic: ChatPageLogicOutput }) {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</>
|
|
||||||
)}
|
|
||||||
<ChatInputH5
|
<ChatInputH5
|
||||||
input={sender.input}
|
input={sender.input}
|
||||||
setInput={sender.setInput}
|
setInput={sender.setInput}
|
||||||
|
|
@ -160,6 +162,8 @@ export default function ChatPageH5({ logic }: { logic: ChatPageLogicOutput }) {
|
||||||
hasId={!!id}
|
hasId={!!id}
|
||||||
showActions={false}
|
showActions={false}
|
||||||
/>
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<ChatDrawers
|
<ChatDrawers
|
||||||
|
|
|
||||||
|
|
@ -389,7 +389,6 @@ body {
|
||||||
background: var(--color-surface);
|
background: var(--color-surface);
|
||||||
border-radius: 14px;
|
border-radius: 14px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
border: 1px solid var(--color-border);
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
@ -398,6 +397,13 @@ body {
|
||||||
box-shadow: var(--shadow-xs);
|
box-shadow: var(--shadow-xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.is-h5 {
|
||||||
|
.agent-card {
|
||||||
|
padding: 12px 12px 0;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.agent-card:hover {
|
.agent-card:hover {
|
||||||
transform: translateY(-2px);
|
transform: translateY(-2px);
|
||||||
box-shadow: var(--shadow-md);
|
box-shadow: var(--shadow-md);
|
||||||
|
|
@ -1220,11 +1226,19 @@ body {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
background: var(--color-surface);
|
background: var(--color-surface);
|
||||||
border: 1px solid var(--color-border);
|
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
box-shadow: var(--shadow-lg);
|
box-shadow: var(--shadow-lg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.is-h5-panel {
|
||||||
|
.agent-model-dropdown-panel {
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
.agent-model-checkbox-item {
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.agent-model-checkbox-group {
|
.agent-model-checkbox-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
@ -1335,6 +1349,12 @@ body {
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.is-h5 {
|
||||||
|
.monica-card {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.monica-header {
|
.monica-header {
|
||||||
height: 56px;
|
height: 56px;
|
||||||
border-bottom: 1px solid var(--color-border);
|
border-bottom: 1px solid var(--color-border);
|
||||||
|
|
@ -1382,6 +1402,17 @@ body {
|
||||||
padding: 22px;
|
padding: 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.is-h5 {
|
||||||
|
.agent-editor-pane {
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 8px;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
.agent-editor-pane-body {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.agent-editor-pane-header {
|
.agent-editor-pane-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
|
@ -1419,11 +1450,10 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.agent-editor-intro {
|
.agent-editor-intro {
|
||||||
border-radius: 18px;
|
border-radius: 16px;
|
||||||
padding: 16px 18px;
|
padding: 12px;
|
||||||
background: linear-gradient(135deg, rgba(236,253,245,0.92) 0%, rgba(240,249,255,0.92) 100%);
|
background: linear-gradient(135deg, rgba(236,253,245,0.92) 0%, rgba(240,249,255,0.92) 100%);
|
||||||
border: 1px solid rgba(8, 145, 178, 0.12);
|
margin-bottom: 12px;
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.agent-editor-intro-title {
|
.agent-editor-intro-title {
|
||||||
|
|
@ -1446,6 +1476,14 @@ body {
|
||||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.65);
|
box-shadow: inset 0 1px 0 rgba(255,255,255,0.65);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.is-h5 {
|
||||||
|
.agent-editor-surface {
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.agent-editor-prompt-wrap {
|
.agent-editor-prompt-wrap {
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
}
|
}
|
||||||
|
|
@ -1469,12 +1507,6 @@ body {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.agent-editor-modal-card {
|
|
||||||
border-radius: 12px;
|
|
||||||
border: 1px solid rgba(148, 163, 184, 0.14);
|
|
||||||
background: linear-gradient(180deg, rgba(255,255,255,0.96) 0%, rgba(248,250,252,0.88) 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.agent-editor-avatar-grid {
|
.agent-editor-avatar-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(6, minmax(0, 1fr));
|
grid-template-columns: repeat(6, minmax(0, 1fr));
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue