feat(web): app page ui upgrade

This commit is contained in:
zhaoying
2026-03-07 13:46:08 +08:00
parent e2b6c713e7
commit 06fe3f2f01
29 changed files with 938 additions and 961 deletions

View File

@@ -2,13 +2,12 @@
* @Author: ZhaoYing
* @Date: 2026-02-03 16:29:21
* @Last Modified by: ZhaoYing
* @Last Modified time: 2026-03-03 14:24:34
* @Last Modified time: 2026-03-04 10:28:59
*/
import { type FC, type ReactNode, useEffect, useRef, useState, forwardRef, useImperativeHandle } from 'react';
import clsx from 'clsx'
import { useEffect, useRef, useState, forwardRef, useImperativeHandle } from 'react';
import { useTranslation } from 'react-i18next'
import { useParams } from 'react-router-dom';
import { Row, Col, Space, Form, Input, Switch, Button, App, Spin } from 'antd'
import { Row, Col, Space, Form, Input, Button, App, Spin, Flex } from 'antd'
import Chat from './components/Chat'
import RbCard from '@/components/RbCard/Card'
@@ -35,92 +34,13 @@ import VariableList from './components/VariableList/VariableList'
import { getApplicationConfig } from '@/api/application'
import { memoryConfigListUrl } from '@/api/memory'
import CustomSelect from '@/components/CustomSelect'
import aiPrompt from '@/assets/images/application/aiPrompt.png'
import AiPromptModal from './components/AiPromptModal'
import ToolList from './components/ToolList/ToolList'
import SkillList from './components/Skill'
import ChatVariableConfigModal from './components/ChatVariableConfigModal';
import type { Skill } from '@/views/Skills/types'
/**
* Description wrapper component
* @param desc - Description text
* @param className - Additional CSS classes
*/
const DescWrapper: FC<{desc: string, className?: string}> = ({desc, className}) => {
return (
<div className={clsx(className, "rb:text-[12px] rb:text-[#5B6167] rb:font-regular rb:leading-4 ")}>
{desc}
</div>
)
}
/**
* Label wrapper component
* @param title - Label title
* @param className - Additional CSS classes
* @param children - Child elements
*/
const LabelWrapper: FC<{title: string, className?: string; children?: ReactNode}> = ({title, className, children}) => {
return (
<div className={clsx(className, "rb:text-[14px] rb:font-medium rb:leading-5")}>
{title}
{children}
</div>
)
}
/**
* Switch wrapper component with label and description
* @param title - Switch title
* @param desc - Optional description
* @param name - Form field name
* @param needTransition - Whether to translate text
*/
const SwitchWrapper: FC<{ title: string, desc?: string, name: string | string[]; needTransition?: boolean; }> = ({ title, desc, name, needTransition = true }) => {
const { t } = useTranslation();
return (
<div className="rb:flex rb:items-center rb:justify-between">
<LabelWrapper title={needTransition ? t(`application.${title}`) : title}>
{desc && <DescWrapper desc={needTransition ? t(`application.${desc}`) : desc} className="rb:mt-2" />}
</LabelWrapper>
<Form.Item
name={name}
valuePropName="checked"
className="rb:mb-0!"
>
<Switch />
</Form.Item>
</div>
)
}
/**
* Select wrapper component with label and description
* @param title - Select title
* @param desc - Description text
* @param name - Form field name
* @param url - API URL for options
*/
const SelectWrapper: FC<{ title: string, desc: string, name: string | string[], url: string }> = ({ title, desc, name, url }) => {
const { t } = useTranslation();
return (
<>
<LabelWrapper title={t(`application.${title}`)} className="rb:mb-2">
</LabelWrapper>
<Form.Item
name={name}
className="rb:mb-0!"
>
<CustomSelect
placeholder={t('common.pleaseSelect')}
url={url}
hasAll={false}
valueKey='config_id'
labelKey="config_name"
/>
</Form.Item>
<DescWrapper desc={t(`application.${desc}`)} className="rb:mt-2" />
</>
)
}
import SwitchFormItem from '@/components/FormItem/SwitchFormItem'
import DescWrapper from '@/components/FormItem/DescWrapper'
/**
* Agent configuration component
@@ -172,8 +92,8 @@ const Agent = forwardRef<AgentRef>((_props, ref) => {
const allSkills = Array.isArray(skills?.skill_ids) ? skills?.skill_ids.map(vo => ({ id: vo })) : []
const allTools = Array.isArray(response.tools) ? response.tools : []
const memoryContent = response.memory?.memory_config_id
const parsedMemoryContent = memoryContent === null || memoryContent === ''
? undefined
const parsedMemoryContent = memoryContent === null || memoryContent === ''
? undefined
: !isNaN(Number(memoryContent)) ? Number(memoryContent) : memoryContent
const variableList = variables?.map((item, index) => ({
...item,
@@ -410,46 +330,48 @@ const Agent = forwardRef<AgentRef>((_props, ref) => {
return (
<>
{loading && <Spin fullscreen></Spin>}
<Row className="rb:h-[calc(100vh-64px)]">
<Col span={12} className="rb:h-full rb:overflow-x-auto rb:border-r rb:border-[#DFE4ED] rb:p-[20px_16px_24px_16px]">
<div className="rb:flex rb:items-center rb:justify-end rb:mb-5">
<Space size={10}>
<Button onClick={handleModelConfig} className="rb:group">
{defaultModel?.name ? <div className="rb:w-4 rb:h-4 rb:bg-[url('@/assets/images/application/model.svg')] rb:group-hover:bg-[url('@/assets/images/application/model_hover.svg')]"></div> : null}
{defaultModel?.name || t('application.chooseModel')}
</Button>
<Button type="primary" onClick={() => handleSave()}>
{t('common.save')}
</Button>
</Space>
</div>
<Row className="rb:h-[calc(100vh-88px)]" gutter={12}>
<Col span={12} className="rb:h-full rb:overflow-y-auto">
<Form form={form}>
<Form.Item name="default_model_config_id" hidden noStyle></Form.Item>
<Form.Item name="model_parameters" hidden noStyle></Form.Item>
<Space size={16} direction="vertical" style={{ width: '100%' }}>
<Card title={t('application.promptConfiguration')}>
<div className="rb:flex rb:items-center rb:justify-between rb:mb-2.75">
<div className="rb:font-medium rb:leading-5">
{t('application.configuration')}
<span className="rb:font-regular rb:text-[12px] rb:text-[#5B6167]"> ({t('application.configurationDesc')})</span>
</div>
<Button style={{ padding: '0 8px', height: '24px' }} onClick={handlePrompt}>
<img src={aiPrompt} className="rb:size-5" />
{t('application.aiPrompt')}
</Button>
<Flex gap={16} vertical>
<Flex align="center" justify="space-between" className="rb:p-3! rb:bg-white rb:rounded-xl">
<Button type="primary" ghost onClick={handleModelConfig} className="rb:group">
{defaultModel?.name ? <div className="rb:size-4 rb:bg-[url('@/assets/images/application/model.svg')]"></div> : null}
{defaultModel?.name || t('application.chooseModel')}
</Button>
<Button type="primary" onClick={() => handleSave()}>
{t('common.save')}
</Button>
</Flex>
<Form.Item name="default_model_config_id" hidden noStyle></Form.Item>
<Form.Item name="model_parameters" hidden noStyle></Form.Item>
<Card
title={t('application.promptConfiguration')}
extra={
<Space
size={1}
className="rb:px-2 rb:h-5.5 rb:rounded-md rb:cursor-pointer rb:border rb:border-[rgba(21,94,239,0.3)] rb:text-[#155EEF]"
onClick={handlePrompt}
>
<div className="rb:size-5 rb:bg-cover rb:bg-[url('@/assets/images/application/aiPrompt.png')]"></div>
<span className="rb:font-[PingFangSC, PingFang_SC]!">{t('application.aiPrompt')}</span>
</Space>
}
>
<div className="rb:leading-4.5 rb:text-[12px] rb:mb-2">
<span className="rb:font-medium">{t('application.configuration')}</span>
<span className="rb:font-regular rb:text-[#5B6167]"> ({t('application.configurationDesc')})</span>
</div>
<Form.Item
name="system_prompt"
className="rb:mb-0!"
rules={[{ max: 10000 }]}
>
<Form.Item name="system_prompt" className="rb:mb-0!">
<Input.TextArea
placeholder={t('application.promptPlaceholder')}
styles={{
textarea: {
minHeight: '200px',
borderRadius: '8px'
borderRadius: '8px',
padding: '12px'
},
}}
/>
@@ -462,15 +384,28 @@ const Agent = forwardRef<AgentRef>((_props, ref) => {
{/* Memory Configuration */}
<Card title={t('application.memoryConfiguration')}>
<Space size={24} direction='vertical' style={{ width: '100%' }}>
<SwitchWrapper title="dialogueHistoricalMemory" desc="dialogueHistoricalMemoryDesc" name={['memory', 'enabled']} />
<SelectWrapper
title="selectMemoryContent"
desc="selectMemoryContentDesc"
name={['memory', 'memory_config_id']}
url={memoryConfigListUrl}
<Flex gap={16} vertical className="rb:bg-[#FAFAFA] rb:rounded-xl rb:p-3!">
<SwitchFormItem
title={t('application.dialogueHistoricalMemory')}
name={['memory', 'enabled']}
desc={t('application.dialogueHistoricalMemoryDesc')}
/>
</Space>
<Form.Item
name={['memory', 'memory_config_id']}
label={t('application.selectMemoryContent')}
extra={<DescWrapper desc={t('application.selectMemoryContentDesc')} className="rb:mt-1" />}
layout="vertical"
className="rb:mb-0!"
>
<CustomSelect
placeholder={t('common.pleaseSelect')}
url={memoryConfigListUrl}
hasAll={false}
valueKey='config_id'
labelKey="config_name"
/>
</Form.Item>
</Flex>
</Card>
<Form.Item name="variables" noStyle>
@@ -485,26 +420,29 @@ const Agent = forwardRef<AgentRef>((_props, ref) => {
<Form.Item name="tools" noStyle>
<ToolList />
</Form.Item>
</Space>
</Flex>
</Form>
</Col>
<Col span={12} className="rb:h-full rb:overflow-x-hidden rb:p-[20px_16px_24px_16px]">
<div className="rb:flex rb:items-center rb:justify-between rb:mb-5">
{t('application.debuggingAndPreview')}
<Space size={10}>
{chatVariables.length > 0 &&
<Col span={12} className="rb:h-full rb:overflow-y-hidden">
<RbCard
title={t('application.debuggingAndPreview')}
extra={
<Space size={10}>
<Button type="primary" ghost onClick={handleOpenVariableConfig}>
{t('application.variableConfig')}
</Button>
}
<Button type="primary" ghost onClick={handleAddModel}>
+ {t('application.addModel')}
</Button>
<div className="rb:w-8 rb:h-8 rb:cursor-pointer rb:bg-[url('@/assets/images/application/clean.svg')]" onClick={handleClearDebugging}></div>
</Space>
</div>
<RbCard height="calc(100vh - 160px)" bodyClassName="rb:p-[0]! rb:h-full rb:overflow-hidden">
<Button type="primary" ghost onClick={handleAddModel}>
+ {t('application.addModel')}
</Button>
<div className="rb:w-8 rb:h-8 rb:cursor-pointer rb:bg-[url('@/assets/images/application/clean.svg')]" onClick={handleClearDebugging}></div>
</Space>
}
headerType="borderless"
headerClassName="rb:h-[56px]! rb:leading-[22px]!"
titleClassName="rb:font-[MiSans-Bold] rb:font-bold"
bodyClassName="rb:p-4! rb:pt-0!"
className="rb:h-full"
>
<Chat
data={data as Config}
chatList={chatList}