feat: Add base project structure with API and web components
This commit is contained in:
61
web/src/views/UserMemory/components/CardList.tsx
Normal file
61
web/src/views/UserMemory/components/CardList.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import { type FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Progress } from 'antd'
|
||||
import type { Data } from '../types'
|
||||
|
||||
import Tag from '@/components/Tag'
|
||||
|
||||
const bgList = [
|
||||
'linear-gradient( 180deg, #F1F6FE 0%, #FBFDFF 100%)',
|
||||
'linear-gradient( 180deg, #F1F9FE 0%, #FBFDFF 100%)',
|
||||
'linear-gradient( 180deg, #FEFBF7 0%, #FBFDFF 100%)',
|
||||
'linear-gradient( 180deg, #F1F9FE 0%, #FBFDFF 100%)',
|
||||
]
|
||||
interface CardListProps {
|
||||
data: Data[]
|
||||
handleViewDetail: (id: string | number) => void
|
||||
}
|
||||
const CardList: FC<CardListProps> = ({
|
||||
data,
|
||||
handleViewDetail
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div className="rb:grid rb:grid-cols-3 rb:gap-[16px]">
|
||||
{data.map((item, index) => {
|
||||
return (
|
||||
<div
|
||||
key={item.id}
|
||||
className="rb:p-[20px] rb:rounded-[12px] rb:border-[1px] rb:border-[#DFE4ED] rb:cursor-pointer"
|
||||
style={{
|
||||
background: bgList[index % bgList.length],
|
||||
}}
|
||||
onClick={() => handleViewDetail(item.id)}
|
||||
>
|
||||
<div className="rb:flex rb:items-center">
|
||||
<div className="rb:w-[48px] rb:h-[48px] rb:text-center rb:font-semibold rb:text-[28px] rb:leading-[48px] rb:rounded-[8px] rb:text-[#FBFDFF] rb:bg-[#155EEF]">{item.username[0]}</div>
|
||||
<div className="rb:text-base rb:font-medium rb:leading-[24px] rb:ml-[12px]">
|
||||
{item.username}<br/>
|
||||
<Tag color={item.role === 'administrator' ? 'processing' : 'error'}>{item.role}</Tag>
|
||||
</div>
|
||||
</div>
|
||||
<div className="rb:grid rb:grid-cols-3 rb:gap-[12px] rb:mt-[28px] rb:mb-[28px]">
|
||||
{['knowledgeEntryCount', 'interactionCount', 'averageTimeConsumption'].map(key => (
|
||||
<div key={key} className="rb:text-center">
|
||||
<div className="rb:text-[24px] rb:leading-[30px] rb:font-extrabold">{item[key] || 0}</div>
|
||||
<div className="rb:break-words">{t(`memory.${key}`)}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="rb:flex rb:items-center rb:justify-between rb:w-full rb:text-[#5B6167] rb:text-[12px]">{t('memory.dataCompletionDegree')}<span>{item.dataCompletionDegree || 0}%</span></div>
|
||||
<Progress percent={item.dataCompletionDegree || 0} showInfo={false} size={{height: 8}} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default CardList
|
||||
127
web/src/views/UserMemory/components/ConfigModal.tsx
Normal file
127
web/src/views/UserMemory/components/ConfigModal.tsx
Normal file
@@ -0,0 +1,127 @@
|
||||
import { forwardRef, useImperativeHandle, useState } from 'react';
|
||||
import { Form, App } from 'antd';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import type { ConfigModalData, ConfigModalRef } from '../types'
|
||||
import { getWorkspaceModels, updateWorkspaceModels } from '@/api/workspaces'
|
||||
import { getModelListUrl } from '@/api/models'
|
||||
import CustomSelect from '@/components/CustomSelect'
|
||||
import RbModal from '@/components/RbModal'
|
||||
|
||||
const ConfigModal = forwardRef<ConfigModalRef>((_props, ref) => {
|
||||
const { t } = useTranslation();
|
||||
const { message } = App.useApp();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [form] = Form.useForm<ConfigModalData>();
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
const values = Form.useWatch([], form);
|
||||
|
||||
// 封装取消方法,添加关闭弹窗逻辑
|
||||
const handleClose = () => {
|
||||
setVisible(false);
|
||||
form.resetFields();
|
||||
setLoading(false)
|
||||
};
|
||||
|
||||
const handleOpen = () => {
|
||||
getWorkspaceModels().then((res) => {
|
||||
const { llm, embedding, rerank } = res as ConfigModalData
|
||||
form.setFieldsValue({
|
||||
llm,
|
||||
embedding,
|
||||
rerank
|
||||
})
|
||||
})
|
||||
setVisible(true);
|
||||
};
|
||||
// 封装保存方法,添加提交逻辑
|
||||
const handleSave = () => {
|
||||
form
|
||||
.validateFields()
|
||||
.then(() => {
|
||||
setLoading(true)
|
||||
// updateWorkspaceModels(values as ConfigModalData)
|
||||
// .then(() => {
|
||||
// setLoading(false)
|
||||
// handleClose()
|
||||
// message.success(t('common.createSuccess'))
|
||||
// })
|
||||
// .catch(() => {
|
||||
// setLoading(false)
|
||||
// });
|
||||
|
||||
handleClose()
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log('err', err)
|
||||
});
|
||||
}
|
||||
|
||||
// 暴露给父组件的方法
|
||||
useImperativeHandle(ref, () => ({
|
||||
handleOpen,
|
||||
handleClose
|
||||
}));
|
||||
|
||||
return (
|
||||
<RbModal
|
||||
title={t(`userMemory.editConfig`)}
|
||||
open={visible}
|
||||
onCancel={handleClose}
|
||||
okText={t('common.save')}
|
||||
onOk={handleSave}
|
||||
confirmLoading={loading}
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
>
|
||||
<Form.Item
|
||||
label={t('space.llmModel')}
|
||||
name="llm"
|
||||
rules={[{ required: true, message: t('common.pleaseSelect') }]}
|
||||
>
|
||||
<CustomSelect
|
||||
url={getModelListUrl}
|
||||
params={{ type: 'llm', pagesize: 100 }}
|
||||
valueKey="id"
|
||||
labelKey="name"
|
||||
hasAll={false}
|
||||
style={{width: '100%'}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t('space.embeddingModel')}
|
||||
name="embedding"
|
||||
rules={[{ required: true, message: t('common.pleaseSelect') }]}
|
||||
>
|
||||
<CustomSelect
|
||||
url={getModelListUrl}
|
||||
params={{ type: 'embedding', pagesize: 100 }}
|
||||
valueKey="id"
|
||||
labelKey="name"
|
||||
hasAll={false}
|
||||
style={{width: '100%'}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t('space.rerankModel')}
|
||||
name="rerank"
|
||||
rules={[{ required: true, message: t('common.pleaseSelect') }]}
|
||||
>
|
||||
<CustomSelect
|
||||
url={getModelListUrl}
|
||||
params={{ type: 'rerank', pagesize: 100 }}
|
||||
valueKey="id"
|
||||
labelKey="name"
|
||||
hasAll={false}
|
||||
style={{width: '100%'}}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</RbModal>
|
||||
);
|
||||
});
|
||||
|
||||
export default ConfigModal;
|
||||
Reference in New Issue
Block a user