连续劳务计算器(依据国家税务总局公告2025年第16号)规则计算,支持税前/税后计算

image
最新政策连续劳务计算器免费分享给大家,网址链接:https://www.heyang-codes.top/

功能特性
🔄 计算模式
正向计算:输入税前收入,计算税后收入及个税

反向计算:输入期望的税后收入,反推税前收入及个税

📊 数据可视化
收入与个税趋势图表

月度计算明细表格

年度汇总统计

🛠️ 数据操作
Excel数据导入导出

批量调整功能

快速填充/清空

历史记录管理

🎯 智能计算
连续劳务计税规则:

  • 本期应预扣预缴税额=(累计收入-累计费用-累计免税收入-累计减除费用-累计依法确定的其他扣除)×预扣率-速算扣除数-累计减免税额-累计已预扣预缴税额
    
  • 其中:累计费用,按累计收入乘以20%计算;累计减除费用,按照5000元/月乘以纳税人当年截至本月在本互联网平台企业连续取得劳务报酬的月份数计算。
    
  • 七级超额累进税率
    
  • 高精度反向计算算法
    
  • 免税优惠:月销售额≤10万元(按自然月统计),全额免征增值税及附加税费(城建税、教育费附加等随增值税免征)
    
  • 征收率减免:月销售额>10万元,按3%征收率减按1%计算缴纳增值税
    
  • 增值税计算公式:增值税=含税收入÷(1+1%)x1%
    
  • 增值税附加计算公式:增值税附加= 增值税x6%
    
  • 多平台收入:若一个月从多个平台取得收入,需合并计算销售额;合计超10万则需缴税,不超则仍可免税
    

📱 用户体验
操作指引系统

响应式设计

实时数据验证

拖动模态框

使用说明
选择计算模式:根据需求选择正向或反向计算

输入收入数据:输入12个月份的收入数据

设置专项扣除:输入每月专项附加扣除总额

查看计算结果:实时查看详细计算结果和图表分析

数据管理:可导入导出数据,保存历史记录
核心计算代码

点击查看代码
/**
 * 正向计算函数
 */
