Skip to content

Commit

Permalink
fix: Adjust the style and correct the related operational logic.
Browse files Browse the repository at this point in the history
  • Loading branch information
dqzboy committed Jul 26, 2024
1 parent 8fb439d commit d924335
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 98 deletions.
4 changes: 2 additions & 2 deletions hubcmdui/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
},
{
"text": "GitHub",
"link": "https://github.com/dqzboy/Docker-Proxy",
"newTab": true
"link": "",
"newTab": false
}
],
"adImages": [
Expand Down
16 changes: 8 additions & 8 deletions hubcmdui/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,14 +156,14 @@ app.get('/api/config', async (req, res) => {

// API 端点:保存配置
app.post('/api/config', requireLogin, async (req, res) => {
try {
const currentConfig = await readConfig();
const newConfig = { ...currentConfig, ...req.body };
await writeConfig(newConfig);
res.json({ success: true });
} catch (error) {
res.status(500).json({ error: 'Failed to save config' });
}
try {
const currentConfig = await readConfig();
const newConfig = { ...currentConfig, ...req.body };
await writeConfig(newConfig);
res.json({ success: true });
} catch (error) {
res.status(500).json({ error: 'Failed to save config' });
}
});

// API 端点:检查会话状态
Expand Down
216 changes: 128 additions & 88 deletions hubcmdui/web/admin.html
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,14 @@
background-color: rgba(0,0,0,0.4);
}
.login-content {
background-color: #fefefe;
background-color: rgba(255, 255, 255, 0.8);
backdrop-filter: blur(10px);
margin: 15% auto;
padding: 20px;
border: 1px solid #888;
width: 30%;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.user-management {
position: absolute;
Expand Down Expand Up @@ -213,7 +215,7 @@ <h2 class="menu-label">修改密码</h2>
<label for="currentPassword">当前密码</label>
<input type="password" id="currentPassword" name="currentPassword">
<label for="newPassword">新密码</label>
<span class="password-hint" id="passwordHint">密码必须包含至少一个字母和一个数字,长度在8到16个字符之间</span>
<span class="password-hint" id="passwordHint">密码必须包含至少一个字母、一个数字和一个特殊字符,长度在8到16个字符之间</span>
<input type="password" id="newPassword" name="newPassword" oninput="checkPasswordStrength()">
<span id="passwordStrength" style="color: red;"></span>
<button type="button" onclick="changePassword()">修改密码</button>
Expand Down Expand Up @@ -248,6 +250,44 @@ <h2>登录</h2>
return menuItems;
}

function setupDeleteButtons() {
const deleteButtons = document.querySelectorAll('.delete-btn');
deleteButtons.forEach((button, index) => {
button.addEventListener('click', () => {
const row = button.closest('tr');
const index = row.getAttribute('data-index');
console.log(`Deleting menu item at index: ${index}`); // 添加日志输出
deleteMenuItem(index);
});
});
}

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>
</td>
</tr>
`;
tbody.innerHTML += row;
});
setupEditButtons();
setupDeleteButtons();
}

function setMenuItems(items) {
menuItems = items;
renderMenuItems();
Expand Down Expand Up @@ -284,45 +324,8 @@ <h2>登录</h2>
});
});
}

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>
</td>
</tr>
`;
tbody.innerHTML += row;
});
setupEditButtons();
setupDeleteButtons();
}


function setupDeleteButtons() {
const deleteButtons = document.querySelectorAll('.delete-btn');
deleteButtons.forEach((button, index) => {
button.addEventListener('click', () => {
const row = button.closest('tr');
const index = row.getAttribute('data-index');
deleteMenuItem(index);
});
});
}

