文件提取地址:https://wenshushu.vip/pan/index.php?id=36      提取码:7bf9

作为程序员,我们不仅要会写代码,更要懂点“税”事!今天给大家分享一个我自己写的个人所得税模拟器,纯JavaScript实现,无需后端,直接在前端运行。这对于财务类网站、薪资计算工具或者个人理财应用来说非常实用。

项目特点

· 💯 纯前端实现,零依赖
· 📱 响应式设计,移动端友好
· 🔢 实时计算,即时反馈
· 📊 详细的计算过程展示
· 💾 本地存储记录

一、个税计算规则(2023年最新)

在开始看代码前,我们先了解下中国的个人所得税计算规则:

```javascript
// 个人所得税税率表(综合所得适用)
const taxRateTable = [
  { min: 0, max: 36000, rate: 0.03, deduction: 0 },
  { min: 36000, max: 144000, rate: 0.10, deduction: 2520 },
  { min: 144000, max: 300000, rate: 0.20, deduction: 16920 },
  { min: 300000, max: 420000, rate: 0.25, deduction: 31920 },
  { min: 420000, max: 660000, rate: 0.30, deduction: 52920 },
  { min: 660000, max: 960000, rate: 0.35, deduction: 85920 },
  { min: 960000, max: Infinity, rate: 0.45, deduction: 181920 }
];

// 个税起征点(每月)
const basicDeduction = 5000;
```

二、核心计算函数

```javascript
/**
 * 计算个人所得税
 * @param {number} monthlySalary - 月薪
 * @param {number} month - 月份数(用于计算累计)
 * @param {Array} specialDeductions - 专项扣除
 * @returns {Object} 计算结果
 */
function calculateIncomeTax(monthlySalary, month = 1, specialDeductions = {}) {
  // 累计收入
  const cumulativeIncome = monthlySalary * month;
  
  // 累计减除费用(起征点)
  const cumulativeBasicDeduction = basicDeduction * month;
  
  // 累计专项扣除
  const cumulativeSpecialDeduction = calculateSpecialDeductions(specialDeductions, month);
  
  // 应纳税所得额
  const taxableIncome = Math.max(0, cumulativeIncome - cumulativeBasicDeduction - cumulativeSpecialDeduction);
  
  // 查找适用税率
  const taxLevel = taxRateTable.find(level => 
    taxableIncome >= level.min && taxableIncome < level.max
  );
  
  // 计算累计应纳税额
  const cumulativeTax = taxableIncome * taxLevel.rate - taxLevel.deduction;
  
  // 本月应纳税额(减去已缴税额)
  const monthlyTax = month === 1 ? cumulativeTax : cumulativeTax - getPreviousTax(month);
  
  return {
    cumulativeIncome,
    cumulativeBasicDeduction,
    cumulativeSpecialDeduction,
    taxableIncome,
    taxRate: taxLevel.rate,
    quickDeduction: taxLevel.deduction,
    cumulativeTax,
    monthlyTax: Math.max(0, monthlyTax),
    afterTaxIncome: monthlySalary - Math.max(0, monthlyTax)
  };
}
```

三、完整HTML实现

下面是完整的HTML文件,包含所有CSS和JavaScript代码:

