完善客户端模块与工作区能力
Some checks failed
Electron E2E / Electron E2E (macos-latest) (push) Has been cancelled
Electron E2E / Electron E2E (ubuntu-latest) (push) Has been cancelled
Electron E2E / Electron E2E (windows-latest) (push) Has been cancelled

This commit is contained in:
inman
2026-08-13 19:45:30 +08:00
parent 0148b91a15
commit 22add3f01f
97 changed files with 4756 additions and 3226 deletions

View File

@@ -1,8 +1,9 @@
import { ArrowRight } from 'lucide-react';
import { useNavigate } from 'react-router-dom';
import moduleCanvasImage from '@/assets/module-canvas.jpg';
import moduleCanvasImage from '@/assets/module-canvas-neon.jpg';
import moduleGameImage from '@/assets/module-game.jpg';
import moduleLearningImage from '@/assets/module-learning.jpg';
import moduleRobotImage from '@/assets/module-robot.jpg';
import logoWordmarkSource from '@/assets/makelore-wordmark-source.png';
import { aiModules, type AiModuleId } from '@/lib/ai-modules';
import { getAuthUserDisplayName } from '@/lib/auth-user-display';
@@ -13,6 +14,7 @@ const moduleSelectionContent: Record<AiModuleId, { label: string; image: string;
programming: { label: 'Code 编程', image: moduleGameImage, imageAlt: '游戏创作工作台' },
painting: { label: 'Canvas 设计', image: moduleCanvasImage, imageAlt: '数位板设计创作' },
learning: { label: 'Learning 学习', image: moduleLearningImage, imageAlt: '数学科技宇宙' },
robot: { label: 'Robot 机器', image: moduleRobotImage, imageAlt: '青少年管理机器人硬件与设备绑定' },
};
export function ModuleSelection({ authRequired = true }: { authRequired?: boolean }) {
@@ -48,7 +50,11 @@ export function ModuleSelection({ authRequired = true }: { authRequired?: boolea
<h1 className="mt-3 whitespace-nowrap text-[clamp(2rem,4vw,4rem)] font-semibold leading-[1.02] tracking-[-0.055em]"></h1>
</section>
<section aria-label="AI 模块列表" className="grid grid-cols-1 justify-items-center gap-5 sm:grid-cols-2 lg:grid-cols-3">
<section
data-testid="ai-module-options"
aria-label="AI 模块列表"
className="module-selection-options"
>
{aiModules.map((module) => {
const content = moduleSelectionContent[module.id];
return (
@@ -60,28 +66,28 @@ export function ModuleSelection({ authRequired = true }: { authRequired?: boolea
onClick={() => openModule(module.route)}
aria-label={`${content.label}${module.description}`}
className={cn(
'module-option-card group motion-press flex h-[254px] w-full max-w-[190px] flex-col justify-end rounded-lg border border-transparent bg-transparent p-0 text-left shadow-none disabled:cursor-not-allowed disabled:bg-transparent disabled:text-muted-foreground/70 disabled:opacity-75',
'module-option-card module-option-card-horizontal group motion-press flex w-full min-w-0 items-stretch rounded-lg border border-transparent bg-transparent p-0 text-left shadow-none disabled:cursor-not-allowed disabled:bg-transparent disabled:text-muted-foreground/70 disabled:opacity-75',
!module.enabled && 'module-option-card-disabled',
)}
>
<div className="module-option-card-surface relative z-10 flex h-full w-full flex-col overflow-hidden rounded-lg bg-background">
<div className="relative h-[118px] shrink-0">
<div className="module-option-card-surface relative z-10 flex h-full w-full overflow-hidden rounded-lg bg-background">
<div className="module-option-card-image relative shrink-0">
<img
src={content.image}
alt={content.imageAlt}
className={cn('h-full w-full object-cover', !module.enabled && 'grayscale')}
className={cn('module-option-card-image-media h-full w-full object-cover', !module.enabled && 'grayscale')}
draggable="false"
/>
{module.enabled ? (
<span className="absolute right-2 top-2 flex h-8 w-8 items-center justify-center rounded-full bg-background/90 text-foreground shadow-sm">
<ArrowRight className="h-5 w-5" strokeWidth={2.6} />
<span className="module-option-card-arrow absolute flex items-center justify-center rounded-full bg-background/90 text-foreground shadow-sm">
<ArrowRight className="module-option-card-arrow-icon" strokeWidth={2.6} />
</span>
) : null}
</div>
<div className="min-h-0 flex-1 p-3">
<p className="text-xl font-medium tracking-[-0.02em]">{content.label}</p>
<p className="mt-2 text-sm font-medium leading-6 text-muted-foreground">{module.description}</p>
{!module.enabled ? <p className="mt-2 text-xs font-semibold"></p> : null}
<div className="module-option-card-content min-h-0 flex-1">
<p className="module-option-card-title font-medium tracking-[-0.02em]">{content.label}</p>
<p className="module-option-card-description font-medium text-muted-foreground">{module.description}</p>
{!module.enabled ? <p className="module-option-card-status font-semibold"></p> : null}
</div>
</div>
</button>