|
|
|
|
<script setup lang="ts">
|
|
|
|
|
import { defineProps, onMounted, watch, ref, computed } from "vue";
|
|
|
|
|
import { WorkflowStepService } from "@/components/service/management/workflowStepService";
|
|
|
|
|
import { WorkflowService } from "@/components/service/management/workflowService"; // ⬅️ 추가
|
|
|
|
|
|
|
|
|
|
const props = defineProps<{ id: number | string }>();
|
|
|
|
|
const emit = defineEmits<{ (e: "close"): void }>();
|
|
|
|
|
|
|
|
|
|
const loading = ref(false);
|
|
|
|
|
const detailRaw = ref<any | null>(null);
|
|
|
|
|
|
|
|
|
|
// ⬇️ 워크플로우 이름은 별도 상태로
|
|
|
|
|
const workflowName = ref<string>("-");
|
|
|
|
|
|
|
|
|
|
const formatIso = (s?: string) => (s ? s.replace("T", " ").slice(0, 19) : "-");
|
|
|
|
|
|
|
|
|
|
const mapToViewModel = (raw: any) => ({
|
|
|
|
|
stepName: raw?.stepName ?? raw?.name ?? "-",
|
|
|
|
|
// 여기 값은 임시, 실제 표시는 아래 computed에서 workflowName ref로 덮어씀
|
|
|
|
|
workflowName: raw?.workflowName ?? raw?.pipelineName ?? "-",
|
|
|
|
|
createdDate: formatIso(raw?.regDttm ?? raw?.regDt ?? raw?.createdAt),
|
|
|
|
|
createdId: raw?.regUserId ?? raw?.createdBy ?? "-",
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const info = computed(() => ({
|
|
|
|
|
...mapToViewModel(detailRaw.value || {}),
|
|
|
|
|
workflowName: workflowName.value, // ⬅️ 최종 표시는 이 값
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
// ⬇️ id → 워크플로우 이름 조회
|
|
|
|
|
async function resolveWorkflowName(raw: any) {
|
|
|
|
|
// 1) 응답에 이미 이름이 있으면 그걸 사용
|
|
|
|
|
const direct =
|
|
|
|
|
raw?.workflowName ||
|
|
|
|
|
raw?.pipelineName ||
|
|
|
|
|
raw?.workflow?.workflowName ||
|
|
|
|
|
raw?.workflow?.name;
|
|
|
|
|
if (direct) {
|
|
|
|
|
workflowName.value = direct;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2) FK 후보에서 워크플로우 id 뽑기 (환경에 따라 필드명이 다를 수 있어 방어적으로)
|
|
|
|
|
const wfId =
|
|
|
|
|
raw?.workflowStepId ?? // 지금 콘솔에 보이는 필드
|
|
|
|
|
raw?.workflowId ??
|
|
|
|
|
raw?.workflow?.id ??
|
|
|
|
|
null;
|
|
|
|
|
|
|
|
|
|
if (!wfId) {
|
|
|
|
|
workflowName.value = "-";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const res = await WorkflowService.view(Number(wfId));
|
|
|
|
|
const w = res?.data ?? res;
|
|
|
|
|
workflowName.value = w?.workflowName || w?.name || `#${wfId}`;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.warn("[ViewComponent] workflow fetch failed:", e);
|
|
|
|
|
workflowName.value = `#${wfId}`; // 최소한 id라도 보여주기
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function fetchDetail(id: number | string) {
|
|
|
|
|
const idNum = typeof id === "string" ? Number(id) : id;
|
|
|
|
|
if (!Number.isFinite(idNum as number)) return;
|
|
|
|
|
|
|
|
|
|
loading.value = true;
|
|
|
|
|
try {
|
|
|
|
|
const res = await WorkflowStepService.view(idNum as number);
|
|
|
|
|
const raw = res?.data ?? res;
|
|
|
|
|
detailRaw.value = raw;
|
|
|
|
|
|
|
|
|
|
// ⬇️ 여기서 이름 해석
|
|
|
|
|
await resolveWorkflowName(raw);
|
|
|
|
|
|
|
|
|
|
console.log("[ViewComponent] raw:", raw);
|
|
|
|
|
console.log("[ViewComponent] info:", info.value);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error("[ViewComponent] fetch detail error:", e);
|
|
|
|
|
} finally {
|
|
|
|
|
loading.value = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onMounted(() => fetchDetail(props.id));
|
|
|
|
|
watch(
|
|
|
|
|
() => props.id,
|
|
|
|
|
(now) => {
|
|
|
|
|
if (now !== undefined && now !== null && now !== "") fetchDetail(now);
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
<v-container fluid class="h-100 pa-5 d-flex flex-column align-center">
|
|
|
|
|
<!-- 상단 타이틀 -->
|
|
|
|
|
<v-card flat class="bg-shades-transparent w-100 mb-6">
|
|
|
|
|
<v-card-item class="text-h5 font-weight-bold pt-0 pa-5 pl-0">
|
|
|
|
|
<div class="d-flex flex-row justify-start align-center">
|
|
|
|
|
<div class="text-primary">View Details</div>
|
|
|
|
|
</div>
|
|
|
|
|
</v-card-item>
|
|
|
|
|
</v-card>
|
|
|
|
|
|
|
|
|
|
<!-- Workflow Step Information -->
|
|
|
|
|
<v-card flat class="bordered-box mb-6 w-100 rounded-lg pa-6" elevation="2">
|
|
|
|
|
<v-card-title class="grey lighten-4 py-2 px-4">
|
|
|
|
|
<span class="font-weight-bold">Workflow Step Information</span>
|
|
|
|
|
</v-card-title>
|
|
|
|
|
<v-card-text class="py-4">
|
|
|
|
|
<v-row align="center" class="mb-2">
|
|
|
|
|
<v-col cols="3" class="font-weight-bold">Workflow Step Name</v-col>
|
|
|
|
|
<v-col cols="3">{{ info.stepName }}</v-col>
|
|
|
|
|
|
|
|
|
|
<v-col cols="3" class="font-weight-bold">Workflow Name</v-col>
|
|
|
|
|
<v-col cols="3">{{ info.workflowName }}</v-col>
|
|
|
|
|
</v-row>
|
|
|
|
|
<v-divider />
|
|
|
|
|
<v-row align="center" class="mt-2">
|
|
|
|
|
<v-col cols="3" class="font-weight-bold">Created Date</v-col>
|
|
|
|
|
<v-col cols="3">{{ info.createdDate }}</v-col>
|
|
|
|
|
|
|
|
|
|
<v-col cols="3" class="font-weight-bold">Created ID</v-col>
|
|
|
|
|
<v-col cols="3">{{ info.createdId }}</v-col>
|
|
|
|
|
</v-row>
|
|
|
|
|
</v-card-text>
|
|
|
|
|
<v-sheet class="d-flex justify-end mt-4">
|
|
|
|
|
<v-btn color="primary" @click="emit('close')">Back to List</v-btn>
|
|
|
|
|
</v-sheet>
|
|
|
|
|
</v-card>
|
|
|
|
|
|
|
|
|
|
<!-- Dataset -->
|
|
|
|
|
<!-- <v-card flat class="bordered-box mb-6 w-100 rounded-lg pa-6" elevation="2">
|
|
|
|
|
<v-card-title class="grey lighten-4 py-2 px-4">
|
|
|
|
|
<span class="font-weight-bold">Dataset</span>
|
|
|
|
|
</v-card-title>
|
|
|
|
|
<v-card-text class="py-4">
|
|
|
|
|
<v-row align="center">
|
|
|
|
|
<v-col cols="3" class="font-weight-bold">Dataset Name</v-col>
|
|
|
|
|
<v-col cols="3">야간 주행용 레이더 데이터셋 구성</v-col>
|
|
|
|
|
<v-col cols="3" class="font-weight-bold">Version</v-col>
|
|
|
|
|
<v-col cols="3">v2.0</v-col>
|
|
|
|
|
</v-row>
|
|
|
|
|
</v-card-text>
|
|
|
|
|
</v-card> -->
|
|
|
|
|
|
|
|
|
|
<!-- Training Script -->
|
|
|
|
|
<!-- <v-card flat class="bordered-box mb-6 w-100 rounded-lg pa-6" elevation="2">
|
|
|
|
|
<v-card-title class="grey lighten-4 py-2 px-4">
|
|
|
|
|
<span class="font-weight-bold">Training Script</span>
|
|
|
|
|
</v-card-title>
|
|
|
|
|
<v-card-text class="py-4">
|
|
|
|
|
<v-row align="center" class="mb-2">
|
|
|
|
|
<v-col cols="3" class="font-weight-bold">Script File</v-col>
|
|
|
|
|
<v-col cols="9">baseline_train.py</v-col>
|
|
|
|
|
</v-row>
|
|
|
|
|
<v-divider />
|
|
|
|
|
<v-row align="center" class="mt-2">
|
|
|
|
|
<v-col cols="3" class="font-weight-bold">Script File Path</v-col>
|
|
|
|
|
<v-col cols="9" style="word-break: break-all">
|
|
|
|
|
/mnt/nfs/model_code/baseline/baseline_train.py
|
|
|
|
|
</v-col>
|
|
|
|
|
</v-row>
|
|
|
|
|
</v-card-text>
|
|
|
|
|
</v-card> -->
|
|
|
|
|
|
|
|
|
|
<!-- Hyperparameters -->
|
|
|
|
|
<!-- <v-card flat class="bordered-box mb-6 w-100 rounded-lg pa-6" elevation="2">
|
|
|
|
|
<v-card-title class="grey lighten-4 py-2 px-4">
|
|
|
|
|
<span class="font-weight-bold">Hyperparameters</span>
|
|
|
|
|
</v-card-title>
|
|
|
|
|
<v-card-text class="py-4">
|
|
|
|
|
<v-row align="center" class="mb-2">
|
|
|
|
|
<v-col cols="3" class="font-weight-bold">Batch Size</v-col>
|
|
|
|
|
<v-col cols="3">64</v-col>
|
|
|
|
|
<v-col cols="3" class="font-weight-bold">Learning Rate</v-col>
|
|
|
|
|
<v-col cols="3">0.001</v-col>
|
|
|
|
|
</v-row>
|
|
|
|
|
<v-divider />
|
|
|
|
|
<v-row align="center" class="mt-2">
|
|
|
|
|
<v-col cols="3" class="font-weight-bold">Optimizer</v-col>
|
|
|
|
|
<v-col cols="3">Adam</v-col>
|
|
|
|
|
<v-col cols="3" class="font-weight-bold">Epochs</v-col>
|
|
|
|
|
<v-col cols="3">20</v-col>
|
|
|
|
|
</v-row>
|
|
|
|
|
</v-card-text>
|
|
|
|
|
</v-card> -->
|
|
|
|
|
|
|
|
|
|
<!-- Resource & Scheduling -->
|
|
|
|
|
<!-- <v-card flat class="bordered-box mb-6 w-100 rounded-lg pa-6" elevation="2">
|
|
|
|
|
<v-card-title class="grey lighten-4 py-2 px-4">
|
|
|
|
|
<span class="font-weight-bold">Resource & Scheduling</span>
|
|
|
|
|
</v-card-title>
|
|
|
|
|
<v-card-text class="py-4">
|
|
|
|
|
<v-row align="center" class="mb-2">
|
|
|
|
|
<v-col cols="3" class="font-weight-bold">CPU Cores</v-col>
|
|
|
|
|
<v-col cols="3">4</v-col>
|
|
|
|
|
<v-col cols="3" class="font-weight-bold">Memory</v-col>
|
|
|
|
|
<v-col cols="3">16Gi</v-col>
|
|
|
|
|
</v-row>
|
|
|
|
|
<v-divider />
|
|
|
|
|
<v-row align="center" class="mt-2">
|
|
|
|
|
<v-col cols="3" class="font-weight-bold">GPU</v-col>
|
|
|
|
|
<v-col cols="9">1 (NVIDIA A100)</v-col>
|
|
|
|
|
</v-row>
|
|
|
|
|
</v-card-text>
|
|
|
|
|
</v-card> -->
|
|
|
|
|
|
|
|
|
|
<!-- Docker image -->
|
|
|
|
|
<!-- <v-card flat class="bordered-box mb-6 w-100 rounded-lg pa-6" elevation="2">
|
|
|
|
|
<v-card-title class="grey lighten-4 py-2 px-4">
|
|
|
|
|
<span class="font-weight-bold">Docker image</span>
|
|
|
|
|
</v-card-title>
|
|
|
|
|
<v-card-text class="py-4">
|
|
|
|
|
<v-sheet class="pa-2" elevation="2">
|
|
|
|
|
kubeflownotebookswg/jupyter-pytorch-cuda-full:v1.9.2
|
|
|
|
|
</v-sheet>
|
|
|
|
|
</v-card-text>
|
|
|
|
|
|
|
|
|
|
</v-card> -->
|
|
|
|
|
</v-container>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<style scoped></style>
|