function calculateForward() {
    const monthlyData = [];
    let totalIncomeValue = 0;
    let totalTaxValue = 0;
    let totalAfterTaxValue = 0;
    let totalVATValue = 0;
    let totalVATAddValue = 0;

    // 累计变量初始化
    let cumulativeIncomeCent = 0;           // 累计收入(不含增值税)
    let cumulativeExpenseCent = 0;          // 累计费用
    let cumulativeStandardDeductionCent = 0; // 累计减除费用
    let cumulativeTaxCent = 0;              // 累计个税
    let consecutiveIncomeMonths = 0;        // 连续月份数
    let cumulativeVATCent = 0;              // 累计增值税
    let cumulativeVATAddCent = 0;           // 累计增值税附加

    const platformIncome = getAllPlatformsMonthlyIncome();
    
    platformIncome.forEach((totalIncome, index) => {
        const month = MONTHS[index];
        const income = totalIncome;
        const incomeCent = toCent(income);

        if (income === 0) {
            const prevMonthData = monthlyData[monthlyData.length - 1] || null;
            monthlyData.push(createZeroMonthData(month, prevMonthData));
            return;
        }

        const prevMonthData = monthlyData[monthlyData.length - 1];
        if (prevMonthData && prevMonthData.income === 0) {
            // 重置所有累计值
            cumulativeIncomeCent = 0;
            cumulativeExpenseCent = 0;
            cumulativeStandardDeductionCent = 0;
            cumulativeTaxCent = 0;
            cumulativeVATCent = 0;
            cumulativeVATAddCent = 0;
            consecutiveIncomeMonths = 0;
        }

        let vatCent = 0;
        let vatAddCent = 0;
        let incomeWithoutVATCent = incomeCent;

        if (income > 100000) {
            vatCent = Math.round(incomeCent / 1.01 * 0.01);
            vatAddCent = Math.round(vatCent * 0.06);
            incomeWithoutVATCent = incomeCent - vatCent;
        } else {
            vatCent = 0;
            vatAddCent = 0;
            incomeWithoutVATCent = incomeCent;
        }

        consecutiveIncomeMonths++;
        cumulativeIncomeCent += incomeWithoutVATCent;
        cumulativeVATCent += vatCent;
        cumulativeVATAddCent += vatAddCent;

        cumulativeExpenseCent = Math.round(cumulativeIncomeCent * SERVICE_FEE_RATE);
        cumulativeStandardDeductionCent = consecutiveIncomeMonths * toCent(STANDARD_DEDUCTION);

        const taxableIncomeCent = Math.max(0, 
            cumulativeIncomeCent - cumulativeExpenseCent - cumulativeStandardDeductionCent - cumulativeVATAddCent
        );
        
        const taxableIncome = fromCent(taxableIncomeCent);

        const { rate, quickDeduction } = getTaxRate(taxableIncome);
        const cumulativeTaxRaw = calculateCumulativeTax(taxableIncome, rate, quickDeduction);
        const cumulativeTaxCentRaw = toCent(cumulativeTaxRaw);
        const newCumulativeTaxCent = Math.max(cumulativeTaxCent, cumulativeTaxCentRaw);
        const monthlyTaxCent = Math.max(0, newCumulativeTaxCent - cumulativeTaxCent);
        cumulativeTaxCent = newCumulativeTaxCent;

        const monthlyTax = fromCent(monthlyTaxCent);
        const vatAmount = fromCent(vatCent);
        const vatAddAmount = fromCent(vatAddCent);

        const afterTaxIncome = fromCent(incomeCent - vatCent - vatAddCent - monthlyTaxCent);

        const totalTaxAndFees = monthlyTax + vatAmount + vatAddAmount;
        const compositeTaxRate = income > 0 ? toFixed2((totalTaxAndFees / income) * 100) : 0;

        monthlyData.push({
            month: month,
            income: toFixed2(income),
            tax: toFixed2(monthlyTax),
            cumulativeIncome: toFixed2(fromCent(cumulativeIncomeCent)),
            cumulativeExpense: toFixed2(fromCent(cumulativeExpenseCent)),
            cumulativeStandardDeduction: toFixed2(fromCent(cumulativeStandardDeductionCent)),
            taxableIncome: toFixed2(taxableIncome),
            taxRate: toFixed2(rate * 100),
            quickDeduction: toFixed2(quickDeduction),
            cumulativeTax: toFixed2(fromCent(cumulativeTaxCent)),
            vat: toFixed2(vatAmount),
            vatAdd: toFixed2(vatAddAmount),
            afterTaxIncome: toFixed2(afterTaxIncome),
            compositeTaxRate: compositeTaxRate
        });

        totalIncomeValue += income;
        totalTaxValue += monthlyTax;
        totalAfterTaxValue += afterTaxIncome;
        totalVATValue += vatAmount;
        totalVATAddValue += vatAddAmount;
    });

    totalIncomeValue = toFixed2(totalIncomeValue);
    totalTaxValue = toFixed2(totalTaxValue);
    totalAfterTaxValue = toFixed2(totalAfterTaxValue);

    calculationMonthlyData = monthlyData;
    updateSummaryAndTable(totalIncomeValue, totalTaxValue, totalAfterTaxValue, monthlyData);
    updateTaxRateChart(monthlyData);
}

/**
 * 反向计算函数
 */
