fix(web): Web 检查 - 格式化拆分模块并修正源码断言
拆分出的前端模块未按 Prettier 格式化导致 CI 格式检查失败;源码断言改为忽略空白差异,导演台引导组件恢复别名导入。同时移除误提交的分析草稿、pnpm 锁文件和调试测试。
This commit is contained in:
@@ -18,13 +18,19 @@ export const creationEmptyBannerFrames = [
|
||||
|
||||
export function CreationEmptyBanner() {
|
||||
const brandName = useAppearanceStore((state) => state.appearance.brandName);
|
||||
return <div className="creation-empty-art" aria-hidden="true">
|
||||
{creationEmptyBannerFrames.map((frame, index) => <figure key={frame.caption} className={`creation-empty-art-frame ${index === 1 ? "is-main" : index === 0 ? "is-back" : "is-front"}`}>
|
||||
<img src={frame.src} alt="" />
|
||||
<span>{frame.caption}</span>
|
||||
</figure>)}
|
||||
<span className="creation-empty-art-caption"><span>{brandName}</span>把每一帧,交给镜头导演</span>
|
||||
</div>;
|
||||
return (
|
||||
<div className="creation-empty-art" aria-hidden="true">
|
||||
{creationEmptyBannerFrames.map((frame, index) => (
|
||||
<figure key={frame.caption} className={`creation-empty-art-frame ${index === 1 ? "is-main" : index === 0 ? "is-back" : "is-front"}`}>
|
||||
<img src={frame.src} alt="" />
|
||||
<span>{frame.caption}</span>
|
||||
</figure>
|
||||
))}
|
||||
<span className="creation-empty-art-caption">
|
||||
<span>{brandName}</span>把每一帧,交给镜头导演
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const creationEmptySuggestions: Array<{ mode: CreationMode; icon: typeof Clapperboard; title: string; hint: string; prompt: string; openLibrary?: boolean }> = [
|
||||
@@ -37,61 +43,108 @@ export const creationEmptySuggestions: Array<{ mode: CreationMode; icon: typeof
|
||||
export function CreationEmptySuggest({ onStartPrompt, onOpenLibrary }: { onStartPrompt: (mode: CreationMode, prompt: string) => void; onOpenLibrary: () => void }) {
|
||||
const reducedMotion = useReducedMotion();
|
||||
const [hovered, setHovered] = useState<string | null>(null);
|
||||
return <LayoutGroup id="creation-empty-suggest">
|
||||
<div className="creation-empty-suggest" aria-label="快捷创作入口">
|
||||
{creationEmptySuggestions.map((item) => {
|
||||
const Icon = item.icon;
|
||||
const start = () => {
|
||||
if (item.openLibrary) onOpenLibrary();
|
||||
else onStartPrompt(item.mode, item.prompt);
|
||||
};
|
||||
return <motion.button
|
||||
key={item.title}
|
||||
type="button"
|
||||
className="suggest-card"
|
||||
onClick={start}
|
||||
onHoverStart={() => setHovered(item.title)}
|
||||
onHoverEnd={() => setHovered(null)}
|
||||
whileHover={reducedMotion ? undefined : { y: -2 }}
|
||||
transition={aceternityMotion.spring.surface}
|
||||
>
|
||||
{hovered === item.title ? (
|
||||
<motion.span
|
||||
layoutId="creation-suggest-hover"
|
||||
className="suggest-card-hover"
|
||||
aria-hidden
|
||||
transition={reducedMotion ? { duration: 0 } : aceternityMotion.spring.surface}
|
||||
/>
|
||||
) : null}
|
||||
<span className="library-icon-tile suggest-icon"><Icon size={18} strokeWidth={2} /></span>
|
||||
<span className="suggest-copy">
|
||||
<strong>{item.title}</strong>
|
||||
<span>{item.hint}</span>
|
||||
</span>
|
||||
</motion.button>;
|
||||
})}
|
||||
</div>
|
||||
</LayoutGroup>;
|
||||
return (
|
||||
<LayoutGroup id="creation-empty-suggest">
|
||||
<div className="creation-empty-suggest" aria-label="快捷创作入口">
|
||||
{creationEmptySuggestions.map((item) => {
|
||||
const Icon = item.icon;
|
||||
const start = () => {
|
||||
if (item.openLibrary) onOpenLibrary();
|
||||
else onStartPrompt(item.mode, item.prompt);
|
||||
};
|
||||
return (
|
||||
<motion.button
|
||||
key={item.title}
|
||||
type="button"
|
||||
className="suggest-card"
|
||||
onClick={start}
|
||||
onHoverStart={() => setHovered(item.title)}
|
||||
onHoverEnd={() => setHovered(null)}
|
||||
whileHover={reducedMotion ? undefined : { y: -2 }}
|
||||
transition={aceternityMotion.spring.surface}
|
||||
>
|
||||
{hovered === item.title ? <motion.span layoutId="creation-suggest-hover" className="suggest-card-hover" aria-hidden transition={reducedMotion ? { duration: 0 } : aceternityMotion.spring.surface} /> : null}
|
||||
<span className="library-icon-tile suggest-icon">
|
||||
<Icon size={18} strokeWidth={2} />
|
||||
</span>
|
||||
<span className="suggest-copy">
|
||||
<strong>{item.title}</strong>
|
||||
<span>{item.hint}</span>
|
||||
</span>
|
||||
</motion.button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</LayoutGroup>
|
||||
);
|
||||
}
|
||||
|
||||
export function CreationFeaturedWorks({ onStartPrompt }: { onStartPrompt: (mode: CreationMode, prompt: string) => void }) {
|
||||
const [filter, setFilter] = useState<"all" | CreationMode>("all");
|
||||
const [limit, setLimit] = useState(12);
|
||||
const filtered = creationFeaturedWorks.filter((item) => filter === "all" || item.mode === filter);
|
||||
return <section className="creation-featured-works" aria-labelledby="creation-featured-title">
|
||||
<div className="creation-featured-heading">
|
||||
<div><h2 id="creation-featured-title">精选灵感</h2></div>
|
||||
<p>{creationFeaturedWorks.length} 个创意起点 · 点击填入提示词,不自动生成</p>
|
||||
</div>
|
||||
<div className="creation-inspiration-filters" role="group" aria-label="灵感类型">
|
||||
{(["all", "video", "image", "text"] as const).map((value) => <button key={value} type="button" aria-pressed={filter === value} onClick={() => { setFilter(value); setLimit(12); }}>{value === "all" ? "全部灵感" : modeLabels[value]}<span>{creationFeaturedWorks.filter((item) => value === "all" || item.mode === value).length}</span></button>)}
|
||||
</div>
|
||||
<div className="creation-featured-layout">
|
||||
{filtered.slice(0, limit).map((item, index) => <button key={item.title} type="button" className={`product-collection-card creation-featured-card ${index === 0 ? "is-featured-hero" : ""}`} onClick={() => onStartPrompt(item.mode, item.prompt)}>
|
||||
<span className="creation-featured-media"><img src={item.image} alt="" loading="lazy" /><span className="creation-inspiration-overlay"><ArrowUp />使用这个创意</span></span>
|
||||
<span className="creation-featured-copy"><strong>{item.title}</strong><span>{item.description}</span><em><Sparkles />{item.source ? "开源改编 · CC0" : "原创提示词"} · {modeLabels[item.mode]}</em></span>
|
||||
</button>)}
|
||||
</div>
|
||||
<footer className="creation-inspiration-footer">{limit < filtered.length ? <Button onClick={() => setLimit((count) => count + 12)}>展开更多灵感<ChevronDown /></Button> : <span>已展示全部 {filtered.length} 个创意</span>}<details><summary>模板与封面来源</summary><p>{inspirationSource.notice}</p><a href={inspirationSource.repository} target="_blank" rel="noreferrer">awesome-chatgpt-prompts · CC0</a></details></footer>
|
||||
</section>;
|
||||
return (
|
||||
<section className="creation-featured-works" aria-labelledby="creation-featured-title">
|
||||
<div className="creation-featured-heading">
|
||||
<div>
|
||||
<h2 id="creation-featured-title">精选灵感</h2>
|
||||
</div>
|
||||
<p>{creationFeaturedWorks.length} 个创意起点 · 点击填入提示词,不自动生成</p>
|
||||
</div>
|
||||
<div className="creation-inspiration-filters" role="group" aria-label="灵感类型">
|
||||
{(["all", "video", "image", "text"] as const).map((value) => (
|
||||
<button
|
||||
key={value}
|
||||
type="button"
|
||||
aria-pressed={filter === value}
|
||||
onClick={() => {
|
||||
setFilter(value);
|
||||
setLimit(12);
|
||||
}}
|
||||
>
|
||||
{value === "all" ? "全部灵感" : modeLabels[value]}
|
||||
<span>{creationFeaturedWorks.filter((item) => value === "all" || item.mode === value).length}</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<div className="creation-featured-layout">
|
||||
{filtered.slice(0, limit).map((item, index) => (
|
||||
<button key={item.title} type="button" className={`product-collection-card creation-featured-card ${index === 0 ? "is-featured-hero" : ""}`} onClick={() => onStartPrompt(item.mode, item.prompt)}>
|
||||
<span className="creation-featured-media">
|
||||
<img src={item.image} alt="" loading="lazy" />
|
||||
<span className="creation-inspiration-overlay">
|
||||
<ArrowUp />
|
||||
使用这个创意
|
||||
</span>
|
||||
</span>
|
||||
<span className="creation-featured-copy">
|
||||
<strong>{item.title}</strong>
|
||||
<span>{item.description}</span>
|
||||
<em>
|
||||
<Sparkles />
|
||||
{item.source ? "开源改编 · CC0" : "原创提示词"} · {modeLabels[item.mode]}
|
||||
</em>
|
||||
</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<footer className="creation-inspiration-footer">
|
||||
{limit < filtered.length ? (
|
||||
<Button onClick={() => setLimit((count) => count + 12)}>
|
||||
展开更多灵感
|
||||
<ChevronDown />
|
||||
</Button>
|
||||
) : (
|
||||
<span>已展示全部 {filtered.length} 个创意</span>
|
||||
)}
|
||||
<details>
|
||||
<summary>模板与封面来源</summary>
|
||||
<p>{inspirationSource.notice}</p>
|
||||
<a href={inspirationSource.repository} target="_blank" rel="noreferrer">
|
||||
awesome-chatgpt-prompts · CC0
|
||||
</a>
|
||||
</details>
|
||||
</footer>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user