|
@@ -162,6 +162,7 @@
|
|
|
<body>
|
|
|
<div class="container hidden" id="adminContainer">
|
|
|
<h1 class="admin-title">Docker 镜像代理加速 - 管理面板</h1>
|
|
|
+ <p></h1>配置添加或修改后,点击【保存更改】保存配置</p>
|
|
|
<form id="adminForm">
|
|
|
<label for="logoUrl">Logo URL: (可选)</label>
|
|
|
<input type="url" id="logoUrl" name="logoUrl">
|
|
@@ -241,34 +242,6 @@
|
|
|
renderMenuItems();
|
|
|
}
|
|
|
|
|
|
- function renderMenuItems() {
|
|
|
- const tbody = document.getElementById('menuTableBody');
|
|
|
- tbody.innerHTML = '';
|
|
|
- menuItems.forEach((item, index) => {
|
|
|
- const row = `
|
|
|
- <tr data-index="${index}">
|
|
|
- <td><input type="text" class="menu-text" value="${item.text}" disabled></td>
|
|
|
- <td><input type="url" class="menu-link" value="${item.link || ''}" disabled></td>
|
|
|
- <td>
|
|
|
- <select class="menu-newtab" disabled>
|
|
|
- <option value="false" ${item.newTab ? '' : 'selected'}>否</option>
|
|
|
- <option value="true" ${item.newTab ? 'selected' : ''}>是</option>
|
|
|
- </select>
|
|
|
- </td>
|
|
|
- <td>
|
|
|
- <button type="button" class="action-btn edit-btn">编辑</button>
|
|
|
- <button type="button" class="action-btn delete-btn">删除</button>
|
|
|
- <span class="drag-handle" style="cursor: move;">☰</span>
|
|
|
- </td>
|
|
|
- </tr>
|
|
|
- `;
|
|
|
- tbody.innerHTML += row;
|
|
|
- });
|
|
|
- setupDragAndDrop();
|
|
|
- setupEditButtons();
|
|
|
- setupDeleteButtons();
|
|
|
- }
|
|
|
-
|
|
|
function setupEditButtons() {
|
|
|
const editButtons = document.querySelectorAll('.edit-btn');
|
|
|
editButtons.forEach((button, index) => {
|
|
@@ -283,16 +256,15 @@
|
|
|
linkInput.disabled = false;
|
|
|
newTabSelect.disabled = false;
|
|
|
button.textContent = '保存';
|
|
|
- editingIndex = row.getAttribute('data-index');
|
|
|
} else {
|
|
|
const text = textInput.value;
|
|
|
const link = linkInput.value;
|
|
|
const newTab = newTabSelect.value === 'true';
|
|
|
|
|
|
if (text) {
|
|
|
- menuItems[editingIndex] = { text, link, newTab };
|
|
|
+ const rowIndex = row.getAttribute('data-index');
|
|
|
+ menuItems[rowIndex] = { text, link, newTab };
|
|
|
renderMenuItems();
|
|
|
- editingIndex = -1;
|
|
|
} else {
|
|
|
alert('请填写菜单项文本');
|
|
|
}
|
|
@@ -300,6 +272,35 @@
|
|
|
});
|
|
|
});
|
|
|
}
|
|
|
+
|
|
|
+ function renderMenuItems() {
|
|
|
+ const tbody = document.getElementById('menuTableBody');
|
|
|
+ tbody.innerHTML = '';
|
|
|
+ menuItems.forEach((item, index) => {
|
|
|
+ const row = `
|
|
|
+ <tr data-index="${index}">
|
|
|
+ <td><input type="text" class="menu-text" value="${item.text}" disabled></td>
|
|
|
+ <td><input type="url" class="menu-link" value="${item.link || ''}" disabled></td>
|
|
|
+ <td>
|
|
|
+ <select class="menu-newtab" disabled>
|
|
|
+ <option value="false" ${item.newTab ? '' : 'selected'}>否</option>
|
|
|
+ <option value="true" ${item.newTab ? 'selected' : ''}>是</option>
|
|
|
+ </select>
|
|
|
+ </td>
|
|
|
+ <td>
|
|
|
+ <button type="button" class="action-btn edit-btn">编辑</button>
|
|
|
+ <button type="button" class="action-btn delete-btn">删除</button>
|
|
|
+ <span class="drag-handle" style="cursor: move;">☰</span>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ `;
|
|
|
+ tbody.innerHTML += row;
|
|
|
+ });
|
|
|
+ setupDragAndDrop();
|
|
|
+ setupEditButtons();
|
|
|
+ setupDeleteButtons();
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
function setupDeleteButtons() {
|
|
|
const deleteButtons = document.querySelectorAll('.delete-btn');
|
|
@@ -317,10 +318,10 @@
|
|
|
const tbody = document.getElementById('menuTableBody');
|
|
|
const newRow = `
|
|
|
<tr id="newMenuItemRow">
|
|
|
- <td><input type="text" id="newMenuItemText" placeholder="菜单项文本"></td>
|
|
|
- <td><input type="url" id="newMenuItemLink" placeholder="菜单项链接 (可选)"></td>
|
|
|
+ <td><input type="text" class="menu-text" placeholder="菜单项文本"></td>
|
|
|
+ <td><input type="url" class="menu-link" placeholder="菜单项链接 (可选)"></td>
|
|
|
<td>
|
|
|
- <select id="newMenuItemNewTab">
|
|
|
+ <select class="menu-newtab">
|
|
|
<option value="false">否</option>
|
|
|
<option value="true">是</option>
|
|
|
</select>
|
|
@@ -334,13 +335,19 @@
|
|
|
tbody.insertAdjacentHTML('beforeend', newRow);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
function saveNewMenuItem() {
|
|
|
- const text = document.getElementById('newMenuItemText').value;
|
|
|
- const link = document.getElementById('newMenuItemLink').value;
|
|
|
- const newTab = document.getElementById('newMenuItemNewTab').value === 'true';
|
|
|
-
|
|
|
+ const newRow = document.getElementById('newMenuItemRow');
|
|
|
+ const textInput = newRow.querySelector('.menu-text');
|
|
|
+ const linkInput = newRow.querySelector('.menu-link');
|
|
|
+ const newTabSelect = newRow.querySelector('.menu-newtab');
|
|
|
+
|
|
|
+ const text = textInput.value;
|
|
|
+ const link = linkInput.value;
|
|
|
+ const newTab = newTabSelect.value === 'true';
|
|
|
+
|
|
|
if (text) {
|
|
|
- menuItems.push({ text, link, newTab });
|
|
|
+ menuItems.push({ text, link, newTab }); // 确保新菜单项被添加到 menuItems 数组中
|
|
|
renderMenuItems();
|
|
|
cancelNewMenuItem();
|
|
|
} else {
|
|
@@ -468,7 +475,7 @@
|
|
|
const config = {
|
|
|
logo: document.getElementById('logoUrl').value,
|
|
|
proxyDomain: document.getElementById('proxyDomain').value,
|
|
|
- menuItems: getMenuItems(),
|
|
|
+ menuItems: menuItems,
|
|
|
adImages: adImages
|
|
|
};
|
|
|
|
|
@@ -486,20 +493,20 @@
|
|
|
} catch (error) {
|
|
|
alert('保存失败: ' + error.message);
|
|
|
}
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
async function loadConfig() {
|
|
|
- try {
|
|
|
- const response = await fetch('/api/config');
|
|
|
- const config = await response.json();
|
|
|
- document.getElementById('logoUrl').value = config.logo || '';
|
|
|
- document.getElementById('proxyDomain').value = config.proxyDomain || '';
|
|
|
- setMenuItems(config.menuItems || []);
|
|
|
- adImages = config.adImages || [];
|
|
|
- renderAdItems();
|
|
|
- } catch (error) {
|
|
|
- console.error('加载配置失败:', error);
|
|
|
- }
|
|
|
+ try {
|
|
|
+ const response = await fetch('/api/config');
|
|
|
+ const config = await response.json();
|
|
|
+ document.getElementById('logoUrl').value = config.logo || '';
|
|
|
+ document.getElementById('proxyDomain').value = config.proxyDomain || '';
|
|
|
+ setMenuItems(config.menuItems || []);
|
|
|
+ adImages = config.adImages || [];
|
|
|
+ renderAdItems();
|
|
|
+ } catch (error) {
|
|
|
+ console.error('加载配置失败:', error);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
async function login() {
|
|
@@ -550,25 +557,25 @@
|
|
|
|
|
|
// 页面加载时检查登录状态
|
|
|
window.onload = async function() {
|
|
|
- try {
|
|
|
- const response = await fetch('/api/check-session');
|
|
|
- if (response.ok) {
|
|
|
- isLoggedIn = localStorage.getItem('isLoggedIn') === 'true'; // 读取登录状态
|
|
|
- if (isLoggedIn) {
|
|
|
- document.getElementById('loginModal').style.display = 'none';
|
|
|
- document.getElementById('adminContainer').classList.remove('hidden');
|
|
|
- loadConfig();
|
|
|
- } else {
|
|
|
- document.getElementById('loginModal').style.display = 'block';
|
|
|
- }
|
|
|
- } else {
|
|
|
- localStorage.removeItem('isLoggedIn'); // 清除登录状态
|
|
|
- document.getElementById('loginModal').style.display = 'block';
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- localStorage.removeItem('isLoggedIn'); // 清除登录状态
|
|
|
+ try {
|
|
|
+ const response = await fetch('/api/check-session');
|
|
|
+ if (response.ok) {
|
|
|
+ isLoggedIn = localStorage.getItem('isLoggedIn') === 'true';
|
|
|
+ if (isLoggedIn) {
|
|
|
+ document.getElementById('loginModal').style.display = 'none';
|
|
|
+ document.getElementById('adminContainer').classList.remove('hidden');
|
|
|
+ loadConfig();
|
|
|
+ } else {
|
|
|
document.getElementById('loginModal').style.display = 'block';
|
|
|
}
|
|
|
+ } else {
|
|
|
+ localStorage.removeItem('isLoggedIn');
|
|
|
+ document.getElementById('loginModal').style.display = 'block';
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ localStorage.removeItem('isLoggedIn');
|
|
|
+ document.getElementById('loginModal').style.display = 'block';
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
// 表单提交事件监听器
|