475950be36
Validators (Pushes and Pull Requests) / validate-ui-and-storage (push) Successful in 22s
Validators (Pushes and Pull Requests) / validate-core (push) Has been cancelled
Prepare Release / Build & Create Release (push) Successful in 1m9s
Prepare Release / Release Notification (push) Successful in 2s
219 lines
9.9 KiB
Plaintext
219 lines
9.9 KiB
Plaintext
@page
|
|
@model QuantEngine.Web.Pages.Admin.Operations.IndexModel
|
|
@{
|
|
ViewData["Title"] = "작업 관리";
|
|
}
|
|
|
|
<div class="page-header d-print-none">
|
|
<div class="row align-items-center">
|
|
<div class="col">
|
|
<h2 class="page-title">작업 관리</h2>
|
|
</div>
|
|
<div class="col-auto">
|
|
<button class="btn btn-secondary" onclick="location.reload()">새로고침</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="page-body">
|
|
@if (TempData["SuccessMessage"] != null)
|
|
{
|
|
<div class="alert alert-success" role="alert" style="background-color: rgba(76, 175, 80, 0.15); border: 1px solid rgba(76, 175, 80, 0.3); color: #81c784; padding: 12px; border-radius: 6px; margin-bottom: 16px;">
|
|
@TempData["SuccessMessage"]
|
|
</div>
|
|
}
|
|
@if (TempData["ErrorMessage"] != null)
|
|
{
|
|
<div class="alert alert-danger" role="alert" style="background-color: rgba(244, 67, 54, 0.15); border: 1px solid rgba(244, 67, 54, 0.3); color: #ff7675; padding: 12px; border-radius: 6px; margin-bottom: 16px;">
|
|
@TempData["ErrorMessage"]
|
|
</div>
|
|
}
|
|
<div class="row row-deck row-cards">
|
|
<!-- 예약된 작업 -->
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h3 class="card-title">예약된 작업</h3>
|
|
</div>
|
|
<div class="table-responsive">
|
|
<table class="table table-vcenter card-table">
|
|
<thead>
|
|
<tr>
|
|
<th>작업명</th>
|
|
<th>스케줄</th>
|
|
<th>다음 실행</th>
|
|
<th>상태</th>
|
|
<th>작업</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@if (Model.ScheduledJobs?.Any() == true)
|
|
{
|
|
@foreach (var job in Model.ScheduledJobs)
|
|
{
|
|
<tr>
|
|
<td>
|
|
<strong>@job.JobName</strong>
|
|
</td>
|
|
<td><small>@job.Schedule</small></td>
|
|
<td>@(job.NextRun?.ToString("yyyy-MM-dd HH:mm:ss") ?? "-")</td>
|
|
<td>
|
|
@if (job.IsEnabled)
|
|
{
|
|
<span class="badge bg-success">활성</span>
|
|
}
|
|
else
|
|
{
|
|
<span class="badge bg-secondary">비활성</span>
|
|
}
|
|
</td>
|
|
<td>
|
|
<form method="post" asp-page-handler="TriggerJob" class="d-inline">
|
|
@Html.AntiForgeryToken()
|
|
<input type="hidden" name="jobId" value="@job.JobId" />
|
|
<button type="submit" class="btn btn-sm btn-success text-white">즉시 실행</button>
|
|
</form>
|
|
<a href="javascript:void(0)" class="btn btn-sm btn-link ms-2">수정</a>
|
|
</td>
|
|
</tr>
|
|
}
|
|
}
|
|
else
|
|
{
|
|
<tr>
|
|
<td colspan="5" class="text-center text-muted">예약된 작업이 없습니다</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 작업 실행 통계 -->
|
|
<div class="col-md-4">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h3 class="card-title">작업 통계</h3>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="space-y-2">
|
|
<div class="d-flex">
|
|
<div>
|
|
<div class="text-muted">전체 작업</div>
|
|
<div class="h2">@Model.TotalJobsCount</div>
|
|
</div>
|
|
</div>
|
|
<div class="d-flex">
|
|
<div>
|
|
<div class="text-muted">활성 작업</div>
|
|
<div class="h2 text-success">@Model.ActiveJobsCount</div>
|
|
</div>
|
|
</div>
|
|
<div class="d-flex">
|
|
<div>
|
|
<div class="text-muted">비활성 작업</div>
|
|
<div class="h2 text-warning">@Model.InactiveJobsCount</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 최근 작업 실행 -->
|
|
<div class="col-md-8">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h3 class="card-title">최근 작업 실행 (상위 10개)</h3>
|
|
</div>
|
|
<div class="table-responsive">
|
|
<table class="table table-sm table-vcenter card-table">
|
|
<thead>
|
|
<tr>
|
|
<th>작업명</th>
|
|
<th>시작 시간</th>
|
|
<th>완료 시간</th>
|
|
<th>소요 시간</th>
|
|
<th>결과</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@if (Model.RecentExecutions?.Any() == true)
|
|
{
|
|
@foreach (var exec in Model.RecentExecutions)
|
|
{
|
|
var duration = exec.CompletedAt.HasValue
|
|
? (exec.CompletedAt.Value - exec.StartedAt).TotalSeconds
|
|
: 0;
|
|
|
|
<tr>
|
|
<td><small>@exec.JobName</small></td>
|
|
<td><small>@exec.StartedAt.ToString("HH:mm:ss")</small></td>
|
|
<td><small>@(exec.CompletedAt?.ToString("HH:mm:ss") ?? "-")</small></td>
|
|
<td><small>@duration.ToString("F1")s</small></td>
|
|
<td>
|
|
@if (exec.IsSuccess)
|
|
{
|
|
<span class="badge bg-success">성공</span>
|
|
}
|
|
else
|
|
{
|
|
<span class="badge bg-danger">실패</span>
|
|
}
|
|
</td>
|
|
</tr>
|
|
}
|
|
}
|
|
else
|
|
{
|
|
<tr>
|
|
<td colspan="5" class="text-center text-muted">최근 실행 기록이 없습니다</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 시스템 상태 -->
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h3 class="card-title">시스템 상태</h3>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-3">
|
|
<div class="text-muted">작업 큐 상태</div>
|
|
<div class="h4">
|
|
@if (Model.IsJobProcessorRunning)
|
|
{
|
|
<span class="badge bg-success">처리 중</span>
|
|
}
|
|
else
|
|
{
|
|
<span class="badge bg-warning">대기 중</span>
|
|
}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="text-muted">대기 중인 작업</div>
|
|
<div class="h4">@Model.PendingJobsCount</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="text-muted">마지막 갱신</div>
|
|
<div class="h6">@(Model.LastRefreshTime?.ToString("HH:mm:ss") ?? "-")</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="text-muted">상태 메시지</div>
|
|
<div class="h6 text-muted">@(Model.StatusMessage ?? "정상")</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|