init
This commit is contained in:
commit
b10790c212
40 changed files with 4149 additions and 0 deletions
150
frontend/js/init.js
Normal file
150
frontend/js/init.js
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
// js/init.js
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const DOMElements = {
|
||||
initForm: document.getElementById('init-form'),
|
||||
initButton: null,
|
||||
toastContainer: document.getElementById('toast-container'),
|
||||
usernameInput: document.getElementById('username'),
|
||||
passwordInput: document.getElementById('password'),
|
||||
confirmPasswordInput: document.getElementById('confirm_password'),
|
||||
};
|
||||
|
||||
const INIT_API_URL = '/v0/api/auth/init';
|
||||
const PASSWORD_MIN_LENGTH = 8;
|
||||
const TOAST_DEFAULT_DURATION = 3000;
|
||||
const REDIRECT_DELAY_SUCCESS = 1500;
|
||||
|
||||
const theme = {
|
||||
init: () => {
|
||||
const storedTheme = localStorage.getItem('theme');
|
||||
const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
const currentTheme = storedTheme || (systemPrefersDark ? 'dark' : 'light');
|
||||
document.documentElement.dataset.theme = currentTheme;
|
||||
}
|
||||
};
|
||||
|
||||
const toast = {
|
||||
_container: null,
|
||||
_icons: { success: 'fa-check-circle', error: 'fa-times-circle', info: 'fa-info-circle' },
|
||||
|
||||
init: (containerElement) => {
|
||||
if (!containerElement) {
|
||||
console.error('Toast container element not found.');
|
||||
return;
|
||||
}
|
||||
toast._container = containerElement;
|
||||
toast._container.addEventListener('click', (e) => {
|
||||
if (e.target.dataset.toastClose !== undefined) {
|
||||
toast._hideToast(e.target.closest('.toast'));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
show: (message, type = 'info', duration = TOAST_DEFAULT_DURATION) => {
|
||||
if (!toast._container) {
|
||||
console.error('Toast module not initialized. Container is missing.');
|
||||
return;
|
||||
}
|
||||
|
||||
const iconClass = toast._icons[type] || 'fa-info-circle';
|
||||
const toastElement = document.createElement('div');
|
||||
toastElement.className = `toast ${type}`;
|
||||
toastElement.innerHTML = `
|
||||
<i class="toast-icon fa-solid ${iconClass}"></i>
|
||||
<p class="toast-message">${message}</p>
|
||||
<button class="toast-close" data-toast-close>×</button>
|
||||
`;
|
||||
toast._container.appendChild(toastElement);
|
||||
requestAnimationFrame(() => toastElement.classList.add('show'));
|
||||
setTimeout(() => toast._hideToast(toastElement), duration);
|
||||
},
|
||||
|
||||
_hideToast: (toastElement) => {
|
||||
if (!toastElement) return;
|
||||
toastElement.classList.remove('show');
|
||||
toastElement.addEventListener('transitionend', () => toastElement.remove(), { once: true });
|
||||
}
|
||||
};
|
||||
|
||||
async function handleInitSubmit(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// 1. 获取并修剪输入值
|
||||
const username = DOMElements.usernameInput.value.trim(); // 获取用户名并去除前后空格
|
||||
const password = DOMElements.passwordInput.value.trim();
|
||||
const confirmPassword = DOMElements.confirmPasswordInput.value.trim();
|
||||
|
||||
// 2. 添加用户名输入框的空值验证
|
||||
if (username === '') {
|
||||
toast.show('管理员用户名不能为空', 'error');
|
||||
DOMElements.usernameInput.focus();
|
||||
return;
|
||||
}
|
||||
// 其他密码验证逻辑不变
|
||||
if (password === '') {
|
||||
toast.show('密码不能为空', 'error');
|
||||
DOMElements.passwordInput.focus();
|
||||
return;
|
||||
}
|
||||
if (confirmPassword === '') {
|
||||
toast.show('确认密码不能为空', 'error');
|
||||
DOMElements.confirmPasswordInput.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
if (password !== confirmPassword) {
|
||||
toast.show('两次输入的密码不匹配', 'error');
|
||||
DOMElements.passwordInput.focus();
|
||||
return;
|
||||
}
|
||||
if (password.length < PASSWORD_MIN_LENGTH) {
|
||||
toast.show(`密码长度至少为 ${PASSWORD_MIN_LENGTH} 位`, 'error');
|
||||
DOMElements.passwordInput.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
DOMElements.initButton.disabled = true;
|
||||
DOMElements.initButton.querySelector('span').textContent = '设置中...';
|
||||
|
||||
try {
|
||||
const formData = new FormData(DOMElements.initForm);
|
||||
formData.set('username', username); // 确保发送的是修剪过的用户名
|
||||
formData.set('password', password); // 确保发送的是修剪过的密码
|
||||
formData.delete('confirm_password');
|
||||
|
||||
const response = await fetch(INIT_API_URL, {
|
||||
method: 'POST',
|
||||
body: new URLSearchParams(formData)
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
toast.show('管理员账户创建成功!正在跳转到登录页面...', 'success');
|
||||
setTimeout(() => { window.location.href = '/login.html'; }, REDIRECT_DELAY_SUCCESS);
|
||||
} else {
|
||||
throw new Error(result.error || `初始化失败: ${response.status}`);
|
||||
}
|
||||
} catch (error) {
|
||||
toast.show(error.message, 'error');
|
||||
DOMElements.initButton.disabled = false;
|
||||
DOMElements.initButton.querySelector('span').textContent = '完成设置';
|
||||
}
|
||||
}
|
||||
|
||||
function initApp() {
|
||||
theme.init();
|
||||
|
||||
if (DOMElements.initForm) {
|
||||
DOMElements.initButton = DOMElements.initForm.querySelector('button[type="submit"]');
|
||||
|
||||
toast.init(DOMElements.toastContainer);
|
||||
|
||||
DOMElements.initForm.addEventListener('submit', handleInitSubmit);
|
||||
} else {
|
||||
console.error('Init form element not found. Script may not function correctly.');
|
||||
}
|
||||
}
|
||||
|
||||
initApp();
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue