feat: FlowStack 发布系统首个可运行版本 (gin + React)
- Go gin 后端:流水线/节点/连线/运行/日志/GitOps/插件 REST API, SQLite(GORM) 自动建表 + seed,模拟执行引擎 + SSE 实时日志推送, 前端产物 go:embed 嵌入单二进制,一个端口同时服务 API 与页面 - React 19 前端:画布式流水线编辑器(React Flow + Tekton 任务库)、 GitOps 部署、批量发布、发布记录等 14 个模块页面, tRPC 全部替换为 REST(TanStack Query) - 首次启动生成随机密码管理员账号(日志 + data/initial-admin-password.txt) - run.sh 一键构建启动(默认端口 9527,支持 start/stop/restart/build/dev)
This commit is contained in:
commit
04d1342b27
115 files changed
+23268
No files matched your search
@@ -0,0 +1,88 @@
|
||||
import { Pencil, Trash2 } from 'lucide-react';
|
||||
import { iconMap } from '@/data/pipelineData';
|
||||
import type { PipelineTask } from '@/types/pipeline';
|
||||
|
||||
interface TaskCardProps {
|
||||
task: PipelineTask;
|
||||
isSelected: boolean;
|
||||
onSelect: () => void;
|
||||
onDelete: () => void;
|
||||
}
|
||||
|
||||
// Subtle type indicator colors — just for the small dot/icon, NOT background
|
||||
const typeConfig: Record<string, { color: string; label: string }> = {
|
||||
build: { color: '#9a6700', label: '构建' },
|
||||
deploy: { color: '#1a7f37', label: '部署' },
|
||||
test: { color: '#8250df', label: '测试' },
|
||||
custom: { color: '#6e7781', label: '自定义' },
|
||||
};
|
||||
|
||||
export default function TaskCard({ task, isSelected, onSelect, onDelete }: TaskCardProps) {
|
||||
const config = typeConfig[task.type] || typeConfig.custom;
|
||||
const IconComponent = iconMap[task.icon] || iconMap.Settings;
|
||||
|
||||
const handleDelete = (e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
onDelete();
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
onClick={onSelect}
|
||||
className="flex items-center gap-2.5 px-3 py-[10px] rounded-md cursor-pointer transition-all duration-150 group mb-[2px] last:mb-0"
|
||||
style={{
|
||||
background: isSelected ? '#f0f5ff' : 'transparent',
|
||||
border: isSelected ? '1px solid #b7d4f0' : '1px solid transparent',
|
||||
...(isSelected
|
||||
? { boxShadow: '0 0 0 1px rgba(9,105,218,0.08)' }
|
||||
: {}),
|
||||
}}
|
||||
>
|
||||
{/* Type icon — small colored dot with icon inside */}
|
||||
<div
|
||||
className="w-6 h-6 rounded-[6px] flex items-center justify-center flex-shrink-0"
|
||||
style={{
|
||||
background: `${config.color}10`,
|
||||
border: `1px solid ${config.color}25`,
|
||||
}}
|
||||
>
|
||||
<IconComponent className="w-3 h-3" style={{ color: config.color }} />
|
||||
</div>
|
||||
|
||||
{/* Task info */}
|
||||
<div className="flex-1 min-w-0">
|
||||
<div
|
||||
className="text-[13px] font-medium truncate leading-tight"
|
||||
style={{ color: isSelected ? 'var(--text-primary)' : 'var(--text-primary)' }}
|
||||
>
|
||||
{task.name}
|
||||
</div>
|
||||
<div
|
||||
className="text-[11px] truncate leading-tight mt-[1px]"
|
||||
style={{ color: 'var(--text-tertiary)' }}
|
||||
>
|
||||
{config.label}
|
||||
{task.scriptType && ` · ${task.scriptType}`}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Actions — hover reveal */}
|
||||
<div className="flex items-center gap-[2px] opacity-0 group-hover:opacity-100 transition-opacity duration-150 flex-shrink-0">
|
||||
<button
|
||||
onClick={(e) => { e.stopPropagation(); onSelect(); }}
|
||||
className="p-1 rounded transition-colors hover:bg-black/5"
|
||||
title="编辑"
|
||||
>
|
||||
<Pencil className="w-3 h-3" style={{ color: 'var(--text-tertiary)' }} />
|
||||
</button>
|
||||
<button
|
||||
onClick={handleDelete}
|
||||
className="p-1 rounded transition-colors hover:bg-red-50"
|
||||
title="删除"
|
||||
>
|
||||
<Trash2 className="w-3 h-3" style={{ color: 'var(--text-tertiary)' }} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user