style(web): translate the comments in the src/views directory into English

This commit is contained in:
zhaoying
2026-02-03 18:38:04 +08:00
parent a191e32f71
commit 9e195ea63b
155 changed files with 4169 additions and 586 deletions

View File

@@ -1,6 +1,21 @@
/*
* @Author: ZhaoYing
* @Date: 2026-02-03 17:27:28
* @Last Modified by: ZhaoYing
* @Last Modified time: 2026-02-03 17:27:28
*/
/**
* Card Component
* Reusable card wrapper for dashboard sections
*/
import { type FC, type ReactNode } from 'react'
import RbCard from '@/components/RbCard/Card'
/**
* Component props
*/
interface CardProps {
children: ReactNode;
title: string;

View File

@@ -1,13 +1,28 @@
/*
* @Author: ZhaoYing
* @Date: 2026-02-03 17:17:05
* @Last Modified by: ZhaoYing
* @Last Modified time: 2026-02-03 17:18:32
*/
/**
* Line Chart Card Component
* Displays time-series data with ECharts line chart
* Supports multiple series and date range selection
*/
import { type FC, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { Select } from 'antd'
import ReactEcharts from 'echarts-for-react';
import * as echarts from 'echarts';
import { formatDateTime } from '@/utils/format';
import Empty from '@/components/Empty'
import Card from './Card'
/**
* Component props
*/
interface LineCardProps {
chartData: Array<Record<string, string | number>>;
limit: number;
@@ -17,6 +32,7 @@ interface LineCardProps {
seriesList: string[];
}
/** ECharts series configuration */
const SeriesConfig = {
type: 'line',
stack: 'Total',
@@ -34,6 +50,7 @@ const SeriesConfig = {
},
data: [220, 302, 181, 234, 210, 290, 150]
}
/** Chart color palette */
const Colors = ['#FFB048', '#4DA8FF', '#155EEF']
const LineCard: FC<LineCardProps> = ({ chartData, limit, onChange, type, className, seriesList }) => {
@@ -47,6 +64,7 @@ const LineCard: FC<LineCardProps> = ({ chartData, limit, onChange, type, classNa
{ label: t('dashboard.lastYear'), value: 365 },
]
/** Generate series data with gradient colors */
const getSeries = () => {
const list = seriesList.map((key, index) => {
return {
@@ -71,6 +89,7 @@ const LineCard: FC<LineCardProps> = ({ chartData, limit, onChange, type, classNa
return list
}
/** Format series list for legend */
const formatSeriesList = () => {
return seriesList.map(key => ({
...SeriesConfig,
@@ -85,11 +104,11 @@ const LineCard: FC<LineCardProps> = ({ chartData, limit, onChange, type, classNa
<Select
value={limit}
options={options}
onChange={(value) => onChange(value, type)}
onChange={(value) => onChange(String(value), type)}
style={{ width: '150px' }}
/>
}
className={`rb:pb-[24px] ${className}`}
className={`rb:pb-6 ${className}`}
>
{chartData && chartData.length > 0 ? (
<ReactEcharts
@@ -157,7 +176,7 @@ const LineCard: FC<LineCardProps> = ({ chartData, limit, onChange, type, classNa
notMerge={true}
lazyUpdate={true}
/>
) : <Empty size={120} className="rb:mt-[48px] rb:mb-[81px]" />}
) : <Empty size={120} className="rb:mt-12 rb:mb-20.25" />}
</Card>
)
}

View File

@@ -1,14 +1,30 @@
/*
* @Author: ZhaoYing
* @Date: 2026-02-03 17:16:45
* @Last Modified by: ZhaoYing
* @Last Modified time: 2026-02-03 17:16:45
*/
/**
* Pie Chart Card Component
* Displays knowledge base type distribution with ECharts donut chart
*/
import { type FC, useRef, useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import ReactEcharts from 'echarts-for-react';
import Card from './Card'
import Loading from '@/components/Empty/Loading'
import Empty from '@/components/Empty'
/**
* Component props
*/
interface PieCardProps {
chartData: Array<Record<string, string | number>>;
loading: boolean;
}
/** Chart color palette */
const Colors = ['#155EEF', '#31E8FF', '#AD88FF', '#FFB048', '#4DA8FF', '#03BDFF']
const PieCard: FC<PieCardProps> = ({ chartData, loading }) => {
@@ -45,7 +61,7 @@ const PieCard: FC<PieCardProps> = ({ chartData, loading }) => {
{loading
? <Loading size={249} />
: !chartData || chartData.length === 0
? <Empty size={120} className="rb:mt-[48px] rb:mb-[81px]" />
? <Empty size={120} className="rb:mt-12 rb:mb-20.25" />
: <ReactEcharts
option={{
color: Colors,

View File

@@ -1,14 +1,19 @@
/*
* @Description:
* @Version: 0.0.1
* @Author: yujiangping
* @Date: 2026-01-05 17:22:23
* @LastEditors: yujiangping
* @LastEditTime: 2026-01-15 14:55:51
* @Author: ZhaoYing
* @Date: 2026-02-03 17:16:38
* @Last Modified by: ZhaoYing
* @Last Modified time: 2026-02-03 17:16:38
*/
/**
* Quick Operation Component
* Displays shortcut cards for common operations
* Includes navigation to application, knowledge base, memory conversation, and help center
*/
import { type FC } from 'react'
import { useTranslation } from 'react-i18next'
import { useNavigate } from 'react-router-dom';
import Card from './Card';
import applicationIcon from '@/assets/images/menu/application_active.svg';
import knowledgeIcon from '@/assets/images/menu/knowledge_active.svg';
@@ -16,6 +21,7 @@ import memoryConversationIcon from '@/assets/images/menu/memoryConversation_acti
import helpCenterIcon from '@/assets/images/menu/helpCenter_active.svg'
import arrowTopRight from '@/assets/images/home/arrow_top_right.svg';
/** Quick operation items configuration */
const quickOperations = [
{ key: 'createNewApplication', url: '/application' },
{ key: 'createNewKnowledge', url: '/knowledge-base' },
@@ -23,6 +29,7 @@ const quickOperations = [
{ key: 'helpCenter', url: '' },
]
/** Icon mapping for quick operations */
const quickOperationIcons: {[key: string]: string | undefined} = {
createNewApplication: applicationIcon,
createNewKnowledge: knowledgeIcon,
@@ -33,6 +40,7 @@ const QuickOperation:FC = () => {
const { t, i18n } = useTranslation()
const navigate = useNavigate();
/** Handle navigation or external link */
const handleJump = (url: string | null) => {
if (url) {
navigate(url)
@@ -41,7 +49,7 @@ const QuickOperation:FC = () => {
const lang = currentLang === 'zh' ? 'zh' : 'en';
const helpUrl = `https://docs.redbearai.com/s/${lang}-memorybear`;
// 创建隐藏的 a 标签来避免弹窗拦截
/** Create hidden link to avoid popup blocking */
const link = document.createElement('a');
link.href = helpUrl;
link.target = '_blank';
@@ -55,15 +63,15 @@ const QuickOperation:FC = () => {
<Card
title={t('dashboard.quickOperation')}
>
<div className="rb:grid rb:grid-cols-4 rb:gap-[16px]">
<div className="rb:grid rb:grid-cols-4 rb:gap-4">
{quickOperations.map(item => (
<div key={item.key} className="rb:rounded-[8px] rb:p-[20px_16px] rb:border-1 rb:border-[#DFE4ED] rb:cursor-pointer rb:hover:border-[#155EEF]" onClick={() => handleJump(item.url)}>
<div key={item.key} className="rb:rounded-lg rb:p-[20px_16px] rb:border rb:border-[#DFE4ED] rb:cursor-pointer rb:hover:border-[#155EEF]" onClick={() => handleJump(item.url)}>
<div className="rb:flex rb:justify-between">
<img className="rb:w-[32px] rb:h-[32px]" src={quickOperationIcons[item.key]} />
<img className="rb:w-[16px] rb:h-[16px]" src={arrowTopRight} />
<img className="rb:w-8 rb:h-8" src={quickOperationIcons[item.key]} />
<img className="rb:w-4 rb:h-4" src={arrowTopRight} />
</div>
<div className="rb:mt-[24px] rb:text-[#212332] rb:text-[16px] rb:leading-[20px] rb:font-medium">{t(`dashboard.${item.key}`)}</div>
<div className="rb:mt-[8px] rb:text-[#5B6167] rb:text-[12px] rb:font-regular">{t(`dashboard.${item.key}Desc`)}</div>
<div className="rb:mt-6 rb:text-[#212332] rb:text-[16px] rb:leading-5 rb:font-medium">{t(`dashboard.${item.key}`)}</div>
<div className="rb:mt-2 rb:text-[#5B6167] rb:text-[12px] rb:font-regular">{t(`dashboard.${item.key}Desc`)}</div>
</div>
))}
</div>

View File

@@ -1,7 +1,20 @@
/*
* @Author: ZhaoYing
* @Date: 2026-02-03 17:15:33
* @Last Modified by: ZhaoYing
* @Last Modified time: 2026-02-03 17:15:33
*/
/**
* Recent Activity Component
* Displays recent memory processing activities with statistics
* Shows chunk count, statements, entity relations, and temporal data
*/
import { type FC, useEffect, useState } from 'react'
import clsx from 'clsx'
import { useTranslation } from 'react-i18next'
import { Skeleton } from 'antd';
import chunkCountIcon from '@/assets/images/home/chunk_count.svg';
import statementsCountIcon from '@/assets/images/home/statements_count.svg';
import tripletCountIcon from '@/assets/images/home/triplet_count.svg';
@@ -11,18 +24,30 @@ import Empty from '@/components/Empty';
import Card from './Card';
import { getRecentActivityStats } from '@/api/memory';
/**
* API response data structure
*/
interface Data {
latest_relative: string;
stats: RecentActivities;
}
/**
* Recent activity statistics
*/
interface RecentActivities {
"chunk_count": number; // 数据分块
"statements_count": number; // 语句提取
"triplet_entities_count": number; // 实体关系萃取-实体节点
"triplet_relations_count": number; // 实体关系萃取 - 关系连接
"temporal_count": number; // 时间萃取
/** Data chunk count */
"chunk_count": number;
/** Statement extraction count */
"statements_count": number;
/** Entity node count */
"triplet_entities_count": number;
/** Relation connection count */
"triplet_relations_count": number;
/** Temporal extraction count */
"temporal_count": number;
}
/** Activity list configuration */
const activityList = [
{ key: 'chunk_count', icon: chunkCountIcon },
{ key: 'statements_count', icon: statementsCountIcon },
@@ -40,7 +65,7 @@ const RecentActivity:FC = () => {
getRecentActivityList()
}, [])
// 最近活动统计
/** Fetch recent activity statistics */
const getRecentActivityList = () => {
setLoading(true)
getRecentActivityStats().then(res => {
@@ -58,13 +83,13 @@ const RecentActivity:FC = () => {
{loading
? <Skeleton />
: !recentActivities || Object.keys(recentActivities).length === 0
? <Empty url={activityEmpty} subTitle={t('dashboard.activityEmpty')} size={120} className="rb:mt-[45px] rb:mb-[81px]" />
? <Empty url={activityEmpty} subTitle={t('dashboard.activityEmpty')} size={120} className="rb:mt-11.25 rb:mb-20.25" />
: activityList.map((item, index) => (
<div key={item.key} className={clsx("rb:flex rb:justify-between rb:items-center rb:not-italic", {
'rb:mt-[24px]': index !== 0
'rb:mt-6': index !== 0
})}>
<div className="rb:flex rb:items-center rb:text-[#060419] rb:text-[16px] rb:font-medium">
<img className="rb:w-[40px] rb:h-[40px] rb:mr-[16px]" src={item.icon} />
<img className="rb:w-10 rb:h-10 rb:mr-4" src={item.icon} />
<div>
{t(`dashboard.${item.key}`)}
<div className="rb:text-[#5B6167] rb:text-[14px] rb:font-normal">

View File

@@ -1,7 +1,19 @@
/*
* @Author: ZhaoYing
* @Date: 2026-02-03 17:15:04
* @Last Modified by: ZhaoYing
* @Last Modified time: 2026-02-03 17:15:04
*/
/**
* Tag List Component
* Displays popular memory tags with frequency counts
*/
import { type FC, useEffect, useState } from 'react'
import clsx from 'clsx'
import { useTranslation } from 'react-i18next'
import { Skeleton } from 'antd';
import tagEmpty from '@/assets/images/home/tagEmpty.svg'
import Empty from '@/components/Empty';
import Card from './Card';
@@ -16,7 +28,7 @@ const TagList:FC = () => {
getTagList()
}, [])
// 热门记忆标签
/** Fetch popular memory tags */
const getTagList = () => {
setLoading(true)
getHotMemoryTags().then(res => {
@@ -30,12 +42,12 @@ const TagList:FC = () => {
{loading
? <Skeleton />
: !tagList || tagList.length === 0
? <Empty url={tagEmpty} title={t('dashboard.activityEmpty')} size={120} className="rb:mt-[36px] rb:mb-[81px]" />
: <div className="rb:gap-[12px] rb:flex rb:flex-wrap">
? <Empty url={tagEmpty} title={t('dashboard.activityEmpty')} size={120} className="rb:mt-9 rb:mb-20.25" />
: <div className="rb:gap-3 rb:flex rb:flex-wrap">
{tagList.map((item, index) => (
<div
key={item.name}
className={clsx("rb:pt-[6px] rb:pb-[6px] rb:pr-[23px] rb:pl-[20px] rb:border-1 rb:leading-[20px] rb:bg-white rb:rounded-[17px]", {
className={clsx("rb:pt-1.5 rb:pb-1.5 rb:pr-5.75 rb:pl-5 rb:border rb:leading-5 rb:bg-white rb:rounded-[17px]", {
'rb:border-[rgba(21,94,239,0.4)] rb:text-[#155EEF]': index % 3 === 0,
'rb:border-[rgba(255,138,76,0.4)] rb:text-[#FF5D34]': index % 3 === 1,
'rb:border-[rgba(54,159,33,0.4)] rb:text-[#369F21]': index % 3 === 2,

View File

@@ -1,13 +1,26 @@
/*
* @Author: ZhaoYing
* @Date: 2026-02-03 17:28:07
* @Last Modified by: ZhaoYing
* @Last Modified time: 2026-02-03 17:28:07
*/
/**
* Top Card List Component
* Displays dashboard summary cards for key metrics
* Shows total memory capacity, applications, knowledge bases, and API calls
*/
import { type FC } from 'react'
import { useTranslation } from 'react-i18next'
import totalMemoryCapacity from '@/assets/images/home/totalMemoryCapacity.svg';
import userMemory from '@/assets/images/home/userMemory.svg';
import knowledgeBaseCount from '@/assets/images/home/knowledgeBaseCount.svg';
import apiCallCount from '@/assets/images/home/apiCallCount.svg';
import styles from './index.module.css'
import clsx from 'clsx';
import type { DashboardData } from '../../index'
/** Card configuration with styling */
const list = [
{
key: 'totalMemoryCapacity',
@@ -46,10 +59,14 @@ const list = [
background: 'linear-gradient( 180deg, #F8F6F5 0%, #FAFDFF 100%)',
},
]
/**
* Component props
* @param data - Dashboard statistics data
*/
const TopCardList: FC<{data?: DashboardData}> = ({ data }) => {
const { t } = useTranslation()
return (
<div className="rb:grid rb:grid-cols-4 rb:gap-[16px]">
<div className="rb:grid rb:grid-cols-4 rb:gap-4">
{list.map((item) => {
return (
<div
@@ -65,11 +82,7 @@ const TopCardList: FC<{data?: DashboardData}> = ({ data }) => {
</div>
<div className={styles.content}>
{data?.[item.key] || item.value || 0}
<div className={styles.contentRight}>
{item.trendValue && <div className={clsx(styles.trend, styles[item.trend])}>{item.trendValue}</div>}
{item.trendDesc && <div>{t(`dashboard.${item.trendDesc}`)}</div>}
</div>
{data?.[item.key as keyof DashboardData] || 0}
</div>
</div>
)

View File

@@ -1,5 +1,16 @@
/*
* @Author: ZhaoYing
* @Date: 2026-02-03 17:12:43
* @Last Modified by: ZhaoYing
* @Last Modified time: 2026-02-03 17:26:04
*/
/**
* Home Dashboard Page
* Main dashboard displaying memory statistics, charts, activities, and quick operations
*/
import { useEffect, useState } from 'react';
import { Row, Col, Space } from 'antd';
import { Row, Col } from 'antd';
import TopCardList from './components/TopCardList'
import LineCard from './components/LineCard'
@@ -9,6 +20,9 @@ import RecentActivity from './components/RecentActivity'
import TagList from './components/TagList'
import QuickOperation from './components/QuickOperation'
/**
* Dashboard statistics data
*/
export interface DashboardData {
totalMemoryCapacity?: number;
application?: number;
@@ -25,12 +39,12 @@ const Home = () => {
const [memoryIncrement, setMemoryIncrement] = useState<Array<{ updated_at: string; total_num: number; }>>([]);
const [limit, setLimit] = useState(7);
// 模拟API获取数据
/** Simulate API data fetch */
useEffect(() => {
getData()
getKnowledgeTypeDistribution()
}, []);
// 记忆总量 / 应用数量 / 知识库数量 / API调用次数
/** Fetch memory total, app count, knowledge base count, API call count */
const getData = () => {
getDashboardData().then(res => {
const response = res as {
@@ -49,16 +63,16 @@ const Home = () => {
}
}
const { storage_type = 'neo4j' } = response || {}
const responseData = response[storage_type + '_data'] || {}
const responseData = storage_type === 'neo4j' ? response.neo4j_data : response.rag_data
setDashboardData({
totalMemoryCapacity: responseData.total_memory || 0,
application: responseData.total_app || 0,
knowledgeBaseCount: responseData.total_knowledge || 0,
apiCallCount: responseData.total_api_call || 0
totalMemoryCapacity: responseData?.total_memory || 0,
application: responseData?.total_app || 0,
knowledgeBaseCount: responseData?.total_knowledge || 0,
apiCallCount: responseData?.total_api_call || 0
})
})
}
// 知识库类型分布 / 知识库数量
/** Fetch knowledge base type distribution */
const getKnowledgeTypeDistribution = () => {
setLoading({
...loading,
@@ -86,7 +100,7 @@ const Home = () => {
})
})
}
// 记忆增长趋势
/** Fetch memory growth trend data */
const getMemoryIncrementData = () => {
getMemoryIncrement(limit).then(res => {
const response = res as { updated_at: string; total_num: number; }[]
@@ -106,12 +120,10 @@ const Home = () => {
}
return (
<div className="rb:pb-[24px]">
{/* 统计卡片 */}
<div className="rb:pb-6">
<TopCardList data={dashboardData} />
<Row className="rb:mt-[16px]" gutter={16}>
{/* 记忆增长趋势 */}
<Row className="rb:mt-4" gutter={16}>
<Col span={12}>
<LineCard
chartData={memoryIncrement}
@@ -121,7 +133,6 @@ const Home = () => {
seriesList={['total_num']}
/>
</Col>
{/* 知识库类型分布 */}
<Col span={12}>
<PieCard
loading={loading.knowledgeTypeDistribution}
@@ -130,20 +141,17 @@ const Home = () => {
</Col>
</Row>
<Row className="rb:mt-[16px]" gutter={16}>
<Row className="rb:mt-4" gutter={16}>
<Col span={12}>
{/* 最近记忆活动 */}
<RecentActivity />
</Col>
<Col span={12}>
{/* 热门记忆标签 */}
<TagList />
</Col>
</Row>
<Row className="rb:mt-[16px]" gutter={16}>
<Row className="rb:mt-4" gutter={16}>
<Col span={24}>
{/* 快速操作 */}
<QuickOperation />
</Col>
</Row>