refactor: 重构项目列表页,拆分为书架组件并统一多页面风格调用
This commit is contained in:
@@ -1,177 +1,210 @@
|
||||
import type { CSSProperties } from 'react';
|
||||
|
||||
// 统一的卡片样式配置
|
||||
export const cardStyles = {
|
||||
// 基础卡片样式
|
||||
base: {
|
||||
borderRadius: 12,
|
||||
transition: 'all 0.3s ease',
|
||||
const bookshelfBaseShadow = `
|
||||
0 10px 22px -12px color-mix(in srgb, var(--ant-color-text) 28%, transparent),
|
||||
inset 0 1px 0 color-mix(in srgb, var(--ant-color-bg-container) 82%, transparent)
|
||||
`;
|
||||
|
||||
const bookshelfHoverShadow = `
|
||||
0 16px 30px -12px color-mix(in srgb, var(--ant-color-text) 34%, transparent),
|
||||
inset 0 1px 0 color-mix(in srgb, var(--ant-color-bg-container) 88%, transparent)
|
||||
`;
|
||||
|
||||
const bookshelfNewBaseShadow = `
|
||||
0 10px 24px -14px color-mix(in srgb, var(--ant-color-text) 30%, transparent),
|
||||
inset 0 1px 0 color-mix(in srgb, var(--ant-color-bg-container) 84%, transparent)
|
||||
`;
|
||||
|
||||
const bookshelfNewHoverShadow = `
|
||||
0 16px 30px -12px color-mix(in srgb, var(--ant-color-text) 36%, transparent),
|
||||
inset 0 1px 0 color-mix(in srgb, var(--ant-color-bg-container) 90%, transparent)
|
||||
`;
|
||||
|
||||
const promptTemplateBaseShadow = `
|
||||
0 6px 16px color-mix(in srgb, var(--ant-color-text) 11%, transparent),
|
||||
0 1px 0 color-mix(in srgb, var(--ant-color-white) 42%, transparent) inset
|
||||
`;
|
||||
|
||||
// BookshelfPage 样式(书架/书本卡片)
|
||||
export const bookshelfCardStyles = {
|
||||
container: {
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(auto-fill, minmax(270px, 1fr))',
|
||||
gap: '20px 18px',
|
||||
padding: '8px 0 16px',
|
||||
alignItems: 'stretch',
|
||||
} as CSSProperties,
|
||||
|
||||
// 悬浮效果
|
||||
hoverable: {
|
||||
cursor: 'pointer',
|
||||
position: 'relative' as const,
|
||||
} as CSSProperties,
|
||||
|
||||
// 角色卡片样式
|
||||
character: {
|
||||
// height: 320,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
borderColor: 'var(--color-info)',
|
||||
borderRadius: 12,
|
||||
} as CSSProperties,
|
||||
|
||||
// 组织卡片样式
|
||||
organization: {
|
||||
// height: 320,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
borderColor: 'var(--color-success)',
|
||||
backgroundColor: 'var(--color-bg-base)', // 使用柔和的背景色
|
||||
borderRadius: 12,
|
||||
} as CSSProperties,
|
||||
|
||||
// 项目卡片样式 - 书籍风格 (Book Style)
|
||||
project: {
|
||||
projectCard: {
|
||||
height: '100%',
|
||||
borderRadius: '6px 16px 16px 6px', // 左侧稍直(书脊),右侧圆润
|
||||
borderRadius: '4px 12px 12px 4px',
|
||||
overflow: 'hidden',
|
||||
background: '#fff',
|
||||
// 基础阴影 + 书籍厚度阴影
|
||||
boxShadow: `
|
||||
0 2px 8px rgba(0, 0, 0, 0.04),
|
||||
4px 0 8px rgba(0, 0, 0, 0.02)
|
||||
`,
|
||||
transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
|
||||
border: '1px solid rgba(0,0,0,0.02)',
|
||||
borderLeft: '6px solid var(--color-primary)', // 书脊效果
|
||||
background: 'linear-gradient(180deg, color-mix(in srgb, var(--ant-color-bg-container) 96%, var(--ant-color-text) 4%) 0%, color-mix(in srgb, var(--ant-color-bg-container) 88%, var(--ant-color-text) 12%) 100%)',
|
||||
boxShadow: bookshelfBaseShadow,
|
||||
transition: 'transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275), box-shadow 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275), border-color 0.3s ease',
|
||||
border: '1px solid color-mix(in srgb, var(--ant-color-text) 18%, transparent)',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
position: 'relative',
|
||||
transformOrigin: 'center bottom',
|
||||
transformStyle: 'preserve-3d',
|
||||
} as CSSProperties,
|
||||
|
||||
// 新建项目卡片样式 - 统一书籍风格
|
||||
newProjectBook: {
|
||||
newProjectCard: {
|
||||
height: '100%',
|
||||
borderRadius: '6px 16px 16px 6px',
|
||||
borderRadius: 12,
|
||||
overflow: 'hidden',
|
||||
background: '#fff',
|
||||
// 基础阴影 + 书籍厚度阴影 (与普通项目一致)
|
||||
boxShadow: `
|
||||
0 2px 8px rgba(0, 0, 0, 0.04),
|
||||
4px 0 8px rgba(0, 0, 0, 0.02)
|
||||
`,
|
||||
border: '1px solid rgba(0,0,0,0.02)',
|
||||
borderLeft: '6px solid var(--color-primary)', // 与普通项目一致的书脊颜色
|
||||
background: 'linear-gradient(180deg, color-mix(in srgb, var(--ant-color-bg-container) 94%, var(--ant-color-warning) 6%) 0%, color-mix(in srgb, var(--ant-color-bg-container) 86%, var(--ant-color-warning) 14%) 100%)',
|
||||
boxShadow: bookshelfNewBaseShadow,
|
||||
border: '2px dashed color-mix(in srgb, var(--ant-color-warning) 40%, var(--ant-color-border) 60%)',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
|
||||
transition: 'transform 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease, background-color 0.3s ease',
|
||||
position: 'relative',
|
||||
} as CSSProperties,
|
||||
|
||||
// 书架风格容器
|
||||
bookshelf: {
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))',
|
||||
gap: '24px',
|
||||
padding: '24px 0',
|
||||
} as CSSProperties,
|
||||
|
||||
// 卡片内容区域样式
|
||||
body: {
|
||||
padding: 20,
|
||||
display: 'flex',
|
||||
flexDirection: 'column' as const,
|
||||
} as CSSProperties,
|
||||
|
||||
// 卡片描述区域样式(固定高度,内容截断)
|
||||
description: {
|
||||
marginTop: 12,
|
||||
maxHeight: 200,
|
||||
overflow: 'hidden' as const,
|
||||
} as CSSProperties,
|
||||
|
||||
// 文本截断样式
|
||||
ellipsis: {
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap' as const,
|
||||
} as CSSProperties,
|
||||
|
||||
// 多行文本截断
|
||||
ellipsisMultiline: (lines: number = 2) => ({
|
||||
display: '-webkit-box',
|
||||
WebkitLineClamp: lines,
|
||||
WebkitBoxOrient: 'vertical' as const,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
} as CSSProperties),
|
||||
};
|
||||
|
||||
// 卡片悬浮动画 - 增强版 (Subtle Lift)
|
||||
export const cardHoverHandlers = {
|
||||
export const bookshelfCardHoverHandlers = {
|
||||
onMouseEnter: (e: React.MouseEvent<HTMLDivElement>) => {
|
||||
const target = e.currentTarget;
|
||||
target.style.transform = 'translateY(-6px) rotateY(-2deg)'; // 悬浮时轻微翻起
|
||||
if (target.dataset.cardStyle !== 'bookshelf-book') {
|
||||
return;
|
||||
}
|
||||
|
||||
// 统一书本悬浮态
|
||||
target.style.boxShadow = `
|
||||
-2px 0 4px rgba(0, 0, 0, 0.1), // 书脊阴影加深
|
||||
8px 12px 24px rgba(0, 0, 0, 0.12)
|
||||
`;
|
||||
if (target.dataset.bookKind === 'new') {
|
||||
target.style.transform = 'translateY(-6px)';
|
||||
target.style.boxShadow = bookshelfNewHoverShadow;
|
||||
target.style.borderColor = 'color-mix(in srgb, var(--ant-color-warning) 48%, var(--ant-color-border) 52%)';
|
||||
target.style.background = 'linear-gradient(180deg, color-mix(in srgb, var(--ant-color-bg-container) 92%, var(--ant-color-warning) 8%) 0%, color-mix(in srgb, var(--ant-color-bg-container) 82%, var(--ant-color-warning) 18%) 100%)';
|
||||
return;
|
||||
}
|
||||
|
||||
target.style.transform = 'translateY(-8px) rotateX(2deg)';
|
||||
target.style.boxShadow = bookshelfHoverShadow;
|
||||
target.style.borderColor = 'color-mix(in srgb, var(--ant-color-primary) 28%, var(--ant-color-border) 72%)';
|
||||
},
|
||||
onMouseLeave: (e: React.MouseEvent<HTMLDivElement>) => {
|
||||
const target = e.currentTarget;
|
||||
target.style.transform = 'translateY(0) rotateY(0)';
|
||||
if (target.dataset.cardStyle !== 'bookshelf-book') {
|
||||
return;
|
||||
}
|
||||
|
||||
// 统一恢复基础阴影
|
||||
target.style.boxShadow = `
|
||||
0 2px 8px rgba(0, 0, 0, 0.04),
|
||||
4px 0 8px rgba(0, 0, 0, 0.02)
|
||||
`;
|
||||
const isNewBook = target.dataset.bookKind === 'new';
|
||||
target.style.transform = 'translateY(0) rotateX(0)';
|
||||
target.style.boxShadow = isNewBook ? bookshelfNewBaseShadow : bookshelfBaseShadow;
|
||||
target.style.borderColor = isNewBook
|
||||
? 'color-mix(in srgb, var(--ant-color-warning) 40%, var(--ant-color-border) 60%)'
|
||||
: 'color-mix(in srgb, var(--ant-color-text) 18%, transparent)';
|
||||
if (isNewBook) {
|
||||
target.style.background = 'linear-gradient(180deg, color-mix(in srgb, var(--ant-color-bg-container) 94%, var(--ant-color-warning) 6%) 0%, color-mix(in srgb, var(--ant-color-bg-container) 86%, var(--ant-color-warning) 14%) 100%)';
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// 响应式网格配置
|
||||
export const gridConfig = {
|
||||
gutter: [16, 16] as [number, number],
|
||||
// PromptTemplates 页面卡片样式
|
||||
export const promptTemplateCardStyles = {
|
||||
templateCard: {
|
||||
height: '100%',
|
||||
borderRadius: 14,
|
||||
overflow: 'hidden',
|
||||
border: '1px solid color-mix(in srgb, var(--ant-color-text) 8%, transparent)',
|
||||
background: 'linear-gradient(180deg, color-mix(in srgb, var(--ant-color-bg-container) 97%, var(--ant-color-primary) 3%) 0%, var(--ant-color-bg-container) 100%)',
|
||||
boxShadow: promptTemplateBaseShadow,
|
||||
transition: 'transform 0.28s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.28s cubic-bezier(0.22, 1, 0.36, 1), border-color 0.28s ease',
|
||||
} as CSSProperties,
|
||||
};
|
||||
|
||||
export const promptTemplateCardHoverHandlers = {
|
||||
onMouseEnter: (e: React.MouseEvent<HTMLDivElement>) => {
|
||||
const target = e.currentTarget;
|
||||
target.style.transform = 'translateY(-6px)';
|
||||
target.style.boxShadow = `
|
||||
0 14px 24px color-mix(in srgb, var(--ant-color-text) 16%, transparent),
|
||||
0 1px 0 color-mix(in srgb, var(--ant-color-white) 48%, transparent) inset
|
||||
`;
|
||||
target.style.borderColor = 'color-mix(in srgb, var(--ant-color-primary) 24%, transparent)';
|
||||
},
|
||||
onMouseLeave: (e: React.MouseEvent<HTMLDivElement>) => {
|
||||
const target = e.currentTarget;
|
||||
target.style.transform = 'translateY(0)';
|
||||
target.style.boxShadow = promptTemplateBaseShadow;
|
||||
target.style.borderColor = 'color-mix(in srgb, var(--ant-color-text) 8%, transparent)';
|
||||
},
|
||||
};
|
||||
|
||||
export const promptTemplateGridConfig = {
|
||||
xs: 24,
|
||||
sm: 12,
|
||||
lg: 8,
|
||||
xl: 6,
|
||||
};
|
||||
|
||||
// 角色卡片网格配置
|
||||
export const characterGridConfig = {
|
||||
gutter: 0, // 移除 gutter,避免负边距
|
||||
xs: 24, // 手机:1列
|
||||
sm: 12, // 平板:2列
|
||||
md: 12, // 中等屏幕:3列
|
||||
lg: 6, // 大屏:4列
|
||||
xl: 6, // 超大屏:4列
|
||||
xxl: 5, // 超超大屏:6列
|
||||
// WorldSetting 页面卡片样式
|
||||
export const worldSettingCardStyles = {
|
||||
sectionCard: {
|
||||
borderRadius: 14,
|
||||
border: '1px solid color-mix(in srgb, var(--ant-color-text) 7%, transparent)',
|
||||
boxShadow: '0 4px 12px color-mix(in srgb, var(--ant-color-text) 8%, transparent)',
|
||||
background: 'linear-gradient(180deg, color-mix(in srgb, var(--ant-color-bg-container) 98%, var(--ant-color-primary) 2%) 0%, var(--ant-color-bg-container) 100%)',
|
||||
transition: 'box-shadow 0.24s ease, border-color 0.24s ease',
|
||||
} as CSSProperties,
|
||||
};
|
||||
|
||||
// 文本样式
|
||||
export const textStyles = {
|
||||
// Characters 页面(CharacterCard + 网格)样式
|
||||
export const characterCardStyles = {
|
||||
characterCard: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
borderRadius: 12,
|
||||
} as CSSProperties,
|
||||
|
||||
organizationCard: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
backgroundColor: 'var(--ant-color-bg-layout)',
|
||||
borderRadius: 12,
|
||||
} as CSSProperties,
|
||||
|
||||
nameEllipsis: {
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
} as CSSProperties,
|
||||
|
||||
descriptionBlock: {
|
||||
marginTop: 12,
|
||||
maxHeight: 200,
|
||||
overflow: 'hidden',
|
||||
} as CSSProperties,
|
||||
};
|
||||
|
||||
export const charactersPageGridConfig = {
|
||||
gutter: 0,
|
||||
xs: 24,
|
||||
sm: 12,
|
||||
md: 12,
|
||||
lg: 6,
|
||||
xl: 6,
|
||||
xxl: 5,
|
||||
};
|
||||
|
||||
// 页面通用文本样式(仅用于信息展示,不与卡片结构耦合)
|
||||
export const commonTextStyles = {
|
||||
label: {
|
||||
fontSize: 12,
|
||||
color: 'rgba(0, 0, 0, 0.45)',
|
||||
color: 'color-mix(in srgb, var(--ant-color-text) 55%, transparent)',
|
||||
} as CSSProperties,
|
||||
|
||||
value: {
|
||||
fontSize: 14,
|
||||
color: 'rgba(0, 0, 0, 0.85)',
|
||||
color: 'var(--ant-color-text)',
|
||||
} as CSSProperties,
|
||||
|
||||
description: {
|
||||
fontSize: 12,
|
||||
color: 'rgba(0, 0, 0, 0.45)',
|
||||
color: 'color-mix(in srgb, var(--ant-color-text) 55%, transparent)',
|
||||
lineHeight: 1.6,
|
||||
} as CSSProperties,
|
||||
};
|
||||
Reference in New Issue
Block a user