新增清潔費欄位 {{清潔費}},並記憶每份範本上次使用的值

- 表單新增「清潔費」欄位,預設 1200
- 後端 PDF 產生成功後自動將 monthlyRent / paymentDay / deposit / cleaningFee
  寫入 templates/defaults.json,key 為範本檔名
- 切換範本時呼叫 /api/templates/:name/defaults 自動帶入上次的值
- 表單版面調整為 2x2:每月租金/繳款日期、保證金/清潔費 各一行
- 4 份逢甲範本加入 {{清潔費}} 佔位符

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 14:17:31 +08:00
parent ef70576f4b
commit bfd978f7e6
8 changed files with 72 additions and 2 deletions
+20 -1
View File
@@ -23,7 +23,10 @@ document.getElementById('leaseStart').addEventListener('change', (e) => {
schedulePreview();
});
templateSelect.addEventListener('change', () => loadPreview());
templateSelect.addEventListener('change', () => {
loadTemplateDefaults(templateSelect.value);
loadPreview();
});
let previewTimer = null;
function schedulePreview() {
@@ -50,6 +53,7 @@ form.addEventListener('submit', async (event) => {
monthlyRent: formData.get('monthlyRent'),
paymentDay: formData.get('paymentDay'),
deposit: formData.get('deposit'),
cleaningFee: formData.get('cleaningFee'),
leaseStart: formData.get('leaseStart'),
leaseEnd: formData.get('leaseEnd'),
}),
@@ -119,6 +123,7 @@ async function loadTemplates() {
}
connectionStatus.textContent = '可使用';
loadTemplateDefaults(templateSelect.value);
loadPreview();
} catch (error) {
templateSelect.append(new Option('讀取失敗', ''));
@@ -129,6 +134,19 @@ async function loadTemplates() {
}
}
async function loadTemplateDefaults(name) {
if (!name) return;
try {
const res = await fetch(`/api/templates/${encodeURIComponent(name)}/defaults`);
if (!res.ok) return;
const defaults = await res.json();
if (defaults.monthlyRent) form.elements.monthlyRent.value = defaults.monthlyRent;
if (defaults.paymentDay) form.elements.paymentDay.value = defaults.paymentDay;
if (defaults.deposit) form.elements.deposit.value = defaults.deposit;
if (defaults.cleaningFee) form.elements.cleaningFee.value = defaults.cleaningFee;
} catch {}
}
let previewGen = 0;
let previewAbortController = null;
let previewBlobUrl = null;
@@ -151,6 +169,7 @@ async function loadPreview() {
monthlyRent: formData.get('monthlyRent') || '',
paymentDay: formData.get('paymentDay') || '',
deposit: formData.get('deposit') || '',
cleaningFee: formData.get('cleaningFee') || '',
leaseStart: formData.get('leaseStart') || '',
leaseEnd: formData.get('leaseEnd') || '',
});
+5 -1
View File
@@ -50,7 +50,7 @@
</div>
<div class="tool-panel fields-panel">
<div class="field-grid">
<div class="field-grid field-grid--2">
<label class="field">
<span>每月租金</span>
<input name="monthlyRent" type="number" inputmode="numeric" min="1" step="1" value="8000" required>
@@ -63,6 +63,10 @@
<span>保證金</span>
<input name="deposit" type="number" inputmode="numeric" min="1" step="1" value="16000" required>
</label>
<label class="field">
<span>清潔費</span>
<input name="cleaningFee" type="number" inputmode="numeric" min="1" step="1" value="1200" required>
</label>
</div>
<div class="field-grid field-grid--2">