You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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等后端语言,必须通过无后端云数据库实现多用户数据同步。以下是具体实现步骤和修改后的代码:

核心问题修正

  1. 原代码直接比较DOM元素与字符串,需改为获取元素的value属性
  2. 未阻止表单默认提交行为,导致页面刷新丢失数据
  3. 积分变量存储在本地,刷新即重置,需迁移到云数据库
  4. 缺少排行榜渲染逻辑,需从数据库拉取数据后更新页面

修改后的实现代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 13:15:24