Files
rmutr/disbursement-plan-preview.html
T
Nut.ไปเรื่อย 2fbb0b3d51 feat: add Thai date selector, HTML prototypes, and SQL script
- Replace xlsx with exceljs in construction calculator; switch date input to Thai Buddhist Era selectors
- Add disbursement plan preview HTML and schedule table prototype
- Add sync_budget_come_from SQL script
- Add budget type select menu design plan

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 10:13:05 +07:00

273 lines
14 KiB
HTML

<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Preview: แผนการเบิกจ่ายเป็นงวด</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: 'Sarabun', sans-serif; background: #f5f5f5; padding: 20px; color: #333; }
/* ─── LIST ROW PREVIEW ─── */
.section-label { font-size: 13px; color: #666; margin-bottom: 8px; text-transform: uppercase; letter-spacing: .5px; }
.list-preview { background: white; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,.1); overflow: hidden; margin-bottom: 32px; }
.list-preview table { width: 100%; border-collapse: collapse; font-size: 13px; }
.list-preview th { background: #1976d2; color: white; padding: 8px 10px; text-align: center; font-weight: 500; border: 1px solid #1565c0; }
.list-preview td { padding: 7px 10px; border: 1px solid #e0e0e0; vertical-align: middle; }
.list-preview tr:nth-child(even) td { background: #fafafa; }
.icon-btn {
width: 32px; height: 32px; border-radius: 50%; border: none; cursor: pointer;
display: inline-flex; align-items: center; justify-content: center;
font-size: 16px; margin: 0 2px; transition: background .2s;
}
.icon-btn.edit { background: #e3f2fd; color: #1976d2; }
.icon-btn.edit:hover { background: #bbdefb; }
.icon-btn.disburse { background: #e8f5e9; color: #388e3c; }
.icon-btn.disburse:hover { background: #c8e6c9; }
.icon-btn.disburse.has-data { background: #388e3c; color: white; }
.badge { display: inline-block; padding: 2px 8px; border-radius: 12px; font-size: 11px; }
.badge.filled { background: #e8f5e9; color: #388e3c; }
.badge.empty { background: #f5f5f5; color: #9e9e9e; }
/* ─── OVERLAY ─── */
.overlay { position: fixed; inset: 0; background: rgba(0,0,0,.5); display: flex; align-items: center; justify-content: center; z-index: 100; }
.overlay.hidden { display: none; }
/* ─── DIALOG ─── */
.dialog {
background: white; border-radius: 8px; box-shadow: 0 8px 32px rgba(0,0,0,.3);
width: 780px; max-width: 95vw; max-height: 90vh; overflow-y: auto;
}
.dialog-header {
background: #1976d2; color: white; padding: 16px 20px;
display: flex; justify-content: space-between; align-items: center;
border-radius: 8px 8px 0 0;
}
.dialog-header h2 { font-size: 16px; font-weight: 600; }
.dialog-close { background: none; border: none; color: white; font-size: 20px; cursor: pointer; line-height: 1; }
.dialog-body { padding: 20px; }
.project-info { background: #f3f8ff; border-left: 4px solid #1976d2; padding: 10px 14px; border-radius: 0 4px 4px 0; margin-bottom: 20px; }
.project-info .label { font-size: 11px; color: #666; }
.project-info .value { font-size: 14px; font-weight: 600; color: #1976d2; }
/* ─── DISBURSE TABLE ─── */
.disburse-table-wrap { overflow-x: auto; margin-bottom: 20px; }
.disburse-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.disburse-table th, .disburse-table td { border: 1px solid #ccc; padding: 0; text-align: center; }
.disburse-table .th-main { background: #1565c0; color: white; padding: 8px; font-weight: 600; font-size: 14px; }
.disburse-table .th-sub { background: #1976d2; color: white; padding: 7px 6px; font-weight: 500; font-size: 12px; }
.disburse-table .th-col { background: #e3f2fd; color: #0d47a1; padding: 6px 4px; font-size: 12px; font-weight: 500; }
.disburse-table .td-total { background: #fff8e1; font-weight: 700; font-size: 14px; color: #e65100; padding: 10px 8px; }
.disburse-table input[type=number], .disburse-table input[type=date] {
width: 100%; border: none; padding: 8px 6px; text-align: right; font-size: 13px;
background: transparent; outline: none; font-family: inherit;
}
.disburse-table input[type=date] { text-align: center; }
.disburse-table input:focus { background: #fff8e1; }
.disburse-table tr:hover td { background: #f9f9f9; }
.disburse-table tr:hover td.td-total { background: #fff3e0; }
/* ─── ACTIONS ─── */
.dialog-actions { display: flex; justify-content: flex-end; gap: 10px; padding: 12px 20px; border-top: 1px solid #e0e0e0; }
.btn { padding: 8px 20px; border-radius: 4px; border: none; cursor: pointer; font-size: 14px; font-family: inherit; font-weight: 500; }
.btn-cancel { background: #f5f5f5; color: #666; border: 1px solid #ddd; }
.btn-cancel:hover { background: #eeeeee; }
.btn-save { background: #1976d2; color: white; }
.btn-save:hover { background: #1565c0; }
/* ─── TOTAL SUMMARY ─── */
.total-bar { background: #fff3e0; border: 1px solid #ffcc80; border-radius: 6px; padding: 10px 16px; display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
.total-bar .label { font-size: 13px; color: #795548; }
.total-bar .amount { font-size: 18px; font-weight: 700; color: #e65100; }
h1 { font-size: 18px; color: #1976d2; margin-bottom: 6px; }
p.desc { font-size: 13px; color: #666; margin-bottom: 20px; }
.arrow { font-size: 24px; color: #1976d2; margin: 0 12px; }
</style>
</head>
<body>
<h1>🔍 Preview: แผนการเบิกจ่ายเป็นงวด</h1>
<p class="desc">ตัวอย่างการแสดงผลใน Angular — ไอคอน <span style="background:#e8f5e9;color:#388e3c;padding:2px 8px;border-radius:12px;font-size:12px;">💰</span> ในตารางรายโครงการ และ dialog form</p>
<!-- ─── LIST PREVIEW ─── -->
<div class="section-label">📋 ตารางรายโครงการ (list20-research) — มีไอคอน 💰 ต่อโครงการ</div>
<div class="list-preview">
<table>
<thead>
<tr>
<th>ลำดับ</th>
<th>ปีงบ</th>
<th>ชื่อโครงการ</th>
<th>หน่วยงาน</th>
<th>แหล่งเงิน</th>
<th>งบประมาณ</th>
<th style="background:#155724;">แผนเบิกจ่าย</th>
<th>เครื่องมือ</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">1</td>
<td style="text-align:center">2567</td>
<td>โครงการพัฒนาคุณภาพการศึกษาด้านวิทยาศาสตร์</td>
<td>คณะวิศวกรรมศาสตร์</td>
<td>กองทุนพัฒนา</td>
<td style="text-align:right">95,000</td>
<td style="text-align:center">
<span class="badge filled">✓ กรอกแล้ว</span>
</td>
<td style="text-align:center">
<button class="icon-btn edit" title="แก้ไข">✏️</button>
<button class="icon-btn disburse has-data" title="แผนการเบิกจ่าย" onclick="openDialog('โครงการพัฒนาคุณภาพการศึกษาด้านวิทยาศาสตร์', 66500, '2567-11-15', 19000, '2568-01-20', 9500, '2568-03-30')">💰</button>
</td>
</tr>
<tr>
<td style="text-align:center">2</td>
<td style="text-align:center">2567</td>
<td>โครงการวิจัยนวัตกรรมดิจิทัล</td>
<td>คณะเทคโนโลยีสารสนเทศ</td>
<td>งบประมาณแผ่นดิน</td>
<td style="text-align:right">150,000</td>
<td style="text-align:center">
<span class="badge empty">ยังไม่กรอก</span>
</td>
<td style="text-align:center">
<button class="icon-btn edit" title="แก้ไข">✏️</button>
<button class="icon-btn disburse" title="แผนการเบิกจ่าย" onclick="openDialog('โครงการวิจัยนวัตกรรมดิจิทัล', null, null, null, null, null, null)">💰</button>
</td>
</tr>
</tbody>
</table>
</div>
<!-- ─── DIALOG ─── -->
<div class="overlay hidden" id="overlay" onclick="closeOnOverlay(event)">
<div class="dialog" onclick="event.stopPropagation()">
<div class="dialog-header">
<h2>📋 แผนการเบิกจ่ายเงินเป็นงวด</h2>
<button class="dialog-close" onclick="closeDialog()"></button>
</div>
<div class="dialog-body">
<div class="project-info">
<div class="label">ชื่อโครงการ</div>
<div class="value" id="project-name"></div>
</div>
<div class="disburse-table-wrap">
<table class="disburse-table">
<thead>
<tr>
<th class="th-main" colspan="7">แผนการเบิกจ่ายเงิน</th>
<th class="th-main" rowspan="2" style="width:130px; vertical-align:middle;">รวมเบิกจ่าย<br>ทั้งสิ้น (บาท)</th>
</tr>
<tr>
<th class="th-sub" colspan="2">งวดที่ 1</th>
<th class="th-sub" colspan="2">งวดที่ 2</th>
<th class="th-sub" colspan="2">งวดสุดท้าย</th>
</tr>
<tr>
<th class="th-col" style="width:120px">จำนวนเงิน (บาท)</th>
<th class="th-col" style="width:130px">ว/ด/ป</th>
<th class="th-col" style="width:120px">จำนวนเงิน (บาท)</th>
<th class="th-col" style="width:130px">ว/ด/ป</th>
<th class="th-col" style="width:120px">จำนวนเงิน (บาท)</th>
<th class="th-col" style="width:130px">ว/ด/ป</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="number" id="amt1" placeholder="0.00" oninput="updateTotal()"></td>
<td><input type="date" id="date1"></td>
<td><input type="number" id="amt2" placeholder="0.00" oninput="updateTotal()"></td>
<td><input type="date" id="date2"></td>
<td><input type="number" id="amtLast" placeholder="0.00" oninput="updateTotal()"></td>
<td><input type="date" id="dateLast"></td>
<td class="td-total" id="total-display">0.00</td>
</tr>
</tbody>
</table>
</div>
<div class="total-bar">
<span class="label">💰 รวมเบิกจ่ายทั้งสิ้น</span>
<span class="amount" id="total-bar-amount">0.00 บาท</span>
</div>
</div>
<div class="dialog-actions">
<button class="btn btn-cancel" onclick="closeDialog()">ยกเลิก</button>
<button class="btn btn-save" onclick="save()">💾 บันทึก</button>
</div>
</div>
</div>
<!-- ─── AFTER SAVE PREVIEW ─── -->
<div class="section-label" style="margin-top:32px;">✅ หลังบันทึก — ข้อมูลที่กรอกจะแสดงใน tooltip หรือ badge</div>
<div class="list-preview">
<table>
<thead>
<tr>
<th>ชื่อโครงการ</th>
<th>งวด 1</th>
<th>ว/ด/ป</th>
<th>งวด 2</th>
<th>ว/ด/ป</th>
<th>งวดสุดท้าย</th>
<th>ว/ด/ป</th>
<th style="background:#e65100;">รวมเบิกจ่าย</th>
</tr>
</thead>
<tbody>
<tr>
<td>โครงการพัฒนาคุณภาพการศึกษาฯ</td>
<td style="text-align:right">66,500</td>
<td style="text-align:center">15/11/2567</td>
<td style="text-align:right">19,000</td>
<td style="text-align:center">20/01/2568</td>
<td style="text-align:right">9,500</td>
<td style="text-align:center">30/03/2568</td>
<td style="text-align:right; background:#fff3e0; font-weight:700; color:#e65100;">95,000</td>
</tr>
</tbody>
</table>
</div>
<script>
function fmt(n) {
if (!n && n !== 0) return '—';
return Number(n).toLocaleString('th-TH', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}
function openDialog(name, a1, d1, a2, d2, aL, dL) {
document.getElementById('project-name').textContent = name;
document.getElementById('amt1').value = a1 || '';
document.getElementById('date1').value = d1 || '';
document.getElementById('amt2').value = a2 || '';
document.getElementById('date2').value = d2 || '';
document.getElementById('amtLast').value = aL || '';
document.getElementById('dateLast').value = dL || '';
updateTotal();
document.getElementById('overlay').classList.remove('hidden');
}
function closeDialog() {
document.getElementById('overlay').classList.add('hidden');
}
function closeOnOverlay(e) {
if (e.target === document.getElementById('overlay')) closeDialog();
}
function updateTotal() {
const a1 = parseFloat(document.getElementById('amt1').value) || 0;
const a2 = parseFloat(document.getElementById('amt2').value) || 0;
const aL = parseFloat(document.getElementById('amtLast').value) || 0;
const total = a1 + a2 + aL;
document.getElementById('total-display').textContent = fmt(total);
document.getElementById('total-bar-amount').textContent = fmt(total) + ' บาท';
}
function save() {
alert('✅ บันทึกสำเร็จ!\n\nในระบบจริงจะเรียก PUT /api/request_budget/change_project_research_detail/{uid}\nพร้อม field: disbursement_1_amount, disbursement_1_date, disbursement_2_amount, disbursement_2_date, disbursement_last_amount, disbursement_last_date');
closeDialog();
}
</script>
</body>
</html>