This commit is contained in:
asp_ly 2024-12-23 21:51:09 +08:00
parent 90e9ab004c
commit 3f1240e972
2 changed files with 232 additions and 275 deletions

View File

@ -1,170 +1,187 @@
.project-card { .project-card {
&:hover { &:hover {
transform: translateY(-4px); transform: translateY(-4px);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}
.ant-card-actions {
background: #fafafa;
border-top: 1px solid #f0f0f0;
li {
margin: 12px 0;
&:not(:last-child) {
border-right: 1px solid #f0f0f0;
}
}
} }
.ant-card-body { .ant-card-body {
padding: 0; padding: 0;
} }
.ant-tag { .project-content {
border: none; padding: 20px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); }
&:hover { // 项目组头部
opacity: 0.8; .project-header {
display: flex;
align-items: flex-start;
gap: 12px;
margin-bottom: 16px;
.project-type {
margin: 0;
padding: 6px;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
} }
}
.ant-typography { .title-section {
margin-bottom: 0; flex: 1;
} min-width: 0;
.ant-btn { .project-name {
&:hover { margin: 0;
transform: scale(1.05); font-size: 16px;
transition: all 0.3s ease; line-height: 1.4;
} color: #1f1f1f;
}
.ant-space {
.anticon {
font-size: 14px;
}
}
.environment-section {
.section-header {
margin-bottom: 16px;
}
}
.environment-list {
.environment-item {
background: #fff;
border-radius: 8px;
padding: 16px;
border: 1px solid #f0f0f0;
margin-bottom: 12px;
transition: all 0.3s ease;
&:last-child {
margin-bottom: 0;
} }
&:hover { .project-code {
transform: translateX(4px); margin-top: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); font-size: 13px;
border-color: #d9d9d9; color: #666;
font-family: 'monaco, monospace';
} }
}
}
.env-header { // 项目组描述
.env-title { .project-desc {
color: #666;
font-size: 13px;
line-height: 1.6;
margin-bottom: 16px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
// 项目组统计
.project-stats {
display: flex;
gap: 16px;
margin-bottom: 20px;
padding: 12px;
background: #fafafa;
border-radius: 6px;
.stat-item {
display: flex;
align-items: center;
gap: 6px;
color: #666;
font-size: 13px;
.anticon {
font-size: 14px;
color: #8c8c8c;
}
}
}
// 环境列表
.environments-section {
margin-bottom: 20px;
.env-list {
display: flex;
flex-direction: column;
gap: 8px;
.env-item {
padding: 12px;
background: #fafafa;
border-radius: 6px;
transition: all 0.3s ease;
&:hover {
background: #f0f0f0;
}
.env-main {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
margin-bottom: 12px; gap: 12px;
}
.env-tags { .env-info {
display: flex; flex: 1;
gap: 6px; min-width: 0;
.env-tag { .env-name {
margin: 0; display: block;
padding: 4px 8px;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
.anticon {
font-size: 14px; font-size: 14px;
font-weight: 500;
color: #262626;
margin-bottom: 4px;
}
.env-code {
display: block;
font-size: 12px;
color: #666;
font-family: 'monaco, monospace';
}
}
.env-tags {
display: flex;
gap: 4px;
flex-shrink: 0;
.ant-tag {
margin: 0;
padding: 4px;
border: none;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
.anticon {
font-size: 12px;
}
} }
} }
} }
.env-meta { .env-desc {
display: flex; margin-top: 8px;
align-items: center; font-size: 12px;
gap: 12px; color: #8c8c8c;
overflow: hidden;
.env-code { text-overflow: ellipsis;
font-family: 'monaco, monospace'; white-space: nowrap;
color: #666;
background: #f5f5f5;
padding: 2px 8px;
border-radius: 4px;
font-size: 12px;
margin: 0;
}
.env-desc {
font-size: 12px;
color: #8c8c8c;
max-width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
cursor: help;
}
}
}
.env-footer {
margin-top: 12px;
padding-top: 12px;
border-top: 1px dashed #f0f0f0;
.anticon {
opacity: 0.6;
} }
} }
} }
} }
.info-section { // 操作按钮
background: #f5f5f5; .project-actions {
border-radius: 8px; display: flex;
padding: 16px; gap: 8px;
margin-bottom: 16px; padding-top: 16px;
transition: all 0.3s ease; border-top: 1px dashed #f0f0f0;
&:hover { .ant-btn {
background: #f0f0f0; padding: 4px 12px;
} height: 32px;
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
}
.section-content {
background: #fff;
border-radius: 4px; border-radius: 4px;
border: 1px solid #f0f0f0;
padding: 8px;
&.code { &:hover {
font-family: 'monaco, monospace'; transform: translateY(-1px);
font-size: 14px; background: #fafafa;
color: #262626; }
&.ant-btn-dangerous:hover {
background: #fff1f0;
} }
} }
} }

View File

