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 {
&:hover {
transform: translateY(-4px);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
}
.ant-card-actions {
background: #fafafa;
border-top: 1px solid #f0f0f0;
li {
margin: 12px 0;
&:not(:last-child) {
border-right: 1px solid #f0f0f0;
}
}
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}
.ant-card-body {
padding: 0;
}
.ant-tag {
border: none;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
.project-content {
padding: 20px;
}
&: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 {
margin-bottom: 0;
}
.title-section {
flex: 1;
min-width: 0;
.ant-btn {
&:hover {
transform: scale(1.05);
transition: all 0.3s ease;
}
}
.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;
.project-name {
margin: 0;
font-size: 16px;
line-height: 1.4;
color: #1f1f1f;
}
&:hover {
transform: translateX(4px);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
border-color: #d9d9d9;
.project-code {
margin-top: 4px;
font-size: 13px;
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;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
}
gap: 12px;
.env-tags {
display: flex;
gap: 6px;
.env-info {
flex: 1;
min-width: 0;
.env-tag {
margin: 0;
padding: 4px 8px;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
.anticon {
.env-name {
display: block;
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 {
display: flex;
align-items: center;
gap: 12px;
.env-code {
font-family: 'monaco, monospace';
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;
.env-desc {
margin-top: 8px;
font-size: 12px;
color: #8c8c8c;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
}
.info-section {
background: #f5f5f5;
border-radius: 8px;
padding: 16px;
margin-bottom: 16px;
transition: all 0.3s ease;
// 操作按钮
.project-actions {
display: flex;
gap: 8px;
padding-top: 16px;
border-top: 1px dashed #f0f0f0;
&:hover {
background: #f0f0f0;
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
}
.section-content {
background: #fff;
.ant-btn {
padding: 4px 12px;
height: 32px;
border-radius: 4px;
border: 1px solid #f0f0f0;
padding: 8px;
&.code {
font-family: 'monaco, monospace';
font-size: 14px;
color: #262626;
&:hover {
transform: translateY(-1px);
background: #fafafa;
}
&.ant-btn-dangerous:hover {
background: #fff1f0;
}
}
}

View File

@ -138,13 +138,85 @@ const ProjectList: React.FC = () => {
hoverable
className="project-card"
style={{
borderRadius: '12px',
borderRadius: '8px',
overflow: 'hidden',
height: '100%',
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
type="text"
icon={<EditOutlined />}
@ -152,8 +224,12 @@ const ProjectList: React.FC = () => {
>
</Button>
</Tooltip>,
<Tooltip title="删除项目组">
<Button
type="text"
icon={<TeamOutlined />}
>
</Button>
<Button
type="text"
danger
@ -162,142 +238,6 @@ const ProjectList: React.FC = () => {
>
</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>
</Card>