feat: 增强前端健壮性并添加刷新功能

- 添加刷新按钮和加载状态指示器
- 改进API请求错误处理和用户反馈
- 优化表单验证和登录逻辑
- 更新后端端口号并处理URL结尾斜杠
- 添加按钮悬停效果和移动端适配
This commit is contained in:
2025-12-23 23:48:12 +08:00
parent af8fdd5f52
commit b49fdeaa9d
7 changed files with 235 additions and 86 deletions

211
script.js
View File

@@ -1,6 +1,6 @@
// 配置
const ADMIN_PASSWORD = 'admin123'; // 管理员密码
const API_BASE_URL = 'http://localhost:6902/api'; // 后端API基础URL
const API_BASE_URL = 'http://47.92.113.131:6903/api'; // 后端API基础URL
// 初始化
function init() {
@@ -21,11 +21,17 @@ function login() {
const password = document.getElementById('password').value;
const message = document.getElementById('loginMessage');
if (!password.trim()) {
message.textContent = '密码不能为空!';
message.style.color = '#ff0000';
return;
}
if (password === ADMIN_PASSWORD) {
localStorage.setItem('isLoggedIn', 'true');
showUploadSection();
message.textContent = '登录成功!';
message.style.color = '#0000ff';
message.style.color = '#008000';
document.getElementById('password').value = '';
} else {
message.textContent = '密码错误,请重试!';
@@ -38,11 +44,15 @@ function showUploadSection() {
document.getElementById('loginSection').style.display = 'none';
document.getElementById('uploadSection').style.display = 'block';
const loginSection = document.getElementById('loginSection');
const logoutBtn = document.createElement('button');
logoutBtn.textContent = '退出登录';
logoutBtn.className = 'logout-btn';
logoutBtn.onclick = logout;
loginSection.appendChild(logoutBtn);
// 检查是否已经添加了退出按钮,避免重复添加
if (!loginSection.querySelector('.logout-btn')) {
const logoutBtn = document.createElement('button');
logoutBtn.textContent = '退出登录';
logoutBtn.className = 'logout-btn';
logoutBtn.onclick = logout;
loginSection.appendChild(logoutBtn);
}
}
// 退出登录
@@ -51,64 +61,100 @@ function logout() {
location.reload();
}
// 显示加载状态
function showLoading() {
const loadingIndicator = document.getElementById('loadingIndicator');
if (loadingIndicator) {
loadingIndicator.style.display = 'inline';
}
}
// 隐藏加载状态
function hideLoading() {
const loadingIndicator = document.getElementById('loadingIndicator');
if (loadingIndicator) {
loadingIndicator.style.display = 'none';
}
}
// 刷新App列表
function refreshAppList() {
loadAppList();
}
// 加载App列表
function loadAppList() {
async function loadAppList() {
const appList = document.getElementById('appList');
fetch(`${API_BASE_URL}/apps`)
.then(response => response.json())
.then(apps => {
if (apps.length === 0) {
appList.innerHTML = '<p style="text-align: center;">暂无App</p>';
return;
}
appList.innerHTML = '';
apps.forEach(app => {
const appItem = document.createElement('div');
appItem.className = 'app-item';
const appInfo = document.createElement('div');
appInfo.className = 'app-info';
const appName = document.createElement('h3');
appName.textContent = app.name;
const appDate = document.createElement('p');
appDate.textContent = `上传时间:${app.date}`;
const downloadBtn = document.createElement('button');
downloadBtn.className = 'download-btn';
downloadBtn.textContent = '下载';
downloadBtn.onclick = () => downloadApp(app.id, app.fileName);
const copyLinkBtn = document.createElement('button');
copyLinkBtn.className = 'download-btn';
copyLinkBtn.textContent = '复制直链';
copyLinkBtn.onclick = () => copyDirectLink(app.id, app.fileName);
appInfo.appendChild(appName);
appInfo.appendChild(appDate);
appItem.appendChild(appInfo);
const buttonsContainer = document.createElement('div');
buttonsContainer.style.display = 'flex';
buttonsContainer.style.gap = '10px';
buttonsContainer.appendChild(downloadBtn);
buttonsContainer.appendChild(copyLinkBtn);
appItem.appendChild(buttonsContainer);
appList.appendChild(appItem);
});
})
.catch(error => {
console.error('获取App列表失败:', error);
appList.innerHTML = '<p style="color: #ff0000; text-align: center;">获取App列表失败</p>';
try {
showLoading();
const response = await fetch(`${API_BASE_URL}/apps`, {
method: 'GET',
headers: {
'Accept': 'application/json'
},
timeout: 10000 // 10秒超时
});
if (!response.ok) {
throw new Error(`HTTP错误状态${response.status}`);
}
const apps = await response.json();
if (apps.length === 0) {
appList.innerHTML = '<p style="text-align: center;">暂无App</p>';
return;
}
appList.innerHTML = '';
apps.forEach(app => {
const appItem = document.createElement('div');
appItem.className = 'app-item';
const appInfo = document.createElement('div');
appInfo.className = 'app-info';
const appName = document.createElement('h3');
appName.textContent = app.name;
const appDate = document.createElement('p');
appDate.textContent = `上传时间:${app.date}`;
const downloadBtn = document.createElement('button');
downloadBtn.className = 'download-btn';
downloadBtn.textContent = '下载';
downloadBtn.onclick = () => downloadApp(app.id, app.fileName);
const copyLinkBtn = document.createElement('button');
copyLinkBtn.className = 'download-btn';
copyLinkBtn.textContent = '复制直链';
copyLinkBtn.onclick = () => copyDirectLink(app.id, app.fileName);
appInfo.appendChild(appName);
appInfo.appendChild(appDate);
appItem.appendChild(appInfo);
const buttonsContainer = document.createElement('div');
buttonsContainer.style.display = 'flex';
buttonsContainer.style.gap = '10px';
buttonsContainer.appendChild(downloadBtn);
buttonsContainer.appendChild(copyLinkBtn);
appItem.appendChild(buttonsContainer);
appList.appendChild(appItem);
});
} catch (error) {
console.error('获取App列表失败:', error);
appList.innerHTML = `<p style="color: #ff0000; text-align: center;">获取App列表失败${error.message}</p>`;
} finally {
hideLoading();
}
}
// 上传App
function uploadApp() {
async function uploadApp() {
let appName = document.getElementById('appName').value;
const appFile = document.getElementById('appFile').files[0];
const message = document.getElementById('uploadMessage');
@@ -135,15 +181,25 @@ function uploadApp() {
formData.append('name', appName);
formData.append('file', appFile);
fetch(`${API_BASE_URL}/apps`, {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(result => {
try {
message.textContent = '上传中...';
message.style.color = '#0000ff';
const response = await fetch(`${API_BASE_URL}/apps`, {
method: 'POST',
body: formData,
timeout: 30000 // 30秒超时
});
if (!response.ok) {
throw new Error(`HTTP错误状态${response.status}`);
}
const result = await response.json();
if (result.success) {
message.textContent = '上传成功!';
message.style.color = '#0000ff';
message.style.color = '#008000';
loadAppList();
// 清空表单
document.getElementById('appName').value = '';
@@ -152,22 +208,26 @@ function uploadApp() {
message.textContent = '上传失败:' + (result.message || '未知错误');
message.style.color = '#ff0000';
}
})
.catch(error => {
} catch (error) {
console.error('上传失败:', error);
message.textContent = '上传失败,请重试!';
message.textContent = '上传失败' + error.message;
message.style.color = '#ff0000';
});
}
}
// 下载App
function downloadApp(appId, fileName) {
const link = document.createElement('a');
link.href = `${API_BASE_URL}/apps/${appId}`;
link.download = fileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
try {
const link = document.createElement('a');
link.href = `${API_BASE_URL}/apps/${appId}`;
link.download = fileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
} catch (error) {
console.error('下载失败:', error);
alert('下载失败:' + error.message);
}
}
// 复制直链
@@ -202,6 +262,7 @@ function copyDirectLink(appId, fileName) {
})
.catch(err => {
console.error('复制失败:', err);
alert('复制失败:' + err.message);
});
}