v1.0.0提交

This commit is contained in:
2026-03-31 15:54:32 +08:00
parent 79bfeb0e18
commit 314e53bf9c
16 changed files with 2110 additions and 1 deletions

108
pages/password.php Normal file
View File

@@ -0,0 +1,108 @@
<?php
/**
* PerToolBox Front - 密码生成器页面
*
* Copyright (C) 2024 Sea Network Technology Studio
* Author: Canglan <admin@sea-studio.top>
* License: AGPL v3
*/
require_once '../config.php';
include_once '../header.php';
include_once '../sidebar.php';
?>
<div class="main-content">
<div class="card">
<h1 class="text-2xl font-bold mb-6">🔑 密码生成器</h1>
<div class="mb-6">
<div class="flex gap-2">
<input type="text" id="password" readonly class="flex-1 font-mono text-xl border rounded-lg px-4 py-3 bg-gray-50">
<button id="copyBtn" class="btn btn-secondary">复制</button>
<button id="generateBtn" class="btn btn-primary">生成</button>
</div>
</div>
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-6">
<label class="flex items-center gap-2"><input type="checkbox" id="useUpper" checked> 大写字母</label>
<label class="flex items-center gap-2"><input type="checkbox" id="useLower" checked> 小写字母</label>
<label class="flex items-center gap-2"><input type="checkbox" id="useDigits" checked> 数字</label>
<label class="flex items-center gap-2"><input type="checkbox" id="useSymbols" checked> 符号</label>
</div>
<div class="mb-6">
<label>密码长度: <span id="lengthValue">12</span></label>
<input type="range" id="length" min="4" max="64" value="12" class="w-full">
</div>
<div class="mb-6">
<label>批量生成数量:</label>
<div class="flex gap-2 mt-1">
<input type="number" id="count" min="1" max="10" value="1" class="form-input w-24">
<button id="batchBtn" class="btn btn-secondary">批量生成</button>
</div>
</div>
<div id="batchResults" class="hidden mt-4 p-4 bg-gray-50 rounded-lg">
<h3 class="font-bold mb-2">生成的密码:</h3>
<div id="passwordList" class="space-y-1 font-mono text-sm"></div>
</div>
</div>
</div>
<script>
async function generatePassword() {
const length = document.getElementById('length').value;
const upper = document.getElementById('useUpper').checked;
const lower = document.getElementById('useLower').checked;
const digits = document.getElementById('useDigits').checked;
const symbols = document.getElementById('useSymbols').checked;
try {
const data = await apiRequest(`/password/generate?length=${length}&upper=${upper}&lower=${lower}&digits=${digits}&symbols=${symbols}`);
document.getElementById('password').value = data.passwords;
} catch (error) {
showToast(error.message, 'error');
}
}
async function batchGenerate() {
const length = document.getElementById('length').value;
const count = document.getElementById('count').value;
const upper = document.getElementById('useUpper').checked;
const lower = document.getElementById('useLower').checked;
const digits = document.getElementById('useDigits').checked;
const symbols = document.getElementById('useSymbols').checked;
try {
const data = await apiRequest(`/password/generate?length=${length}&upper=${upper}&lower=${lower}&digits=${digits}&symbols=${symbols}&count=${count}`);
const passwords = Array.isArray(data.passwords) ? data.passwords : [data.passwords];
const listHtml = passwords.map(p => `<div>• ${escapeHtml(p)}</div>`).join('');
document.getElementById('passwordList').innerHTML = listHtml;
document.getElementById('batchResults').classList.remove('hidden');
} catch (error) {
showToast(error.message, 'error');
}
}
function copyPassword() {
const pwd = document.getElementById('password').value;
if (pwd) {
navigator.clipboard.writeText(pwd);
showToast('已复制到剪贴板');
}
}
document.getElementById('length').addEventListener('input', (e) => {
document.getElementById('lengthValue').textContent = e.target.value;
});
document.getElementById('generateBtn').addEventListener('click', generatePassword);
document.getElementById('copyBtn').addEventListener('click', copyPassword);
document.getElementById('batchBtn').addEventListener('click', batchGenerate);
recordUsage('password');
generatePassword();
</script>
<?php include_once '../footer.php'; ?>