```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>个人所得税模拟器</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
            line-height: 1.6;
            background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
            color: #333;
            min-height: 100vh;
            padding: 20px;
        }
        
        .container {
            max-width: 1000px;
            margin: 0 auto;
            background: white;
            border-radius: 15px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
            overflow: hidden;
        }
        
        header {
            background: linear-gradient(90deg, #2c3e50, #4a6491);
            color: white;
            padding: 30px;
            text-align: center;
        }
        
        h1 {
            font-size: 2.5rem;
            margin-bottom: 10px;
        }
        
        .subtitle {
            font-size: 1.1rem;
            opacity: 0.9;
        }
        
        .content {
            display: flex;
            flex-wrap: wrap;
            padding: 20px;
        }
        
        .input-section {
            flex: 1;
            min-width: 300px;
            padding: 20px;
            border-right: 1px solid #eee;
        }
        
        .result-section {
            flex: 1;
            min-width: 300px;
            padding: 20px;
        }
        
        .form-group {
            margin-bottom: 20px;
        }
        
        label {
            display: block;
            margin-bottom: 8px;
            font-weight: 600;
            color: #2c3e50;
        }
        
        input, select {
            width: 100%;
            padding: 12px 15px;
            border: 2px solid #ddd;
            border-radius: 8px;
            font-size: 16px;
            transition: border-color 0.3s;
        }
        
        input:focus, select:focus {
            border-color: #4a6491;
            outline: none;
        }
        
        .checkbox-group {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
            gap: 10px;
            margin-top: 10px;
        }
        
        .checkbox-item {
            display: flex;
            align-items: center;
        }
        
        .checkbox-item input {
            width: auto;
            margin-right: 8px;
        }
        
        .btn {
            display: block;
            width: 100%;
            padding: 15px;
            background: linear-gradient(90deg, #3498db, #2980b9);
            color: white;
            border: none;
            border-radius: 8px;
            font-size: 18px;
            font-weight: 600;
            cursor: pointer;
            transition: transform 0.2s, box-shadow 0.2s;
        }
        
        .btn:hover {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(52, 152, 219, 0.3);
        }
        
        .result-box {
            background: #f8f9fa;
            border-radius: 10px;
            padding: 20px;
            margin-bottom: 20px;
            border-left: 5px solid #3498db;
        }
        
        .result-title {
            font-size: 1.2rem;
            color: #2c3e50;
            margin-bottom: 15px;
            padding-bottom: 10px;
            border-bottom: 2px solid #eee;
        }
        
        .result-item {
            display: flex;
            justify-content: space-between;
            margin-bottom: 12px;
            padding-bottom: 12px;
            border-bottom: 1px dashed #ddd;
        }
        
        .result-item:last-child {
            border-bottom: none;
            margin-bottom: 0;
            padding-bottom: 0;
        }
        
        .result-label {
            color: #666;
        }
        
        .result-value {
            font-weight: 600;
            color: #2c3e50;
        }
        
        .highlight {
            color: #e74c3c;
            font-size: 1.5rem;
        }
        
        .calculation-details {
            background: #f1f8ff;
            border-radius: 10px;
            padding: 20px;
            margin-top: 20px;
            font-size: 0.9rem;
        }
        
        .history-section {
            padding: 20px;
            border-top: 1px solid #eee;
        }
        
        table {
            width: 100%;
            border-collapse: collapse;
            margin-top: 15px;
        }
        
        th, td {
            padding: 12px 15px;
            text-align: left;
            border-bottom: 1px solid #ddd;
        }
        
        th {
            background: #f1f8ff;
            font-weight: 600;
        }
        
        footer {
            text-align: center;
            padding: 20px;
            color: #666;
            font-size: 0.9rem;
            border-top: 1px solid #eee;
        }
        
        @media (max-width: 768px) {
            .content {
                flex-direction: column;
            }
            
            .input-section {
                border-right: none;
                border-bottom: 1px solid #eee;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>个人所得税模拟器</h1>
            <p class="subtitle">纯JavaScript实现 · 实时计算 · 详细过程展示</p>
        </header>
        
        <div class="content">
            <div class="input-section">
                <div class="form-group">
                    <label for="salary">月薪(元)</label>
                    <input type="number" id="salary" min="0" step="100" value="15000" placeholder="请输入月薪">
                </div>
                
                <div class="form-group">
                    <label for="month">当前月份</label>
                    <select id="month">
                        <option value="1">1月</option>
                        <option value="2">2月</option>
                        <option value="3">3月</option>
                        <option value="4">4月</option>
                        <option value="5">5月</option>
                        <option value="6">6月</option>
                        <option value="7">7月</option>
                        <option value="8">8月</option>
                        <option value="9">9月</option>
                        <option value="10">10月</option>
                        <option value="11">11月</option>
                        <option value="12">12月</option>
                    </select>
                </div>
                
                <div class="form-group">
                    <label>专项附加扣除</label>
                    <div class="checkbox-group">
                        <div class="checkbox-item">
                            <input type="checkbox" id="children" value="1000">
                            <label for="children">子女教育 (1000元/月)</label>
                        </div>
                        <div class="checkbox-item">
                            <input type="checkbox" id="elderly" value="2000">
                            <label for="elderly">赡养老人 (2000元/月)</label>
                        </div>
                        <div class="checkbox-item">
                            <input type="checkbox" id="housing" value="1000">
                            <label for="housing">住房贷款 (1000元/月)</label>
                        </div>
                        <div class="checkbox-item">
                            <input type="checkbox" id="rent" value="1500">
                            <label for="rent">住房租金 (1500元/月)</label>
                        </div>
                        <div class="checkbox-item">
                            <input type="checkbox" id="education" value="400">
                            <label for="education">继续教育 (400元/月)</label>
                        </div>
                    </div>
                </div>
                
                <button id="calculateBtn" class="btn">计算个人所得税</button>
            </div>
            
            <div class="result-section">
                <div class="result-box">
                    <h3 class="result-title">计算结果</h3>
                    <div class="result-item">
                        <span class="result-label">应纳税所得额:</span>
                        <span class="result-value" id="taxableIncome">0</span>
                    </div>
                    <div class="result-item">
                        <span class="result-label">适用税率:</span>
                        <span class="result-value" id="taxRate">0%</span>
                    </div>
                    <div class="result-item">
                        <span class="result-label">速算扣除数:</span>
                        <span class="result-value" id="quickDeduction">0</span>
                    </div>
                    <div class="result-item">
                        <span class="result-label">本月应纳税额:</span>
                        <span class="result-value highlight" id="monthlyTax">0</span>
                    </div>
                    <div class="result-item">
                        <span class="result-label">税后收入:</span>
                        <span class="result-value highlight" id="afterTaxIncome">0</span>
                    </div>
                </div>
                
                <div class="calculation-details">
                    <h3 class="result-title">计算过程</h3>
                    <div id="calculationSteps">
                        输入数据后查看详细计算过程...
                    </div>
                </div>
            </div>
        </div>
        
        <div class="history-section">
            <h3>计算记录</h3>
            <table id="historyTable">
                <thead>
                    <tr>
                        <th>时间</th>
                        <th>月薪</th>
                        <th>月份</th>
                        <th>应纳税额</th>
                        <th>税后收入</th>
                    </tr>
                </thead>
                <tbody id="historyBody">
                    <!-- 历史记录将动态插入 -->
                </tbody>
            </table>
        </div>
        
        <footer>
            <p>本工具根据2023年个人所得税法计算,结果仅供参考</p>
            <p>© 2023 个人所得税模拟器 | 纯JavaScript实现 | CSDN风格演示</p>
        </footer>
    </div>

    <script>
        // 个人所得税税率表(综合所得适用)
        const taxRateTable = [
            { min: 0, max: 36000, rate: 0.03, deduction: 0 },
            { min: 36000, max: 144000, rate: 0.10, deduction: 2520 },
            { min: 144000, max: 300000, rate: 0.20, deduction: 16920 },
            { min: 300000, max: 420000, rate: 0.25, deduction: 31920 },
            { min: 420000, max: 660000, rate: 0.30, deduction: 52920 },
            { min: 660000, max: 960000, rate: 0.35, deduction: 85920 },
            { min: 960000, max: Infinity, rate: 0.45, deduction: 181920 }
        ];

        // 个税起征点(每月)
        const basicDeduction = 5000;

        // 存储计算历史
        let calculationHistory = JSON.parse(localStorage.getItem('taxHistory')) || [];

        // 页面加载时初始化
        document.addEventListener('DOMContentLoaded', function() {
            // 初始化计算
            calculateTax();
            
            // 绑定计算按钮事件
            document.getElementById('calculateBtn').addEventListener('click', calculateTax);
            
            // 绑定输入变化事件
            document.getElementById('salary').addEventListener('input', calculateTax);
            document.getElementById('month').addEventListener('change', calculateTax);
            
            // 绑定专项扣除变化事件
            document.querySelectorAll('.checkbox-group input').forEach(checkbox => {
                checkbox.addEventListener('change', calculateTax);
            });
            
            // 加载历史记录
            loadHistory();
        });

        /**
         * 计算个人所得税
         */
        function calculateTax() {
            // 获取输入值
            const salary = parseFloat(document.getElementById('salary').value) || 0;
            const month = parseInt(document.getElementById('month').value);
            
            // 获取专项扣除
            const specialDeductions = getSpecialDeductions();
            
            // 执行计算
            const result = calculateIncomeTax(salary, month, specialDeductions);
            
            // 显示结果
            displayResult(result);
            
            // 显示计算过程
            displayCalculationSteps(result, salary, month, specialDeductions);
            
            // 保存到历史记录
            saveToHistory(result, salary, month);
        }

        /**
         * 核心计算函数
         */
        function calculateIncomeTax(monthlySalary, month = 1, specialDeductions = {}) {
            // 累计收入
            const cumulativeIncome = monthlySalary * month;
            
            // 累计减除费用(起征点)
            const cumulativeBasicDeduction = basicDeduction * month;
            
            // 累计专项扣除
            const cumulativeSpecialDeduction = calculateTotalSpecialDeductions(specialDeductions, month);
            
            // 应纳税所得额
            const taxableIncome = Math.max(0, cumulativeIncome - cumulativeBasicDeduction - cumulativeSpecialDeduction);
            
            // 查找适用税率
            const taxLevel = taxRateTable.find(level => 
                taxableIncome >= level.min && taxableIncome < level.max
            ) || taxRateTable[0];
            
            // 计算累计应纳税额
            const cumulativeTax = taxableIncome * taxLevel.rate - taxLevel.deduction;
            
            // 本月应纳税额(减去已缴税额)
            const monthlyTax = month === 1 ? cumulativeTax : cumulativeTax - getPreviousTax(month);
            
            return {
                cumulativeIncome,
                cumulativeBasicDeduction,
                cumulativeSpecialDeduction,
                taxableIncome,
                taxRate: taxLevel.rate,
                quickDeduction: taxLevel.deduction,
                cumulativeTax,
                monthlyTax: Math.max(0, monthlyTax),
                afterTaxIncome: monthlySalary - Math.max(0, monthlyTax)
            };
        }

        /**
         * 获取专项扣除
         */
        function getSpecialDeductions() {
            const deductions = {};
            document.querySelectorAll('.checkbox-group input:checked').forEach(checkbox => {
                deductions[checkbox.id] = parseFloat(checkbox.value);
            });
            return deductions;
        }

        /**
         * 计算累计专项扣除
         */
        function calculateTotalSpecialDeductions(deductions, month) {
            let total = 0;
            for (const key in deductions) {
                total += deductions[key];
            }
            return total * month;
        }

        /**
         * 获取之前月份已缴税额(简化版)
         */
        function getPreviousTax(currentMonth) {
            // 简化处理:假设之前月份已按累计预扣法计算
            // 实际应用中这里需要更复杂的逻辑
            if (currentMonth <= 1) return 0;
            
            // 这里简化处理,实际应根据历史数据计算
            const previousMonth = currentMonth - 1;
            const salary = parseFloat(document.getElementById('salary').value) || 0;
            const specialDeductions = getSpecialDeductions();
            
            const previousResult = calculateIncomeTax(salary, previousMonth, specialDeductions);
            return previousResult.cumulativeTax;
        }

        /**
         * 显示计算结果
         */
        function displayResult(result) {
            document.getElementById('taxableIncome').textContent = 
                result.taxableIncome.toFixed(2) + ' 元';
            document.getElementById('taxRate').textContent = 
                (result.taxRate * 100).toFixed(1) + '%';
            document.getElementById('quickDeduction').textContent = 
                result.quickDeduction.toFixed(2) + ' 元';
            document.getElementById('monthlyTax').textContent = 
                result.monthlyTax.toFixed(2) + ' 元';
            document.getElementById('afterTaxIncome').textContent = 
                result.afterTaxIncome.toFixed(2) + ' 元';
        }

        /**
         * 显示计算过程
         */
        function displayCalculationSteps(result, salary, month, deductions) {
            const steps = `
                <div><strong>1. 累计收入:</strong>${salary.toFixed(2)} × ${month} = ${result.cumulativeIncome.toFixed(2)}元</div>
                <div><strong>2. 累计基本减除费用:</strong>${basicDeduction} × ${month} = ${result.cumulativeBasicDeduction.toFixed(2)}元</div>
                <div><strong>3. 累计专项附加扣除:</strong>${Object.keys(deductions).length > 0 ? Object.values(deductions).reduce((a, b) => a + b) : 0} × ${month} = ${result.cumulativeSpecialDeduction.toFixed(2)}元</div>
                <div><strong>4. 应纳税所得额:</strong>${result.cumulativeIncome.toFixed(2)} - ${result.cumulativeBasicDeduction.toFixed(2)} - ${result.cumulativeSpecialDeduction.toFixed(2)} = ${result.taxableIncome.toFixed(2)}元</div>
                <div><strong>5. 适用税率:</strong>${(result.taxRate * 100).toFixed(1)}%</div>
                <div><strong>6. 速算扣除数:</strong>${result.quickDeduction.toFixed(2)}元</div>
                <div><strong>7. 累计应纳税额:</strong>${result.taxableIncome.toFixed(2)} × ${(result.taxRate * 100).toFixed(1)}% - ${result.quickDeduction.toFixed(2)} = ${result.cumulativeTax.toFixed(2)}元</div>
                <div><strong>8. 本月应纳税额:</strong>${result.monthlyTax.toFixed(2)}元</div>
            `;
            
            document.getElementById('calculationSteps').innerHTML = steps;
        }

        /**
         * 保存到历史记录
         */
        function saveToHistory(result, salary, month) {
            const historyItem = {
                id: Date.now(),
                timestamp: new Date().toLocaleString(),
                salary: salary,
                month: month,
                tax: result.monthlyTax,
                afterTaxIncome: result.afterTaxIncome
            };
            
            // 添加到历史记录数组
            calculationHistory.unshift(historyItem);
            
            // 只保留最近10条记录
            if (calculationHistory.length > 10) {
                calculationHistory = calculationHistory.slice(0, 10);
            }
            
            // 保存到本地存储
            localStorage.setItem('taxHistory', JSON.stringify(calculationHistory));
            
            // 更新历史记录显示
            loadHistory();
        }

        /**
         * 加载历史记录
         */
        function loadHistory() {
            const historyBody = document.getElementById('historyBody');
            historyBody.innerHTML = '';
            
            if (calculationHistory.length === 0) {
                historyBody.innerHTML = '<tr><td colspan="5" style="text-align:center;">暂无计算记录</td></tr>';
                return;
            }
            
            calculationHistory.forEach(item => {
                const row = document.createElement('tr');
                row.innerHTML = `
                    <td>${item.timestamp}</td>
                    <td>${item.salary.toFixed(2)}元</td>
                    <td>${item.month}月</td>
                    <td>${item.tax.toFixed(2)}元</td>
                    <td>${item.afterTaxIncome.toFixed(2)}元</td>
                `;
                historyBody.appendChild(row);
            });
        }
    </script>
</body>
</html>

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