mirror of
https://github.com/headporter81/specialsource-homepage-frontend.git
synced 2026-10-07 15:21:10 +09:00
This commit is contained in:
+29
-2
@@ -160,7 +160,8 @@ body, html { margin: 0; padding: 0; width: 100%; height: 100%; background-color:
|
|||||||
.status-dot.secure-mode { background: var(--tui-color); box-shadow: 0 0 8px var(--tui-color); }
|
.status-dot.secure-mode { background: var(--tui-color); box-shadow: 0 0 8px var(--tui-color); }
|
||||||
|
|
||||||
/* --- 컨텐츠 영역 --- */
|
/* --- 컨텐츠 영역 --- */
|
||||||
.content-area { flex: 1; padding: 8px 20px; min-height: 220px; overflow-y: auto; display: flex; flex-direction: column; }
|
.content-area { flex: 1 1 auto; padding: 8px 20px; min-height: 220px; overflow-y: auto; display: flex; flex-direction: column; transition: flex-grow 0.6s ease; }
|
||||||
|
.homepage-wrapper.intro-done .content-area { flex-grow: 0; }
|
||||||
.sub-page { max-width: 1000px; margin: 0 auto; padding-top: 15px; width: 100%; }
|
.sub-page { max-width: 1000px; margin: 0 auto; padding-top: 15px; width: 100%; }
|
||||||
.page-title { border-bottom: 1px solid var(--tui-border); padding-bottom: 10px; margin-bottom: 20px; color: var(--tui-color);}
|
.page-title { border-bottom: 1px solid var(--tui-border); padding-bottom: 10px; margin-bottom: 20px; color: var(--tui-color);}
|
||||||
|
|
||||||
@@ -172,7 +173,11 @@ body, html { margin: 0; padding: 0; width: 100%; height: 100%; background-color:
|
|||||||
justify-content: center; align-items: center; pointer-events: all;
|
justify-content: center; align-items: center; pointer-events: all;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ascii-container { width: 100%; overflow-x: auto; overflow-y: hidden; padding: 6px 20px; box-sizing: border-box; position: relative; }
|
.ascii-container {
|
||||||
|
width: 100%; overflow-x: auto; overflow-y: hidden; padding: 6px 20px; box-sizing: border-box; position: relative;
|
||||||
|
max-height: 600px; opacity: 1; transition: max-height 0.6s ease, opacity 0.5s ease, padding 0.6s ease;
|
||||||
|
}
|
||||||
|
.ascii-container.is-collapsed { max-height: 0; opacity: 0; padding-top: 0; padding-bottom: 0; }
|
||||||
.ascii-clip { width: max-content; margin: 0 auto; overflow: hidden; }
|
.ascii-clip { width: max-content; margin: 0 auto; overflow: hidden; }
|
||||||
.ascii-art {
|
.ascii-art {
|
||||||
font-weight: bold; white-space: pre; display: block; margin: 0 auto; width: max-content;
|
font-weight: bold; white-space: pre; display: block; margin: 0 auto; width: max-content;
|
||||||
@@ -258,6 +263,27 @@ iframe { width: 100%; height: 180px; border-radius: 4px; }
|
|||||||
}
|
}
|
||||||
.terminal-box { width: 100%; height: 100%; padding: 10px; box-sizing: border-box; }
|
.terminal-box { width: 100%; height: 100%; padding: 10px; box-sizing: border-box; }
|
||||||
|
|
||||||
|
/* ==============================================================
|
||||||
|
부팅 로그 스크린 (초기 진입 시 로그 출력 후 사라짐)
|
||||||
|
============================================================== */
|
||||||
|
.boot-log-screen {
|
||||||
|
position: fixed; top: 0; left: 0; width: 100vw; height: 100vh;
|
||||||
|
background-color: #000; z-index: 10000; display: flex;
|
||||||
|
justify-content: center; align-items: center; pointer-events: all;
|
||||||
|
}
|
||||||
|
.boot-log-box {
|
||||||
|
width: 100%; max-width: 620px; padding: 0 20px; box-sizing: border-box;
|
||||||
|
font-family: 'JetBrains Mono', monospace;
|
||||||
|
}
|
||||||
|
.boot-log-line {
|
||||||
|
margin: 0 0 6px; font-size: 13px; color: var(--tui-color);
|
||||||
|
text-shadow: 0 0 5px var(--tui-glow); letter-spacing: 0.5px;
|
||||||
|
animation: bootLineIn 0.2s ease-out;
|
||||||
|
}
|
||||||
|
.boot-cursor {
|
||||||
|
color: var(--tui-color); font-size: 14px; animation: blink 1s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
/* ==============================================================
|
/* ==============================================================
|
||||||
진행률 바 (TuiProgressBar.vue)
|
진행률 바 (TuiProgressBar.vue)
|
||||||
============================================================== */
|
============================================================== */
|
||||||
@@ -481,6 +507,7 @@ iframe { width: 100%; height: 180px; border-radius: 4px; }
|
|||||||
@keyframes textPulse { 0%, 100% { opacity: 0.3; } 50% { opacity: 1; text-shadow: 0 0 8px var(--tui-glow); } }
|
@keyframes textPulse { 0%, 100% { opacity: 0.3; } 50% { opacity: 1; text-shadow: 0 0 8px var(--tui-glow); } }
|
||||||
@keyframes badgeBlink { 0%, 100% { opacity: 0.6; box-shadow: 0 0 5px rgba(255, 59, 59, 0.2); } 50% { opacity: 1; box-shadow: 0 0 15px rgba(255, 59, 59, 0.6); text-shadow: 0 0 12px #ff3b3b; } }
|
@keyframes badgeBlink { 0%, 100% { opacity: 0.6; box-shadow: 0 0 5px rgba(255, 59, 59, 0.2); } 50% { opacity: 1; box-shadow: 0 0 15px rgba(255, 59, 59, 0.6); text-shadow: 0 0 12px #ff3b3b; } }
|
||||||
@keyframes dashReveal { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
|
@keyframes dashReveal { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
|
||||||
|
@keyframes bootLineIn { from { opacity: 0; transform: translateX(-4px); } to { opacity: 1; transform: translateX(0); } }
|
||||||
@keyframes once-cyber-glitch-wobble {
|
@keyframes once-cyber-glitch-wobble {
|
||||||
0%, 25% { transform: translate(0) scale(1) skewX(0deg); color: var(--tui-color) !important; text-shadow: 0 0 8px var(--tui-glow) !important; opacity: 1; }
|
0%, 25% { transform: translate(0) scale(1) skewX(0deg); color: var(--tui-color) !important; text-shadow: 0 0 8px var(--tui-glow) !important; opacity: 1; }
|
||||||
26% { transform: translate(-3px, 1.5px) scale(1.02); color: #ffffff !important; text-shadow: 2px 0 #ff0000, -2px 0 #0000ff !important; }
|
26% { transform: translate(-3px, 1.5px) scale(1.02); color: #ffffff !important; text-shadow: 2px 0 #ff0000, -2px 0 #0000ff !important; }
|
||||||
|
|||||||
+52
-4
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div :class="['homepage-wrapper', `theme-${activeTheme}`]">
|
<div :class="['homepage-wrapper', `theme-${activeTheme}`, { 'intro-done': logoDone }]">
|
||||||
<nav class="auth-nav">
|
<nav class="auth-nav">
|
||||||
<div class="nav-left">
|
<div class="nav-left">
|
||||||
<span class="status-dot" :class="{ 'secure-mode': isLoggedIn }"></span>
|
<span class="status-dot" :class="{ 'secure-mode': isLoggedIn }"></span>
|
||||||
@@ -50,13 +50,20 @@
|
|||||||
<transition name="fade" mode="out-in">
|
<transition name="fade" mode="out-in">
|
||||||
|
|
||||||
<div v-if="activeMenu === 'main'" class="sub-page main-page" key="main">
|
<div v-if="activeMenu === 'main'" class="sub-page main-page" key="main">
|
||||||
<div class="ascii-container">
|
<div class="ascii-container" :class="{ 'is-collapsed': logoDone }">
|
||||||
<div class="ascii-clip">
|
<div class="ascii-clip">
|
||||||
<pre class="ascii-art" v-html="formattedAscii"></pre>
|
<transition name="fade">
|
||||||
|
<pre
|
||||||
|
v-if="!isBooting && !logoDone"
|
||||||
|
class="ascii-art"
|
||||||
|
v-html="formattedAscii"
|
||||||
|
@animationend="logoDone = true"
|
||||||
|
></pre>
|
||||||
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="dash-grid">
|
<div v-if="!isBooting" class="dash-grid">
|
||||||
<div v-if="isLoggedIn" class="dash-panel">
|
<div v-if="isLoggedIn" class="dash-panel">
|
||||||
<h4>LIVE SESSION</h4>
|
<h4>LIVE SESSION</h4>
|
||||||
<div class="dash-stat"><span>LIVE</span><b class="pulse-text">{{ activeNow }}</b></div>
|
<div class="dash-stat"><span>LIVE</span><b class="pulse-text">{{ activeNow }}</b></div>
|
||||||
@@ -177,6 +184,15 @@
|
|||||||
<TuiAlert :message="systemAlert.message" @close="systemAlert.show = false" />
|
<TuiAlert :message="systemAlert.message" @close="systemAlert.show = false" />
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
|
<transition name="fade">
|
||||||
|
<div v-if="isBooting" class="boot-log-screen">
|
||||||
|
<div class="boot-log-box">
|
||||||
|
<p v-for="(line, idx) in bootLines" :key="idx" class="boot-log-line">{{ line }}</p>
|
||||||
|
<span class="boot-cursor">_</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -217,6 +233,36 @@ const isProcessing = ref(false);
|
|||||||
const overlayProgress = ref(0);
|
const overlayProgress = ref(0);
|
||||||
const overlayStatus = ref('');
|
const overlayStatus = ref('');
|
||||||
|
|
||||||
|
const isBooting = ref(true);
|
||||||
|
const logoDone = ref(false);
|
||||||
|
const bootLines = ref([]);
|
||||||
|
const BOOT_SEQUENCE = [
|
||||||
|
'[SYS] SPECIALSOURCE.SYSTEM BIOS V3.2',
|
||||||
|
'[SYS] PERFORMING MEMORY CHECK... OK',
|
||||||
|
'[SYS] INITIALIZING KERNEL MODULES...',
|
||||||
|
'[SYS] MOUNTING VIRTUAL FILESYSTEM... OK',
|
||||||
|
'[SYS] ESTABLISHING SECURE NETWORK LINK...',
|
||||||
|
'[SYS] LOADING DASHBOARD INTERFACE...',
|
||||||
|
'[SYS] SPAWNING TERMINAL CONSOLE...',
|
||||||
|
'[SUCCESS] BOOT SEQUENCE COMPLETE.'
|
||||||
|
];
|
||||||
|
|
||||||
|
const runBootSequence = () => {
|
||||||
|
let i = 0;
|
||||||
|
const pushLine = () => {
|
||||||
|
if (i < BOOT_SEQUENCE.length) {
|
||||||
|
bootLines.value.push(BOOT_SEQUENCE[i]);
|
||||||
|
i++;
|
||||||
|
setTimeout(pushLine, 220);
|
||||||
|
} else {
|
||||||
|
setTimeout(() => {
|
||||||
|
isBooting.value = false;
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
pushLine();
|
||||||
|
};
|
||||||
|
|
||||||
const systemAlert = ref({ show: false, message: '' });
|
const systemAlert = ref({ show: false, message: '' });
|
||||||
const showSystemAlert = (message) => {
|
const showSystemAlert = (message) => {
|
||||||
systemAlert.value = { show: true, message };
|
systemAlert.value = { show: true, message };
|
||||||
@@ -449,6 +495,8 @@ const handleLoginSubmit = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
runBootSequence();
|
||||||
|
|
||||||
fetchVideos();
|
fetchVideos();
|
||||||
fetchAnalyticsData();
|
fetchAnalyticsData();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user