init
This commit is contained in:
@@ -0,0 +1,231 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-TW">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>CFDive平台 - Google登入測試</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<style>
|
||||
.container { max-width: 800px; margin-top: 50px; }
|
||||
.card { margin-bottom: 20px; }
|
||||
pre { background-color: #f8f9fa; padding: 15px; border-radius: 5px; max-height: 300px; overflow: auto; }
|
||||
.btn-google { background-color: #4285F4; color: white; }
|
||||
.hidden { display: none; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1 class="mb-4">CFDive平台 - Google登入測試</h1>
|
||||
|
||||
<!-- 登入卡片 -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
會員登入選項
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">選擇登入方式</h5>
|
||||
<p class="card-text">您可以使用以下方式登入系統:</p>
|
||||
|
||||
<!-- Google登入按鈕 -->
|
||||
<a href="/api/auth/google/redirect" class="btn btn-google mb-3">
|
||||
<i class="bi bi-google"></i> 使用Google帳號登入
|
||||
</a>
|
||||
|
||||
<!-- 一般登入表單 -->
|
||||
<div class="mt-4">
|
||||
<h6>或使用電子郵件登入</h6>
|
||||
<form id="loginForm" class="mt-3">
|
||||
<div class="mb-3">
|
||||
<label for="email" class="form-label">電子郵件</label>
|
||||
<input type="email" class="form-control" id="email" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">密碼</label>
|
||||
<input type="password" class="form-control" id="password" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">登入</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Token顯示區域 -->
|
||||
<div id="tokenCard" class="card hidden">
|
||||
<div class="card-header">
|
||||
授權Token
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">登入成功</h5>
|
||||
<p class="card-text">您已成功登入系統,可以使用以下token進行API測試:</p>
|
||||
<pre id="tokenInfo"></pre>
|
||||
<button id="copyToken" class="btn btn-sm btn-secondary">複製Token</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- API測試區域 -->
|
||||
<div id="apiTestCard" class="card hidden">
|
||||
<div class="card-header">
|
||||
API測試
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">測試會員API</h5>
|
||||
<p class="card-text">使用您的授權token測試以下API:</p>
|
||||
|
||||
<div class="mb-3">
|
||||
<button id="getProfile" class="btn btn-info">獲取個人資料</button>
|
||||
<button id="updateProfile" class="btn btn-warning">更新個人資料</button>
|
||||
<button id="logout" class="btn btn-danger">登出</button>
|
||||
</div>
|
||||
|
||||
<h6 class="mt-4">API回應結果:</h6>
|
||||
<pre id="apiResponse">尚未執行API請求</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// 檢查URL參數,處理登入後的回調
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// 檢查URL是否包含登入成功的資訊
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
if (urlParams.has('login_success')) {
|
||||
try {
|
||||
// 從localStorage獲取用戶資訊
|
||||
const userInfo = JSON.parse(localStorage.getItem('user_info'));
|
||||
if (userInfo && userInfo.token) {
|
||||
showTokenInfo(userInfo);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('無法解析用戶資訊', e);
|
||||
}
|
||||
}
|
||||
|
||||
// 檢查URL是否包含完整的用戶資訊(從callback獲取)
|
||||
const hashParams = new URLSearchParams(window.location.hash.substring(1));
|
||||
if (hashParams.has('user_info')) {
|
||||
try {
|
||||
const userInfo = JSON.parse(decodeURIComponent(hashParams.get('user_info')));
|
||||
if (userInfo && userInfo.token) {
|
||||
// 儲存到localStorage以便重新整理後仍可使用
|
||||
localStorage.setItem('user_info', JSON.stringify(userInfo));
|
||||
showTokenInfo(userInfo);
|
||||
|
||||
// 清除URL中的hash,避免重新整理後重複處理
|
||||
history.replaceState(null, document.title, window.location.pathname + '?login_success=true');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('無法解析用戶資訊', e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 一般登入表單處理
|
||||
document.getElementById('loginForm').addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const email = document.getElementById('email').value;
|
||||
const password = document.getElementById('password').value;
|
||||
|
||||
fetch('/api/member/login', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ email, password })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.status && data.data && data.data.token) {
|
||||
const userInfo = {
|
||||
user: data.data.user,
|
||||
token: data.data.token,
|
||||
token_type: data.data.token_type
|
||||
};
|
||||
localStorage.setItem('user_info', JSON.stringify(userInfo));
|
||||
showTokenInfo(userInfo);
|
||||
} else {
|
||||
alert('登入失敗:' + (data.message || '未知錯誤'));
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('登入錯誤', error);
|
||||
alert('登入過程發生錯誤,請檢查網路連線');
|
||||
});
|
||||
});
|
||||
|
||||
// 顯示Token資訊
|
||||
function showTokenInfo(userInfo) {
|
||||
document.getElementById('tokenCard').classList.remove('hidden');
|
||||
document.getElementById('apiTestCard').classList.remove('hidden');
|
||||
|
||||
const tokenInfo = document.getElementById('tokenInfo');
|
||||
tokenInfo.textContent = JSON.stringify(userInfo, null, 2);
|
||||
|
||||
// 設定複製按鈕功能
|
||||
document.getElementById('copyToken').addEventListener('click', function() {
|
||||
navigator.clipboard.writeText(userInfo.token)
|
||||
.then(() => alert('Token已複製到剪貼簿'))
|
||||
.catch(err => console.error('複製失敗', err));
|
||||
});
|
||||
|
||||
// 設定API測試按鈕
|
||||
setupApiButtons(userInfo.token);
|
||||
}
|
||||
|
||||
// 設定API測試按鈕
|
||||
function setupApiButtons(token) {
|
||||
// 獲取個人資料
|
||||
document.getElementById('getProfile').addEventListener('click', function() {
|
||||
callApi('/api/member/profile', 'GET', null, token);
|
||||
});
|
||||
|
||||
// 更新個人資料
|
||||
document.getElementById('updateProfile').addEventListener('click', function() {
|
||||
const newName = prompt('請輸入新的姓名', '');
|
||||
if (newName) {
|
||||
callApi('/api/member/profile', 'PUT', { name: newName }, token);
|
||||
}
|
||||
});
|
||||
|
||||
// 登出
|
||||
document.getElementById('logout').addEventListener('click', function() {
|
||||
callApi('/api/member/logout', 'POST', null, token)
|
||||
.then(() => {
|
||||
localStorage.removeItem('user_info');
|
||||
document.getElementById('tokenCard').classList.add('hidden');
|
||||
document.getElementById('apiTestCard').classList.add('hidden');
|
||||
alert('已成功登出');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 呼叫API
|
||||
function callApi(url, method, data, token) {
|
||||
const headers = {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json'
|
||||
};
|
||||
|
||||
const options = {
|
||||
method: method,
|
||||
headers: headers
|
||||
};
|
||||
|
||||
if (data && (method === 'POST' || method === 'PUT')) {
|
||||
options.body = JSON.stringify(data);
|
||||
}
|
||||
|
||||
return fetch(url, options)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
document.getElementById('apiResponse').textContent = JSON.stringify(data, null, 2);
|
||||
return data;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('API錯誤', error);
|
||||
document.getElementById('apiResponse').textContent = `錯誤: ${error.message}`;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user