1.33 日志通用查询
This commit is contained in:
parent
5056b133ca
commit
9225414a87
@ -6,6 +6,7 @@ interface UsePendingApprovalOptions {
|
|||||||
teams: DeployTeam[];
|
teams: DeployTeam[];
|
||||||
currentTeamId?: number | null; // 当前选中的团队ID
|
currentTeamId?: number | null; // 当前选中的团队ID
|
||||||
currentEnvId?: number | null; // 当前选中的环境ID
|
currentEnvId?: number | null; // 当前选中的环境ID
|
||||||
|
canApprove?: boolean; // 当前用户是否有审批权限
|
||||||
pollingEnabled?: boolean;
|
pollingEnabled?: boolean;
|
||||||
pollingInterval?: number; // 轮询间隔,默认30秒
|
pollingInterval?: number; // 轮询间隔,默认30秒
|
||||||
}
|
}
|
||||||
@ -20,6 +21,7 @@ export function usePendingApproval({
|
|||||||
teams,
|
teams,
|
||||||
currentTeamId,
|
currentTeamId,
|
||||||
currentEnvId,
|
currentEnvId,
|
||||||
|
canApprove = false,
|
||||||
pollingEnabled = true,
|
pollingEnabled = true,
|
||||||
pollingInterval = 30000 // 默认30秒
|
pollingInterval = 30000 // 默认30秒
|
||||||
}: UsePendingApprovalOptions) {
|
}: UsePendingApprovalOptions) {
|
||||||
@ -41,7 +43,9 @@ export function usePendingApproval({
|
|||||||
|
|
||||||
// 加载待审批数量 - 使用 useCallback 避免重复创建
|
// 加载待审批数量 - 使用 useCallback 避免重复创建
|
||||||
const loadPendingApprovalCount = useCallback(async () => {
|
const loadPendingApprovalCount = useCallback(async () => {
|
||||||
if (!pollingEnabled || workflowDefinitionKeys.length === 0) {
|
// 只有当用户有审批权限时才调用接口
|
||||||
|
if (!canApprove || !pollingEnabled || workflowDefinitionKeys.length === 0) {
|
||||||
|
setPendingApprovalCount(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,11 +63,18 @@ export function usePendingApproval({
|
|||||||
// 静默失败,不影响主页面
|
// 静默失败,不影响主页面
|
||||||
console.error('Failed to load pending approval count:', error);
|
console.error('Failed to load pending approval count:', error);
|
||||||
}
|
}
|
||||||
}, [workflowDefinitionKeys, currentTeamId, currentEnvId, pollingEnabled]);
|
}, [canApprove, workflowDefinitionKeys, currentTeamId, currentEnvId, pollingEnabled]);
|
||||||
|
|
||||||
// 轮询待审批数量
|
// 轮询待审批数量
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!pollingEnabled || workflowDefinitionKeys.length === 0) {
|
// 只有当用户有审批权限时才启动轮询
|
||||||
|
if (!canApprove || !pollingEnabled || workflowDefinitionKeys.length === 0) {
|
||||||
|
// 清除计数并停止轮询
|
||||||
|
setPendingApprovalCount(0);
|
||||||
|
if (intervalRef.current) {
|
||||||
|
clearInterval(intervalRef.current);
|
||||||
|
intervalRef.current = null;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +94,7 @@ export function usePendingApproval({
|
|||||||
clearInterval(intervalRef.current);
|
clearInterval(intervalRef.current);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [loadPendingApprovalCount, pollingEnabled, workflowDefinitionKeys.length, pollingInterval]);
|
}, [canApprove, loadPendingApprovalCount, pollingEnabled, workflowDefinitionKeys.length, pollingInterval]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
approvalModalOpen,
|
approvalModalOpen,
|
||||||
|
|||||||
@ -55,10 +55,22 @@ const Dashboard: React.FC = () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 计算当前用户是否有审批权限(需要在 usePendingApproval 之前计算)
|
||||||
|
const currentCanApprove = React.useMemo(() => {
|
||||||
|
if (!deploymentData.currentTeam || !deploymentData.currentEnvId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const currentEnv = deploymentData.currentTeam.environments.find(
|
||||||
|
env => env.environmentId === deploymentData.currentEnvId
|
||||||
|
);
|
||||||
|
return currentEnv?.canApprove === true;
|
||||||
|
}, [deploymentData.currentTeam, deploymentData.currentEnvId]);
|
||||||
|
|
||||||
const approvalData = usePendingApproval({
|
const approvalData = usePendingApproval({
|
||||||
teams: deploymentData.teams,
|
teams: deploymentData.teams,
|
||||||
currentTeamId: deploymentData.currentTeamId,
|
currentTeamId: deploymentData.currentTeamId,
|
||||||
currentEnvId: deploymentData.currentEnvId,
|
currentEnvId: deploymentData.currentEnvId,
|
||||||
|
canApprove: currentCanApprove,
|
||||||
pollingEnabled: !deploymentData.loading
|
pollingEnabled: !deploymentData.loading
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,85 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { Label } from '@/components/ui/label';
|
||||||
|
import { Input } from '@/components/ui/input';
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from '@/components/ui/select';
|
||||||
|
import { getServerList } from '@/pages/Resource/Server/List/service';
|
||||||
|
import type { ServerResponse } from '@/pages/Resource/Server/List/types';
|
||||||
|
|
||||||
|
interface DockerRuntimeConfigProps {
|
||||||
|
dockerServerId: number | null;
|
||||||
|
dockerContainerName: string;
|
||||||
|
onDockerServerChange: (serverId: number | null) => void;
|
||||||
|
onDockerContainerNameChange: (containerName: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DockerRuntimeConfig: React.FC<DockerRuntimeConfigProps> = ({
|
||||||
|
dockerServerId,
|
||||||
|
dockerContainerName,
|
||||||
|
onDockerServerChange,
|
||||||
|
onDockerContainerNameChange,
|
||||||
|
}) => {
|
||||||
|
const [servers, setServers] = useState<ServerResponse[]>([]);
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
loadServers();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const loadServers = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const result = await getServerList();
|
||||||
|
setServers(result || []);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载服务器列表失败:', error);
|
||||||
|
setServers([]);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-4 pl-4 border-l-2 border-muted">
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label>Docker服务器</Label>
|
||||||
|
<Select
|
||||||
|
value={dockerServerId?.toString() || ''}
|
||||||
|
onValueChange={(value) => onDockerServerChange(value ? Number(value) : null)}
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder={loading ? '加载中...' : '选择Docker服务器'} />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{servers.length === 0 ? (
|
||||||
|
<div className="p-4 text-center text-sm text-muted-foreground">
|
||||||
|
{loading ? '加载中...' : '暂无服务器'}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
servers.map((server) => (
|
||||||
|
<SelectItem key={server.id} value={server.id!.toString()}>
|
||||||
|
{server.serverName} ({server.hostIp})
|
||||||
|
</SelectItem>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label>容器名称</Label>
|
||||||
|
<Input
|
||||||
|
placeholder="请输入Docker容器名称"
|
||||||
|
value={dockerContainerName}
|
||||||
|
onChange={(e) => onDockerContainerNameChange(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -0,0 +1,197 @@
|
|||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { Label } from '@/components/ui/label';
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from '@/components/ui/select';
|
||||||
|
import { Loader2 } from 'lucide-react';
|
||||||
|
import { getExternalSystemList } from '@/pages/Resource/External/List/service';
|
||||||
|
import { getK8sNamespaceList, getK8sDeploymentByNamespace } from '@/pages/Resource/K8s/List/service';
|
||||||
|
|
||||||
|
interface K8sRuntimeConfigProps {
|
||||||
|
k8sSystemId: number | null;
|
||||||
|
k8sNamespaceId: number | null;
|
||||||
|
k8sDeploymentId: number | null;
|
||||||
|
onK8sSystemChange: (systemId: number | null) => void;
|
||||||
|
onK8sNamespaceChange: (namespaceId: number | null) => void;
|
||||||
|
onK8sDeploymentIdChange: (deploymentId: number | null) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const K8sRuntimeConfig: React.FC<K8sRuntimeConfigProps> = ({
|
||||||
|
k8sSystemId,
|
||||||
|
k8sNamespaceId,
|
||||||
|
k8sDeploymentId,
|
||||||
|
onK8sSystemChange,
|
||||||
|
onK8sNamespaceChange,
|
||||||
|
onK8sDeploymentIdChange,
|
||||||
|
}) => {
|
||||||
|
const [k8sSystems, setK8sSystems] = useState<any[]>([]);
|
||||||
|
const [namespaces, setNamespaces] = useState<any[]>([]);
|
||||||
|
const [deployments, setDeployments] = useState<any[]>([]);
|
||||||
|
const [loadingNamespaces, setLoadingNamespaces] = useState(false);
|
||||||
|
const [loadingDeployments, setLoadingDeployments] = useState(false);
|
||||||
|
|
||||||
|
// 加载K8S系统列表
|
||||||
|
useEffect(() => {
|
||||||
|
const loadK8sSystems = async () => {
|
||||||
|
try {
|
||||||
|
const systems = await getExternalSystemList({ type: 'K8S' });
|
||||||
|
setK8sSystems(systems || []);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载K8S系统失败:', error);
|
||||||
|
setK8sSystems([]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
loadK8sSystems();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// 加载Namespace列表
|
||||||
|
useEffect(() => {
|
||||||
|
const loadNamespaces = async () => {
|
||||||
|
if (!k8sSystemId) {
|
||||||
|
setNamespaces([]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoadingNamespaces(true);
|
||||||
|
try {
|
||||||
|
const data = await getK8sNamespaceList(k8sSystemId);
|
||||||
|
setNamespaces(data || []);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载Namespace失败:', error);
|
||||||
|
setNamespaces([]);
|
||||||
|
} finally {
|
||||||
|
setLoadingNamespaces(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
loadNamespaces();
|
||||||
|
}, [k8sSystemId]);
|
||||||
|
|
||||||
|
// 加载Deployment列表
|
||||||
|
useEffect(() => {
|
||||||
|
const loadDeployments = async () => {
|
||||||
|
if (!k8sSystemId || !k8sNamespaceId) {
|
||||||
|
setDeployments([]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoadingDeployments(true);
|
||||||
|
try {
|
||||||
|
const data = await getK8sDeploymentByNamespace(k8sSystemId, k8sNamespaceId);
|
||||||
|
setDeployments(data || []);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载Deployment失败:', error);
|
||||||
|
setDeployments([]);
|
||||||
|
} finally {
|
||||||
|
setLoadingDeployments(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
loadDeployments();
|
||||||
|
}, [k8sSystemId, k8sNamespaceId]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-4 p-4 border rounded-lg bg-muted/30">
|
||||||
|
<div className="flex items-center gap-2 mb-2">
|
||||||
|
<div className="h-1 w-1 rounded-full bg-blue-500" />
|
||||||
|
<span className="text-sm font-medium text-muted-foreground">Kubernetes 配置</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* K8S系统选择 */}
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label>K8S系统</Label>
|
||||||
|
<Select
|
||||||
|
value={k8sSystemId?.toString() || ''}
|
||||||
|
onValueChange={(value) => {
|
||||||
|
onK8sSystemChange(Number(value));
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="选择K8S系统" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{k8sSystems.length === 0 ? (
|
||||||
|
<div className="p-4 text-center text-sm text-muted-foreground">
|
||||||
|
暂无K8S系统
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
k8sSystems.map((system) => (
|
||||||
|
<SelectItem key={system.id} value={system.id.toString()}>
|
||||||
|
{system.name}
|
||||||
|
</SelectItem>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Namespace选择 */}
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label>Namespace</Label>
|
||||||
|
<Select
|
||||||
|
value={k8sNamespaceId?.toString() || ''}
|
||||||
|
onValueChange={(value) => {
|
||||||
|
onK8sNamespaceChange(Number(value));
|
||||||
|
}}
|
||||||
|
disabled={!k8sSystemId || loadingNamespaces}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder={loadingNamespaces ? '加载中...' : '选择Namespace'} />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{loadingNamespaces ? (
|
||||||
|
<div className="p-4 text-center">
|
||||||
|
<Loader2 className="h-4 w-4 animate-spin mx-auto" />
|
||||||
|
</div>
|
||||||
|
) : namespaces.length === 0 ? (
|
||||||
|
<div className="p-4 text-center text-sm text-muted-foreground">
|
||||||
|
{k8sSystemId ? '暂无Namespace' : '请先选择K8S系统'}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
namespaces.map((ns) => (
|
||||||
|
<SelectItem key={ns.id} value={ns.id.toString()}>
|
||||||
|
{ns.namespaceName}
|
||||||
|
</SelectItem>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Deployment选择 */}
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label>Deployment</Label>
|
||||||
|
<Select
|
||||||
|
value={k8sDeploymentId?.toString() || ''}
|
||||||
|
onValueChange={(value) => {
|
||||||
|
onK8sDeploymentIdChange(Number(value));
|
||||||
|
}}
|
||||||
|
disabled={!k8sNamespaceId || loadingDeployments}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder={loadingDeployments ? '加载中...' : '选择Deployment'} />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{loadingDeployments ? (
|
||||||
|
<div className="p-4 text-center">
|
||||||
|
<Loader2 className="h-4 w-4 animate-spin mx-auto" />
|
||||||
|
</div>
|
||||||
|
) : deployments.length === 0 ? (
|
||||||
|
<div className="p-4 text-center text-sm text-muted-foreground">
|
||||||
|
{k8sNamespaceId ? '暂无Deployment' : '请先选择Namespace'}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
deployments.map((deployment) => (
|
||||||
|
<SelectItem key={deployment.id} value={deployment.id.toString()}>
|
||||||
|
{deployment.deploymentName}
|
||||||
|
</SelectItem>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -0,0 +1,114 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Label } from '@/components/ui/label';
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from '@/components/ui/select';
|
||||||
|
import { K8sRuntimeConfig } from './K8sRuntimeConfig';
|
||||||
|
import { DockerRuntimeConfig } from './DockerRuntimeConfig';
|
||||||
|
import { ServerRuntimeConfig } from './ServerRuntimeConfig';
|
||||||
|
import type { RuntimeType } from '../types';
|
||||||
|
import { RUNTIME_TYPE_OPTIONS } from '../types';
|
||||||
|
|
||||||
|
interface RuntimeConfigSectionProps {
|
||||||
|
runtimeType: RuntimeType | null;
|
||||||
|
onRuntimeTypeChange: (type: RuntimeType | null) => void;
|
||||||
|
// K8S配置
|
||||||
|
k8sSystemId: number | null;
|
||||||
|
k8sNamespaceId: number | null;
|
||||||
|
k8sDeploymentId: number | null;
|
||||||
|
onK8sSystemChange: (systemId: number | null) => void;
|
||||||
|
onK8sNamespaceChange: (namespaceId: number | null) => void;
|
||||||
|
onK8sDeploymentIdChange: (deploymentId: number | null) => void;
|
||||||
|
// Docker配置(预留)
|
||||||
|
dockerServerId?: number | null;
|
||||||
|
dockerContainerName?: string;
|
||||||
|
onDockerServerChange?: (serverId: number | null) => void;
|
||||||
|
onDockerContainerNameChange?: (containerName: string) => void;
|
||||||
|
// Server配置(预留)
|
||||||
|
serverId?: number | null;
|
||||||
|
logQueryCommand?: string;
|
||||||
|
onServerChange?: (serverId: number | null) => void;
|
||||||
|
onLogQueryCommandChange?: (command: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const RuntimeConfigSection: React.FC<RuntimeConfigSectionProps> = ({
|
||||||
|
runtimeType,
|
||||||
|
onRuntimeTypeChange,
|
||||||
|
k8sSystemId,
|
||||||
|
k8sNamespaceId,
|
||||||
|
k8sDeploymentId,
|
||||||
|
onK8sSystemChange,
|
||||||
|
onK8sNamespaceChange,
|
||||||
|
onK8sDeploymentIdChange,
|
||||||
|
dockerServerId,
|
||||||
|
dockerContainerName,
|
||||||
|
onDockerServerChange,
|
||||||
|
onDockerContainerNameChange,
|
||||||
|
serverId,
|
||||||
|
logQueryCommand,
|
||||||
|
onServerChange,
|
||||||
|
onLogQueryCommandChange,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div className="space-y-4">
|
||||||
|
{/* 运行时类型选择 */}
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label>运行时类型</Label>
|
||||||
|
<Select
|
||||||
|
value={runtimeType || ''}
|
||||||
|
onValueChange={(value) => {
|
||||||
|
onRuntimeTypeChange(value as RuntimeType);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="选择运行时类型" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{RUNTIME_TYPE_OPTIONS.map((option) => (
|
||||||
|
<SelectItem key={option.value} value={option.value}>
|
||||||
|
{option.label}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<p className="text-xs text-muted-foreground">
|
||||||
|
选择应用的运行时环境类型,用于日志查询和监控
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 根据运行时类型显示对应的配置 */}
|
||||||
|
{runtimeType === 'K8S' && (
|
||||||
|
<K8sRuntimeConfig
|
||||||
|
k8sSystemId={k8sSystemId}
|
||||||
|
k8sNamespaceId={k8sNamespaceId}
|
||||||
|
k8sDeploymentId={k8sDeploymentId}
|
||||||
|
onK8sSystemChange={onK8sSystemChange}
|
||||||
|
onK8sNamespaceChange={onK8sNamespaceChange}
|
||||||
|
onK8sDeploymentIdChange={onK8sDeploymentIdChange}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{runtimeType === 'DOCKER' && (
|
||||||
|
<DockerRuntimeConfig
|
||||||
|
dockerServerId={dockerServerId || null}
|
||||||
|
dockerContainerName={dockerContainerName || ''}
|
||||||
|
onDockerServerChange={onDockerServerChange || (() => {})}
|
||||||
|
onDockerContainerNameChange={onDockerContainerNameChange || (() => {})}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{runtimeType === 'SERVER' && (
|
||||||
|
<ServerRuntimeConfig
|
||||||
|
serverId={serverId || null}
|
||||||
|
logQueryCommand={logQueryCommand || ''}
|
||||||
|
onServerChange={onServerChange || (() => {})}
|
||||||
|
onLogQueryCommandChange={onLogQueryCommandChange || (() => {})}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -0,0 +1,88 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { Label } from '@/components/ui/label';
|
||||||
|
import { Input } from '@/components/ui/input';
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from '@/components/ui/select';
|
||||||
|
import { getServerList } from '@/pages/Resource/Server/List/service';
|
||||||
|
import type { ServerResponse } from '@/pages/Resource/Server/List/types';
|
||||||
|
|
||||||
|
interface ServerRuntimeConfigProps {
|
||||||
|
serverId: number | null;
|
||||||
|
logQueryCommand: string;
|
||||||
|
onServerChange: (serverId: number | null) => void;
|
||||||
|
onLogQueryCommandChange: (command: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ServerRuntimeConfig: React.FC<ServerRuntimeConfigProps> = ({
|
||||||
|
serverId,
|
||||||
|
logQueryCommand,
|
||||||
|
onServerChange,
|
||||||
|
onLogQueryCommandChange,
|
||||||
|
}) => {
|
||||||
|
const [servers, setServers] = useState<ServerResponse[]>([]);
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
loadServers();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const loadServers = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const result = await getServerList();
|
||||||
|
setServers(result || []);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载服务器列表失败:', error);
|
||||||
|
setServers([]);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-4 pl-4 border-l-2 border-muted">
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label>服务器</Label>
|
||||||
|
<Select
|
||||||
|
value={serverId?.toString() || ''}
|
||||||
|
onValueChange={(value) => onServerChange(value ? Number(value) : null)}
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder={loading ? '加载中...' : '选择服务器'} />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{servers.length === 0 ? (
|
||||||
|
<div className="p-4 text-center text-sm text-muted-foreground">
|
||||||
|
{loading ? '加载中...' : '暂无服务器'}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
servers.map((server) => (
|
||||||
|
<SelectItem key={server.id} value={server.id!.toString()}>
|
||||||
|
{server.serverName} ({server.hostIp})
|
||||||
|
</SelectItem>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label>日志查询命令</Label>
|
||||||
|
<Input
|
||||||
|
placeholder="请输入日志查询命令,如:tail -f /var/log/app.log"
|
||||||
|
value={logQueryCommand}
|
||||||
|
onChange={(e) => onLogQueryCommandChange(e.target.value)}
|
||||||
|
/>
|
||||||
|
<p className="text-xs text-muted-foreground">
|
||||||
|
用于查询应用日志的Shell命令
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -26,8 +26,10 @@ import type {
|
|||||||
TeamApplication,
|
TeamApplication,
|
||||||
Application,
|
Application,
|
||||||
BuildType,
|
BuildType,
|
||||||
|
RuntimeType,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import { BUILD_TYPE_OPTIONS } from '../types';
|
import { BUILD_TYPE_OPTIONS } from '../types';
|
||||||
|
import { RuntimeConfigSection } from './RuntimeConfigSection';
|
||||||
import type { RepositoryBranchResponse } from '@/pages/Resource/Git/List/types';
|
import type { RepositoryBranchResponse } from '@/pages/Resource/Git/List/types';
|
||||||
import type { WorkflowDefinition } from '@/pages/Workflow/Definition/List/types';
|
import type { WorkflowDefinition } from '@/pages/Workflow/Definition/List/types';
|
||||||
import { getExternalSystemList } from '@/pages/Resource/External/List/service';
|
import { getExternalSystemList } from '@/pages/Resource/External/List/service';
|
||||||
@ -57,9 +59,18 @@ interface TeamApplicationDialogProps {
|
|||||||
workflowDefinitionId: number | null;
|
workflowDefinitionId: number | null;
|
||||||
sourceGitSystemId: number | null;
|
sourceGitSystemId: number | null;
|
||||||
sourceGitProjectId: number | null;
|
sourceGitProjectId: number | null;
|
||||||
targetGitSystemId: number | null; // 🆕 目标Git系统ID
|
targetGitSystemId: number | null;
|
||||||
targetGitProjectId: number | null; // 🆕 目标Git项目ID
|
targetGitProjectId: number | null;
|
||||||
targetBranch: string; // 🆕 目标分支
|
targetBranch: string;
|
||||||
|
// 运行时配置
|
||||||
|
runtimeType: RuntimeType | null;
|
||||||
|
k8sSystemId: number | null;
|
||||||
|
k8sNamespaceId: number | null;
|
||||||
|
k8sDeploymentId: number | null;
|
||||||
|
dockerServerId: number | null;
|
||||||
|
dockerContainerName: string;
|
||||||
|
serverId: number | null;
|
||||||
|
logQueryCommand: string;
|
||||||
}) => Promise<void>;
|
}) => Promise<void>;
|
||||||
onLoadBranches: (appId: number, app: Application) => Promise<RepositoryBranchResponse[]>;
|
onLoadBranches: (appId: number, app: Application) => Promise<RepositoryBranchResponse[]>;
|
||||||
onLoadJenkinsJobs: (systemId: number) => Promise<any[]>;
|
onLoadJenkinsJobs: (systemId: number) => Promise<any[]>;
|
||||||
@ -97,6 +108,15 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
|
|||||||
targetGitSystemId: null as number | null, // 目标Git系统ID
|
targetGitSystemId: null as number | null, // 目标Git系统ID
|
||||||
targetGitProjectId: null as number | null, // 目标Git项目ID
|
targetGitProjectId: null as number | null, // 目标Git项目ID
|
||||||
targetBranch: '', // 目标分支名称
|
targetBranch: '', // 目标分支名称
|
||||||
|
// 运行时配置
|
||||||
|
runtimeType: null as RuntimeType | null, // 运行时类型
|
||||||
|
k8sSystemId: null as number | null, // K8S系统ID
|
||||||
|
k8sNamespaceId: null as number | null, // K8S命名空间ID
|
||||||
|
k8sDeploymentId: null as number | null, // K8S Deployment ID
|
||||||
|
dockerServerId: null as number | null, // Docker服务器ID
|
||||||
|
dockerContainerName: '', // Docker容器名称
|
||||||
|
serverId: null as number | null, // 服务器ID
|
||||||
|
logQueryCommand: '', // 日志查询命令
|
||||||
});
|
});
|
||||||
|
|
||||||
// 加载状态
|
// 加载状态
|
||||||
@ -137,6 +157,15 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
|
|||||||
targetGitSystemId: application.targetGitSystemId || null,
|
targetGitSystemId: application.targetGitSystemId || null,
|
||||||
targetGitProjectId: application.targetGitProjectId || null,
|
targetGitProjectId: application.targetGitProjectId || null,
|
||||||
targetBranch: application.targetBranch || '',
|
targetBranch: application.targetBranch || '',
|
||||||
|
// 运行时配置
|
||||||
|
runtimeType: application.runtimeType || null,
|
||||||
|
k8sSystemId: application.k8sSystemId || null,
|
||||||
|
k8sNamespaceId: application.k8sNamespaceId || null,
|
||||||
|
k8sDeploymentId: application.k8sDeploymentId || null,
|
||||||
|
dockerServerId: application.dockerServerId || null,
|
||||||
|
dockerContainerName: application.dockerContainerName || '',
|
||||||
|
serverId: application.serverId || null,
|
||||||
|
logQueryCommand: application.logQueryCommand || '',
|
||||||
});
|
});
|
||||||
|
|
||||||
// 加载源仓库项目
|
// 加载源仓库项目
|
||||||
@ -184,6 +213,15 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
|
|||||||
targetGitSystemId: null,
|
targetGitSystemId: null,
|
||||||
targetGitProjectId: null,
|
targetGitProjectId: null,
|
||||||
targetBranch: '',
|
targetBranch: '',
|
||||||
|
// 运行时配置
|
||||||
|
runtimeType: null,
|
||||||
|
k8sSystemId: null,
|
||||||
|
k8sNamespaceId: null,
|
||||||
|
k8sDeploymentId: null,
|
||||||
|
dockerServerId: null,
|
||||||
|
dockerContainerName: '',
|
||||||
|
serverId: null,
|
||||||
|
logQueryCommand: '',
|
||||||
});
|
});
|
||||||
setBranches([]);
|
setBranches([]);
|
||||||
setJenkinsJobs([]);
|
setJenkinsJobs([]);
|
||||||
@ -279,6 +317,15 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
|
|||||||
targetGitSystemId: null,
|
targetGitSystemId: null,
|
||||||
targetGitProjectId: null,
|
targetGitProjectId: null,
|
||||||
targetBranch: '',
|
targetBranch: '',
|
||||||
|
// 保留运行时配置
|
||||||
|
runtimeType: formData.runtimeType,
|
||||||
|
k8sSystemId: formData.k8sSystemId,
|
||||||
|
k8sNamespaceId: formData.k8sNamespaceId,
|
||||||
|
k8sDeploymentId: formData.k8sDeploymentId,
|
||||||
|
dockerServerId: formData.dockerServerId,
|
||||||
|
dockerContainerName: formData.dockerContainerName,
|
||||||
|
serverId: formData.serverId,
|
||||||
|
logQueryCommand: formData.logQueryCommand,
|
||||||
});
|
});
|
||||||
// 清空分支列表(分支现在基于代码源,不基于应用)
|
// 清空分支列表(分支现在基于代码源,不基于应用)
|
||||||
setBranches([]);
|
setBranches([]);
|
||||||
@ -435,6 +482,34 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 运行时配置验证
|
||||||
|
if (formData.runtimeType === 'K8S') {
|
||||||
|
if (!formData.k8sSystemId) {
|
||||||
|
toast({
|
||||||
|
variant: 'destructive',
|
||||||
|
title: '请选择K8S系统',
|
||||||
|
description: '已选择K8S运行时类型,必须配置K8S系统',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!formData.k8sNamespaceId) {
|
||||||
|
toast({
|
||||||
|
variant: 'destructive',
|
||||||
|
title: '请选择Namespace',
|
||||||
|
description: '已选择K8S运行时类型,必须配置Namespace',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!formData.k8sDeploymentId) {
|
||||||
|
toast({
|
||||||
|
variant: 'destructive',
|
||||||
|
title: '请选择Deployment',
|
||||||
|
description: '已选择K8S运行时类型,必须配置Deployment',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setSaving(true);
|
setSaving(true);
|
||||||
try {
|
try {
|
||||||
await onSave({
|
await onSave({
|
||||||
@ -450,6 +525,15 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
|
|||||||
targetGitSystemId: formData.targetGitSystemId,
|
targetGitSystemId: formData.targetGitSystemId,
|
||||||
targetGitProjectId: formData.targetGitProjectId,
|
targetGitProjectId: formData.targetGitProjectId,
|
||||||
targetBranch: formData.targetBranch,
|
targetBranch: formData.targetBranch,
|
||||||
|
// 运行时配置
|
||||||
|
runtimeType: formData.runtimeType,
|
||||||
|
k8sSystemId: formData.k8sSystemId,
|
||||||
|
k8sNamespaceId: formData.k8sNamespaceId,
|
||||||
|
k8sDeploymentId: formData.k8sDeploymentId,
|
||||||
|
dockerServerId: formData.dockerServerId,
|
||||||
|
dockerContainerName: formData.dockerContainerName,
|
||||||
|
serverId: formData.serverId,
|
||||||
|
logQueryCommand: formData.logQueryCommand,
|
||||||
});
|
});
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
@ -783,6 +867,48 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
|
|||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* 运行时配置 */}
|
||||||
|
<RuntimeConfigSection
|
||||||
|
runtimeType={formData.runtimeType}
|
||||||
|
onRuntimeTypeChange={(type) => {
|
||||||
|
setFormData({
|
||||||
|
...formData,
|
||||||
|
runtimeType: type,
|
||||||
|
// 切换类型时清空所有运行时配置
|
||||||
|
k8sSystemId: null,
|
||||||
|
k8sNamespaceId: null,
|
||||||
|
k8sDeploymentId: null,
|
||||||
|
dockerServerId: null,
|
||||||
|
dockerContainerName: '',
|
||||||
|
serverId: null,
|
||||||
|
logQueryCommand: '',
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
k8sSystemId={formData.k8sSystemId}
|
||||||
|
k8sNamespaceId={formData.k8sNamespaceId}
|
||||||
|
k8sDeploymentId={formData.k8sDeploymentId}
|
||||||
|
onK8sSystemChange={(systemId) => setFormData(prev => ({
|
||||||
|
...prev,
|
||||||
|
k8sSystemId: systemId,
|
||||||
|
k8sNamespaceId: null,
|
||||||
|
k8sDeploymentId: null
|
||||||
|
}))}
|
||||||
|
onK8sNamespaceChange={(namespaceId) => setFormData(prev => ({
|
||||||
|
...prev,
|
||||||
|
k8sNamespaceId: namespaceId,
|
||||||
|
k8sDeploymentId: null
|
||||||
|
}))}
|
||||||
|
onK8sDeploymentIdChange={(deploymentId) => setFormData(prev => ({ ...prev, k8sDeploymentId: deploymentId }))}
|
||||||
|
dockerServerId={formData.dockerServerId}
|
||||||
|
dockerContainerName={formData.dockerContainerName}
|
||||||
|
onDockerServerChange={(serverId) => setFormData(prev => ({ ...prev, dockerServerId: serverId }))}
|
||||||
|
onDockerContainerNameChange={(containerName) => setFormData(prev => ({ ...prev, dockerContainerName: containerName }))}
|
||||||
|
serverId={formData.serverId}
|
||||||
|
logQueryCommand={formData.logQueryCommand}
|
||||||
|
onServerChange={(serverId) => setFormData(prev => ({ ...prev, serverId: serverId }))}
|
||||||
|
onLogQueryCommandChange={(command) => setFormData(prev => ({ ...prev, logQueryCommand: command }))}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</DialogBody>
|
</DialogBody>
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import { Button } from '@/components/ui/button';
|
|||||||
import { useToast } from '@/components/ui/use-toast';
|
import { useToast } from '@/components/ui/use-toast';
|
||||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
|
||||||
import { PaginatedTable, type ColumnDef, type PaginatedTableRef } from '@/components/ui/paginated-table';
|
import { PaginatedTable, type ColumnDef, type PaginatedTableRef } from '@/components/ui/paginated-table';
|
||||||
import { Plus, Edit, Trash2, GitBranch } from 'lucide-react';
|
import { Plus, Edit, Trash2, GitBranch, Hammer, Box, Container, Server } from 'lucide-react';
|
||||||
import type { Environment } from '@/pages/Deploy/Environment/List/types';
|
import type { Environment } from '@/pages/Deploy/Environment/List/types';
|
||||||
import type { TeamApplication, Application } from '../types';
|
import type { TeamApplication, Application } from '../types';
|
||||||
import type { WorkflowDefinition } from '@/pages/Workflow/Definition/List/types';
|
import type { WorkflowDefinition } from '@/pages/Workflow/Definition/List/types';
|
||||||
@ -129,9 +129,18 @@ export const TeamApplicationManageDialog: React.FC<
|
|||||||
workflowDefinitionId: number | null;
|
workflowDefinitionId: number | null;
|
||||||
sourceGitSystemId: number | null;
|
sourceGitSystemId: number | null;
|
||||||
sourceGitProjectId: number | null;
|
sourceGitProjectId: number | null;
|
||||||
targetGitSystemId: number | null; // 🆕 目标Git系统ID
|
targetGitSystemId: number | null;
|
||||||
targetGitProjectId: number | null; // 🆕 目标Git项目ID
|
targetGitProjectId: number | null;
|
||||||
targetBranch: string; // 🆕 目标分支
|
targetBranch: string;
|
||||||
|
// 运行时配置
|
||||||
|
runtimeType: 'K8S' | 'DOCKER' | 'SERVER' | null;
|
||||||
|
k8sSystemId: number | null;
|
||||||
|
k8sNamespaceId: number | null;
|
||||||
|
k8sDeploymentId: number | null;
|
||||||
|
dockerServerId: number | null;
|
||||||
|
dockerContainerName: string;
|
||||||
|
serverId: number | null;
|
||||||
|
logQueryCommand: string;
|
||||||
}) => {
|
}) => {
|
||||||
if (!editingEnvironment) return;
|
if (!editingEnvironment) return;
|
||||||
|
|
||||||
@ -147,10 +156,19 @@ export const TeamApplicationManageDialog: React.FC<
|
|||||||
workflowDefinitionId: data.workflowDefinitionId || undefined,
|
workflowDefinitionId: data.workflowDefinitionId || undefined,
|
||||||
sourceGitSystemId: data.sourceGitSystemId || undefined,
|
sourceGitSystemId: data.sourceGitSystemId || undefined,
|
||||||
sourceGitProjectId: data.sourceGitProjectId || undefined,
|
sourceGitProjectId: data.sourceGitProjectId || undefined,
|
||||||
// 🆕 目标Git相关字段
|
// 目标Git相关字段
|
||||||
targetGitSystemId: data.targetGitSystemId || undefined,
|
targetGitSystemId: data.targetGitSystemId || undefined,
|
||||||
targetGitProjectId: data.targetGitProjectId || undefined,
|
targetGitProjectId: data.targetGitProjectId || undefined,
|
||||||
targetBranch: data.targetBranch || undefined,
|
targetBranch: data.targetBranch || undefined,
|
||||||
|
// 运行时配置字段
|
||||||
|
runtimeType: data.runtimeType || undefined,
|
||||||
|
k8sSystemId: data.k8sSystemId || undefined,
|
||||||
|
k8sNamespaceId: data.k8sNamespaceId || undefined,
|
||||||
|
k8sDeploymentId: data.k8sDeploymentId || undefined,
|
||||||
|
dockerServerId: data.dockerServerId || undefined,
|
||||||
|
dockerContainerName: data.dockerContainerName || undefined,
|
||||||
|
serverId: data.serverId || undefined,
|
||||||
|
logQueryCommand: data.logQueryCommand || undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (appDialogMode === 'edit' && data.id) {
|
if (appDialogMode === 'edit' && data.id) {
|
||||||
@ -295,26 +313,50 @@ export const TeamApplicationManageDialog: React.FC<
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'buildType',
|
key: 'buildConfig',
|
||||||
title: '构建类型',
|
title: '构建配置',
|
||||||
width: '120px',
|
width: '250px',
|
||||||
render: (_, app) =>
|
render: (_, app) => {
|
||||||
app.buildType === 'JENKINS' ? 'Jenkins构建' : app.buildType === 'NATIVE' ? '脚本部署' : '-',
|
if (!app.buildType) {
|
||||||
},
|
return <span className="text-muted-foreground">-</span>;
|
||||||
{
|
}
|
||||||
key: 'deploySystemName',
|
|
||||||
title: 'Jenkins系统',
|
// Jenkins 构建
|
||||||
width: '150px',
|
if (app.buildType === 'JENKINS') {
|
||||||
render: (_, app) =>
|
return (
|
||||||
app.buildType === 'JENKINS'
|
<div className="space-y-1">
|
||||||
? (app.deploySystemName || (app.deploySystemId ? `系统 ${app.deploySystemId}` : '-'))
|
<div className="flex items-center gap-1.5">
|
||||||
: '-',
|
<Hammer className="h-3.5 w-3.5 text-blue-500" />
|
||||||
},
|
<span className="inline-flex items-center rounded-md bg-blue-50 px-2 py-0.5 text-xs font-medium text-blue-700 ring-1 ring-inset ring-blue-700/10">
|
||||||
{
|
Jenkins构建
|
||||||
key: 'deployJob',
|
</span>
|
||||||
title: 'Jenkins Job',
|
</div>
|
||||||
width: '150px',
|
<div className="text-xs text-muted-foreground pl-5">
|
||||||
render: (_, app) => (app.buildType === 'JENKINS' ? (app.deployJob || '-') : '-'),
|
{app.deploySystemName || '-'}
|
||||||
|
</div>
|
||||||
|
{app.deployJob && (
|
||||||
|
<div className="text-xs text-muted-foreground pl-5 truncate" title={app.deployJob}>
|
||||||
|
{app.deployJob}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 脚本部署
|
||||||
|
if (app.buildType === 'NATIVE') {
|
||||||
|
return (
|
||||||
|
<div className="flex items-center gap-1.5">
|
||||||
|
<Hammer className="h-3.5 w-3.5 text-green-500" />
|
||||||
|
<span className="inline-flex items-center rounded-md bg-green-50 px-2 py-0.5 text-xs font-medium text-green-700 ring-1 ring-inset ring-green-700/10">
|
||||||
|
脚本部署
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <span className="text-muted-foreground">-</span>;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'workflowDefinitionName',
|
key: 'workflowDefinitionName',
|
||||||
@ -323,6 +365,85 @@ export const TeamApplicationManageDialog: React.FC<
|
|||||||
width: '180px',
|
width: '180px',
|
||||||
render: (value) => value || '-',
|
render: (value) => value || '-',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'runtimeConfig',
|
||||||
|
title: '运行时配置',
|
||||||
|
width: '250px',
|
||||||
|
render: (_, app) => {
|
||||||
|
if (!app.runtimeType) {
|
||||||
|
return <span className="text-muted-foreground">-</span>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// K8S 运行时配置
|
||||||
|
if (app.runtimeType === 'K8S') {
|
||||||
|
const k8sPath = [
|
||||||
|
app.k8sSystemName,
|
||||||
|
app.k8sNamespaceName,
|
||||||
|
app.k8sDeploymentName
|
||||||
|
].filter(Boolean).join(' / ') || '-';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-1">
|
||||||
|
<div className="flex items-center gap-1.5">
|
||||||
|
<Box className="h-3.5 w-3.5 text-purple-500" />
|
||||||
|
<span className="inline-flex items-center rounded-md bg-purple-50 px-2 py-0.5 text-xs font-medium text-purple-700 ring-1 ring-inset ring-purple-700/10">
|
||||||
|
Kubernetes
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="text-xs text-muted-foreground pl-5 truncate" title={k8sPath}>
|
||||||
|
{k8sPath}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Docker 运行时配置
|
||||||
|
if (app.runtimeType === 'DOCKER') {
|
||||||
|
return (
|
||||||
|
<div className="space-y-1">
|
||||||
|
<div className="flex items-center gap-1.5">
|
||||||
|
<Container className="h-3.5 w-3.5 text-orange-500" />
|
||||||
|
<span className="inline-flex items-center rounded-md bg-orange-50 px-2 py-0.5 text-xs font-medium text-orange-700 ring-1 ring-inset ring-orange-700/10">
|
||||||
|
Docker
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="text-xs text-muted-foreground pl-5">
|
||||||
|
{app.dockerServerName || '-'}
|
||||||
|
</div>
|
||||||
|
{app.dockerContainerName && (
|
||||||
|
<div className="text-xs text-muted-foreground pl-5 truncate" title={app.dockerContainerName}>
|
||||||
|
{app.dockerContainerName}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Server 运行时配置
|
||||||
|
if (app.runtimeType === 'SERVER') {
|
||||||
|
return (
|
||||||
|
<div className="space-y-1">
|
||||||
|
<div className="flex items-center gap-1.5">
|
||||||
|
<Server className="h-3.5 w-3.5 text-gray-500" />
|
||||||
|
<span className="inline-flex items-center rounded-md bg-gray-50 px-2 py-0.5 text-xs font-medium text-gray-700 ring-1 ring-inset ring-gray-700/10">
|
||||||
|
服务器
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="text-xs text-muted-foreground pl-5">
|
||||||
|
{app.serverName || '-'}
|
||||||
|
</div>
|
||||||
|
{app.logQueryCommand && (
|
||||||
|
<div className="text-xs text-muted-foreground pl-5 truncate" title={app.logQueryCommand}>
|
||||||
|
{app.logQueryCommand}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <span className="text-muted-foreground">-</span>;
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'actions',
|
key: 'actions',
|
||||||
title: '操作',
|
title: '操作',
|
||||||
|
|||||||
@ -172,6 +172,20 @@ export const BUILD_TYPE_OPTIONS = [
|
|||||||
{ value: 'NATIVE', label: '脚本部署' },
|
{ value: 'NATIVE', label: '脚本部署' },
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 运行时类型枚举
|
||||||
|
*/
|
||||||
|
export type RuntimeType = 'K8S' | 'DOCKER' | 'SERVER';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 运行时类型选项
|
||||||
|
*/
|
||||||
|
export const RUNTIME_TYPE_OPTIONS = [
|
||||||
|
{ value: 'K8S', label: 'Kubernetes' },
|
||||||
|
{ value: 'DOCKER', label: 'Docker' },
|
||||||
|
{ value: 'SERVER', label: '服务器' },
|
||||||
|
] as const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 团队应用关联响应
|
* 团队应用关联响应
|
||||||
*/
|
*/
|
||||||
@ -189,6 +203,16 @@ export interface TeamApplication extends BaseResponse {
|
|||||||
targetGitSystemId?: number; // 目标Git系统ID(仅SYNC_MODE)
|
targetGitSystemId?: number; // 目标Git系统ID(仅SYNC_MODE)
|
||||||
targetGitProjectId?: number; // 目标Git项目ID
|
targetGitProjectId?: number; // 目标Git项目ID
|
||||||
targetBranch?: string; // 目标分支名称
|
targetBranch?: string; // 目标分支名称
|
||||||
|
// 运行时配置字段
|
||||||
|
runtimeType?: RuntimeType; // 运行时类型
|
||||||
|
k8sSystemId?: number; // K8S系统ID
|
||||||
|
k8sNamespaceId?: number; // K8S命名空间ID
|
||||||
|
k8sDeploymentId?: number; // K8S Deployment ID
|
||||||
|
dockerServerId?: number; // Docker服务器ID
|
||||||
|
dockerContainerName?: string; // Docker容器名称
|
||||||
|
serverId?: number; // 服务器ID
|
||||||
|
logQueryCommand?: string; // 日志查询命令(Server类型使用)
|
||||||
|
// 关联数据
|
||||||
teamName?: string;
|
teamName?: string;
|
||||||
applicationName?: string;
|
applicationName?: string;
|
||||||
applicationCode?: string;
|
applicationCode?: string;
|
||||||
@ -199,6 +223,12 @@ export interface TeamApplication extends BaseResponse {
|
|||||||
sourceGitProjectName?: string; // 源Git项目名称
|
sourceGitProjectName?: string; // 源Git项目名称
|
||||||
targetGitSystemName?: string; // 目标Git系统名称
|
targetGitSystemName?: string; // 目标Git系统名称
|
||||||
targetGitProjectName?: string; // 目标Git项目名称
|
targetGitProjectName?: string; // 目标Git项目名称
|
||||||
|
// 运行时配置关联数据
|
||||||
|
k8sSystemName?: string; // K8S系统名称
|
||||||
|
k8sNamespaceName?: string; // K8S命名空间名称
|
||||||
|
k8sDeploymentName?: string; // K8S Deployment名称
|
||||||
|
dockerServerName?: string; // Docker服务器名称
|
||||||
|
serverName?: string; // 服务器名称
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -218,5 +248,14 @@ export interface TeamApplicationRequest {
|
|||||||
targetGitSystemId?: number; // 目标Git系统ID(仅SYNC_MODE)
|
targetGitSystemId?: number; // 目标Git系统ID(仅SYNC_MODE)
|
||||||
targetGitProjectId?: number; // 目标Git项目ID
|
targetGitProjectId?: number; // 目标Git项目ID
|
||||||
targetBranch?: string; // 目标分支名称
|
targetBranch?: string; // 目标分支名称
|
||||||
|
// 运行时配置字段
|
||||||
|
runtimeType?: RuntimeType; // 运行时类型
|
||||||
|
k8sSystemId?: number; // K8S系统ID
|
||||||
|
k8sNamespaceId?: number; // K8S命名空间ID
|
||||||
|
k8sDeploymentId?: number; // K8S Deployment ID
|
||||||
|
dockerServerId?: number; // Docker服务器ID
|
||||||
|
dockerContainerName?: string; // Docker容器名称
|
||||||
|
serverId?: number; // 服务器ID
|
||||||
|
logQueryCommand?: string; // 日志查询命令(Server类型使用)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user