基于 HTML+CSS+JavaScript 的薪资实时计算器(含本地存储和炫酷动画)

💰 基于 HTML+CSS+JavaScript 的薪资实时计算器(含本地存储和炫酷动画)

1. 前言

在日常工作中,我们经常会关心自己每天、甚至每分钟赚了多少钱。

于是我用 原生 HTML + CSS + JavaScript 实现了一个 薪资实时计算器

  • 📅 输入本月薪资 & 工作天数 → 自动计算日薪
  • 🕒 输入上下班时间 → 根据当前时间实时计算当日已赚金额
  • 💾 支持本地存储(刷新仍可保持数据)
  • 动态动画效果(数字变化 & 进度条)
  • 📱 响应式设计,PC / 手机均可使用

它不仅是一款小工具,也能让学习前端的同学练习 DOM 操作时间计算localStorage 以及 UI 动效 的综合能力。


2. 实现思路

📝 我们可以将这个功能拆解为 4 个核心模块:

  1. 数据输入与保存

    • 用户输入:月薪、工作天数、上班时间、下班时间
    • 使用 localStorage 持久化存储
  2. 日薪计算公式
    日薪=月薪工作天数 \text{日薪} = \frac{\text{月薪}}{\text{工作天数}} 日薪=工作天数月薪

  3. 实时薪资计算公式

    • 获取当前时间 now
    • 计算上下班时间差 totalTime
    • 计算已工作时间 elapsed
    • 计算已赚金额:
      实时薪资=elapsedtotalTime×日薪 \text{实时薪资} = \frac{elapsed}{totalTime} \times \text{日薪} 实时薪资=totalTimeelapsed×日薪
  4. UI 展示与动态更新

    • 使用 setInterval 每秒更新计算
    • 数字渐变效果
    • 进度条展示已完成工作进度

3. 页面效果展示

我们先来看看完整效果(PC + 移动端均可运行):

特点:

  • 🌈 玻璃拟态风格(半透明背景 + 模糊)
  • 📊 进度条动画(已工作时间比例)
  • 实时更新数字(每秒跳动)
  • 💾 刷新不丢数据

4. 核心代码

下面是完整的 index.html(可直接运行):