function calculateReverse() {
    try {
        const monthlyData = [];
        let totalIncomeValue = 0;
        let totalTaxValue = 0;
        let totalAfterTaxValue = 0;
        let totalVATValue = 0;
        let totalVATAddValue = 0;

        // 累计变量初始化
        let cumulativeIncomeCent = 0;
        let cumulativeExpenseCent = 0;
        let cumulativeStandardDeductionCent = 0;
        let cumulativeTaxCent = 0;
        let consecutiveIncomeMonths = 0;
        let cumulativeVATCent = 0;
        let cumulativeVATAddCent = 0;

        const inputs = document.querySelectorAll('.monthly-input');
        let hasValidData = false;

        inputs.forEach((input, index) => {
            const month = MONTHS[index];
            const inputValue = input.value.trim();

            const userAfterTaxIncome = inputValue ? toFixed2(parseFloat(input.dataset.rawValue || inputValue)) : 0;
            const afterTaxCent = toCent(userAfterTaxIncome);

            if (userAfterTaxIncome === 0) {
                const prevMonthData = monthlyData[monthlyData.length - 1] || null;
                monthlyData.push(createZeroMonthData(month, prevMonthData));
                return;
            }

            hasValidData = true;

            const prevMonthData = monthlyData[monthlyData.length - 1];
            if (prevMonthData && prevMonthData.income === 0) {
                cumulativeIncomeCent = 0;
                cumulativeExpenseCent = 0;
                cumulativeStandardDeductionCent = 0;
                cumulativeTaxCent = 0;
                cumulativeVATCent = 0;
                cumulativeVATAddCent = 0;
                consecutiveIncomeMonths = 0;
            }

            consecutiveIncomeMonths++;
            cumulativeStandardDeductionCent = consecutiveIncomeMonths * toCent(STANDARD_DEDUCTION);

            const result = calculatePreTaxWithPlatformRule(
                afterTaxCent,
                cumulativeIncomeCent,
                cumulativeStandardDeductionCent,
                cumulativeTaxCent,
                cumulativeVATCent,
                cumulativeVATAddCent
            );

            const preTaxCent = result.preTax;
            const monthlyTaxCent = result.tax;
            const vatCent = result.vat;
            const vatAddCent = result.vatAdd;
            const rate = result.rate;
            const quickDeduction = result.quickDeduction;

            cumulativeTaxCent = result.cumulativeTax;
            cumulativeVATCent += vatCent;
            cumulativeVATAddCent += vatAddCent;

            cumulativeIncomeCent += (preTaxCent - vatCent);

            cumulativeExpenseCent = Math.round(cumulativeIncomeCent * SERVICE_FEE_RATE);

            const taxableIncomeCent = Math.max(0,
                cumulativeIncomeCent - cumulativeExpenseCent - cumulativeStandardDeductionCent - cumulativeVATAddCent
            );

            const preTaxIncome = fromCent(preTaxCent);
            const monthlyTax = fromCent(monthlyTaxCent);
            const vatAmount = fromCent(vatCent);
            const vatAddAmount = fromCent(vatAddCent);

            const finalPreTaxIncome = monthlyTax === 0 && vatCent === 0 && vatAddCent === 0 ?
                                    userAfterTaxIncome : preTaxIncome;
            const finalTax = monthlyTax === 0 ? 0 : monthlyTax;

            const totalTaxAndFees = finalTax + vatAmount + vatAddAmount;
            const compositeTaxRate = finalPreTaxIncome > 0 ?
                toFixed2((totalTaxAndFees / finalPreTaxIncome) * 100) : 0;

            monthlyData.push({
                month: month,
                income: toFixed2(finalPreTaxIncome),
                tax: toFixed2(finalTax),
                cumulativeIncome: toFixed2(fromCent(cumulativeIncomeCent)),
                cumulativeExpense: toFixed2(fromCent(cumulativeExpenseCent)),
                cumulativeStandardDeduction: toFixed2(fromCent(cumulativeStandardDeductionCent)),
                taxableIncome: toFixed2(fromCent(taxableIncomeCent)),
                taxRate: toFixed2(rate > 0 ? rate * 100 : 3),
                quickDeduction: toFixed2(quickDeduction),
                cumulativeTax: toFixed2(fromCent(cumulativeTaxCent)),
                vat: toFixed2(vatAmount),
                vatAdd: toFixed2(vatAddAmount),
                afterTaxIncome: toFixed2(userAfterTaxIncome),
                compositeTaxRate: compositeTaxRate
            });

            totalIncomeValue += finalPreTaxIncome;
            totalTaxValue += finalTax;
            totalAfterTaxValue += userAfterTaxIncome;
            totalVATValue += vatAmount;
            totalVATAddValue += vatAddAmount;
        });

        totalIncomeValue = toFixed2(totalIncomeValue);
        totalTaxValue = toFixed2(totalTaxValue);
        totalAfterTaxValue = toFixed2(totalAfterTaxValue);

        calculationMonthlyData = monthlyData;
        updateSummaryAndTable(totalIncomeValue, totalTaxValue, totalAfterTaxValue, monthlyData);
        updateTaxRateChart(monthlyData);

        if (!hasValidData) {
            showToast('请输入至少一个月份的税后收入', 'info');
        }

    } catch (error) {
        console.error('反向计算错误:', error);
        showToast('计算过程中出现错误,请检查输入数据', 'error');
    }
}

