| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- @page "{id:int}"
- @model Admin.Pages.Channel.List.ViewModel
- @{
- ViewData["Title"] = "채널 정보";
- }
- <div class="container">
- <h3>@ViewData["Title"]</h3>
- <hr />
- <partial name="_StatusMessage" />
- @* ── DB 채널 정보 ───────────────────────────────────────────── *@
- <h5 class="mt-3 mb-2"><i class="bi bi-database"></i> 채널 기본 정보</h5>
- <div class="overflow-hidden border rounded mb-4">
- <div class="row g-0 border-bottom">
- <div class="col-12 col-md-2 fw-bold p-2 bg-light">PK</div>
- <div class="col-12 col-md-10 p-2">@Model.ID</div>
- </div>
- <div class="row g-0 border-bottom">
- <div class="col-12 col-md-2 fw-bold p-2 bg-light">회원(소유자)</div>
- <div class="col-12 col-md-10 p-2">@Model.MemberInfo</div>
- </div>
- <div class="row g-0 border-bottom">
- <div class="col-12 col-md-2 fw-bold p-2 bg-light">SID</div>
- <div class="col-12 col-md-10 p-2"><code>@Model.SID</code></div>
- </div>
- <div class="row g-0 border-bottom">
- <div class="col-12 col-md-2 fw-bold p-2 bg-light">이름</div>
- <div class="col-12 col-md-10 p-2">@Model.Name</div>
- </div>
- <div class="row g-0 border-bottom">
- <div class="col-12 col-md-2 fw-bold p-2 bg-light">핸들</div>
- <div class="col-12 col-md-10 p-2">@(Model.Handle ?? "-")</div>
- </div>
- <div class="row g-0 border-bottom">
- <div class="col-12 col-md-2 fw-bold p-2 bg-light">YouTube 주소</div>
- <div class="col-12 col-md-10 p-2">
- <a href="@Model.YouTubeUrl" target="_blank" rel="external">@Model.YouTubeUrl</a>
- </div>
- </div>
- <div class="row g-0 border-bottom">
- <div class="col-12 col-md-2 fw-bold p-2 bg-light">수수료(%)</div>
- <div class="col-12 col-md-10 p-2">@Model.PlatformFeeRate%</div>
- </div>
- <div class="row g-0 border-bottom">
- <div class="col-12 col-md-2 fw-bold p-2 bg-light">인증 여부</div>
- <div class="col-12 col-md-10 p-2">
- @if (Model.IsVerified)
- {
- <span class="badge bg-success">인증됨</span>
- }
- else
- {
- <span class="badge bg-secondary">미인증</span>
- }
- </div>
- </div>
- <div class="row g-0 border-bottom">
- <div class="col-12 col-md-2 fw-bold p-2 bg-light">사용 여부</div>
- <div class="col-12 col-md-10 p-2">
- @if (Model.IsActive)
- {
- <span class="badge bg-primary">활성</span>
- }
- else
- {
- <span class="badge bg-danger">비활성</span>
- }
- </div>
- </div>
- <div class="row g-0 border-bottom">
- <div class="col-12 col-md-2 fw-bold p-2 bg-light">수정일시</div>
- <div class="col-12 col-md-10 p-2">@(Model.UpdatedAt ?? "-")</div>
- </div>
- <div class="row g-0">
- <div class="col-12 col-md-2 fw-bold p-2 bg-light">등록일시</div>
- <div class="col-12 col-md-10 p-2">@Model.CreatedAt</div>
- </div>
- </div>
- @* ── YouTube API 채널 정보 ───────────────────────────────────── *@
- <h5 class="mt-4 mb-2"><i class="bi bi-youtube"></i> YouTube 채널 상세 정보</h5>
- @if (Model.YouTubeApiFailed)
- {
- <div class="alert alert-warning mt-3">
- <i class="bi bi-exclamation-triangle"></i> @Model.YouTubeApiError
- </div>
- }
- else if (Model.YouTubeChannel is not null)
- {
- var yt = Model.YouTubeChannel;
- <div class="border rounded mb-4">
- @* 채널 프로필 헤더 *@
- <div class="d-flex align-items-center p-3 bg-light border-bottom">
- <img src="@yt.ThumbnailUrl" alt="@yt.Title" class="rounded-circle me-3"
- style="width:64px; height:64px; object-fit:cover;" />
- <div>
- <h5 class="mb-0">@yt.Title</h5>
- @if (yt.CustomUrl is not null)
- {
- <a href="https://youtube.com/@@(yt.CustomUrl.TrimStart('@@'))" target="_blank"
- class="text-muted small">
- @@(yt.CustomUrl.TrimStart('@@'))
- </a>
- }
- </div>
- </div>
- @* 통계 카드 *@
- <div class="row g-0 text-center border-bottom">
- <div class="col-4 p-3 border-end">
- <div class="fs-4 fw-bold">@FormatNumber(yt.SubscriberCount)</div>
- <div class="text-muted small">구독자</div>
- </div>
- <div class="col-4 p-3 border-end">
- <div class="fs-4 fw-bold">@FormatNumber(yt.VideoCount)</div>
- <div class="text-muted small">동영상</div>
- </div>
- <div class="col-4 p-3">
- <div class="fs-4 fw-bold">@FormatNumber(yt.ViewCount)</div>
- <div class="text-muted small">총 조회수</div>
- </div>
- </div>
- @* 상세 정보 테이블 *@
- <div class="row g-0 border-bottom">
- <div class="col-12 col-md-2 fw-bold p-2 bg-light">채널 ID</div>
- <div class="col-12 col-md-10 p-2">
- <code>@yt.ChannelID</code>
- <a href="https://youtube.com/channel/@yt.ChannelID" target="_blank" class="ms-2 small">
- <i class="bi bi-box-arrow-up-right"></i>
- </a>
- </div>
- </div>
- <div class="row g-0 border-bottom">
- <div class="col-12 col-md-2 fw-bold p-2 bg-light">채널 이름</div>
- <div class="col-12 col-md-10 p-2">@yt.Title</div>
- </div>
- <div class="row g-0 border-bottom">
- <div class="col-12 col-md-2 fw-bold p-2 bg-light">커스텀 URL</div>
- <div class="col-12 col-md-10 p-2">@(yt.CustomUrl ?? "-")</div>
- </div>
- <div class="row g-0 border-bottom">
- <div class="col-12 col-md-2 fw-bold p-2 bg-light">구독자 수</div>
- <div class="col-12 col-md-10 p-2">@yt.SubscriberCount.ToString("N0")</div>
- </div>
- <div class="row g-0 border-bottom">
- <div class="col-12 col-md-2 fw-bold p-2 bg-light">동영상 수</div>
- <div class="col-12 col-md-10 p-2">@yt.VideoCount.ToString("N0")</div>
- </div>
- <div class="row g-0 border-bottom">
- <div class="col-12 col-md-2 fw-bold p-2 bg-light">총 조회수</div>
- <div class="col-12 col-md-10 p-2">@yt.ViewCount.ToString("N0")</div>
- </div>
- <div class="row g-0 border-bottom">
- <div class="col-12 col-md-2 fw-bold p-2 bg-light">썸네일</div>
- <div class="col-12 col-md-10 p-2">
- <img src="@yt.ThumbnailUrl" alt="thumbnail" class="rounded" style="max-width:120px;" />
- </div>
- </div>
- <div class="row g-0">
- <div class="col-12 col-md-2 fw-bold p-2 bg-light">설명</div>
- <div class="col-12 col-md-10 p-2">
- @if (!string.IsNullOrWhiteSpace(yt.Description))
- {
- <div style="max-height:200px; overflow-y:auto; white-space:pre-wrap;">@yt.Description</div>
- }
- else
- {
- <span class="text-muted">-</span>
- }
- </div>
- </div>
- </div>
- }
- @* ── 생방송 방송 상태 (PubSub 기반 — Redis 조회, API 0 unit) ──── *@
- <h5 class="mt-4 mb-2"><i class="bi bi-broadcast"></i> 생방송 상태</h5>
- @if (Model.LiveStream is not null)
- {
- var live = Model.LiveStream;
- <div class="border rounded mb-4 border-danger">
- <div class="d-flex align-items-center p-3 bg-danger bg-opacity-10 border-bottom">
- <span class="badge bg-danger me-2 fs-6">LIVE</span>
- <h6 class="mb-0">@live.Title</h6>
- </div>
- <div class="row g-0 border-bottom">
- <div class="col-12 col-md-2 fw-bold p-2 bg-light">Video ID</div>
- <div class="col-12 col-md-10 p-2">
- <code>@live.VideoId</code>
- <a href="https://youtube.com/watch?v=@live.VideoId" target="_blank" class="ms-2 small">
- <i class="bi bi-box-arrow-up-right"></i>
- </a>
- </div>
- </div>
- <div class="row g-0 border-bottom">
- <div class="col-12 col-md-2 fw-bold p-2 bg-light">Live Chat ID</div>
- <div class="col-12 col-md-10 p-2"><code>@(live.ActiveLiveChatId ?? "-")</code></div>
- </div>
- <div class="row g-0 border-bottom">
- <div class="col-12 col-md-2 fw-bold p-2 bg-light">방송 시작</div>
- <div class="col-12 col-md-10 p-2">@(live.ActualStartTime?.ToString("yyyy-MM-dd HH:mm:ss") ?? "-")</div>
- </div>
- <div class="row g-0">
- <div class="col-12 col-md-2 fw-bold p-2 bg-light">상태</div>
- <div class="col-12 col-md-10 p-2">
- @if (live.IsLive)
- {
- <span class="badge bg-danger">생방송 중</span>
- }
- else if (live.IsUpcoming)
- {
- <span class="badge bg-warning text-dark">예정됨 — @(live.ScheduledStartTime?.ToString("yyyy-MM-dd HH:mm") ?? "")</span>
- }
- </div>
- </div>
- </div>
- }
- else
- {
- <div class="border rounded p-3 mb-4 text-muted bg-light">
- 방송 종료
- </div>
- }
- <div class="d-grid gap-2 text-center d-md-block mt-3">
- <a href="/Channel/List/Edit/@Model.ID" class="btn btn-info text-white">수정</a>
- <a href="/Channel/List" class="btn btn-secondary">목록</a>
- </div>
- <br />
- <br />
- </div>
- @section Styles {
- <style>
- @@media (min-width: 768px) {
- .border-end-md {
- border-right: 1px solid var(--bs-border-color) !important;
- }
- }
- </style>
- }
- @functions {
- static string FormatNumber(long value)
- {
- if (value >= 100_000_000)
- {
- return $"{value / 100_000_000.0:0.#}억";
- }
- if (value >= 10_000)
- {
- return $"{value / 10_000.0:0.#}만";
- }
- if (value >= 1_000)
- {
- return $"{value / 1_000.0:0.#}천";
- }
- return value.ToString("N0");
- }
- }
|