function showNewMenuItemRow() {
const tbody = document.getElementById('menuTableBody');
const newRow = `
Expand Down Expand Up @@ -406,13 +409,54 @@ <h2>登录</h2>
});
setupAdEditButtons();
setupAdDeleteButtons();
}
}

function setupAdEditButtons() {
const editButtons = document.querySelectorAll('.edit-btn');
editButtons.forEach((button, index) => {
button.addEventListener('click', () => {
const row = button.closest('tr');
const urlInput = row.querySelector('.ad-url');
const linkInput = row.querySelector('.ad-link');

if (urlInput.disabled) {
urlInput.disabled = false;
linkInput.disabled = false;
button.textContent = '保存';
editingIndex = row.getAttribute('data-index');
} else {
const url = urlInput.value || '';
const link = linkInput.value || '';

adImages[editingIndex] = { url, link };
renderAdItems(); // 重新渲染广告项
saveAd(editingIndex, { url, link });
editingIndex = -1;
}
});
});
}

function setupAdDeleteButtons() {
const deleteButtons = document.querySelectorAll('.delete-btn');
deleteButtons.forEach((button, index) => {
button.addEventListener('click', () => {
const row = button.closest('tr');
const index = row.getAttribute('data-index');
deleteAd(index);
});
});
}

function saveNewAd() {
const url = document.getElementById('newAdUrl').value || '';
const link = document.getElementById('newAdLink').value || '';

if (!url) {
alert('广告URL为必填项');
return;
}

const newAd = { url, link };
adImages.push(newAd);
renderAdItems(); // 先更新页面
Expand Down Expand Up @@ -447,43 +491,6 @@ <h2>登录</h2>
setupAdDeleteButtons();
}

function setupAdEditButtons() {
const editButtons = document.querySelectorAll('.edit-btn');
editButtons.forEach((button, index) => {
button.addEventListener('click', () => {
const row = button.closest('tr');
const urlInput = row.querySelector('.ad-url');
const linkInput = row.querySelector('.ad-link');

if (urlInput.disabled) {
urlInput.disabled = false;
linkInput.disabled = false;
button.textContent = '保存';
editingIndex = row.getAttribute('data-index');
} else {
const url = urlInput.value || '';
const link = linkInput.value || '';

adImages[editingIndex] = { url, link };
renderAdItems(); // 重新渲染广告项
saveAd(editingIndex, { url, link });
editingIndex = -1;
}
});
});
}

function setupAdDeleteButtons() {
const deleteButtons = document.querySelectorAll('.delete-btn');
deleteButtons.forEach((button, index) => {
button.addEventListener('click', () => {
const row = button.closest('tr');
const index = row.getAttribute('data-index');
deleteAd(index);
});
});
}

async function saveLogo() {
const logoUrl = document.getElementById('logoUrl').value;
if (!logoUrl) {
Expand Down Expand Up @@ -519,9 +526,23 @@ <h2>登录</h2>
}

async function deleteMenuItem(index) {
menuItems.splice(index, 1);
renderMenuItems(); // 先更新页面
await saveConfig({ menuItems: menuItems });
try {
const response = await fetch('/api/config', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ menuItems: menuItems.filter((_, i) => i !== parseInt(index)) })
});
if (response.ok) {
menuItems.splice(index, 1);
renderMenuItems(); // 先更新页面
await loadConfig(); // 重新加载配置
} else {
alert('删除菜单项失败');
}
} catch (error) {
console.error('删除菜单项失败: ' + error.message);
alert('删除菜单项失败: ' + error.message);
}
}

async function saveAd(index, ad) {
Expand All @@ -531,9 +552,23 @@ <h2>登录</h2>
}

async function deleteAd(index) {
adImages.splice(index, 1);
renderAdItems(); // 先更新页面
await saveConfig({ adImages: adImages });
try {
const response = await fetch('/api/config', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ adImages: adImages.filter((_, i) => i !== parseInt(index)) })
});
if (response.ok) {
adImages.splice(index, 1);
renderAdItems(); // 先更新页面
await loadConfig(); // 重新加载配置
} else {
alert('删除广告项失败');
}
} catch (error) {
console.error('删除广告项失败: ' + error.message);
alert('删除广告项失败: ' + error.message);
}
}

async function saveConfig(partialConfig) {
Expand All @@ -550,7 +585,7 @@ <h2>登录</h2>
console.error('保存失败: ' + error.message);
throw error;
}
}
}

async function loadConfig() {
try {
Expand Down Expand Up @@ -594,12 +629,14 @@ <h2>登录</h2>
async function changePassword() {
const currentPassword = document.getElementById('currentPassword').value;
const newPassword = document.getElementById('newPassword').value;
const passwordRegex = /^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,16}$/;

if (!currentPassword || !newPassword) {
alert('请填写当前密码和新密码');
return;
}
if (!/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,16}$/.test(newPassword)) {
alert('密码必须包含至少一个字母和一个数字,长度在8到16个字符之间');
if (!passwordRegex.test(newPassword)) {
alert('密码必须包含至少一个字母、一个数字和一个特殊字符,长度在8到16个字符之间');
return;
}
try {
Expand All @@ -619,9 +656,12 @@ <h2>登录</h2>
}

function checkPasswordStrength() {
const newPassword = document.getElementById('newPassword');
const newPassword = document.getElementById('newPassword').value;
const passwordHint = document.getElementById('passwordHint');
if (!/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,16}$/.test(newPassword.value)) {

const passwordRegex = /^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,16}$/;

if (!passwordRegex.test(newPassword)) {
passwordHint.style.display = 'block';
} else {
passwordHint.style.display = 'none';
Expand Down

0 comments on commit d924335

Please sign in to comment.