/**
 * 平台规则反向计算函数
 */
function calculatePreTaxWithPlatformRule(
    afterTaxCent,
    cumulativeIncomeCent,
    cumulativeStandardDeductionCent,
    cumulativeTaxCent,
    cumulativeVATCent,
    cumulativeVATAddCent
) {
    // 二分查找范围
    let low = afterTaxCent;
    let high = afterTaxCent * 3;

    // 最佳结果初始化
    let bestGuess = afterTaxCent;
    let bestTax = 0;
    let bestVAT = 0;
    let bestVATAdd = 0;
    let bestCumulativeTax = cumulativeTaxCent;
    let bestRate = 0;
    let bestQuickDeduction = 0;
    let minError = Infinity;

    // 二分查找
    for (let i = 0; i < 100; i++) {
        const mid = Math.round((low + high) / 2);

        let vatCent = 0;
        let vatAddCent = 0;
        let incomeWithoutVATCent = mid;

        if (mid > toCent(100000)) {
            vatCent = Math.round(mid / 1.01 * 0.01);
            vatAddCent = Math.round(vatCent * 0.06);
            incomeWithoutVATCent = mid - vatCent;
        }

        const newCumulativeIncomeCent = cumulativeIncomeCent + incomeWithoutVATCent;

        const cumulativeExpenseCent = Math.round(newCumulativeIncomeCent * SERVICE_FEE_RATE);

        const cumulativeVATAddTotal = cumulativeVATAddCent + vatAddCent;
        const taxableIncomeCent = Math.max(0,
            newCumulativeIncomeCent - cumulativeExpenseCent - cumulativeStandardDeductionCent - cumulativeVATAddTotal
        );

        let monthlyTaxCent = 0;
        let cumulativeTaxNew = cumulativeTaxCent;
        let rate = 0;
        let quickDeduction = 0;

        if (taxableIncomeCent > 0) {
            const taxableIncomeYuan = fromCent(taxableIncomeCent);
            const rateInfo = getTaxRate(taxableIncomeYuan);
            rate = rateInfo.rate;
            quickDeduction = rateInfo.quickDeduction;

            const cumulativeTaxRaw = calculateCumulativeTax(taxableIncomeYuan, rate, quickDeduction);
            const cumulativeTaxCentRaw = toCent(cumulativeTaxRaw);
            cumulativeTaxNew = Math.max(cumulativeTaxCent, cumulativeTaxCentRaw);
            monthlyTaxCent = Math.max(0, cumulativeTaxNew - cumulativeTaxCent);
        }

        const calculatedAfterTax = mid - vatCent - vatAddCent - monthlyTaxCent;
        const error = Math.abs(calculatedAfterTax - afterTaxCent);

        if (error < minError) {
            minError = error;
            bestGuess = mid;
            bestTax = monthlyTaxCent;
            bestVAT = vatCent;
            bestVATAdd = vatAddCent;
            bestCumulativeTax = cumulativeTaxNew;
            bestRate = rate;
            bestQuickDeduction = quickDeduction;
        }

        if (error <= 1) break;

        if (calculatedAfterTax > afterTaxCent) {
            high = mid - 1;
        } else {
            low = mid + 1;
        }

        if (high <= low) break;
    }

    // 精确搜索(步长1分)
    for (let adj = -10; adj <= 10; adj++) {
        const candidate = bestGuess + adj;
        if (candidate < afterTaxCent) continue;

        let vatCent = 0;
        let vatAddCent = 0;
        let incomeWithoutVATCent = candidate;

        if (candidate > toCent(100000)) {
            vatCent = Math.round(candidate / 1.01 * 0.01);
            vatAddCent = Math.round(vatCent * 0.06);
            incomeWithoutVATCent = candidate - vatCent;
        }

        const newCumulativeIncomeCent = cumulativeIncomeCent + incomeWithoutVATCent;
        const cumulativeExpenseCent = Math.round(newCumulativeIncomeCent * SERVICE_FEE_RATE);
        const cumulativeVATAddTotal = cumulativeVATAddCent + vatAddCent;
        const taxableIncomeCent = Math.max(0,
            newCumulativeIncomeCent - cumulativeExpenseCent - cumulativeStandardDeductionCent - cumulativeVATAddTotal
        );

        let candidateTaxCent = 0;
        let candidateCumulativeTax = cumulativeTaxCent;
        let candidateRate = bestRate;
        let candidateQuickDeduction = bestQuickDeduction;

        if (taxableIncomeCent > 0) {
            const taxableIncomeYuan = fromCent(taxableIncomeCent);
            const candidateRateInfo = getTaxRate(taxableIncomeYuan);
            candidateRate = candidateRateInfo.rate;
            candidateQuickDeduction = candidateRateInfo.quickDeduction;

            const candidateTaxRaw = calculateCumulativeTax(taxableIncomeYuan, candidateRate, candidateQuickDeduction);
            const candidateTaxCentRaw = toCent(candidateTaxRaw);
            candidateCumulativeTax = Math.max(cumulativeTaxCent, candidateTaxCentRaw);
            candidateTaxCent = Math.max(0, candidateCumulativeTax - cumulativeTaxCent);
        }

        const candidateAfterTax = candidate - vatCent - vatAddCent - candidateTaxCent;
        const candidateError = Math.abs(candidateAfterTax - afterTaxCent);

        if (candidateError < minError) {
            minError = candidateError;
            bestGuess = candidate;
            bestTax = candidateTaxCent;
            bestVAT = vatCent;
            bestVATAdd = vatAddCent;
            bestCumulativeTax = candidateCumulativeTax;
            bestRate = candidateRate;
            bestQuickDeduction = candidateQuickDeduction;
        }

        if (candidateError === 0) break;
    }

    return {
        preTax: bestGuess,
        tax: bestTax,
        vat: bestVAT,
        vatAdd: bestVATAdd,
        cumulativeTax: bestCumulativeTax,
        rate: bestRate,
        quickDeduction: bestQuickDeduction
    };
}

