mirror of
https://github.com/headporter81/specialsource-homepage-frontend.git
synced 2026-08-08 15:21:11 +09:00
This commit is contained in:
+64
-20
@@ -32,7 +32,26 @@
|
|||||||
<main class="content-area">
|
<main class="content-area">
|
||||||
<transition name="fade" mode="out-in">
|
<transition name="fade" mode="out-in">
|
||||||
|
|
||||||
<div v-if="activeMenu === 'main'" id="videos-container" key="main">
|
<div v-if="activeMenu === 'main'" class="sub-page main-page" key="main">
|
||||||
|
<div class="ascii-container">
|
||||||
|
<pre class="ascii-art">
|
||||||
|
_ _
|
||||||
|
___ _ __ ___ ___(_) __ _| |___ ___ _ _ _ __ ___ ___
|
||||||
|
/ __| '_ \ / _ \/ __| |/ _` | / __|/ _ \| | | | '__/ __/ _ \
|
||||||
|
\__ \ |_) | __/ (__| | (_| | \__ \ (_) | |_| | | | (_| __/
|
||||||
|
|___/ .__/ \___|\___|_|\__,_|_|___/\___/ \__,_|_| \___\___|
|
||||||
|
|_|
|
||||||
|
|
||||||
|
___ ___ _ __ ___ _ __ __ _ _ __ _ _
|
||||||
|
/ __/ _ \| '_ ` _ \| '_ \ / _` | '_ \| | | |
|
||||||
|
| (_| (_) | | | | | | |_) | (_| | | | | |_| |
|
||||||
|
\___\___/|_| |_| |_| .__/ \__,_|_| |_|\__, |
|
||||||
|
|_| |___/
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else-if="activeMenu === 'youtube'" id="videos-container" key="youtube">
|
||||||
<div
|
<div
|
||||||
v-for="(video, index) in videos"
|
v-for="(video, index) in videos"
|
||||||
:key="video.id.videoId"
|
:key="video.id.videoId"
|
||||||
@@ -63,7 +82,7 @@
|
|||||||
class="login-input"
|
class="login-input"
|
||||||
placeholder="ENTER ACCESS ID"
|
placeholder="ENTER ACCESS ID"
|
||||||
@keyup.enter="handleLoginSubmit"
|
@keyup.enter="handleLoginSubmit"
|
||||||
>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="login-input-group">
|
<div class="login-input-group">
|
||||||
<label class="login-label">ACCESS KEY_</label>
|
<label class="login-label">ACCESS KEY_</label>
|
||||||
@@ -132,22 +151,22 @@ const videos = ref([]);
|
|||||||
const terminalRef = ref(null);
|
const terminalRef = ref(null);
|
||||||
const termInstance = ref(null);
|
const termInstance = ref(null);
|
||||||
|
|
||||||
// 로그인 폼 양방향 바인딩 변수
|
// 로그인 폼 초기값 세팅 유지
|
||||||
const loginId = ref('admin');
|
const loginId = ref('admin');
|
||||||
const loginPw = ref('1234');
|
const loginPw = ref('1234');
|
||||||
|
|
||||||
// 메뉴 및 인증 토큰 반응형 변수화
|
|
||||||
const activeMenu = ref('main');
|
const activeMenu = ref('main');
|
||||||
const authToken = ref(localStorage.getItem('token'));
|
const authToken = ref(localStorage.getItem('token'));
|
||||||
|
|
||||||
|
// 🟢 [NEW] 메뉴 아이템 배열에 YOUTUBE 명시적으로 배치
|
||||||
const menuItems = [
|
const menuItems = [
|
||||||
{ id: 'main', name: 'HOME' },
|
{ id: 'main', name: 'HOME' },
|
||||||
|
{ id: 'youtube', name: 'YOUTUBE' },
|
||||||
{ id: 'project', name: 'PROJECT' },
|
{ id: 'project', name: 'PROJECT' },
|
||||||
{ id: 'about', name: 'ABOUT' },
|
{ id: 'about', name: 'ABOUT' },
|
||||||
{ id: 'contact', name: 'CONTACT' }
|
{ id: 'contact', name: 'CONTACT' }
|
||||||
];
|
];
|
||||||
|
|
||||||
// 실시간 로그인 여부 체크
|
|
||||||
const isLoggedIn = computed(() => !!authToken.value);
|
const isLoggedIn = computed(() => !!authToken.value);
|
||||||
|
|
||||||
const changeMenu = (id) => {
|
const changeMenu = (id) => {
|
||||||
@@ -157,7 +176,6 @@ const changeMenu = (id) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 📺 유튜브 API 세팅 (8개 출력)
|
|
||||||
const apiKey = 'AIzaSyD51LHwqoY8spjq6rsY_RlhBXzb96j7D6o';
|
const apiKey = 'AIzaSyD51LHwqoY8spjq6rsY_RlhBXzb96j7D6o';
|
||||||
const channelId = 'UC8L92ju0V88s6TcmLPb8Bkg';
|
const channelId = 'UC8L92ju0V88s6TcmLPb8Bkg';
|
||||||
const maxResults = 8;
|
const maxResults = 8;
|
||||||
@@ -173,7 +191,6 @@ const fetchVideos = async () => {
|
|||||||
const openVideo = (id) => window.open(`https://www.youtube.com/watch?v=${id}`);
|
const openVideo = (id) => window.open(`https://www.youtube.com/watch?v=${id}`);
|
||||||
const handleRegister = () => alert("회원가입은 현재 관리자 승인제로 운영됩니다.");
|
const handleRegister = () => alert("회원가입은 현재 관리자 승인제로 운영됩니다.");
|
||||||
|
|
||||||
// 로그아웃 로직 (새로고침 없이 실시간 상태 갱신)
|
|
||||||
const handleLogout = () => {
|
const handleLogout = () => {
|
||||||
localStorage.removeItem('token');
|
localStorage.removeItem('token');
|
||||||
authToken.value = null;
|
authToken.value = null;
|
||||||
@@ -183,7 +200,6 @@ const handleLogout = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 🔥 [핵심 기능] 보안 로그인 처리 및 터미널 동시 출력 로직
|
|
||||||
const handleLoginSubmit = async () => {
|
const handleLoginSubmit = async () => {
|
||||||
if (!loginId.value || !loginPw.value) {
|
if (!loginId.value || !loginPw.value) {
|
||||||
alert("아이디와 비밀번호를 모두 입력해 주세요.");
|
alert("아이디와 비밀번호를 모두 입력해 주세요.");
|
||||||
@@ -202,11 +218,9 @@ const handleLoginSubmit = async () => {
|
|||||||
const response = await axios.post(`${apiBaseUrl}/api/login`, {
|
const response = await axios.post(`${apiBaseUrl}/api/login`, {
|
||||||
username: loginId.value,
|
username: loginId.value,
|
||||||
password: loginPw.value
|
password: loginPw.value
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
withCredentials: true
|
withCredentials: true
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
if (response.data && response.data.token) {
|
if (response.data && response.data.token) {
|
||||||
localStorage.setItem('token', response.data.token);
|
localStorage.setItem('token', response.data.token);
|
||||||
@@ -278,7 +292,6 @@ onMounted(() => {
|
|||||||
|
|
||||||
.auth-group { display: flex; align-items: center; }
|
.auth-group { display: flex; align-items: center; }
|
||||||
|
|
||||||
/* 로그인/회원가입 버튼 테마 깔맞춤 고정 */
|
|
||||||
.nav-item {
|
.nav-item {
|
||||||
color: #00ff00 !important;
|
color: #00ff00 !important;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
@@ -305,11 +318,41 @@ onMounted(() => {
|
|||||||
.content-area {
|
.content-area {
|
||||||
flex: 1; padding: 20px; min-height: 400px;
|
flex: 1; padding: 20px; min-height: 400px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
.sub-page { max-width: 1000px; margin: 0 auto; padding-top: 15px; }
|
.sub-page { max-width: 1000px; margin: 0 auto; padding-top: 15px; width: 100%; }
|
||||||
.page-title { font-family: monospace; border-bottom: 1px solid #113311; padding-bottom: 10px; margin-bottom: 20px; color: #00ff00;}
|
.page-title { font-family: monospace; border-bottom: 1px solid #113311; padding-bottom: 10px; margin-bottom: 20px; color: #00ff00;}
|
||||||
|
|
||||||
/* 📺 유튜브 그리드 레이아웃 (4열 8개 무화) */
|
/* 🟢 [NEW] 메인 홈 아스키 전광판 전용 스타일 클래스 양식 */
|
||||||
|
.main-page {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.ascii-container {
|
||||||
|
width: 100%;
|
||||||
|
overflow-x: auto;
|
||||||
|
padding: 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.ascii-art {
|
||||||
|
font-family: 'Courier New', Courier, monospace !important;
|
||||||
|
color: #33ff33 !important;
|
||||||
|
line-height: 1.25;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-shadow: 0 0 8px rgba(51, 255, 51, 0.8) !important;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
margin: 0 auto;
|
||||||
|
white-space: pre;
|
||||||
|
display: block;
|
||||||
|
width: max-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 📺 유튜브 그리드 레이아웃 */
|
||||||
#videos-container {
|
#videos-container {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(4, 1fr);
|
grid-template-columns: repeat(4, 1fr);
|
||||||
@@ -339,7 +382,7 @@ iframe { width: 100%; height: 180px; border-radius: 4px; }
|
|||||||
padding: 2px 5px; box-shadow: 0 0 5px #00ff00; z-index: 10;
|
padding: 2px 5px; box-shadow: 0 0 5px #00ff00; z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 🔐 [신규 추가] 컨텐츠 내장형 해커 로그인 박스 디자인 스타일 양식 */
|
/* 보안 로그인 프레임 */
|
||||||
.login-terminal-frame {
|
.login-terminal-frame {
|
||||||
max-width: 550px; margin: 40px auto;
|
max-width: 550px; margin: 40px auto;
|
||||||
border: 1px dashed #00ff00; padding: 35px;
|
border: 1px dashed #00ff00; padding: 35px;
|
||||||
@@ -363,18 +406,18 @@ iframe { width: 100%; height: 180px; border-radius: 4px; }
|
|||||||
}
|
}
|
||||||
.login-submit-btn:hover { background: #00ff00; color: #000; box-shadow: 0 0 15px #00ff00; }
|
.login-submit-btn:hover { background: #00ff00; color: #000; box-shadow: 0 0 15px #00ff00; }
|
||||||
|
|
||||||
/* 프로젝트 리스트 */
|
/* 프로젝트 리스트 및 기타 소형 요소 */
|
||||||
.project-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
|
.project-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
|
||||||
.project-item { border: 1px solid #113311; padding: 15px; background: #080808; font-family: monospace;}
|
.project-item { border: 1px solid #113311; padding: 15px; background: #080808; font-family: monospace;}
|
||||||
.item-header { font-weight: bold; margin-bottom: 10px; color: #00ff00; }
|
.item-header { font-weight: bold; margin-bottom: 10px; color: #00ff00; }
|
||||||
.about-text { font-family: monospace; line-height: 2; color: #00cc00;}
|
.about-text { font-family: monospace; line-height: 2; color: #00cc00;}
|
||||||
.contact-form { font-family: monospace; line-height: 2; color: #00cc00;}
|
.contact-form { font-family: monospace; line-height: 2; color: #00cc00;}
|
||||||
|
|
||||||
/* 애니메이션 트랜지션 */
|
/* 애니메이션 */
|
||||||
.fade-enter-active, .fade-leave-active { transition: opacity 0.25s ease; }
|
.fade-enter-active, .fade-leave-active { transition: opacity 0.25s ease; }
|
||||||
.fade-enter-from, .fade-leave-to { opacity: 0; }
|
.fade-enter-from, .fade-leave-to { opacity: 0; }
|
||||||
|
|
||||||
/* --- 하단 CRT 터미널 영역 --- */
|
/* 하단 CRT 터미널 */
|
||||||
.crt-monitor-frame {
|
.crt-monitor-frame {
|
||||||
height: 300px; margin: 10px 40px 30px;
|
height: 300px; margin: 10px 40px 30px;
|
||||||
border: 2px solid #1a1a1a; background: #0a0a0a; overflow: hidden;
|
border: 2px solid #1a1a1a; background: #0a0a0a; overflow: hidden;
|
||||||
@@ -394,7 +437,7 @@ iframe { width: 100%; height: 180px; border-radius: 4px; }
|
|||||||
text-shadow: 0 0 5px rgba(51, 255, 51, 0.6) !important;
|
text-shadow: 0 0 5px rgba(51, 255, 51, 0.6) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 📱 반응형 분기점 */
|
/* 📱 반응형 처리 */
|
||||||
@media screen and (max-width: 1100px) {
|
@media screen and (max-width: 1100px) {
|
||||||
#videos-container { grid-template-columns: repeat(2, 1fr); }
|
#videos-container { grid-template-columns: repeat(2, 1fr); }
|
||||||
.project-grid { grid-template-columns: repeat(2, 1fr); }
|
.project-grid { grid-template-columns: repeat(2, 1fr); }
|
||||||
@@ -403,6 +446,7 @@ iframe { width: 100%; height: 180px; border-radius: 4px; }
|
|||||||
#videos-container { grid-template-columns: 1fr; }
|
#videos-container { grid-template-columns: 1fr; }
|
||||||
.project-grid { grid-template-columns: 1fr; }
|
.project-grid { grid-template-columns: 1fr; }
|
||||||
.auth-nav { flex-direction: column; gap: 12px; padding: 15px 20px; }
|
.auth-nav { flex-direction: column; gap: 12px; padding: 15px 20px; }
|
||||||
|
.ascii-art { font-size: 8px; /* 모바일 대응 크기 축소 */ }
|
||||||
}
|
}
|
||||||
@keyframes blink { 0%, 100% { opacity: 0.4; } 50% { opacity: 1; } }
|
@keyframes blink { 0%, 100% { opacity: 0.4; } 50% { opacity: 1; } }
|
||||||
</style>
|
</style>
|
||||||
Reference in New Issue
Block a user