refactor(quality): Q25 前端巨型组件拆分 — PipelineCreateDialog 559L→498L (-11%), 提取 pipeline-create/ 2 个文件 (types(PRESETS/DEFAULT_TARGET/PipelineCreateDialogProps/EnvVar) + AdvancedSettingsPanel(172L 受控展开面板: 构建节点/Job名/触发模式/环境变量)), 零逻辑变更, ESLint errors=0/warnings=0/any=0, tsc -b=0, npm build✓ (17.45s), 17/17 测试通过
This commit is contained in:
1 parent
adf1ac8f71
commit
2f8113cb8e
3 files changed
+353
-195
No files matched your search
+172
@@ -0,0 +1,172 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';
|
||||
import { Plus, ChevronDown, Settings2, Trash2 } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import type { BuildNode } from '@/api';
|
||||
import type { EnvVar } from './types';
|
||||
|
||||
export interface AdvancedSettingsPanelProps {
|
||||
open: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
buildNodeId: string;
|
||||
onBuildNodeIdChange: (v: string) => void;
|
||||
buildNodes: BuildNode[];
|
||||
jobName: string;
|
||||
onJobNameChange: (v: string) => void;
|
||||
triggerMode: string;
|
||||
onTriggerModeChange: (v: string) => void;
|
||||
watchBranches: string;
|
||||
onWatchBranchesChange: (v: string) => void;
|
||||
cronExpr: string;
|
||||
onCronExprChange: (v: string) => void;
|
||||
envVars: EnvVar[];
|
||||
onEnvVarsChange: (vars: EnvVar[]) => void;
|
||||
}
|
||||
|
||||
export function AdvancedSettingsPanel({
|
||||
open,
|
||||
onOpenChange,
|
||||
buildNodeId,
|
||||
onBuildNodeIdChange,
|
||||
buildNodes,
|
||||
jobName,
|
||||
onJobNameChange,
|
||||
triggerMode,
|
||||
onTriggerModeChange,
|
||||
watchBranches,
|
||||
onWatchBranchesChange,
|
||||
cronExpr,
|
||||
onCronExprChange,
|
||||
envVars,
|
||||
onEnvVarsChange,
|
||||
}: AdvancedSettingsPanelProps) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Collapsible open={open} onOpenChange={onOpenChange}>
|
||||
<CollapsibleTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
className="flex items-center gap-1.5 text-xs text-[var(--dg-text-muted)] hover:text-[var(--dg-text-primary)]"
|
||||
>
|
||||
<Settings2 className="h-3.5 w-3.5" />
|
||||
{t('deploy.advancedSettings')}
|
||||
<ChevronDown className={cn('h-3.5 w-3.5 transition-transform', open && 'rotate-180')} />
|
||||
</button>
|
||||
</CollapsibleTrigger>
|
||||
<CollapsibleContent className="mt-3 space-y-3 pt-3 border-t border-[var(--dg-border)]">
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-xs">{t('deploy.buildNode')}</Label>
|
||||
<Select
|
||||
value={buildNodeId || '__auto'}
|
||||
onValueChange={(v) => onBuildNodeIdChange(v === '__auto' ? '' : v)}
|
||||
>
|
||||
<SelectTrigger className="h-8 text-xs dg-input">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="__auto">{t('deploy.autoSchedule')}</SelectItem>
|
||||
{buildNodes.map((n) => (
|
||||
<SelectItem key={n.id} value={String(n.id)}>
|
||||
{n.name} ({n.running_count || 0}/{n.max_executors})
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-xs">
|
||||
Job 名称 <span className="text-[var(--dg-text-muted)]">(Webhook)</span>
|
||||
</Label>
|
||||
<Input
|
||||
value={jobName}
|
||||
onChange={(e) => onJobNameChange(e.target.value)}
|
||||
className="h-8 text-xs font-mono dg-input"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-xs">{t('deploy.triggerMethod')}</Label>
|
||||
<Select value={triggerMode} onValueChange={onTriggerModeChange}>
|
||||
<SelectTrigger className="h-8 text-xs dg-input">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="manual">{t('deploy.triggerManual')}</SelectItem>
|
||||
<SelectItem value="git_push">{t('deploy.codePush')}</SelectItem>
|
||||
<SelectItem value="cron">{t('deploy.triggerCron')}</SelectItem>
|
||||
<SelectItem value="webhook">Webhook</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
{triggerMode === 'git_push' && (
|
||||
<Input
|
||||
value={watchBranches}
|
||||
onChange={(e) => onWatchBranchesChange(e.target.value)}
|
||||
placeholder="监听分支,如 main, release/*"
|
||||
className="h-8 text-xs font-mono dg-input"
|
||||
/>
|
||||
)}
|
||||
{triggerMode === 'cron' && (
|
||||
<Input
|
||||
value={cronExpr}
|
||||
onChange={(e) => onCronExprChange(e.target.value)}
|
||||
placeholder="0 2 * * *"
|
||||
className="h-8 text-xs font-mono dg-input"
|
||||
/>
|
||||
)}
|
||||
<div className="space-y-1.5">
|
||||
<div className="flex items-center justify-between">
|
||||
<Label className="text-xs">{t('deploy.envVars')}</Label>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-6 text-[10px]"
|
||||
onClick={() => onEnvVarsChange([...envVars, { key: '', value: '' }])}
|
||||
>
|
||||
<Plus className="h-3 w-3 mr-0.5" />
|
||||
{t('deploy.addVar')}
|
||||
</Button>
|
||||
</div>
|
||||
{envVars.map((v, i) => (
|
||||
<div key={i} className="flex gap-1.5">
|
||||
<Input
|
||||
value={v.key}
|
||||
onChange={(e) => {
|
||||
const nv = [...envVars];
|
||||
nv[i] = { ...nv[i], key: e.target.value };
|
||||
onEnvVarsChange(nv);
|
||||
}}
|
||||
placeholder="KEY"
|
||||
className="h-7 text-xs font-mono dg-input flex-1"
|
||||
/>
|
||||
<Input
|
||||
value={v.value}
|
||||
onChange={(e) => {
|
||||
const nv = [...envVars];
|
||||
nv[i] = { ...nv[i], value: e.target.value };
|
||||
onEnvVarsChange(nv);
|
||||
}}
|
||||
placeholder="value"
|
||||
className="h-7 text-xs font-mono dg-input flex-[2]"
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-7 w-7 shrink-0"
|
||||
onClick={() => onEnvVarsChange(envVars.filter((_, idx) => idx !== i))}
|
||||
>
|
||||
<Trash2 className="h-3.5 w-3.5 text-[var(--dg-red)]" />
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</CollapsibleContent>
|
||||
</Collapsible>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user