html 复制代码
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>薪资实时计算器</title>
<style>
    body {
        font-family: 'Segoe UI', sans-serif;
        background: linear-gradient(135deg, #232526, #414345);
        color: white;
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100vh;
        margin: 0;
    }
    .container {
        background: rgba(255, 255, 255, 0.08);
        padding: 25px;
        border-radius: 15px;
        box-shadow: 0 8px 32px rgba(0, 0, 0, 0.37);
        backdrop-filter: blur(12px);
        width: 350px;
    }
    h2 {
        text-align: center;
        margin-bottom: 15px;
    }
    label {
        display: block;
        margin-top: 10px;
        font-size: 14px;
        color: #ccc;
    }
    input {
        width: 100%;
        padding: 8px;
        margin-top: 5px;
        border: none;
        outline: none;
        border-radius: 5px;
        background: rgba(255, 255, 255, 0.15);
        color: #fff;
    }
    button {
        margin-top: 15px;
        width: 100%;
        padding: 10px;
        border: none;
        border-radius: 5px;
        background: linear-gradient(90deg, #ff7eb3, #ff758c);
        color: white;
        font-weight: bold;
        cursor: pointer;
        transition: transform 0.2s;
    }
    button:hover {
        transform: scale(1.05);
    }
    .result {
        margin-top: 20px;
        font-size: 18px;
        text-align: center;
    }
    .salary-number {
        font-size: 32px;
        font-weight: bold;
        color: #ffde59;
        text-shadow: 0 0 10px #ffde59;
        transition: all 0.3s ease;
    }
    .progress-bar {
        margin-top: 10px;
        height: 8px;
        background: rgba(255,255,255,0.2);
        border-radius: 5px;
        overflow: hidden;
    }
    .progress {
        height: 100%;
        background: linear-gradient(90deg, #ff758c, #ff7eb3);
        transition: width 0.5s ease;
    }
</style>
</head>
<body>
<div class="container">
    <h2>💰 薪资实时计算器</h2>
    <label>当月薪资(¥)</label>
    <input type="number" id="salary" placeholder="输入当月薪资">

    <label>当月工作天数</label>
    <input type="number" id="workDays" placeholder="输入工作天数">

    <label>上班时间(HH:MM)</label>
    <input type="time" id="startTime">

    <label>下班时间(HH:MM)</label>
    <input type="time" id="endTime">

    <button id="saveBtn">保存设置</button>

    <div class="result">
        <div>日薪:<span id="dailySalary" class="salary-number">0</span> 元</div>
        <div>今日实时薪资:</div>
        <div id="realTimeSalary" class="salary-number">0</div>
        <div class="progress-bar">
            <div id="progress" class="progress" style="width:0%"></div>
        </div>
    </div>
</div>

<script>
    const salaryInput = document.getElementById("salary");
    const workDaysInput = document.getElementById("workDays");
    const startInput = document.getElementById("startTime");
    const endInput = document.getElementById("endTime");
    const dailySalaryEl = document.getElementById("dailySalary");
    const realTimeSalaryEl = document.getElementById("realTimeSalary");
    const progressEl = document.getElementById("progress");

    function loadSettings() {
        const settings = JSON.parse(localStorage.getItem("salarySettings"));
        if (settings) {
            salaryInput.value = settings.salary;
            workDaysInput.value = settings.workDays;
            startInput.value = settings.startTime;
            endInput.value = settings.endTime;
        }
    }

    function saveSettings() {
        const settings = {
            salary: Number(salaryInput.value),
            workDays: Number(workDaysInput.value),
            startTime: startInput.value,
            endTime: endInput.value
        };
        localStorage.setItem("salarySettings", JSON.stringify(settings));
        calculateDailySalary();
    }

    function calculateDailySalary() {
        const salary = Number(salaryInput.value);
        const workDays = Number(workDaysInput.value);
        if (salary > 0 && workDays > 0) {
            const daily = salary / workDays;
            dailySalaryEl.textContent = daily.toFixed(2);
        }
    }

    function calculateRealTimeSalary() {
        const settings = JSON.parse(localStorage.getItem("salarySettings"));
        if (!settings) return;
        const { salary, workDays, startTime, endTime } = settings;
        if (!salary || !workDays || !startTime || !endTime) return;
        
        const daily = salary / workDays;
        const now = new Date();
        
        const [sh, sm] = startTime.split(":").map(Number);
        const [eh, em] = endTime.split(":").map(Number);
        const start = new Date(now.getFullYear(), now.getMonth(), now.getDate(), sh, sm);
        const end = new Date(now.getFullYear(), now.getMonth(), now.getDate(), eh, em);

        const totalTime = end - start;
        const elapsed = Math.max(0, Math.min(now - start, totalTime));
        
        const progress = (elapsed / totalTime) * 100;
        progressEl.style.width = progress + "%";

        let earned = (elapsed / totalTime) * daily;
        if (earned < 0) earned = 0;
        if (earned > daily) earned = daily;

        realTimeSalaryEl.textContent = earned.toFixed(2);
    }

    document.getElementById("saveBtn").addEventListener("click", saveSettings);

    loadSettings();
    calculateDailySalary();
    setInterval(() => {
        calculateDailySalary();
        calculateRealTimeSalary();
    }, 1000);
</script>
</body>
</html>

5. 技术要点

5.1 时间计算

  • 使用 Date 对象计算上下班总工时和已工作时长。
  • Math.min & Math.max 确保数据不会越界(下班后不继续涨薪)。

5.2 动态进度条

  • 进度条宽度 = elapsed / totalTime * 100%
  • CSS transition 实现平滑动画。

5.3 本地存储

  • localStorage.setItem(key, value) 保存数据
  • localStorage.getItem(key) 读取数据
  • JSON.stringify / JSON.parse 存取对象

5.4 UI 亮点

  • 玻璃拟态(backdrop-filter: blur()
  • 渐变背景(linear-gradient
  • 阴影与高光效果

6. 可扩展优化方向

💡 未来可以优化:

  1. 数字滚动动画(像余额实时跳动效果)
  2. PWA 支持(可安装到手机桌面使用)
  3. 夜间/日间主题切换
  4. 多币种汇率换算

7. 总结

通过本项目你可以学到:

  • HTML 表单数据获取
  • JavaScript 时间差计算
  • 进度条动画
  • localStorage 数据持久化
  • 响应式 & 美化设计

这是一个非常适合前端初中级学习者的综合练习项目。

相关推荐
醉方休4 小时前
React Fiber 风格任务调度库
前端·javascript·react.js
华仔啊4 小时前
摸鱼神器!前端大佬私藏的 11 个 JS 神级 API,复制粘贴就能用,效率翻倍
前端·javascript
念念不忘 必有回响4 小时前
js设计模式-状态模式
javascript·设计模式·状态模式
我的写法有点潮4 小时前
Scss 的四种导入方式你都知道吗
前端·css
小桥风满袖4 小时前
极简三分钟ES6 - 箭头函数
前端·javascript
bug_kada4 小时前
前端后端3步联调:Cookie认证实战,让登录功能完美上线!
前端·javascript
hj5914_前端新手4 小时前
深入分析 —— JavaScript 深拷贝
前端·javascript
jqq6664 小时前
解析ElementPlus打包源码(二、buildFullBundle)
前端·javascript·vue.js
织_网5 小时前
UniApp 页面通讯方案全解析:从 API 到状态管理的最佳实践
前端·javascript·uni-app