用戶期望:幣種(一級) → 存期(二級) → 年利率(三級,文本框可輸入)。但實際上「幣種+存期」決定年利率,屬於二級聯動 + 手工輸入,非標準三級聯動(三級通常也是下拉選擇)。
前端 後端
┌─────────────┐ AJAX ┌─────────────┐
│ 幣種下拉 │ ───────────▶ │ GET /terms? │
│ 存期下拉 │ ◀─────────── │ currency=CNY│
│ 年利率輸入框│ (可選驗證) │ 返回存期列表 │
└─────────────┘ └─────────────┘
/api/terms?currency=XXX,獲取該幣種對應的存期列表。<option>,若列表為空則禁用存期下拉。CREATE TABLE deposit_rate (
id BIGINT PRIMARY KEY,
currency CHAR(3) NOT NULL, -- 幣種
term_months INT NOT NULL, -- 存期(月)
annual_rate DECIMAL(5,4) NOT NULL, -- 年利率
UNIQUE KEY uk_currency_term (currency, term_months)
);
$('#currency').change(function() {
const currency = $(this).val();
$('#term').prop('disabled', true).empty().append('');
$('#rate').val('').prop('readonly', true);
if (!currency) return;
$.getJSON('/api/terms', {currency}, function(terms) {
terms.forEach(t => $('#term').append(``));
$('#term').prop('disabled', false);
});
});
$('#term').change(function() {
const term = $(this).val();
if (!term) return;
// 方案A:前端查表
const rate = RATE_TABLE[$('#currency').val()][term];
$('#rate').val(rate).prop('readonly', false);
// 方案B:後端查詢
// $.getJSON('/api/rate', {currency: $('#currency').val(), term}, function(r) { $('#rate').val(r.rate).prop('readonly', false); });
});
axios 取消舊請求或標記 requestId 校驗。BigDecimal(後端)或 decimal.js(前端),避免 0.015 * 10000 = 150.0000000002 類問題。核心思想:**聯動只負責「選項篩選」,輸入框負責「數值錄入/修正」,職責分離,前後端雙重校驗**。