房贷计算器

概念

计算公式

月供金额 = 月供本金 + 月供利息
月供利息 =(总贷款额 - 已还本金)* 月利率

等额本金

等额本金是每个月偿还的本金相同,利息逐月减少,总贷款利息较少,起始月供较高,每月递减。

月供本金 = 总贷款额/月供期数
月供金额 = (总贷款额/月供期数) + 月供利息

等额本息

每个月偿还的月供金额相同,月供本金随利息的减少逐月递增,总贷款利息较高,月供固定不变,相对月供较低。

月供金额 = 总贷款额 * 月利率 * ( 1+月利率 ) ^ 还款期数 / ( ( 1+月利率 ) ^ 还款期数 -1 )
月供本金 = 月供金额 - 月供利息

代码

/*
 * @Description: 房贷计算器
 * @Date: 2025-03-27 20:00:07
 */
import React, { useState, useEffect } from 'react';
import { Button, Form, InputNumber, Table, Tabs } from 'antd';

const FormItem = Form.Item;
const { TabPane } = Tabs;

const MortgageCalculator = () => {

    const [form] = Form.useForm();

    const [activeKey, setActiveKey] = useState('1');

    /** 等额本息表格 */
    const [interestData, setInterestData] = useState<any>([]);
    /** 等额本金表格 */
    const [principalData, setPrincipalData] = useState<any>([]);

    useEffect(() => {
        if (activeKey === '1') {
            equalPrincipal();
        } else {
            equalInterest();
        }
    }, [activeKey])

    const calculateLoans = () => {
        if (activeKey === '1') {
            equalPrincipal();
        } else {
            equalInterest();
        }
    }

    /** 等额本息 */
    const equalInterest = () => {
        form.validateFields();
        const formValue = form.getFieldsValue();
        // 贷款期数
        const month = Number(formValue.years || 0) * 12;
        // 公积金总金额
        const providentFundAmount = Number(formValue.providentFundAmount || 0) * 10000;
        // 商业贷总金额
        const commercialLoanAmount = Number(formValue.commercialLoanAmount || 0) * 10000;
        // 公积金月利率
        const monthProvidentFundRate = Number(formValue.providentFundRate || 0) / 100 / 12;
        // 商业贷月利率
        const monthCommercialLoanRate = Number(formValue.commercialLoanRate || 0) / 100 / 12;

        // 每月还款额=总贷款额 * 月利率 * ( 1+月利率 ) ^ 还款期数 / ( ( 1+月利率 ) ^ 还款期数 -1 )
        let monthProvidentAmount = 0;
        if (providentFundAmount) {
            monthProvidentAmount = (providentFundAmount * monthProvidentFundRate * (Math.pow(1 + monthProvidentFundRate, month))) / (Math.pow(1 + monthProvidentFundRate, month) - 1);
        }
        let monthCommercialAmount = 0;
        if (commercialLoanAmount) {
            monthCommercialAmount = (commercialLoanAmount * monthCommercialLoanRate * (Math.pow(1 + monthCommercialLoanRate, month))) / (Math.pow(1 + monthCommercialLoanRate, month) - 1);
        }

        // 每月月供金额
        const monthAmount = monthProvidentAmount + monthCommercialAmount;

        // 已还公积金本金
        let repaymentProvidentPrincipal = 0;
        // 已还商贷本金
        let repaymentCommercialPrincipal = 0;
        // 已还公积金利息
        let repaymentProvidentInterest = 0;
        // 已还商贷利息
        let repaymentCommercialInterest = 0;
        const newInterestData: Record<string, any> = [];

        for (let i = 0; i < month; i++) {
            // 公积金月利息
            const monthProvidentInterest = getMonthInterest(providentFundAmount, repaymentProvidentPrincipal, Number(formValue.providentFundRate || 0));
            // 商业贷月利息
            const monthCommercialInterest = getMonthInterest(commercialLoanAmount, repaymentCommercialPrincipal, Number(formValue.commercialLoanRate || 0));
            // 月利息
            const monthInterest = monthProvidentInterest + monthCommercialInterest;
            // 已还本金 = 商业贷已还本金 + 公积金已还本金
            const repaymentAmount = repaymentProvidentPrincipal + repaymentCommercialPrincipal;
            newInterestData.push({
                period: i + 1,
                monthAmount: monthAmount,
                remainingAmount: providentFundAmount + commercialLoanAmount - repaymentAmount,
                repaymentAmount: repaymentAmount,
                repaymentInterest: repaymentProvidentInterest + repaymentCommercialInterest,
                monthPrincipal: monthAmount - monthInterest,
                monthInterest: monthInterest
            });
            repaymentProvidentPrincipal += (monthProvidentAmount - monthProvidentInterest);
            repaymentCommercialPrincipal += monthCommercialAmount - monthCommercialInterest;
            repaymentProvidentInterest += monthProvidentInterest;
            repaymentCommercialInterest += monthCommercialInterest;
        }
        setInterestData(newInterestData);

    }

    /** 等额本金 */
    const equalPrincipal = () => {
        form.validateFields();
        const formValue = form.getFieldsValue();
        // 贷款期数
        const month = Number(formValue.years || 0) * 12;
        // 公积金总金额
        const providentFundAmount = Number(formValue.providentFundAmount || 0) * 10000;
        // 商业贷总金额
        const commercialLoanAmount = Number(formValue.commercialLoanAmount || 0) * 10000
        // 公积金贷款月供本金
        const monthProvidentPrincipal = providentFundAmount / month;
        // 商业贷款月供本金
        const monthCommercialLoanPrincipal = commercialLoanAmount / month;
        // 月供本金
        const monthPrincipal = monthProvidentPrincipal + monthCommercialLoanPrincipal;

        // 已还公积金本金
        let repaymentProvidentPrincipal = 0;
        // 已还商贷本金
        let repaymentCommercialPrincipal = 0;
        // 已还公积金利息
        let repaymentProvidentInterest = 0;
        // 已还商贷利息
        let repaymentCommercialInterest = 0;
        const newPrincipalData: Record<string, any> = [];

        for (let i = 0; i < month; i++) {
            // 公积金月利息
            const monthProvidentInterest = getMonthInterest(providentFundAmount, repaymentProvidentPrincipal, Number(formValue.providentFundRate || 0));
            // 商业贷月利息
            const monthCommercialInterest = getMonthInterest(commercialLoanAmount, repaymentCommercialPrincipal, Number(formValue.commercialLoanRate || 0));
            // 月利息
            const monthInterest = monthProvidentInterest + monthCommercialInterest;
            // 月供金额 = 月利息 + 月供本金
            const monthAmount = monthInterest + monthPrincipal;
            // 已还本金 = 商业贷已还本金 + 公积金已还本金
            const repaymentAmount = repaymentProvidentPrincipal + repaymentCommercialPrincipal;
            newPrincipalData.push({
                period: i + 1,
                monthAmount: monthAmount,
                remainingAmount: providentFundAmount + commercialLoanAmount - repaymentAmount,
                repaymentAmount: repaymentAmount,
                repaymentInterest: repaymentProvidentInterest + repaymentCommercialInterest,
                monthPrincipal: monthPrincipal,
                monthInterest: monthInterest
            });
            repaymentProvidentPrincipal += monthProvidentPrincipal;
            repaymentCommercialPrincipal += monthCommercialLoanPrincipal;
            repaymentProvidentInterest += monthProvidentInterest;
            repaymentCommercialInterest += monthCommercialInterest;
        }
        setPrincipalData(newPrincipalData);
    }

    /** 每月应还利息 */
    const getMonthInterest = (
        amount: number,
        repaymentPrincipal: number,
        rate: number,
    ) => {
        // 月利率
        const monthRate = rate / 100 / 12;
        // 每月应还利息 = (贷款本金-已还本金)*月利率
        return (amount - repaymentPrincipal) * monthRate;
    }

    /** 金额格式化 */
    const formatMoney = (value: number) => {
        if (value > 10000) {
            return (value / 10000).toFixed(2) + "万元";
        }
        return value.toFixed(2) + "元";
    }

    const columns = [
        {
            title: '期数',
            dataIndex: 'period',
        },
        {
            title: '月供总金额',
            dataIndex: 'monthAmount',
            render: (text, record) => {
                return formatMoney(text);
            },
        },
        {
            title: '月供本金',
            dataIndex: 'monthPrincipal',
            render: (text, record) => {
                return formatMoney(text);
            },
        },
        {
            title: '月供利息',
            dataIndex: 'monthInterest',
            render: (text, record) => {
                return formatMoney(text);
            },
        },
        {
            title: '剩余本金',
            dataIndex: 'remainingAmount',
            render: (text, record) => {
                return formatMoney(text);
            },
        },
        {
            title: '已还本金',
            dataIndex: 'repaymentAmount',
            render: (text, record) => {
                return formatMoney(text);
            },
        },
        {
            title: '已还利息',
            dataIndex: 'repaymentInterest',
            render: (text, record) => {
                return formatMoney(text);
            },
        },
    ]




    return (
        <div>
            <Form layout="vertical" form={form} initialValues={{
                years: 30,
                providentFundAmount: 60,
                providentFundRate: 2.85,
                commercialLoanAmount: 16,
                commercialLoanRate: 3.0,
            }}
            >
                <FormItem label="贷款年限" name="years" required rules={[{ required: true, message: '请输入贷款年限' }]}>
                    <InputNumber addonAfter="年" style={{ width: 300 }} />
                </FormItem>
                <FormItem label="公积金贷款金额" name="providentFundAmount">
                    <InputNumber addonAfter="万" style={{ width: 300 }} />
                </FormItem>
                <FormItem label="公积金贷款年利率" name="providentFundRate" >
                    <InputNumber addonAfter="%" style={{ width: 300 }} />
                </FormItem>
                <FormItem label="商业贷款金额" name="commercialLoanAmount">
                    <InputNumber addonAfter="万" style={{ width: 300 }} />
                </FormItem>
                <FormItem label="商业贷款年利率" name="commercialLoanRate" >
                    <InputNumber addonAfter="%" style={{ width: 300 }} />
                </FormItem>
                <FormItem >
                    <Button type="primary" onClick={calculateLoans}>计算</Button>
                </FormItem>
            </Form>
            <Tabs onChange={(activeKey: string) => setActiveKey(activeKey)}>
                <TabPane tab="等额本金" key="1">
                    <div>概念:每个月偿还的本金不变,利息逐月减少,总贷款利息较少,起始月供较高,每月递减。</div>
                    <div style={{ display: 'flex' }}>
                        <div style={{ marginRight: 24 }}>贷款总额度:{formatMoney(principalData[0]?.remainingAmount || 0)}</div>
                        <div>贷款总利息:{formatMoney(principalData[principalData.length - 1]?.repaymentInterest || 0)}</div>
                    </div>
                    <Table columns={columns} pagination={false} dataSource={principalData} />
                </TabPane>
                <TabPane tab="等额本息" key="2">
                    <div>概念:每个月偿还的月供固定,月供本金随利息的减少逐月递增,总贷款利息较高,月供固定不变,相对每月偿还基数较低。</div>
                    <div style={{ display: 'flex' }}>
                        <div style={{ marginRight: 24 }}>贷款总额度:{formatMoney(interestData[0]?.remainingAmount || 0)}</div>
                        <div>贷款总利息:{formatMoney(interestData[interestData.length - 1]?.repaymentInterest || 0)}</div>
                    </div>
                    <Table columns={columns} pagination={false} dataSource={interestData} />
                </TabPane>
            </Tabs>
        </div>
    )
}

export default MortgageCalculator;

效果图

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值