如何通过HTML表单输入更新全站可见的排行榜积分?
问题描述
我是Web开发新手,正在制作一个展示排行榜的网站。需求是用户输入上次记录后新增的积分,该数值需累加至对应用户的当前积分,且所有用户刷新页面后都能看到更新后的排行榜。
目前排行榜基于代码内的变量可正常展示,但无法实现以下功能:
- 用户输入的数值无法正确累加到对应积分
- 积分更新无法同步给所有用户
试过PHP但托管平台Neocities不支持,本地存储仅能在单设备保留数据,首次尝试的pointValue = pointValue + inputtedValue;代码也未更新主页面。记录表单当前在独立.html页面,与主站共用同一.js文件,也可改为主页面的模态弹窗。
原代码如下:
原JavaScript代码
//Get Elements const username = document.getElementById("username"); const pswd = document.getElementById("pswd"); const words = document.getElementById("words"); //usernames+passwords const avaUser = "username0"; const avaPwd = "pswd0"; const ellaUser = "username1"; const ellaPwd = "pswd1"; const abiUser = "username2"; const abiPwd = "pswd2"; const nataleeUser = "username3"; const nataleePwd = "pswd3"; const mercyUser = "username4"; const mercyPwd = "pswd4"; const maddieUser = "username5"; const maddiePwd = "pswd5"; //Points var avaPoints = 1973; var ellaPoints = 0; var abiPoints = 445; var nataleePoints = 1; var mercyPoints = 0; var maddiePoints = 2064; if (username == avaUser && pswd == avaPwd) { avaPoints = avaPoints + words; } else if (username == ellaUser && pswd == ellaPwd) { ellaPoints = ellaPoints + words; } else if (username == abiUser && pswd == abiPwd) { abiPoints = abiPoints + words; } else if (username == nataleeUser && pswd == nataleePwd) { nataleePoints = nataleePoints + words; } else if (username == mercyUser && pswd == mercyPwd) { mercyPoints = mercyPoints + words; } else if (username == maddieUser && pswd == maddiePwd) { maddiePoints = maddiePoints + words; }
原CSS代码
/* Log Page: "Log Word Count" Title */ .logTitle { text-align: center; font-family: 'Nanum Pen Script', sans-serif; font-weight: bold; font-size: 5vw; margin: 0 0 2.5% 0; filter: drop-shadow(2px 2px 3px rgba(30,92,76, 1)); } /* Log Page: Inputs */ .usernameInput, .pswdInput, .wordsInput { display: block; margin: auto; font-family: 'Nanum Pen Script', sans-serif; font-size: 1.5vw; padding: 1% 3%; border: solid 3px rgba(37,99,83, .8); border-radius: 255px 15px 225px 15px/15px 225px 15px 255px; background-color: rgba(255,255,255,0.9); } /* Log Page: labels */ .usernameLabel, .pswdLabel, .wordsLabel { display: block; text-align: center; font-family: 'Nanum Pen Script', sans-serif; font-size: 2.5vw; } /* Log Page: Username Label */ .usernameLabel { margin: 0 0 1% 0; } /* Log Page: Password Label */ .pswdLabel, .wordsLabel { margin: 4% 0 1% 0; } /* Log Page: Forgot Password Link */ .forgot { display: block; text-align: center; font-family: 'Nanum Pen Script', sans-serif; margin: 1% 0 0 0; font-size: 1.5vw; } .link, .link:visited { color: rgba(37,99,83, .8); } .usernameInput:focus, .pswdInput:focus, .wordsInput:focus { outline: none; } /** Log Page: spacer between form and button */ .spacer { margin: 6% 0; } /* Log Page: Log Button */ .signInButton { margin: auto; background-color: rgba(255, 255, 255, 1); border-radius: 100px; box-shadow: rgba(109, 109, 109, .2) 0 -25px 18px -14px inset,rgba(109, 109, 109, .15) 0 1px 2px,rgba(109, 109, 109, .15) 0 2px 4px,rgba(109, 109, 109, .15) 0 4px 8px,rgba(109, 109, 109, .15) 0 8px 16px,rgba(109, 109, 109, .15) 0 16px 32px; color: rgba(0,0,0, 0.6); cursor: pointer; display: block; font-family: 'Nanum Pen Script', sans-serif; font-weight: bold; padding: 1.5% 7%; text-align: center; text-shadow: 1px 1px 3px rgba(124, 124, 124, 1); transition: all 250ms; border: 0; font-size: 1.75vw; user-select: none; -webkit-user-select: none; -ms-user-select: none; -moz-user-select: none; touch-action: manipulation; } /* Log Page: Log Button:Hover */ .signInButton:hover { box-shadow: rgba(109, 109, 109,.35) 0 -25px 18px -14px inset,rgba(109, 109, 109,.25) 0 1px 2px,rgba(109, 109, 109,.25) 0 2px 4px,rgba(109, 109, 109,.25) 0 4px 8px,rgba(109, 109, 109,.25) 0 8px 16px,rgba(109, 109, 109,.25) 0 16px 32px; transform: scale(1.05) rotate(-1deg); }
原HTML代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link href="/style.css" rel="stylesheet" type="text/css" media="all"> <script src="/script.js" defer></script> <link href='https://fonts.googleapis.com/css?family=La Belle Aurore' rel='stylesheet'> <link href='https://fonts.googleapis.com/css?family=Nanum Pen Script' rel='stylesheet'> </head> <body> <h2 class="logTitle"> Log Word Count </h2> <form> <div class="form"> <label class="usernameLabel"><b>Username</b></label> <input class="usernameInput" id="username" type="text" placeholder="Enter Username" name="uname" required> <label class="pswdLabel"><b>Password</b></label> <input class="pswdInput" id="pswd" type="password" placeholder="Enter Password" name="psw" required> <span class="forgot"><a class="link" href="mailto:232197@ystu.ycsd.york.va.us?subject=Forgot My Password&body=I forgor my password T^T. Can you remind me please? Thanks!">Forgot password?</a></span> <label class="wordsLabel"><b>Number of Words</b></label> <input class="wordsInput" id="words" type="text" placeholder="#" name="words" required> <div class="spacer"></div> <button class=signInButton type="submit">Log</button> </div> </form> </body> </html>
解决方案
由于Neocities仅支持静态文件托管,无法使用PHP等后端语言,必须通过无后端云数据库实现多用户数据同步。以下是具体实现步骤和修改后的代码:
核心问题修正
- 原代码直接比较DOM元素与字符串,需改为获取元素的
value属性 - 未阻止表单默认提交行为,导致页面刷新丢失数据
- 积分变量存储在本地,刷新即重置,需迁移到云数据库
- 缺少排行榜渲染逻辑,需从数据库拉取数据后更新页面
修改后的实现代码
1. 重构后的JavaScript代码(结合云数据库)
// 初始化云数据库(以实时数据库为例,需自行完成平台配置) // 注意:需在HTML中引入对应数据库的SDK脚本 // 表单元素 const loginForm = document.querySelector('form'); const usernameInput = document.getElementById("username"); const pswdInput = document.getElementById("pswd"); const wordsInput = document.getElementById("words"); // 用户数据结构(存储在云数据库) const users = { "username0": { password: "pswd0", points: 1973 }, "username1": { password: "pswd1", points: 0 }, "username2": { password: "pswd2", points: 445 }, "username3": { password: "pswd3", points: 1 }, "username4": { password: "pswd4", points: 0 }, "username5": { password: "pswd5", points: 2064 } }; // 页面加载时拉取最新排行榜数据 window.addEventListener('load', () => { // 从云数据库获取最新积分并渲染排行榜 // 示例:db.ref('users').on('value', snapshot => { renderLeaderboard(snapshot.val()) }); }); // 处理表单提交 loginForm.addEventListener('submit', (e) => { e.preventDefault(); // 阻止页面刷新 const username = usernameInput.value.trim(); const password = pswdInput.value.trim(); const addedPoints = parseInt(wordsInput.value.trim()); // 验证用户输入 if (isNaN(addedPoints) || addedPoints < 0) { alert('请输入有效的正整数积分'); return; } // 验证账号密码 const user = users[username]; if (!user || user.password !== password) { alert('账号或密码错误'); return; } // 更新云数据库中的积分 const newPoints = user.points + addedPoints; // 示例:db.ref(`users/${username}/points`).set(newPoints); // 重置表单 loginForm.reset(); alert('积分已成功更新'); }); // 渲染排行榜函数 function renderLeaderboard(userData) { // 将用户按积分排序,生成排行榜HTML并插入页面 const sortedUsers = Object.entries(userData).sort((a, b) => b[1].points - a[1].points); const leaderboardHtml = sortedUsers.map(([name, data]) => `<div class="leaderboard-item">${name}: ${data.points} 积分</div>` ).join(''); document.getElementById('leaderboard').innerHTML = leaderboardHtml; }
2. 修改后的HTML(添加排行榜容器)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link href="/style.css" rel="stylesheet" type="text/css" media="all"> <!-- 引入云数据库SDK脚本 --> <script src="/script.js" defer></script> <link href='https://fonts.googleapis.com/css?family=La Belle Aurore' rel='stylesheet'> <link href='https://fonts.googleapis.com/css?family=Nanum Pen Script' rel='stylesheet'> </head> <body> <h2 class="logTitle"> 积分排行榜 </h2> <!-- 排行榜容器 --> <div id="leaderboard" class="leaderboard"></div> <h2 class="logTitle"> 记录新增积分 </h2> <form> <div class="form"> <label class="usernameLabel"><b>用户名</b></label> <input class="usernameInput" id="username" type="text" placeholder="输入用户名" name="uname" required> <label class="pswdLabel"><b>密码</b></label> <input class="pswdInput" id="pswd" type="password" placeholder="输入密码" name="psw" required> <span class="forgot"><a class="link" href="mailto:232197@ystu.ycsd.york.va.us?subject=找回密码&body=我忘记密码了T^T,请帮忙提醒我,谢谢!">忘记密码?</a></span> <label class="wordsLabel"><b>新增积分</b></label> <input class="wordsInput" id="words" type="number" placeholder="输入数值" name="words" required min="0"> <div class="spacer"></div> <button class=signInButton type="submit">提交</button> </div> </form> </body> </html>
3. 新增排行榜CSS样式
/* 排行榜样式 */ .leaderboard { width: 80%; margin: 2% auto; padding: 2%; background-color: rgba(255,255,255,0.9); border-radius: 15px; box-shadow: 0 0 10px rgba(30,92,76,0.3); } .leaderboard-item { font-family: 'Nanum Pen Script', sans-serif; font-size: 2vw; padding: 1% 0; border-bottom: 1px solid rgba(37,99,83,0.5); } .leaderboard-item:last-child { border-bottom: none; }
关键说明
- 云数据库选择:需使用支持前端直接调用的实时数据库服务,完成注册和配置后,将SDK脚本引入HTML
- 安全性:当前代码仅为基础实现,生产环境需添加数据验证、权限控制等安全措施
- 表单优化:将积分输入框改为
type="number"并设置min="0",避免无效输入
内容的提问来源于stack exchange,提问作者RP5715
相关产品推荐
相关产品推荐

