219 lines
11 KiB
PHP
219 lines
11 KiB
PHP
<?php
|
||
declare(strict_types=1);
|
||
/** @var array $me */
|
||
?>
|
||
<div class="card fin-tool-page">
|
||
<h3 class="section-title">利息计算器</h3>
|
||
<div class="quick-links-col" style="margin-bottom:14px">
|
||
<a class="tree-link" href="index.php?action=quick_queries">← 返回便捷查询</a>
|
||
</div>
|
||
<div class="fin-two-col">
|
||
<div class="fin-panel">
|
||
<h4>输入</h4>
|
||
<div class="fin-row">
|
||
<label for="ic_principal">本金(元)</label>
|
||
<div>
|
||
<input id="ic_principal" type="text" inputmode="decimal" autocomplete="off" placeholder="如 1000000" style="width:100%;max-width:320px">
|
||
<div id="ic_principal_fmt" class="fin-muted"></div>
|
||
<div id="ic_principal_cap" class="fin-cn-cap"></div>
|
||
</div>
|
||
</div>
|
||
<div class="fin-row">
|
||
<label for="ic_rate">利率数值</label>
|
||
<div>
|
||
<input id="ic_rate" type="text" inputmode="decimal" style="width:140px">
|
||
<select id="ic_rate_kind" style="margin-left:8px">
|
||
<option value="annual">年利率 %</option>
|
||
<option value="monthly">月利率 %</option>
|
||
<option value="daily">日利率 %</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
<div class="fin-row">
|
||
<label>计息天数</label>
|
||
<div>
|
||
<label class="inline small"><input type="radio" name="ic_day_mode" value="manual" checked> 模式A:直接输入天数</label>
|
||
<label class="inline small" style="margin-left:12px"><input type="radio" name="ic_day_mode" value="range"> 模式B:起止日期</label>
|
||
</div>
|
||
</div>
|
||
<div class="fin-row" id="ic_row_manual">
|
||
<label for="ic_days">天数</label>
|
||
<div>
|
||
<input id="ic_days" type="number" min="0" step="1" style="width:120px" placeholder="正整数">
|
||
<span class="fin-muted" id="ic_days_hint"></span>
|
||
</div>
|
||
</div>
|
||
<div class="fin-row" id="ic_row_range" style="display:none">
|
||
<label>起止日期</label>
|
||
<div style="display:flex;flex-wrap:wrap;gap:8px;align-items:center">
|
||
<input id="ic_d1" type="date">
|
||
<span>至</span>
|
||
<input id="ic_d2" type="date">
|
||
<span class="fin-muted" id="ic_range_days_label"></span>
|
||
</div>
|
||
</div>
|
||
<div class="fin-row">
|
||
<label for="ic_count_mode">结息方式</label>
|
||
<select id="ic_count_mode">
|
||
<option value="inclusive">记首记尾(算头又算尾,天数+1)</option>
|
||
<option value="exclusive" selected>记首不记尾(算头不算尾)</option>
|
||
</select>
|
||
</div>
|
||
<div class="fin-row">
|
||
<label for="ic_basis">计息基准</label>
|
||
<select id="ic_basis">
|
||
<option value="360" selected>360 天/年(银行常用)</option>
|
||
<option value="365">365 天/年</option>
|
||
</select>
|
||
</div>
|
||
<div class="fin-actions">
|
||
<button type="button" class="toolbar-btn primary" id="ic_calc">计算</button>
|
||
<button type="button" class="toolbar-btn" id="ic_copy">一键复制结果</button>
|
||
<button type="button" class="btn-gray" id="ic_reset">重置</button>
|
||
</div>
|
||
</div>
|
||
<div class="fin-result-card" id="ic_result_wrap">
|
||
<h4 style="margin:0 0 10px">计算结果</h4>
|
||
<p class="fin-muted" style="margin:0 0 8px" id="ic_placeholder">请先填写左侧数据并点击「计算」</p>
|
||
<div id="ic_result_body" style="display:none">
|
||
<p class="small muted" style="margin:0">应付利息</p>
|
||
<div class="fin-out-num" id="ic_out_interest">—</div>
|
||
<p class="small muted" style="margin:12px 0 0">本息合计</p>
|
||
<div class="fin-out-num" id="ic_out_total" style="font-size:18px">—</div>
|
||
<p style="margin:12px 0 4px;font-size:13px">实际计息天数:<strong id="ic_out_days">—</strong></p>
|
||
<p style="margin:0;font-size:13px">参考日利率:<strong id="ic_out_daily">—</strong></p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<script>
|
||
(function(){
|
||
var DIG='零壹贰叁肆伍陆柒捌玖', UNIT=['','拾','佰','仟'], GRP=['','万','亿','兆'];
|
||
function sectionFour(n){
|
||
var s='', str=('0000'+n).slice(-4);
|
||
for(var i=0;i<4;i++){
|
||
var d=+str[i]; if(d===0){ s+=DIG[0]; continue; }
|
||
s=s.replace(/零+$/,'');
|
||
s+=DIG[d]+UNIT[3-i];
|
||
}
|
||
s=s.replace(/零+/g,'零').replace(/零$/,'');
|
||
return s||DIG[0];
|
||
}
|
||
function toRmbUpper(x){
|
||
if(!isFinite(x)||x<=0) return '';
|
||
var yi=Math.floor(x/1e8), wan=Math.floor((x%1e8)/1e4), ge=Math.floor(x%1e4);
|
||
var out='';
|
||
if(yi>0) out+=sectionFour(yi)+'亿';
|
||
if(wan>0||(yi>0&&ge>0)) out+=sectionFour(wan)+'万';
|
||
out+=sectionFour(ge)+'元整';
|
||
return out.replace(/^壹拾/g,'拾');
|
||
}
|
||
function parseNum(s){
|
||
s=String(s||'').replace(/,/g,'').trim();
|
||
if(s==='') return NaN;
|
||
var v=parseFloat(s);
|
||
return isFinite(v)?v:NaN;
|
||
}
|
||
function fmtMoney(n){
|
||
if(!isFinite(n)) return '';
|
||
var p=(Math.round(n*100)/100).toFixed(2).split('.');
|
||
p[0]=p[0].replace(/\B(?=(\d{3})+(?!\d))/g,',');
|
||
return p.join('.');
|
||
}
|
||
function syncPrincipalFmt(){
|
||
var raw=document.getElementById('ic_principal').value;
|
||
var v=parseNum(raw);
|
||
document.getElementById('ic_principal_fmt').textContent=isFinite(v)&&v>0?('格式化:'+fmtMoney(v)+' 元'):'';
|
||
document.getElementById('ic_principal_cap').textContent=isFinite(v)&&v>0?('大写:'+toRmbUpper(Math.floor(v))):'';
|
||
}
|
||
function daysFromRange(d1,d2,mode){
|
||
if(!d1||!d2) return NaN;
|
||
var t0=new Date(d1+'T12:00:00').getTime(), t1=new Date(d2+'T12:00:00').getTime();
|
||
if(t1<t0) return NaN;
|
||
var diff=Math.round((t1-t0)/86400000);
|
||
return mode==='inclusive'?diff+1:diff;
|
||
}
|
||
function getEffectiveDays(){
|
||
var mode=document.querySelector('input[name="ic_day_mode"]:checked').value;
|
||
var cm=document.getElementById('ic_count_mode').value;
|
||
if(mode==='manual'){
|
||
var n=parseInt(document.getElementById('ic_days').value,10);
|
||
return isFinite(n)&&n>=0?n:NaN;
|
||
}
|
||
return daysFromRange(document.getElementById('ic_d1').value,document.getElementById('ic_d2').value,cm);
|
||
}
|
||
function dailyRef(P,Rk,rate,basis){
|
||
var b=+basis;
|
||
if(Rk==='annual') return (rate/100)/b;
|
||
if(Rk==='monthly') return (rate/100)/30;
|
||
return rate/100;
|
||
}
|
||
function interestAmount(P,Rk,rate,days,basis){
|
||
if(!(P>0)||!(days>=0)||!(rate>0)) return NaN;
|
||
var b=+basis;
|
||
if(Rk==='annual') return P*(rate/100)*(days/b);
|
||
if(Rk==='monthly') return P*(rate/100)*(days/30);
|
||
return P*(rate/100)*days;
|
||
}
|
||
function calc(){
|
||
var P=parseNum(document.getElementById('ic_principal').value);
|
||
var rate=parseNum(document.getElementById('ic_rate').value);
|
||
var Rk=document.getElementById('ic_rate_kind').value;
|
||
var basis=document.getElementById('ic_basis').value;
|
||
var days=getEffectiveDays();
|
||
if(!(P>0)){ alert('请输入有效本金'); return; }
|
||
if(!(rate>0)){ alert('请输入有效利率'); return; }
|
||
if(!isFinite(days)||days<0){ alert('请检查计息天数或起止日期'); return; }
|
||
var intr=interestAmount(P,Rk,rate,days,basis);
|
||
var dref=dailyRef(P,Rk,rate,basis);
|
||
document.getElementById('ic_out_interest').textContent=fmtMoney(intr)+' 元';
|
||
document.getElementById('ic_out_total').textContent=fmtMoney(P+intr)+' 元';
|
||
document.getElementById('ic_out_days').textContent=String(days);
|
||
document.getElementById('ic_out_daily').textContent=(dref*100).toFixed(6)+'%(按当前利率种类换算,仅供参考)';
|
||
document.getElementById('ic_result_body').style.display='block';
|
||
var ph=document.getElementById('ic_placeholder'); if(ph) ph.style.display='none';
|
||
}
|
||
function copyTxt(){
|
||
var t='利息 '+document.getElementById('ic_out_interest').textContent+' | 本息合计 '+document.getElementById('ic_out_total').textContent+' | 天数 '+document.getElementById('ic_out_days').textContent;
|
||
if(navigator.clipboard) navigator.clipboard.writeText(t).then(function(){alert('已复制');},function(){alert(t);});
|
||
else alert(t);
|
||
}
|
||
function resetAll(){
|
||
document.getElementById('ic_principal').value='';
|
||
document.getElementById('ic_rate').value='';
|
||
document.getElementById('ic_days').value='';
|
||
document.getElementById('ic_d1').value='';
|
||
document.getElementById('ic_d2').value='';
|
||
syncPrincipalFmt();
|
||
document.getElementById('ic_result_body').style.display='none';
|
||
var ph=document.getElementById('ic_placeholder'); if(ph) ph.style.display='block';
|
||
}
|
||
document.getElementById('ic_principal').addEventListener('input',syncPrincipalFmt);
|
||
document.getElementById('ic_principal').addEventListener('paste',function(){setTimeout(syncPrincipalFmt,0);});
|
||
document.querySelectorAll('input[name="ic_day_mode"]').forEach(function(r){
|
||
r.addEventListener('change',function(){
|
||
var m=document.querySelector('input[name="ic_day_mode"]:checked').value;
|
||
document.getElementById('ic_row_manual').style.display=m==='manual'?'':'none';
|
||
document.getElementById('ic_row_range').style.display=m==='range'?'':'none';
|
||
});
|
||
});
|
||
function syncRangeLabel(){
|
||
var cm=document.getElementById('ic_count_mode').value;
|
||
var d=daysFromRange(document.getElementById('ic_d1').value,document.getElementById('ic_d2').value,cm);
|
||
document.getElementById('ic_range_days_label').textContent=isFinite(d)?('→ 计息天数 '+d):'';
|
||
}
|
||
['ic_d1','ic_d2','ic_count_mode'].forEach(function(id){
|
||
var el=document.getElementById(id);
|
||
if(el) el.addEventListener('change',syncRangeLabel);
|
||
});
|
||
document.getElementById('ic_days').addEventListener('input',function(){
|
||
if(this.value && document.getElementById('ic_d1').value){ document.getElementById('ic_d1').value=''; document.getElementById('ic_d2').value=''; document.getElementById('ic_range_days_label').textContent=''; }
|
||
});
|
||
document.getElementById('ic_d1').addEventListener('change',function(){ if(this.value) document.getElementById('ic_days').value=''; });
|
||
document.getElementById('ic_d2').addEventListener('change',function(){ if(this.value) document.getElementById('ic_days').value=''; });
|
||
document.getElementById('ic_calc').addEventListener('click',calc);
|
||
document.getElementById('ic_copy').addEventListener('click',copyTxt);
|
||
document.getElementById('ic_reset').addEventListener('click',resetAll);
|
||
})();
|
||
</script>
|