470 lines
25 KiB
HTML
470 lines
25 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<!-- 头部内容 -->
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>PPanel - Application Initialization</title>
|
|
<!-- 引入 Tailwind CSS -->
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
<!-- Tailwind CSS 配置 -->
|
|
<script>
|
|
tailwind.config = {
|
|
darkMode: ["class"],
|
|
theme: {
|
|
container: { center: true, padding: "2rem" },
|
|
extend: {
|
|
colors: {
|
|
border: "hsl(var(--border))",
|
|
input: "hsl(var(--input))",
|
|
ring: "hsl(var(--ring))",
|
|
background: "hsl(var(--background))",
|
|
foreground: "hsl(var(--foreground))",
|
|
primary: { DEFAULT: "hsl(var(--primary))", foreground: "hsl(var(--primary-foreground))" },
|
|
destructive: { DEFAULT: "hsl(var(--destructive))", foreground: "hsl(var(--destructive-foreground))" },
|
|
},
|
|
borderRadius: { lg: "var(--radius)", md: "calc(var(--radius) - 2px)", sm: "calc(var(--radius) - 4px)" },
|
|
},
|
|
},
|
|
}
|
|
</script>
|
|
<!-- 自定义样式 -->
|
|
<style>
|
|
:root {
|
|
--background: 0 0% 100%;
|
|
--foreground: 222.2 84% 4.9%;
|
|
--border: 214.3 31.8% 91.4%;
|
|
--input: 214.3 31.8% 91.4%;
|
|
--ring: 221.2 83.2% 53.3%;
|
|
--radius: 0.5rem;
|
|
--primary: 221.2 83.2% 53.3%;
|
|
--primary-foreground: 210 40% 98%;
|
|
--destructive: 346.8 77.2% 49.8%;
|
|
--destructive-foreground: 355.7 100% 97.3%;
|
|
}
|
|
.dark {
|
|
--background: 222.2 84% 4.9%;
|
|
--foreground: 210 40% 98%;
|
|
}
|
|
body {
|
|
background-color: hsl(var(--background));
|
|
color: hsl(var(--foreground));
|
|
}
|
|
</style>
|
|
</head>
|
|
<body class="min-h-screen font-sans antialiased">
|
|
<div id="appContainer" class="container mx-auto p-4 flex flex-col items-center min-h-screen">
|
|
<div class="w-full max-w-2xl space-y-6">
|
|
<!-- 设置卡片 -->
|
|
<div id="setupCard" class="p-6 space-y-6 bg-white rounded-lg border">
|
|
<div class="flex justify-between items-center">
|
|
<h1 id="title" class="text-3xl font-bold">Welcome to PPanel Setup</h1>
|
|
<button onclick="switchLanguage()" id="langSwitch" class="h-10 px-4 py-2 border rounded-md text-sm font-medium bg-background hover:bg-accent hover:text-accent-foreground">中文</button>
|
|
</div>
|
|
<p id="description" class="text-gray-600 !mt-0">Let's get your PPanel application up and running. Please provide the necessary information below.</p>
|
|
|
|
<form id="setupForm" class="space-y-6" onsubmit="handleSubmit(event)">
|
|
<!-- 管理员详情 -->
|
|
<div class="space-y-4">
|
|
<h2 id="adminInfoTitle" class="font-bold text-xl">Administrator Details</h2>
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<div>
|
|
<label for="adminEmail" id="labelAdminEmail" class="text-sm font-medium">Administrator Email</label>
|
|
<input type="email" id="adminEmail" name="adminEmail" required class="input-field mt-1 block w-full rounded-md border px-3 py-2" placeholder="Enter administrator email" data-placeholder-en="Enter administrator email" data-placeholder-zh="请输入管理员邮箱" oninput="validateInput(this)">
|
|
<span id="adminEmailError" class="text-red-500 text-sm mt-1 hidden">Invalid email address.</span>
|
|
</div>
|
|
<div>
|
|
<label for="adminPassword" id="labelAdminPassword" class="text-sm font-medium">Administrator Password</label>
|
|
<input type="password" id="adminPassword" name="adminPassword" required minlength="6" class="input-field mt-1 block w-full rounded-md border px-3 py-2" placeholder="Enter administrator password" data-placeholder-en="Enter administrator password" data-placeholder-zh="请输入管理员密码" oninput="validateInput(this)">
|
|
<span id="adminPasswordError" class="text-red-500 text-sm mt-1 hidden">Password must be at least 6 characters.</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- MySQL 数据库设置 -->
|
|
<div class="space-y-4">
|
|
<div class="flex justify-between items-center">
|
|
<h2 id="mysqlInfoTitle" class="font-bold text-xl">MySQL Database Setup</h2>
|
|
<button type="button" onclick="testConnection('mysql')" id="testMySQLButton" class="h-10 px-4 py-2 border rounded-md text-sm font-medium bg-background hover:bg-accent hover:text-accent-foreground">Test MySQL Connection</button>
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<div>
|
|
<label for="mysqlHost" id="labelMysqlHost" class="text-sm font-medium">Database Host</label>
|
|
<input type="text" id="mysqlHost" name="mysqlHost" required class="input-field mt-1 block w-full rounded-md border px-3 py-2" value="localhost" placeholder="Enter database host" data-placeholder-en="Enter database host" data-placeholder-zh="请输入数据库主机">
|
|
<span id="mysqlHostError" class="text-red-500 text-sm mt-1 hidden">Please enter a valid host.</span>
|
|
</div>
|
|
<div>
|
|
<label for="mysqlPort" id="labelMysqlPort" class="text-sm font-medium">Database Port</label>
|
|
<input type="number" id="mysqlPort" name="mysqlPort" required min="1" max="65535" class="input-field mt-1 block w-full rounded-md border px-3 py-2" value="3306" placeholder="Enter database port" data-placeholder-en="Enter database port" data-placeholder-zh="请输入数据库端口">
|
|
<span id="mysqlPortError" class="text-red-500 text-sm mt-1 hidden">Please enter a valid port number.</span>
|
|
</div>
|
|
<div>
|
|
<label for="mysqlUser" id="labelMysqlUser" class="text-sm font-medium">Database User</label>
|
|
<input type="text" id="mysqlUser" name="mysqlUser" required class="input-field mt-1 block w-full rounded-md border px-3 py-2" value="root" placeholder="Enter database user" data-placeholder-en="Enter database user" data-placeholder-zh="请输入数据库用户名">
|
|
<span id="mysqlUserError" class="text-red-500 text-sm mt-1 hidden">Please enter a username.</span>
|
|
</div>
|
|
<div>
|
|
<label for="mysqlPassword" id="labelMysqlPassword" class="text-sm font-medium">Database Password</label>
|
|
<input type="password" id="mysqlPassword" name="mysqlPassword" class="input-field mt-1 block w-full rounded-md border px-3 py-2" placeholder="Enter database password" data-placeholder-en="Enter database password" data-placeholder-zh="请输入数据库密码">
|
|
</div>
|
|
<div>
|
|
<label for="mysqlDatabase" id="labelMysqlDatabase" class="text-sm font-medium">Database Name</label>
|
|
<input type="text" id="mysqlDatabase" name="mysqlDatabase" required class="input-field mt-1 block w-full rounded-md border px-3 py-2" value="ppanel_db" placeholder="Enter database name" data-placeholder-en="Enter database name" data-placeholder-zh="请输入数据库名称">
|
|
<span id="mysqlDatabaseError" class="text-red-500 text-sm mt-1 hidden">Please enter a database name.</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Redis 缓存设置 -->
|
|
<div class="space-y-4">
|
|
<div class="flex justify-between items-center">
|
|
<h2 id="redisInfoTitle" class="font-bold text-xl">Redis Cache Setup</h2>
|
|
<button type="button" onclick="testConnection('redis')" id="testRedisButton" class="h-10 px-4 py-2 border rounded-md text-sm font-medium bg-background hover:bg-accent hover:text-accent-foreground">Test Redis Connection</button>
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<div>
|
|
<label for="redisHost" id="labelRedisHost" class="text-sm font-medium">Redis Host</label>
|
|
<input type="text" id="redisHost" name="redisHost" required class="input-field mt-1 block w-full rounded-md border px-3 py-2" value="127.0.0.1" placeholder="Enter Redis host" data-placeholder-en="Enter Redis host" data-placeholder-zh="请输入 Redis 主机">
|
|
<span id="redisHostError" class="text-red-500 text-sm mt-1 hidden">Please enter a valid host.</span>
|
|
</div>
|
|
<div>
|
|
<label for="redisPort" id="labelRedisPort" class="text-sm font-medium">Redis Port</label>
|
|
<input type="number" id="redisPort" name="redisPort" required min="1" max="65535" class="input-field mt-1 block w-full rounded-md border px-3 py-2" value="6379" placeholder="Enter Redis port" data-placeholder-en="Enter Redis port" data-placeholder-zh="请输入 Redis 端口">
|
|
<span id="redisPortError" class="text-red-500 text-sm mt-1 hidden">Please enter a valid port number.</span>
|
|
</div>
|
|
<div>
|
|
<label for="redisPassword" id="labelRedisPassword" class="text-sm font-medium">Redis Password</label>
|
|
<input type="password" id="redisPassword" name="redisPassword" class="input-field mt-1 block w-full rounded-md border px-3 py-2" placeholder="Enter Redis password (optional)" data-placeholder-en="Enter Redis password (optional)" data-placeholder-zh="请输入 Redis 密码(可选)">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 提交按钮 -->
|
|
<button type="submit" id="submitButton" disabled class="w-full h-10 px-4 py-2 bg-primary text-white rounded-md opacity-50 cursor-not-allowed">Start Initialization</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 安装中卡片 -->
|
|
<div id="installingCard" class="fixed inset-0 flex items-center justify-center bg-white p-6 hidden">
|
|
<div class="w-full max-w-md space-y-6 text-center">
|
|
<h1 id="installingTitle" class="text-3xl font-bold">Installing...</h1>
|
|
<p id="installingMessage">Please wait while we initialize your application.</p>
|
|
<div class="flex justify-center">
|
|
<svg class="animate-spin h-10 w-10 text-primary" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
|
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
|
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8z"></path>
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 安装完成卡片 -->
|
|
<div id="installationCompleteCard" class="fixed inset-0 flex items-center justify-center bg-white p-6 hidden">
|
|
<div class="w-full max-w-md space-y-6 text-center">
|
|
<h1 id="installationCompleteTitle" class="text-3xl font-bold">Installation Complete</h1>
|
|
<p id="installationCompleteMessage">You can now close this page.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 已初始化页面 -->
|
|
<div id="alreadyInitializedCard" class="fixed inset-0 flex items-center justify-center bg-white p-6 hidden">
|
|
<div class="w-full max-w-md space-y-6 text-center">
|
|
<h1 id="alreadyInitializedTitle" class="text-3xl font-bold">Already Initialized</h1>
|
|
<p id="alreadyInitializedMessage">Your PPanel application has already been initialized.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 对话框 -->
|
|
<div id="dialog" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden">
|
|
<div class="bg-white rounded-lg p-6 w-96">
|
|
<h2 id="dialogTitle" class="text-xl font-bold mb-4"></h2>
|
|
<p id="dialogMessage" class="mb-4"></p>
|
|
<div class="flex justify-end">
|
|
<button onclick="closeDialog()" class="h-10 px-4 py-2 bg-primary text-white rounded-md">Close</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- JavaScript -->
|
|
<script>
|
|
let currentLang = 'en';
|
|
const translations = {
|
|
en: {
|
|
// 英文翻译内容
|
|
title: 'Welcome to PPanel Setup',
|
|
description: "Let's get your PPanel application up and running. Please provide the necessary information below.",
|
|
adminInfoTitle: 'Administrator Details',
|
|
mysqlInfoTitle: 'MySQL Database Setup',
|
|
redisInfoTitle: 'Redis Cache Setup',
|
|
adminEmail: 'Administrator Email',
|
|
adminPassword: 'Administrator Password',
|
|
mysqlHost: 'Database Host',
|
|
mysqlPort: 'Database Port',
|
|
mysqlUser: 'Database User',
|
|
mysqlPassword: 'Database Password',
|
|
mysqlDatabase: 'Database Name',
|
|
redisHost: 'Redis Host',
|
|
redisPort: 'Redis Port',
|
|
redisPassword: 'Redis Password',
|
|
submit: 'Start Initialization',
|
|
switchLang: '中文',
|
|
testMySQLConnection: 'Test MySQL Connection',
|
|
testRedisConnection: 'Test Redis Connection',
|
|
connectionSuccess: 'Connection Successful',
|
|
connectionError: 'Connection Failed',
|
|
initializationError: 'Initialization Error',
|
|
initializationErrorMessage: 'An error occurred during initialization. Please try again.',
|
|
installingTitle: 'Installing...',
|
|
installingMessage: 'Please wait while we initialize your application.',
|
|
installationCompleteTitle: 'Installation Complete',
|
|
installationCompleteMessage: 'You can now close this page.',
|
|
proceedButton: 'Go to Application',
|
|
mysqlConnectionSuccess: 'Successfully connected to the MySQL database.',
|
|
mysqlConnectionError: 'Failed to connect to the MySQL database. Please check your settings.',
|
|
redisConnectionSuccess: 'Successfully connected to the Redis server.',
|
|
redisConnectionError: 'Failed to connect to the Redis server. Please check your settings.',
|
|
alreadyInitializedTitle: 'Already Initialized',
|
|
alreadyInitializedMessage: 'Your PPanel application has already been initialized.',
|
|
invalidEmail: 'Invalid email address.',
|
|
invalidPassword: 'Password must be at least 6 characters.',
|
|
},
|
|
zh: {
|
|
// 中文翻译内容
|
|
title: '欢迎使用 PPanel 设置向导',
|
|
description: '让我们一起启动您的 PPanel 应用程序。请提供以下必要信息。',
|
|
adminInfoTitle: '管理员详情',
|
|
mysqlInfoTitle: 'MySQL 数据库设置',
|
|
redisInfoTitle: 'Redis 缓存设置',
|
|
adminEmail: '管理员邮箱',
|
|
adminPassword: '管理员密码',
|
|
mysqlHost: '数据库主机',
|
|
mysqlPort: '数据库端口',
|
|
mysqlUser: '数据库用户',
|
|
mysqlPassword: '数据库密码',
|
|
mysqlDatabase: '数据库名称',
|
|
redisHost: 'Redis 主机',
|
|
redisPort: 'Redis 端口',
|
|
redisPassword: 'Redis 密码',
|
|
submit: '开始初始化',
|
|
switchLang: 'English',
|
|
testMySQLConnection: '测试 MySQL 连接',
|
|
testRedisConnection: '测试 Redis 连接',
|
|
connectionSuccess: '连接成功',
|
|
connectionError: '连接失败',
|
|
initializationError: '初始化错误',
|
|
initializationErrorMessage: '初始化过程中发生错误。请重试。',
|
|
installingTitle: '正在安装...',
|
|
installingMessage: '请稍候,我们正在初始化您的应用程序。',
|
|
installationCompleteTitle: '安装完成',
|
|
installationCompleteMessage: '您现在可以关闭此页面。',
|
|
proceedButton: '前往应用程序',
|
|
mysqlConnectionSuccess: '成功连接到 MySQL 数据库。',
|
|
mysqlConnectionError: '无法连接到 MySQL 数据库。请检查您的设置。',
|
|
redisConnectionSuccess: '成功连接到 Redis 服务器。',
|
|
redisConnectionError: '无法连接到 Redis 服务器。请检查您的设置。',
|
|
alreadyInitializedTitle: '已初始化',
|
|
alreadyInitializedMessage: '您的 PPanel 应用程序已被初始化。',
|
|
invalidEmail: '无效的邮箱地址。',
|
|
invalidPassword: '密码至少需要6个字符。',
|
|
}
|
|
};
|
|
|
|
function switchLanguage() {
|
|
currentLang = currentLang === 'en' ? 'zh' : 'en';
|
|
updateTexts();
|
|
}
|
|
|
|
function updateTexts() {
|
|
const t = translations[currentLang];
|
|
document.getElementById('title').textContent = t.title;
|
|
document.getElementById('description').textContent = t.description;
|
|
document.getElementById('adminInfoTitle').textContent = t.adminInfoTitle;
|
|
document.getElementById('mysqlInfoTitle').textContent = t.mysqlInfoTitle;
|
|
document.getElementById('redisInfoTitle').textContent = t.redisInfoTitle;
|
|
document.getElementById('labelAdminEmail').textContent = t.adminEmail;
|
|
document.getElementById('labelAdminPassword').textContent = t.adminPassword;
|
|
document.getElementById('labelMysqlHost').textContent = t.mysqlHost;
|
|
document.getElementById('labelMysqlPort').textContent = t.mysqlPort;
|
|
document.getElementById('labelMysqlUser').textContent = t.mysqlUser;
|
|
document.getElementById('labelMysqlPassword').textContent = t.mysqlPassword;
|
|
document.getElementById('labelMysqlDatabase').textContent = t.mysqlDatabase;
|
|
document.getElementById('labelRedisHost').textContent = t.redisHost;
|
|
document.getElementById('labelRedisPort').textContent = t.redisPort;
|
|
document.getElementById('labelRedisPassword').textContent = t.redisPassword;
|
|
document.getElementById('submitButton').textContent = t.submit;
|
|
document.getElementById('langSwitch').textContent = t.switchLang;
|
|
document.getElementById('testMySQLButton').textContent = t.testMySQLConnection;
|
|
document.getElementById('testRedisButton').textContent = t.testRedisConnection;
|
|
document.getElementById('installingTitle').textContent = t.installingTitle;
|
|
document.getElementById('installingMessage').textContent = t.installingMessage;
|
|
document.getElementById('installationCompleteTitle').textContent = t.installationCompleteTitle;
|
|
document.getElementById('installationCompleteMessage').textContent = t.installationCompleteMessage;
|
|
document.getElementById('alreadyInitializedTitle').textContent = t.alreadyInitializedTitle;
|
|
document.getElementById('alreadyInitializedMessage').textContent = t.alreadyInitializedMessage;
|
|
|
|
// 更新 placeholder 文本
|
|
const inputs = document.querySelectorAll('.input-field');
|
|
inputs.forEach((input) => {
|
|
const placeholder = input.getAttribute(`data-placeholder-${currentLang}`);
|
|
if (placeholder) {
|
|
input.setAttribute('placeholder', placeholder);
|
|
}
|
|
});
|
|
}
|
|
|
|
function checkInitialization() {
|
|
const isInitialized = false; // 需要从服务器获取实际状态
|
|
if (isInitialized) {
|
|
document.getElementById('appContainer').classList.add('hidden');
|
|
document.getElementById('alreadyInitializedCard').classList.remove('hidden');
|
|
}
|
|
}
|
|
|
|
function testConnection(type) {
|
|
const t = translations[currentLang];
|
|
let data = {};
|
|
let url = '';
|
|
if (type === 'mysql') {
|
|
data = {
|
|
host: document.getElementById('mysqlHost').value,
|
|
port: document.getElementById('mysqlPort').value,
|
|
user: document.getElementById('mysqlUser').value,
|
|
password: document.getElementById('mysqlPassword').value,
|
|
database: document.getElementById('mysqlDatabase').value,
|
|
};
|
|
url = '/init/mysql/test';
|
|
} else if (type === 'redis') {
|
|
data = {
|
|
host: document.getElementById('redisHost').value,
|
|
port: document.getElementById('redisPort').value,
|
|
password: document.getElementById('redisPassword').value,
|
|
};
|
|
url = '/init/redis/test';
|
|
}
|
|
|
|
fetch(url, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify(data),
|
|
})
|
|
.then(response => response.json())
|
|
.then(result => {
|
|
console.log(result);
|
|
if (result.code === 200 && result.status) {
|
|
showDialog(t.connectionSuccess, result.msg || (type === 'mysql' ? t.mysqlConnectionSuccess : t.redisConnectionSuccess));
|
|
} else {
|
|
showDialog(t.connectionError, result.msg || (type === 'mysql' ? t.mysqlConnectionError : t.redisConnectionError));
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
showDialog(t.connectionError, t.initializationErrorMessage);
|
|
});
|
|
}
|
|
|
|
function handleSubmit(event) {
|
|
event.preventDefault();
|
|
const form = document.getElementById('setupForm');
|
|
if (!form.checkValidity()) {
|
|
form.reportValidity();
|
|
return;
|
|
}
|
|
const t = translations[currentLang];
|
|
const formData = new FormData(form);
|
|
const data = Object.fromEntries(formData.entries());
|
|
|
|
// 显示安装中界面
|
|
document.getElementById('setupCard').classList.add('hidden');
|
|
document.getElementById('installingCard').classList.remove('hidden');
|
|
|
|
// 发送初始化请求
|
|
fetch('/init/config', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify(data),
|
|
})
|
|
.then(response => response.json())
|
|
.then(result => {
|
|
document.getElementById('installingCard').classList.add('hidden');
|
|
if (result.code === 200 && result.status) {
|
|
document.getElementById('installationCompleteCard').classList.remove('hidden');
|
|
} else {
|
|
showDialog(t.initializationError, result.msg || t.initializationErrorMessage);
|
|
document.getElementById('setupCard').classList.remove('hidden');
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
document.getElementById('installingCard').classList.add('hidden');
|
|
showDialog(t.initializationError, t.initializationErrorMessage);
|
|
document.getElementById('setupCard').classList.remove('hidden');
|
|
});
|
|
}
|
|
|
|
function showDialog(title, message) {
|
|
document.getElementById('dialogTitle').textContent = title;
|
|
document.getElementById('dialogMessage').textContent = message;
|
|
document.getElementById('dialog').classList.remove('hidden');
|
|
}
|
|
|
|
function closeDialog() {
|
|
document.getElementById('dialog').classList.add('hidden');
|
|
}
|
|
|
|
// 实时表单校验
|
|
function validateInput(input) {
|
|
const errorSpan = document.getElementById(input.id + 'Error');
|
|
|
|
if (input.type === 'email') {
|
|
// 邮箱格式验证
|
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
if (!emailRegex.test(input.value)) {
|
|
errorSpan.textContent = translations[currentLang].invalidEmail;
|
|
errorSpan.classList.remove('hidden');
|
|
input.setCustomValidity(translations[currentLang].invalidEmail);
|
|
} else {
|
|
input.setCustomValidity('');
|
|
errorSpan.classList.add('hidden');
|
|
}
|
|
} else if (input.validity.valid) {
|
|
errorSpan.classList.add('hidden');
|
|
input.setCustomValidity('');
|
|
} else {
|
|
errorSpan.classList.remove('hidden');
|
|
}
|
|
|
|
updateSubmitButtonState();
|
|
}
|
|
|
|
function updateSubmitButtonState() {
|
|
const form = document.getElementById('setupForm');
|
|
const submitButton = document.getElementById('submitButton');
|
|
if (form.checkValidity()) {
|
|
submitButton.disabled = false;
|
|
submitButton.classList.remove('opacity-50', 'cursor-not-allowed');
|
|
} else {
|
|
submitButton.disabled = true;
|
|
submitButton.classList.add('opacity-50', 'cursor-not-allowed');
|
|
}
|
|
}
|
|
|
|
// 添加事件监听器
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const inputs = document.querySelectorAll('.input-field');
|
|
inputs.forEach((input) => {
|
|
input.addEventListener('input', () => validateInput(input));
|
|
});
|
|
updateSubmitButtonState();
|
|
updateTexts();
|
|
checkInitialization();
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|