statichtml / index.html
z9760405's picture
Update index.html
c4569bc verified
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PKM_RAG 系統登入</title>
<style>
/* --- 基本與通用樣式 --- */
body,
html {
margin: 0;
padding: 0;
font-family: 'Poppins', sans-serif, 'Microsoft JhengHei', sans-serif;
height: 100vh;
overflow: hidden;
}
/* --- 登入頁面 (來自 HTML02) --- */
#login-section {
background: url("https://images.unsplash.com/photo-1503264116251-35a269479413") no-repeat center center/cover;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
transition: opacity 0.6s ease-out;
}
.login-container {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(15px);
border-radius: 20px;
padding: 40px;
width: 380px;
text-align: center;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
animation: fadeIn 1.5s ease;
border: 1px solid rgba(255, 255, 255, 0.2);
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(-50px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.login-container h2 {
color: white;
margin-bottom: 25px;
font-size: 2em;
}
.input-box {
margin-bottom: 20px;
text-align: left;
}
.input-box label {
color: white;
font-weight: bold;
display: block;
margin-bottom: 8px;
}
.input-box input {
width: 100%;
padding: 12px;
border: 1px solid transparent;
border-radius: 10px;
background: rgba(255, 255, 255, 0.2);
color: white;
font-size: 16px;
outline: none;
transition: all 0.3s ease;
box-sizing: border-box;
}
.input-box input::placeholder {
color: rgba(255, 255, 255, 0.7);
}
.input-box input:focus {
background: rgba(255, 255, 255, 0.3);
box-shadow: 0 0 10px rgba(0, 242, 254, 0.5);
border-color: rgba(0, 242, 254, 0.7);
}
.captcha-container {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 5px;
}
#captcha-input {
width: 55%;
margin: 0;
}
#captcha-display {
font-size: 24px;
font-weight: bold;
padding: 5px 15px;
border-radius: 10px;
background: rgba(0, 0, 0, 0.3);
color: #fff;
letter-spacing: 4px;
user-select: none;
cursor: pointer;
text-decoration: line-through;
border: 1px solid rgba(255, 255, 255, 0.2);
}
.btn {
width: 100%;
padding: 12px;
border: none;
border-radius: 10px;
background: linear-gradient(135deg, #4facfe, #00f2fe);
color: white;
font-size: 18px;
font-weight: bold;
cursor: pointer;
transition: all 0.3s ease;
margin-top: 15px;
}
.btn:hover {
transform: scale(1.05);
box-shadow: 0 0 15px rgba(0, 242, 254, 0.6);
background: linear-gradient(135deg, #00f2fe, #4facfe);
}
.msg {
margin-top: 15px;
font-size: 14px;
color: #ffc107;
font-weight: bold;
min-height: 20px;
}
.msg.error {
color: #ff4d4d;
}
/* --- 主系統頁面 --- */
#main-app-section {
display: flex;
height: 100vh;
opacity: 0;
transition: opacity 0.6s ease-in;
}
.sidebar {
width: 260px;
background-color: #1c2833;
color: white;
display: flex;
flex-direction: column;
padding: 20px;
box-shadow: 2px 0 5px rgba(0, 0, 0, 0.1);
box-sizing: border-box;
}
.sidebar h1 {
font-size: 24px;
text-align: center;
color: #ecf0f1;
margin: 0 0 30px 0;
border-bottom: 1px solid #2c3e50;
padding-bottom: 15px;
}
.tabs {
flex-grow: 1;
}
.tab-button {
width: 100%;
padding: 15px 20px;
border: none;
border-radius: 8px;
margin-bottom: 10px;
cursor: pointer;
transition: all 0.3s ease;
font-size: 16px;
text-align: left;
background-color: #2c3e50;
color: white;
}
.tab-button.active {
background-color: #3498db;
transform: translateX(5px);
}
.tab-button:not(.active):hover {
background-color: #34495e;
transform: translateX(2px);
}
#logout-button {
padding: 12px;
border: none;
border-radius: 10px;
background-color: #e74c3c;
color: white;
font-size: 16px;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
#logout-button:hover {
background-color: #c0392b;
transform: translateY(-2px);
}
.content-area {
flex-grow: 1;
background-color: #ecf0f1;
position: relative;
}
.tab-content {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
opacity: 0;
transition: opacity 0.3s ease;
display: none;
}
.tab-content.active {
opacity: 1;
display: block;
}
.content-area iframe {
width: 100%;
height: 100%;
border: none;
}
/* --- 顯示/隱藏控制 --- */
.hidden {
display: none !important;
opacity: 0 !important;
}
/* 添加測試帳號顯示區域 */
.test-info {
position: fixed;
bottom: 20px;
right: 20px;
background: rgba(0, 0, 0, 0.8);
color: white;
padding: 15px;
border-radius: 10px;
font-size: 12px;
z-index: 1000;
}
</style>
</head>
<body>
<section id="login-section">
<div class="login-container">
<h2>PKM_RAG System</h2>
<form id="login-form" autocomplete="off">
<div class="input-box">
<label for="username">帳號 (Username)</label>
<input type="text" id="username" placeholder="請輸入帳號" required>
</div>
<div class="input-box">
<label for="password">密碼 (Password)</label>
<input type="password" id="password" placeholder="請輸入密碼" required>
</div>
<div class="input-box">
<label for="captcha-input">驗證碼 (Captcha)</label>
<div class="captcha-container">
<input type="text" id="captcha-input" placeholder="輸入右側文字" required>
<span id="captcha-display" title="點擊更換驗證碼"></span>
</div>
</div>
<button class="btn" type="submit">登入 (Login)</button>
<p class="msg" id="msg"></p>
</form>
</div>
</section>
<section id="main-app-section" class="hidden">
<div class="sidebar">
<h1>主選單</h1>
<div class="tabs">
<button class="tab-button active" onclick="openTab(event, 'iframe01')">ESG爬蟲</button>
<button class="tab-button" onclick="openTab(event, 'iframe02')">多模態API 應用</button>
<button class="tab-button" onclick="openTab(event, 'iframe03')">Grop+Linebot+Webcam</button>
<button class="tab-button" onclick="openTab(event, 'iframe04')">RAG知識庫</button>
<button class="tab-button" onclick="openTab(event, 'iframe05')">Gemini比對+Resend</button>
</div>
<button id="logout-button">回到登入頁面</button>
</div>
<div class="content-area">
<div id="iframe01" class="tab-content active">
<iframe src="https://z9760405-steamlit.hf.space" frameborder="0"></iframe>
</div>
<div id="iframe02" class="tab-content">
<iframe src="https://cjian2025-groq-api-gradio.hf.space" frameborder="0"></iframe>
</div>
<div id="iframe03" class="tab-content">
<iframe src="https://z9760405-webcam-groq-linebot-application.hf.space" frameborder="0"
allow="camera; microphone"></iframe>
</div>
<div id="iframe04" class="tab-content">
<iframe src="https://z9760405-resendlangchain.hf.space" frameborder="0"></iframe>
</div>
<div id="iframe05" class="tab-content">
<iframe src="https://z9760405-gemini-ocr-resend0914.hf.space" frameborder="0"></iframe>
</div>
</div>
</section>
<!-- 測試用帳號密碼顯示 -->
<div class="test-info">
<strong>測試帳號:</strong><br>
帳號: ROOT2025 (不區分大小寫)<br>
密碼: 123456<br>
驗證碼: 點擊右側文字更換
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
console.log('頁面載入完成,開始初始化...');
// --- DOM 元素 ---
const loginSection = document.getElementById('login-section');
const mainAppSection = document.getElementById('main-app-section');
const loginForm = document.getElementById('login-form');
const usernameInput = document.getElementById('username');
const passwordInput = document.getElementById('password');
const captchaInput = document.getElementById('captcha-input');
const captchaDisplay = document.getElementById('captcha-display');
const msg = document.getElementById('msg');
const logoutButton = document.getElementById('logout-button');
// 檢查所有 DOM 元素是否正確載入
const elements = {
loginSection, mainAppSection, loginForm, usernameInput,
passwordInput, captchaInput, captchaDisplay, msg, logoutButton
};
for (const [name, element] of Object.entries(elements)) {
if (!element) {
console.error(`錯誤: 找不到元素 ${name}`);
return;
}
}
console.log('所有 DOM 元素載入成功');
// --- 預先計算好的 SHA-256 HASH 值 ---
// 正確帳號: ROOT2025 -> sha256 -> d7113846e19051e6d5752f60dcb53329e9563b2c7655452fb9aea5f27969cc4f
const correctUserHash = 'd7113846e19051e6d5752f60dcb53329e9563b2c7655452fb9aea5f27969cc4f';
// 正確密碼: 123456 -> sha256 -> 8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92
const correctPassHash = '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92';
let currentCaptcha = '';
// --- 功能函式 ---
async function sha256(str) {
try {
const textBuffer = new TextEncoder().encode(str);
const hashBuffer = await crypto.subtle.digest('SHA-256', textBuffer);
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hash = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
console.log(`SHA256("${str}") = ${hash}`);
return hash;
} catch (error) {
console.error('SHA256 計算錯誤:', error);
throw error;
}
}
function generateCaptcha() {
const chars = 'AbCdEfGhIjKlMnOpQrStUvWxYz0123456789';
let captcha = '';
for (let i = 0; i < 5; i++) {
captcha += chars.charAt(Math.floor(Math.random() * chars.length));
}
currentCaptcha = captcha;
captchaDisplay.textContent = currentCaptcha;
console.log('新驗證碼生成:', currentCaptcha);
}
function showMessage(message, isError = true) {
msg.textContent = message;
msg.className = isError ? 'msg error' : 'msg';
console.log('顯示訊息:', message, '錯誤狀態:', isError);
}
async function handleLogin(e) {
e.preventDefault();
console.log('開始處理登入...');
showMessage('', false);
const username = usernameInput.value.trim();
const password = passwordInput.value;
const captcha = captchaInput.value.trim();
console.log('輸入資訊:');
console.log('- 帳號:', username);
console.log('- 密碼長度:', password.length);
console.log('- 驗證碼:', captcha);
console.log('- 當前驗證碼:', currentCaptcha);
// 步驟 1: 優先檢查驗證碼
if (captcha.toLowerCase() !== currentCaptcha.toLowerCase()) {
console.log('驗證碼錯誤');
showMessage('❌ 驗證碼錯誤!請重新輸入。');
generateCaptcha();
captchaInput.value = '';
return;
}
try {
// 步驟 2: 雜湊使用者輸入
const enteredUserHash = await sha256(username.toUpperCase());
const enteredPassHash = await sha256(password);
console.log('Hash 比對:');
console.log('- 輸入帳號 Hash:', enteredUserHash);
console.log('- 正確帳號 Hash:', correctUserHash);
console.log('- 輸入密碼 Hash:', enteredPassHash);
console.log('- 正確密碼 Hash:', correctPassHash);
// 步驟 3: 比對 HASH 值
if (enteredUserHash === correctUserHash && enteredPassHash === correctPassHash) {
// 登入成功
console.log('登入成功!');
showMessage('✅ 登入成功!正在載入系統...', false);
loginSection.style.opacity = '0';
setTimeout(() => {
loginSection.classList.add('hidden');
mainAppSection.classList.remove('hidden');
mainAppSection.style.opacity = '1';
console.log('切換到主頁面完成');
}, 600);
} else {
// 登入失敗
console.log('帳號或密碼錯誤');
showMessage('❌ 帳號或密碼錯誤!');
generateCaptcha();
passwordInput.value = '';
captchaInput.value = '';
}
} catch (error) {
console.error('登入處理錯誤:', error);
showMessage('❌ 系統錯誤,請重試!');
}
}
function handleLogout() {
console.log('處理登出...');
mainAppSection.style.opacity = '0';
setTimeout(() => {
mainAppSection.classList.add('hidden');
loginSection.classList.remove('hidden');
loginSection.style.opacity = '1';
loginForm.reset();
showMessage('');
generateCaptcha();
console.log('登出完成');
}, 600);
}
// --- 事件監聽 ---
loginForm.addEventListener('submit', handleLogin);
logoutButton.addEventListener('click', handleLogout);
captchaDisplay.addEventListener('click', generateCaptcha);
// --- 初始化 ---
console.log('開始初始化驗證碼...');
generateCaptcha();
console.log('系統初始化完成');
// 測試用途:10秒後隱藏測試資訊
setTimeout(() => {
const testInfo = document.querySelector('.test-info');
if (testInfo) {
testInfo.style.display = 'none';
}
}, 10000);
});
// --- 選單切換功能 ---
function openTab(evt, tabName) {
console.log('切換到頁籤:', tabName);
// 隱藏所有內容
var tabContents = document.getElementsByClassName("tab-content");
for (var i = 0; i < tabContents.length; i++) {
tabContents[i].classList.remove("active");
}
// 移除所有按鈕的 active 類別
var tabButtons = document.getElementsByClassName("tab-button");
for (var i = 0; i < tabButtons.length; i++) {
tabButtons[i].classList.remove("active");
}
// 顯示選中的內容並激活按鈕
document.getElementById(tabName).classList.add("active");
evt.currentTarget.classList.add("active");
console.log('頁籤切換完成:', tabName);
}
</script>
</body>
</html>