feat: update Makelore modules and conversations
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-07-31 10:08:41 +08:00
parent b8ca3f8eea
commit 80e8386fa6
175 changed files with 8036 additions and 10581 deletions

View File

@@ -1,14 +1,18 @@
import { ArrowRight } from 'lucide-react';
import { useNavigate } from 'react-router-dom';
import logoSvg from '@/assets/logo.svg';
import moduleCanvasImage from '@/assets/module-canvas.jpg';
import moduleGameImage from '@/assets/module-game.jpg';
import moduleLearningImage from '@/assets/module-learning.jpg';
import logoWordmarkSource from '@/assets/makelore-wordmark-source.png';
import { aiModules, type AiModuleId } from '@/lib/ai-modules';
import { getAuthUserDisplayName } from '@/lib/auth-user-display';
import { cn } from '@/lib/utils';
import { useAuthStore } from '@/stores/auth';
const moduleToneClasses: Record<AiModuleId, { icon: string; badge: string }> = {
programming: { icon: 'bg-[#E9EFF5] text-[#3A5578]', badge: 'bg-[#E9EFF5] text-[#3A5578]' },
painting: { icon: 'bg-[#FDE8E1] text-[#F26A3D]', badge: 'bg-[#FDE8E1] text-[#B94624]' },
const moduleSelectionContent: Record<AiModuleId, { label: string; image: string; imageAlt: string }> = {
programming: { label: 'Code 编程', image: moduleGameImage, imageAlt: '游戏创作工作台' },
painting: { label: 'Canvas 设计', image: moduleCanvasImage, imageAlt: '数位板设计创作' },
learning: { label: 'Learning 学习', image: moduleLearningImage, imageAlt: '数学科技宇宙' },
};
export function ModuleSelection() {
@@ -17,32 +21,26 @@ export function ModuleSelection() {
const userDisplayName = getAuthUserDisplayName(authUser);
return (
<main data-testid="ai-module-selection-page" className="min-h-[100dvh] overflow-auto bg-white px-4 py-6 text-[#26384D] sm:px-8 sm:py-10">
<main data-testid="ai-module-selection-page" className="relative min-h-[100dvh] overflow-auto bg-background px-4 py-6 text-foreground sm:px-8 sm:py-10">
<div className="mx-auto flex min-h-[calc(100dvh-3rem)] max-w-6xl flex-col">
<header className="flex items-center justify-between gap-4">
<div className="flex items-center gap-3">
<img src={logoSvg} alt="Makelore" className="h-9 w-12 object-contain" />
<div>
<p className="text-sm font-bold tracking-[-0.01em]">Makelore</p>
<p className="text-xs font-medium text-[#68788B]"></p>
</div>
</div>
<span className="rounded-full border border-[#D8E0E8] bg-[#F6F8FA] px-3 py-1 text-xs font-semibold text-[#68788B]">Makelore 2.0</span>
<header
data-testid="module-selection-drag-region"
className="drag-region absolute inset-x-0 top-0 flex h-16 items-start justify-end px-6 pt-6 sm:px-8 sm:pt-8"
>
<img src={logoWordmarkSource} alt="Makelore" className="h-8 w-40 object-cover object-center" draggable="false" />
</header>
<div className="grid flex-1 items-center gap-8 py-12 lg:grid-cols-[1fr_1.4fr] lg:gap-16">
<section className="max-w-md">
<p className="text-sm font-semibold tracking-[0.08em] text-[#68788B]">
<div className="grid flex-1 items-center gap-8 py-12 lg:grid-cols-[minmax(0,1fr)_minmax(0,1.35fr)] lg:gap-12">
<section className="min-w-0">
<p className="text-sm font-semibold tracking-[0.08em] text-muted-foreground">
{userDisplayName ? `${userDisplayName},欢迎回来!` : '欢迎回来!'}
</p>
<h1 className="mt-3 text-4xl font-bold leading-tight tracking-[-0.04em]"></h1>
<p className="mt-4 max-w-sm text-sm leading-6 text-[#68788B]"></p>
<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 gap-3">
<section aria-label="AI 模块列表" className="grid grid-cols-1 justify-items-center gap-5 sm:grid-cols-2 lg:grid-cols-3">
{aiModules.map((module) => {
const tone = moduleToneClasses[module.id];
const ModuleIcon = module.Icon;
const content = moduleSelectionContent[module.id];
return (
<button
key={module.id}
@@ -52,27 +50,32 @@ export function ModuleSelection() {
onClick={() => {
if (module.route) navigate(module.route);
}}
aria-label={`${content.label}${module.description}`}
className={cn(
'group flex min-h-28 w-full items-center justify-between gap-5 rounded-2xl border border-[#D8E0E8] bg-white p-5 text-left shadow-[0_10px_30px_rgba(38,56,77,0.06)] transition-[border-color,background-color,transform,box-shadow,opacity] hover:-translate-y-0.5 hover:border-[#3A5578] hover:bg-[#FAFBFC] hover:shadow-[0_16px_40px_rgba(38,56,77,0.10)] active:translate-y-0 disabled:cursor-not-allowed disabled:bg-[#EEF3F7] disabled:text-[#8A98A8] disabled:opacity-75',
'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.enabled && 'module-option-card-disabled',
)}
>
<span className="flex min-w-0 items-center gap-4">
<span className={cn('flex h-14 w-14 shrink-0 items-center justify-center rounded-xl', tone.icon)}>
<ModuleIcon className="h-7 w-7" strokeWidth={2.4} />
</span>
<span className="min-w-0">
<span className="flex flex-wrap items-center gap-2">
<span className="text-xl font-bold tracking-[-0.02em]">{module.title}</span>
<span className={cn('rounded-full px-2.5 py-1 text-[11px] font-semibold', tone.badge)}>{module.subtitle}</span>
</span>
<span className="mt-2 block text-sm font-medium leading-6 text-[#68788B]">{module.description}</span>
</span>
</span>
{module.enabled ? (
<ArrowRight className="h-6 w-6 shrink-0 transition-transform group-hover:translate-x-1" strokeWidth={2.6} />
) : (
<span className="shrink-0 text-xs font-black"></span>
)}
<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">
<img
src={content.image}
alt={content.imageAlt}
className={cn('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>
) : 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>
</div>
</button>
);
})}