v0.3测试

This commit is contained in:
2026-04-10 17:59:28 +08:00
parent 916b0bac4a
commit 81153806ed
4 changed files with 21 additions and 127 deletions

View File

@@ -9,19 +9,12 @@
* 版权所有 © Sea Network Technology Studio * 版权所有 © Sea Network Technology Studio
*/ */
// API 使用相对路径,由 Nginx 反向代理 /api/ 到后端
const API_BASE_URL = '';
const JWT_STORAGE_KEY = 'class_system_token';
const USER_STORAGE_KEY = 'class_system_user';
// 获取Token
function getToken() { function getToken() {
return localStorage.getItem(JWT_STORAGE_KEY); return localStorage.getItem(window.JWT_STORAGE_KEY || 'class_system_token');
} }
// 获取用户信息
function getUserInfo() { function getUserInfo() {
const userStr = localStorage.getItem(USER_STORAGE_KEY); const userStr = localStorage.getItem(window.USER_STORAGE_KEY || 'class_system_user');
if (!userStr) return null; if (!userStr) return null;
try { try {
return JSON.parse(userStr); return JSON.parse(userStr);
@@ -30,28 +23,15 @@ function getUserInfo() {
} }
} }
// 保存用户信息
function setUserInfo(user) { function setUserInfo(user) {
localStorage.setItem(USER_STORAGE_KEY, JSON.stringify(user)); localStorage.setItem(window.USER_STORAGE_KEY || 'class_system_user', JSON.stringify(user));
} }
// 清除登录信息
function clearAuth() { function clearAuth() {
localStorage.removeItem(JWT_STORAGE_KEY); localStorage.removeItem(window.JWT_STORAGE_KEY || 'class_system_token');
localStorage.removeItem(USER_STORAGE_KEY); localStorage.removeItem(window.USER_STORAGE_KEY || 'class_system_user');
} }
// 检查登录状态
function checkAuth() {
const token = getToken();
if (!token) {
window.location.href = '/index.php';
return false;
}
return true;
}
// API请求封装
async function apiRequest(url, options = {}) { async function apiRequest(url, options = {}) {
const token = getToken(); const token = getToken();
const headers = { const headers = {
@@ -62,16 +42,11 @@ async function apiRequest(url, options = {}) {
headers['Authorization'] = `Bearer ${token}`; headers['Authorization'] = `Bearer ${token}`;
} }
// 确保 url 以 /api/ 开头 const baseUrl = window.API_BASE_URL;
const fullUrl = url.startsWith('/api/') ? url : `/api${url}`; const fullUrl = `${baseUrl}${url}`;
const config = {
...options,
headers
};
try { try {
const response = await fetch(fullUrl, config); const response = await fetch(fullUrl, { ...options, headers });
const data = await response.json(); const data = await response.json();
if (response.status === 401) { if (response.status === 401) {
@@ -87,60 +62,50 @@ async function apiRequest(url, options = {}) {
} }
} }
// GET请求 function apiGet(url, params = {}) {
async function apiGet(url, params = {}) {
const queryString = new URLSearchParams(params).toString(); const queryString = new URLSearchParams(params).toString();
const fullUrl = queryString ? `${url}?${queryString}` : url; const fullUrl = queryString ? `${url}?${queryString}` : url;
return apiRequest(fullUrl, { method: 'GET' }); return apiRequest(fullUrl, { method: 'GET' });
} }
// POST请求 function apiPost(url, data = {}) {
async function apiPost(url, data = {}) {
return apiRequest(url, { return apiRequest(url, {
method: 'POST', method: 'POST',
body: JSON.stringify(data) body: JSON.stringify(data)
}); });
} }
// PUT请求 function apiPut(url, data = {}) {
async function apiPut(url, data = {}) {
return apiRequest(url, { return apiRequest(url, {
method: 'PUT', method: 'PUT',
body: JSON.stringify(data) body: JSON.stringify(data)
}); });
} }
// DELETE请求 function apiDelete(url) {
async function apiDelete(url) {
return apiRequest(url, { method: 'DELETE' }); return apiRequest(url, { method: 'DELETE' });
} }
// 显示提示消息
function showToast(message, type = 'success') { function showToast(message, type = 'success') {
const toast = document.createElement('div'); const toast = document.createElement('div');
toast.className = `toast toast-${type}`; toast.className = `toast toast-${type}`;
toast.textContent = message; toast.textContent = message;
document.body.appendChild(toast); document.body.appendChild(toast);
setTimeout(() => { setTimeout(() => toast.remove(), 3000);
toast.remove();
}, 3000);
} }
// 格式化日期
function formatDate(dateStr) { function formatDate(dateStr) {
if (!dateStr) return '-'; if (!dateStr) return '-';
const date = new Date(dateStr); const date = new Date(dateStr);
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`; return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
} }
// 格式化日期时间
function formatDateTime(dateStr) { function formatDateTime(dateStr) {
if (!dateStr) return '-'; if (!dateStr) return '-';
const date = new Date(dateStr); const date = new Date(dateStr);
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')} ${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`; return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')} ${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;
} }
// 获取状态标签HTML
function getStatusBadge(status, type = 'homework') { function getStatusBadge(status, type = 'homework') {
const statusMap = { const statusMap = {
homework: { homework: {
@@ -179,49 +144,12 @@ function getStatusBadge(status, type = 'homework') {
return `<span class="${className}">${text}</span>`; return `<span class="${className}">${text}</span>`;
} }
// 退出登录
async function logout() { async function logout() {
await apiPost('/api/auth/logout'); await apiPost('/api/auth/logout');
clearAuth(); clearAuth();
window.location.href = '/index.php'; window.location.href = '/index.php';
} }
// 加载用户信息
function loadUserInfo() {
const user = getUserInfo();
const userNameSpan = document.getElementById('userName');
if (userNameSpan && user) {
userNameSpan.textContent = user.real_name || user.username;
}
}
// 检查是否需要修改密码
function checkNeedChangePassword() {
const user = getUserInfo();
if (user && user.need_change_password) {
const newPassword = prompt('首次登录请设置新密码6-20位需包含字母和数字');
if (newPassword) {
changePassword(newPassword);
}
}
}
// 修改密码
async function changePassword(newPassword) {
const res = await apiPost('/api/auth/change-password', {
old_password: newPassword,
new_password: newPassword
});
if (res && res.success) {
showToast('密码修改成功,请重新登录');
setTimeout(() => logout(), 1500);
} else {
showToast(res?.message || '密码修改失败', 'error');
checkNeedChangePassword();
}
}
// HTML转义
function escapeHtml(str) { function escapeHtml(str) {
if (!str) return ''; if (!str) return '';
return str.replace(/[&<>]/g, function(m) { return str.replace(/[&<>]/g, function(m) {
@@ -232,14 +160,14 @@ function escapeHtml(str) {
}); });
} }
// 页面加载时初始化
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
loadUserInfo(); const user = getUserInfo();
const userNameSpan = document.getElementById('userName');
if (userNameSpan && user) {
userNameSpan.textContent = user.real_name || user.username;
}
const logoutBtn = document.getElementById('logoutBtn'); const logoutBtn = document.getElementById('logoutBtn');
if (logoutBtn) { if (logoutBtn) {
logoutBtn.addEventListener('click', logout); logoutBtn.addEventListener('click', logout);
} }
if (window.location.pathname.includes('/student/') || window.location.pathname.includes('/parent/')) {
checkNeedChangePassword();
}
}); });

View File

@@ -52,7 +52,7 @@ if (!empty($missingKeys)) {
} }
// 定义常量 // 定义常量
define('API_BASE_URL', ''); define('API_BASE_URL', $config['API_BASE_URL']);
define('API_TIMEOUT', (int)$config['API_TIMEOUT']); define('API_TIMEOUT', (int)$config['API_TIMEOUT']);
define('JWT_STORAGE_KEY', $config['JWT_STORAGE_KEY']); define('JWT_STORAGE_KEY', $config['JWT_STORAGE_KEY']);
define('USER_STORAGE_KEY', $config['USER_STORAGE_KEY']); define('USER_STORAGE_KEY', $config['USER_STORAGE_KEY']);

View File

@@ -12,15 +12,13 @@
require_once __DIR__ . '/config.php'; require_once __DIR__ . '/config.php';
// 如果已登录,跳转到对应页面
if (isset($_SESSION['user_id']) && isset($_SESSION['user_type'])) { if (isset($_SESSION['user_id']) && isset($_SESSION['user_type'])) {
$redirect = [ $redirect = [
'student' => '/student/dashboard.php', 'student' => '/student/dashboard.php',
'parent' => '/parent/dashboard.php', 'parent' => '/parent/dashboard.php',
'admin' => '/admin/dashboard.php' 'admin' => '/admin/dashboard.php'
]; ];
$target = $redirect[$_SESSION['user_type']] ?? '/index.php'; header("Location: " . ($redirect[$_SESSION['user_type']] ?? '/index.php'));
header("Location: $target");
exit(); exit();
} }
?> ?>
@@ -42,7 +40,7 @@ if (isset($_SESSION['user_id']) && isset($_SESSION['user_type'])) {
<form id="loginForm" class="login-form"> <form id="loginForm" class="login-form">
<div class="form-group"> <div class="form-group">
<label>用户名</label> <label>用户名</label>
<input type="text" id="username" name="username" required autocomplete="off" placeholder="请输入用户名"> <input type="text" id="username" name="username" required autocomplete="off" placeholder="学号/手机号/管理员账号">
</div> </div>
<div class="form-group"> <div class="form-group">
<label>密码</label> <label>密码</label>
@@ -84,11 +82,8 @@ if (isset($_SESSION['user_id']) && isset($_SESSION['user_type'])) {
const data = await response.json(); const data = await response.json();
if (data.success && data.data) { if (data.success && data.data) {
// 存储Token和用户信息
localStorage.setItem(JWT_STORAGE_KEY, data.data.token); localStorage.setItem(JWT_STORAGE_KEY, data.data.token);
localStorage.setItem(USER_STORAGE_KEY, JSON.stringify(data.data)); localStorage.setItem(USER_STORAGE_KEY, JSON.stringify(data.data));
// 跳转
window.location.href = data.data.redirect; window.location.href = data.data.redirect;
} else { } else {
showError(data.message || '登录失败'); showError(data.message || '登录失败');

View File

@@ -1,29 +0,0 @@
# 前端站点配置
server {
listen 443 ssl http2;
server_name class.sea-studio.top;
root /www/wwwroot/ClassManager/frontend;
index index.php;
# 反向代理 /api/ 到后端
location /api/ {
proxy_pass https://classbackendapi.sea-studio.top/api/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass_request_headers on;
}
# PHP 处理
location ~ \.php$ {
fastcgi_pass unix:/tmp/php-cgi-80.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# 静态资源缓存
location ~* \.(css|js|jpg|png|gif|ico)$ {
expires 30d;
}
}