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); }
|
||||
|
||||
/* --- 컨텐츠 영역 --- */
|
||||
.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%; }
|
||||
.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;
|
||||
}
|
||||
|
||||
.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-art {
|
||||
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; }
|
||||
|
||||
/* ==============================================================
|
||||
부팅 로그 스크린 (초기 진입 시 로그 출력 후 사라짐)
|
||||
============================================================== */
|
||||
.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)
|
||||
============================================================== */
|
||||
@@ -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 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 bootLineIn { from { opacity: 0; transform: translateX(-4px); } to { opacity: 1; transform: translateX(0); } }
|
||||
@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; }
|
||||
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>
|
||||
<div :class="['homepage-wrapper', `theme-${activeTheme}`]">
|
||||
<div :class="['homepage-wrapper', `theme-${activeTheme}`, { 'intro-done': logoDone }]">
|
||||
<nav class="auth-nav">
|
||||
<div class="nav-left">
|
||||
<span class="status-dot" :class="{ 'secure-mode': isLoggedIn }"></span>
|
||||
@@ -50,13 +50,20 @@
|
||||
<transition name="fade" mode="out-in">
|
||||
|
||||
<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">
|
||||
<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 class="dash-grid">
|
||||
<div v-if="!isBooting" class="dash-grid">
|
||||
<div v-if="isLoggedIn" class="dash-panel">
|
||||
<h4>LIVE SESSION</h4>
|
||||
<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" />
|
||||
</div>
|
||||
</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>
|
||||
</template>
|
||||
|
||||
@@ -217,6 +233,36 @@ const isProcessing = ref(false);
|
||||
const overlayProgress = ref(0);
|
||||
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 showSystemAlert = (message) => {
|
||||
systemAlert.value = { show: true, message };
|
||||
@@ -449,6 +495,8 @@ const handleLoginSubmit = async () => {
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
runBootSequence();
|
||||
|
||||
fetchVideos();
|
||||
fetchAnalyticsData();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user