feat: Refactor download queue UI with real-time updates, add queue management buttons, and streamline socket event handling.

This commit is contained in:
2026-01-01 00:32:59 +09:00
parent 681fc0790c
commit 9e25f1f02e
13 changed files with 1431 additions and 845 deletions

View File

@@ -21,12 +21,19 @@
<!-- </div>-->
</div>
</div>
<div>
<form id="program_list">
{{ macros.setting_input_text_and_buttons('code', '작품 Code',
[['analysis_btn', '분석'], ['go_linkkf_btn', 'Go 링크 애니']], desc='예)
"https://linkkf.app/코드" 나 "코드"') }}
</form>
<div class="search-input-container">
<div class="search-label"><i class="fa fa-link"></i> 작품 URL 또는 코드로 분석하기</div>
<div class="search-input-wrapper">
<input id="code" name="code" type="text" class="form-control custom-input" placeholder="링크애니 URL 또는 코드를 입력하세요...">
<div class="search-buttons">
<button id="analysis_btn" class="custom-btn btn-search"><i class="fa fa-magic"></i> 분석 시작</button>
<button id="go_linkkf_btn" class="custom-btn btn-reset">원래 사이트로 이동</button>
</div>
</div>
<div class="search-desc">
<em><i class="fa fa-info-circle"></i> 예) "https://linkkf.app/코드" 나 "코드" 직접 입력</em>
</div>
</div>
<form id="program_auto_form">
<div id="episode_list"></div>
</form>
@@ -39,7 +46,7 @@
const package_name = "{{arg['package_name'] }}";
const sub = "{{arg['sub'] }}";
const ohli24_url = "{{arg['ohli24_url']}}";
{#let current_data = '';#}
// let current_data = '';
const params = new Proxy(new URLSearchParams(window.location.search), {
get: (searchParams, prop) => searchParams.get(prop),
@@ -163,7 +170,7 @@
for (let i in data.episode) {
str += '<div class="episode-card">';
str += '<div class="episode-thumb">';
str += '<span class="episode-num">' + (parseInt(i) + 1) + '화</span>';
str += '<span class="episode-num">' + data.episode[i].ep_num + '화</span>';
str += '</div>';
str += '<div class="episode-info">';
str += '<div class="episode-title">' + data.episode[i].title + '</div>';
@@ -348,13 +355,137 @@
}
body {
background-image: linear-gradient(90deg, #33242c, #263341, #17273a);
background-image: linear-gradient(90deg, #022c22, #064e3b, #065f46);
}
#anime_downloader_wrapper {
color: #ecfdf5;
padding: 5px;
}
color: #d6eaf8;
/* Navigation (Tabs) Optimization */
.nav-pills {
background: rgba(6, 78, 59, 0.4) !important;
padding: 6px !important;
border-radius: 12px !important;
border: 1px solid rgba(16, 185, 129, 0.1) !important;
margin-bottom: 20px !important;
display: inline-flex !important;
gap: 4px !important;
box-shadow: 0 4px 15px rgba(0,0,0,0.2) !important;
}
.nav-pills .nav-link {
color: #d1fae5 !important;
font-weight: 600 !important;
padding: 8px 20px !important;
border-radius: 8px !important;
transition: all 0.3s ease !important;
border: 1px solid transparent !important;
}
.nav-pills .nav-link:hover {
background: rgba(16, 185, 129, 0.1) !important;
color: #fff !important;
transform: translateY(-1px);
}
.nav-pills .nav-link.active {
background: linear-gradient(135deg, #10b981 0%, #059669 100%) !important;
color: #fff !important;
box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3) !important;
border: 1px solid rgba(255,255,255,0.1) !important;
}
/* Search Input Polishing */
.search-input-container {
background: rgba(6, 78, 59, 0.4);
backdrop-filter: blur(12px);
padding: 24px;
border-radius: 20px;
border: 1px solid rgba(16, 185, 129, 0.2);
margin-bottom: 30px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
}
.search-label {
font-size: 16px;
font-weight: 700;
color: #ecfdf5;
margin-bottom: 12px;
display: flex;
align-items: center;
gap: 8px;
}
.search-input-wrapper {
display: flex;
gap: 12px;
flex-wrap: wrap;
}
.custom-input {
background-color: rgba(2, 44, 34, 0.6) !important;
border: 1px solid rgba(16, 185, 129, 0.3) !important;
color: #fff !important;
border-radius: 12px !important;
padding: 12px 18px !important;
height: 50px !important;
flex: 1;
min-width: 300px;
font-size: 15px;
transition: all 0.2s;
}
.custom-input:focus {
border-color: #10b981 !important;
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.2) !important;
background-color: rgba(2, 44, 34, 0.8) !important;
}
.search-buttons {
display: flex;
gap: 10px;
}
.custom-btn {
height: 50px;
padding: 0 24px;
border-radius: 12px;
font-weight: 700;
cursor: pointer;
transition: all 0.2s;
border: none;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
.btn-search {
background: linear-gradient(135deg, #10b981, #059669);
color: white;
box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3);
}
.btn-search:hover {
transform: translateY(-2px);
box-shadow: 0 6px 16px rgba(16, 185, 129, 0.4);
}
.btn-reset {
background: rgba(255, 255, 255, 0.05);
color: #6ee7b7;
border: 1px solid rgba(16, 185, 129, 0.2);
}
.btn-reset:hover {
background: rgba(255, 255, 255, 0.1);
color: #fff;
}
.search-desc {
margin-top: 12px;
font-size: 13px;
color: #6ee7b7;
opacity: 0.7;
}
button.code-button {
@@ -456,16 +587,14 @@
.card {
border: none;
box-shadow: inset 1px 1px hsl(0deg 0% 100% / 20%), inset -1px -1px hsl(0deg 0% 100% / 10%), 1px 3px 24px -1px rgb(0 0 0 / 15%);
background-color: transparent;
background-image: linear-gradient(125deg, hsla(0, 0%, 100%, .3), hsla(0, 0%, 100%, .2) 70%);
backdrop-filter: blur(5px);
box-shadow: inset 1px 1px hsl(0deg 0% 100% / 10%), inset -1px -1px hsl(0deg 0% 100% / 5%), 0 12px 24px rgba(0,0,0,0.3);
background-color: rgba(6, 78, 59, 0.4);
backdrop-filter: blur(12px);
}
.card.border-light {
border-radius: 30px 10px;
--bs-border-opacity: 1;
border-color: rgba(var(--bs-light-rgb), var(--bs-border-opacity)) !important;
border-radius: 20px;
border: 1px solid rgba(16, 185, 129, 0.2) !important;
}
/* 에피소드 목록 컨테이너 */
@@ -504,7 +633,7 @@
height: 40px;
border-radius: 8px;
overflow: hidden;
background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%);
background: linear-gradient(135deg, #10b981 0%, #059669 100%);
display: flex;
align-items: center;
justify-content: center;