🌐 chore: translate non-English comments to English in memory module (#12547)

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
LobeHub Bot
2026-03-01 14:58:23 +08:00
committed by GitHub
parent c1d2e761fe
commit 5e3a8146d1
6 changed files with 67 additions and 67 deletions

View File

@@ -7,22 +7,22 @@ import * as THREE from 'three';
import { type QueryTagsResult } from '@/database/models/userMemory';
import UserAvatar from '@/features/User/UserAvatar';
// 配置常量
// Configuration constants
const CONFIG = {
// 连接线数量系数 (实际数量 = 标签数 * 系数)
// Connection line count ratio (actual count = tag count * ratio)
CONNECTION_RATIO: 0.8,
// 最大连接线数量
// Maximum number of connection lines
MAX_CONNECTIONS: 40,
MAX_DURATION: 8,
// 连接线生命周期范围(秒)
// Connection line lifetime range (seconds)
MIN_DURATION: 2,
// 流动粒子数量(每条线)
// Number of flowing particles (per line)
PARTICLES_PER_LINE: 3,
// 新连接线生成概率(每次检查)
// Probability of generating new connection lines (per check)
SPAWN_PROBABILITY: 0.3,
// 检查间隔(秒)
// Check interval (seconds)
UPDATE_INTERVAL: 0.1,
} as const;
@@ -77,7 +77,7 @@ const Word = memo<WordProps>(
);
},
(prevProps, nextProps) => {
// 只在 positiontext、size 改变时才重新渲染
// Only re-render when position, text, or size changes
return (
prevProps.position === nextProps.position &&
prevProps.text === nextProps.text &&
@@ -92,7 +92,7 @@ interface ParticleProps {
start: THREE.Vector3;
}
// 流动的光点粒子
// Flowing light point particles
const FlowingParticle = memo<ParticleProps>(
({ start, end, index }) => {
const theme = useTheme();
@@ -105,14 +105,14 @@ const FlowingParticle = memo<ParticleProps>(
const speed = 0.5 + index * 0.1;
const progress = ((time * speed + offset) % (Math.PI * 2)) / (Math.PI * 2);
// 沿着线条移动
// Move along the line
ref.current.position.lerpVectors(start, end, progress);
// 脉冲效果
// Pulse effect
const pulse = Math.sin(time * 3 + offset) * 0.5 + 1;
ref.current.scale.setScalar(pulse * 0.3);
// 渐变透明度(两端透明,中间明亮)
// Gradient opacity (transparent at both ends, bright in the middle)
const alpha = Math.sin(progress * Math.PI) * 0.8;
if (ref.current.material instanceof THREE.MeshBasicMaterial) {
ref.current.material.opacity = alpha;
@@ -128,7 +128,7 @@ const FlowingParticle = memo<ParticleProps>(
);
},
(prevProps, nextProps) => {
// 只在 start、end 引用改变时才重新渲染
// Only re-render when start or end reference changes
return (
prevProps.start === nextProps.start &&
prevProps.end === nextProps.end &&
@@ -151,34 +151,34 @@ const ConnectionLine = memo<ConnectionLineProps>(
const lineRef = useRef<THREE.Line>(null);
const glowRef = useRef<THREE.Line>(null);
// 为每条线生成独特的相位偏移
// Generate unique phase offset for each line
const phaseOffset = useMemo(() => Math.random() * Math.PI * 2, []);
useFrame((state) => {
const time = state.clock.getElapsedTime();
// 在内部计算 lifeProgress
// Calculate lifeProgress internally
const elapsed = time - birthTime;
const lifeProgress = Math.min(Math.max(elapsed / duration, 0), 1);
if (lineRef.current) {
// 淡入淡出效果:基于生命周期进度
// Fade in/out effect: based on lifecycle progress
let lifeCycleOpacity = 1;
if (lifeProgress < 0.15) {
// 淡入阶段 (0-15%)
// Fade-in phase (0-15%)
lifeCycleOpacity = lifeProgress / 0.15;
} else if (lifeProgress > 0.85) {
// 淡出阶段 (85%-100%)
// Fade-out phase (85%-100%)
lifeCycleOpacity = (1 - lifeProgress) / 0.15;
}
// 主线条:波动透明度 * 生命周期透明度
// Main line: oscillating opacity * lifecycle opacity
const baseOpacity = (Math.sin(time * 1.5 + phaseOffset) * 0.2 + 0.4) * lifeCycleOpacity;
(lineRef.current.material as THREE.LineBasicMaterial).opacity = baseOpacity;
}
if (glowRef.current) {
// 光晕效果
// Glow effect
let lifeCycleOpacity = 1;
const elapsed = time - birthTime;
const lifeProgress = Math.min(Math.max(elapsed / duration, 0), 1);
@@ -194,12 +194,12 @@ const ConnectionLine = memo<ConnectionLineProps>(
}
});
// 创建渐变色线条
// Create gradient color lines
const { mainLine, glowLine } = useMemo(() => {
const points = [start, end];
const geom = new THREE.BufferGeometry().setFromPoints(points);
// 创建颜色渐变
// Create color gradient
const colorArray = new Float32Array(6); // 2 points * 3 (RGB)
const color1 = new THREE.Color(theme.colorPrimary);
const color2 = new THREE.Color(theme.colorInfo);
@@ -213,7 +213,7 @@ const ConnectionLine = memo<ConnectionLineProps>(
geom.setAttribute('color', new THREE.BufferAttribute(colorArray, 3));
// 创建主线条
// Create main line
const mainMaterial = new THREE.LineBasicMaterial({
color: theme.colorPrimary,
opacity: 0.4,
@@ -222,7 +222,7 @@ const ConnectionLine = memo<ConnectionLineProps>(
});
const main = new THREE.Line(geom, mainMaterial);
// 创建光晕线条
// Create glow line
const glowMaterial = new THREE.LineBasicMaterial({
blending: THREE.AdditiveBlending,
color: theme.colorInfo,
@@ -234,7 +234,7 @@ const ConnectionLine = memo<ConnectionLineProps>(
return { geometry: geom, glowLine: glow, mainLine: main };
}, [start, end, theme.colorPrimary, theme.colorInfo]);
// 生成流动粒子
// Generate flowing particles
const particles = useMemo(() => {
return Array.from({ length: CONFIG.PARTICLES_PER_LINE }, (_, i) => (
<FlowingParticle end={end} index={i} key={`particle-${index}-${i}`} start={start} />
@@ -243,20 +243,20 @@ const ConnectionLine = memo<ConnectionLineProps>(
return (
<group>
{/* 主线条 */}
{/* Main line */}
<primitive object={mainLine} ref={lineRef} />
{/* 光晕层 - 更粗更透明 */}
{/* Glow layer - thicker and more transparent */}
<primitive object={glowLine} ref={glowRef} />
{/* 流动粒子 */}
{/* Flowing particles */}
{particles}
</group>
);
},
(prevProps, nextProps) => {
// 只在 start、end 引用改变时才重新渲染
// birthTime duration 对于同一个连接应该是不变的
// Only re-render when start or end reference changes
// birthTime and duration should be unchanged for the same connection
return (
prevProps.start === nextProps.start &&
prevProps.end === nextProps.end &&
@@ -266,7 +266,7 @@ const ConnectionLine = memo<ConnectionLineProps>(
},
);
// 中心头像组件
// Center avatar component
const CenterAvatar = memo(() => {
return (
<Html
@@ -289,7 +289,7 @@ interface CloudProps {
const Cloud = memo<CloudProps>(({ tags, radius = 20 }) => {
const groupRef = useRef<THREE.Group>(null);
// 计算标签位置和大小
// Calculate tag positions and sizes
const wordsData = useMemo(() => {
if (!tags.length) return [];
@@ -299,13 +299,13 @@ const Cloud = memo<CloudProps>(({ tags, radius = 20 }) => {
const spherical = new THREE.Spherical();
const data = tags.map((tag, i) => {
// 使用黄金角螺旋分布算法,使标签在球面上均匀分布
// Use golden angle spiral distribution algorithm to evenly distribute tags on a sphere
const phi = Math.acos(1 - (2 * (i + 0.5)) / tags.length);
const theta = Math.PI * (1 + Math.sqrt(5)) * i;
const position = new THREE.Vector3().setFromSpherical(spherical.set(radius, phi, theta));
// 根据 count 计算字体大小 (范围: 1.5 - 4)
// Calculate font size based on count (range: 1.5 - 4)
const normalizedCount = (tag.count - minCount) / countRange;
const size = 1.5 + normalizedCount * 2.5;
@@ -319,13 +319,13 @@ const Cloud = memo<CloudProps>(({ tags, radius = 20 }) => {
return data;
}, [tags, radius]);
// 连接线数量
// Number of connection lines
const connectionCount = useMemo(() => {
if (wordsData.length < 2) return 0;
return Math.min(Math.floor(wordsData.length * CONFIG.CONNECTION_RATIO), CONFIG.MAX_CONNECTIONS);
}, [wordsData.length]);
// 动态连接线状态
// Dynamic connection line state
interface ConnectionState {
birthTime: number;
duration: number;
@@ -340,7 +340,7 @@ const Cloud = memo<CloudProps>(({ tags, radius = 20 }) => {
const currentTime = useRef(0);
const connectionIdCounter = useRef(0);
// 生成一个随机连接
// Generate a random connection
const generateRandomConnection = useMemo(
() => (currentTime: number) => {
if (wordsData.length < 2) return null;
@@ -356,11 +356,11 @@ const Cloud = memo<CloudProps>(({ tags, radius = 20 }) => {
if (attempts >= 50) return null;
// 随机持续时间
// Random duration
const duration =
CONFIG.MIN_DURATION + Math.random() * (CONFIG.MAX_DURATION - CONFIG.MIN_DURATION);
// 生成唯一 ID
// Generate unique ID
connectionIdCounter.current += 1;
const id = `conn-${connectionIdCounter.current}`;
@@ -375,24 +375,24 @@ const Cloud = memo<CloudProps>(({ tags, radius = 20 }) => {
[wordsData],
);
// wordsData connectionCount 变化时重置初始化状态
// Reset initialization state when wordsData or connectionCount changes
useEffect(() => {
isInitialized.current = false;
setConnections([]);
}, [connectionCount]);
// 动态更新连接线
// Dynamically update connection lines
useFrame((state) => {
const time = state.clock.getElapsedTime();
currentTime.current = time;
// 初始化连接线(在第一帧)
// Initialize connection lines (on first frame)
if (!isInitialized.current && connectionCount > 0) {
isInitialized.current = true;
const initialConnections: ConnectionState[] = [];
for (let i = 0; i < connectionCount; i++) {
// 给初始连接线随机的起始时间,制造交错效果
// Give initial connection lines random start times to create a staggered effect
const connection = generateRandomConnection(time - Math.random() * 2);
if (connection) {
initialConnections.push(connection);
@@ -404,18 +404,18 @@ const Cloud = memo<CloudProps>(({ tags, radius = 20 }) => {
return;
}
// 定期检查
// Periodic check
if (time - lastUpdateTime.current > CONFIG.UPDATE_INTERVAL) {
lastUpdateTime.current = time;
setConnections((prev) => {
// 过滤掉已经过期的连接
// Filter out expired connections
const active = prev.filter((conn) => time - conn.birthTime < conn.duration);
// 如果连接数量不足,随机添加新连接
// If there are not enough connections, randomly add new ones
const needed = connectionCount - active.length;
if (
needed > 0 && // 随机决定这次是否添加新连接
needed > 0 && // Randomly decide whether to add a new connection this time
Math.random() < CONFIG.SPAWN_PROBABILITY
) {
const newConnection = generateRandomConnection(time);
@@ -428,7 +428,7 @@ const Cloud = memo<CloudProps>(({ tags, radius = 20 }) => {
});
}
// 自动旋转动画
// Auto-rotation animation
if (groupRef.current) {
groupRef.current.rotation.y += 0.001;
groupRef.current.rotation.x += 0.0005;
@@ -437,10 +437,10 @@ const Cloud = memo<CloudProps>(({ tags, radius = 20 }) => {
return (
<group ref={groupRef} rotation={[0.3, 0.5, 0.1]}>
{/* 中心用户头像 */}
{/* Center user avatar */}
<CenterAvatar />
{/* 渲染连线 */}
{/* Render connection lines */}
{connections.map((connection, index) => (
<ConnectionLine
birthTime={connection.birthTime}
@@ -451,7 +451,7 @@ const Cloud = memo<CloudProps>(({ tags, radius = 20 }) => {
start={connection.start}
/>
))}
{/* 渲染标签 */}
{/* Render tags */}
{wordsData.map((word, index) => (
<Word key={`word-${index}`} {...word} />
))}

View File

@@ -1,7 +1,7 @@
import { createStaticStyles } from 'antd-style';
export const styles = createStaticStyles(({ css, cssVar }) => ({
// 主容器
// Main container
mainContainer: css`
position: relative;
overflow: hidden;

View File

@@ -43,18 +43,18 @@ const ContextsArea = memo(() => {
{ label: t('filter.sort.scoreUrgency'), value: 'scoreUrgency' },
];
// 转换 sortcapturedAt 转为 undefined(后端默认)
// Convert sort: capturedAt becomes undefined (backend default)
const apiSort =
sortValue === 'capturedAt' ? undefined : (sortValue as 'scoreImpact' | 'scoreUrgency');
// 当搜索或排序变化时重置列表
// Reset list when search or sort changes
useEffect(() => {
if (!apiSort) return;
const sort = viewMode === 'grid' ? apiSort : undefined;
resetContextsList({ q: searchValue || undefined, sort });
}, [searchValue, apiSort, viewMode]);
// 调用 SWR hook 获取数据
// Call SWR hook to fetch data
const { isLoading } = useFetchContexts({
page: contextsPage,
pageSize: 12,
@@ -77,7 +77,7 @@ const ContextsArea = memo(() => {
[setSortValueRaw],
);
// 显示 loading:搜索/重置中 或 首次加载中
// Show loading: during search/reset or initial load
const showLoading = contextsSearchLoading || !contextsInit;
return (

View File

@@ -42,17 +42,17 @@ const ExperiencesArea = memo(() => {
{ label: t('filter.sort.scoreConfidence'), value: 'scoreConfidence' },
];
// 转换 sortcapturedAt 转为 undefined(后端默认)
// Convert sort: capturedAt becomes undefined (backend default)
const apiSort = sortValue === 'capturedAt' ? undefined : (sortValue as 'scoreConfidence');
// 当搜索或排序变化时重置列表
// Reset list when search or sort changes
useEffect(() => {
if (!apiSort) return;
const sort = viewMode === 'grid' ? apiSort : undefined;
resetExperiencesList({ q: searchValue || undefined, sort });
}, [searchValue, apiSort, viewMode]);
// 调用 SWR hook 获取数据
// Call SWR hook to fetch data
const { isLoading } = useFetchExperiences({
page: experiencesPage,
pageSize: 12,
@@ -75,7 +75,7 @@ const ExperiencesArea = memo(() => {
[setSortValueRaw],
);
// 显示 loading:搜索/重置中 或 首次加载中
// Show loading: during search/reset or initial load
const showLoading = experiencesSearchLoading || !experiencesInit;
return (

View File

@@ -37,13 +37,13 @@ const IdentitiesArea = memo(() => {
const useFetchIdentities = useUserMemoryStore((s) => s.useFetchIdentities);
const resetIdentitiesList = useUserMemoryStore((s) => s.resetIdentitiesList);
// 当搜索或类型变化时重置列表
// Reset list when search or type filter changes
useEffect(() => {
const types = typeFilter === 'all' ? undefined : [typeFilter as TypesEnum];
resetIdentitiesList({ q: searchValue || undefined, types });
}, [searchValue, typeFilter]);
// 调用 SWR hook 获取数据
// Call SWR hook to fetch data
const { isLoading } = useFetchIdentities({
page: identitiesPage,
pageSize: 12,
@@ -66,7 +66,7 @@ const IdentitiesArea = memo(() => {
[setTypeFilterRaw],
);
// 显示 loading:搜索/重置中 或 首次加载中
// Show loading: during search/reset or initial load
const showLoading = identitiesSearchLoading || !identitiesInit;
return (

View File

@@ -42,17 +42,17 @@ const PreferencesArea = memo(() => {
{ label: t('filter.sort.scorePriority'), value: 'scorePriority' },
];
// 转换 sortcapturedAt 转为 undefined(后端默认)
// Convert sort: capturedAt becomes undefined (backend default)
const apiSort = sortValue === 'capturedAt' ? undefined : (sortValue as 'scorePriority');
// 当搜索或排序变化时重置列表
// Reset list when search or sort changes
useEffect(() => {
if (!apiSort) return;
const sort = viewMode === 'grid' ? apiSort : undefined;
resetPreferencesList({ q: searchValue || undefined, sort });
}, [searchValue, apiSort, viewMode]);
// 调用 SWR hook 获取数据
// Call SWR hook to fetch data
const { isLoading } = useFetchPreferences({
page: preferencesPage,
pageSize: 12,
@@ -75,7 +75,7 @@ const PreferencesArea = memo(() => {
[setSortValueRaw],
);
// 显示 loading:搜索/重置中 或 首次加载中
// Show loading: during search/reset or initial load
const showLoading = preferencesSearchLoading || !preferencesInit;
return (