@ -138,13 +138,85 @@ const ProjectList: React.FC = () => {
hoverable hoverable
className="project-card" className="project-card"
style={{ style={{
borderRadius: '12px', borderRadius: '8px',
overflow: 'hidden', overflow: 'hidden',
height: '100%', height: '100%',
transition: 'all 0.3s ease', transition: 'all 0.3s ease',
}} }}
actions={[ >
<Tooltip title="编辑项目组"> <div className="project-content">
{/* 项目组标题和类型 */}
<div className="project-header">
<Tag className="project-type" color={typeInfo.color}>
{typeInfo.icon}
</Tag>
<div className="title-section">
<Title level={4} className="project-name">
{project.projectGroupName}
</Title>
<div className="project-code">
{project.projectGroupCode}
</div>
</div>
</div>
{/* 项目组描述 */}
<div className="project-desc">
{project.projectGroupDesc || '暂无描述'}
</div>
{/* 项目组统计信息 */}
<div className="project-stats">
<div className="stat-item">
<EnvironmentOutlined />
<span>{project.environments?.length || 0} </span>
</div>
<div className="stat-item">
<TeamOutlined />
<span>5 </span>
</div>
<div className="stat-item">
<ClockCircleOutlined />
<span>2</span>
</div>
</div>
{/* 环境列表 */}
{project.environments && project.environments.length > 0 && (
<div className="environments-section">
<div className="env-list">
{project.environments.map(env => {
const buildType = buildTypeMap[env.buildType];
const deployType = deployTypeMap[env.deployType];
return (
<div key={env.id} className="env-item">
<div className="env-main">
<div className="env-info">
<span className="env-name">{env.envName}</span>
<span className="env-code">{env.envCode}</span>
</div>
<div className="env-tags">
<Tooltip title={buildType.label}>
<Tag color={buildType.color}>{buildType.icon}</Tag>
</Tooltip>
<Tooltip title={deployType.label}>
<Tag color={deployType.color}>{deployType.icon}</Tag>
</Tooltip>
</div>
</div>
{env.envDesc && (
<div className="env-desc">{env.envDesc}</div>
)}
</div>
);
})}
</div>
</div>
)}
{/* 操作按钮 */}
<div className="project-actions">
<Button <Button
type="text" type="text"
icon={<EditOutlined />} icon={<EditOutlined />}
@ -152,8 +224,12 @@ const ProjectList: React.FC = () => {
> >
</Button> </Button>
</Tooltip>, <Button
<Tooltip title="删除项目组"> type="text"
icon={<TeamOutlined />}
>
</Button>
<Button <Button
type="text" type="text"
danger danger
@ -162,142 +238,6 @@ const ProjectList: React.FC = () => {
> >
</Button> </Button>
</Tooltip>,
<Tooltip title="管理成员">
<Button
type="text"
icon={<TeamOutlined />}
>
</Button>
</Tooltip>
]}
>
<div style={{ position: 'relative', padding: '16px' }}>
<div style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: '16px'
}}>
<Title level={4} style={{ margin: 0 }}>
{project.projectGroupName}
</Title>
<Tooltip title={typeInfo.description}>
<Tag color={typeInfo.color} style={{ borderRadius: '12px', padding: '0 12px' }}>
{typeInfo.icon} {typeInfo.label}
</Tag>
</Tooltip>
</div>
<Text
type="secondary"
style={{
display: 'block',
marginBottom: '24px',
height: '40px',
overflow: 'hidden',
textOverflow: 'ellipsis',
WebkitLineClamp: 2,
WebkitBoxOrient: 'vertical',
display: '-webkit-box',
}}
>
{project.projectGroupDesc || '暂无描述'}
</Text>
<div className="info-section">
<div className="section-header">
<Text type="secondary"></Text>
</div>
<div className="section-content code">
{project.projectGroupCode}
</div>
</div>
{project.environments && project.environments.length > 0 && (
<div className="info-section environment-section">
<div className="section-header">
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
<Text type="secondary"></Text>
<Tag color="blue" style={{ margin: 0, borderRadius: '10px' }}>
{project.environments.length}
</Tag>
</div>
<Tooltip title="查看更多">
<Button type="link" size="small" style={{ padding: 0 }}>
</Button>
</Tooltip>
</div>
<div className="environment-list">
{project.environments.map(env => {
const buildType = buildTypeMap[env.buildType];
const deployType = deployTypeMap[env.deployType];
return (
<div key={env.id} className="environment-item">
<div className="env-header">
<div className="env-title">
<Text strong style={{ fontSize: '15px' }}>{env.envName}</Text>
<div className="env-tags">
<Tooltip title={`构建方式:${buildType.label}`}>
<Tag color={buildType.color} className="env-tag">
{buildType.icon}
</Tag>
</Tooltip>
<Tooltip title={`部署方式:${deployType.label}`}>
<Tag color={deployType.color} className="env-tag">
{deployType.icon}
</Tag>
</Tooltip>
</div>
</div>
<div className="env-meta">
<Tooltip title="环境编码">
<Tag className="env-code">
{env.envCode}
</Tag>
</Tooltip>
{env.envDesc && (
<Tooltip title={env.envDesc}>
<Text type="secondary" className="env-desc">
{env.envDesc}
</Text>
</Tooltip>
)}
</div>
</div>
<div className="env-footer">
<Space size={16}>
<Text type="secondary" style={{ fontSize: '12px' }}>
<ClockCircleOutlined style={{ marginRight: '4px' }} />
2
</Text>
<Text type="secondary" style={{ fontSize: '12px' }}>
<RocketOutlined style={{ marginRight: '4px' }} />
12
</Text>
</Space>
</div>
</div>
);
})}
</div>
</div>
)}
<div style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
marginTop: '16px'
}}>
<Space>
<ClockCircleOutlined style={{ color: typeInfo.color }} />
<Text type="secondary">2</Text>
</Space>
<Text type="secondary">: {project.sort}</Text>
</div> </div>
</div> </div>
</Card> </Card>