/**
 * 根据应纳税所得额获取税率信息
 */
function getTaxRate(taxableIncome) {
    const income = Number(taxableIncome) || 0;
    for (const bracket of TAX_RATES) {
        if (income >= bracket.min && (income < bracket.max || bracket.max === Infinity)) {
            return {
                rate: bracket.rate,
                quickDeduction: bracket.quickDeduction
            };
        }
    }
    const maxBracket = TAX_RATES[TAX_RATES.length - 1];
    return {
        rate: maxBracket.rate,
        quickDeduction: maxBracket.quickDeduction
    };
}

/**
 * 计算累计个税
 */
function calculateCumulativeTax(taxableIncome, rate, quickDeduction) {
    return Math.round((taxableIncome * rate - quickDeduction) * 100) / 100;
}

/**
 * 创建零收入月份数据
 */
function createZeroMonthData(month, prevMonthData) {
    if (prevMonthData) {
        return {
            month: month,
            income: 0,
            tax: 0,
            cumulativeIncome: toFixed2(fromCent(prevMonthData.cumulativeIncomeCent || 0)),
            cumulativeExpense: toFixed2(fromCent(prevMonthData.cumulativeExpenseCent || 0)),
            cumulativeStandardDeduction: toFixed2(fromCent(prevMonthData.cumulativeStandardDeductionCent || 0)),
            taxableIncome: 0,
            taxRate: 0,
            quickDeduction: 0,
            cumulativeTax: toFixed2(fromCent(prevMonthData.cumulativeTaxCent || 0)),
            vat: 0,
            vatAdd: 0,
            afterTaxIncome: 0,
            compositeTaxRate: 0
        };
    } else {
        return {
            month: month,
            income: 0,
            tax: 0,
            cumulativeIncome: 0,
            cumulativeExpense: 0,
            cumulativeStandardDeduction: 0,
            taxableIncome: 0,
            taxRate: 0,
            quickDeduction: 0,
            cumulativeTax: 0,
            vat: 0,
            vatAdd: 0,
            afterTaxIncome: 0,
            compositeTaxRate: 0
        };
    }
}

posted @ 2026-03-02 14:08  小木爱学习  阅读(0)  评论(0)    收藏  举报