新增後台居民開通
This commit is contained in:
parent
dec5b54c50
commit
14af35f674
@ -1,41 +1,188 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-Hant">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>居民開通</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #f0f0f0;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.activation-container {
|
||||
background-color: white;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #666;
|
||||
}
|
||||
</style>
|
||||
<meta charset="UTF-8">
|
||||
<title>未開通居民列表</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<!-- Bootstrap -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<style>
|
||||
#qrcodeModal .modal-body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="activation-container">
|
||||
<h1>居民開通</h1>
|
||||
<p>這裡是居民開通的頁面內容。</p>
|
||||
</div>
|
||||
</body>
|
||||
<div class="container mt-4">
|
||||
<h2 class="mb-4">未開通居民列表</h2>
|
||||
|
||||
<!-- 搜尋列 -->
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-3">
|
||||
<input type="text" id="searchName" class="form-control" placeholder="搜尋姓名">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<input type="text" id="searchEmail" class="form-control" placeholder="搜尋 Email">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<button class="btn btn-primary w-100" onclick="search()">搜尋</button>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<button class="btn btn-danger w-100" onclick="deleteSelected()">刪除勾選</button>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<button class="btn btn-secondary w-100" onclick="scanResident()">掃描住戶</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 表格 -->
|
||||
<table class="table table-striped table-bordered">
|
||||
<thead class="table-dark">
|
||||
<tr>
|
||||
<th><input type="checkbox" id="selectAll" onclick="toggleAll(this)"></th>
|
||||
<th>編號</th>
|
||||
<th>姓名</th>
|
||||
<th>Email</th>
|
||||
<th>聯絡電話</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="residentTable">
|
||||
<!-- 動態資料列 -->
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- 分頁 -->
|
||||
<nav>
|
||||
<ul class="pagination justify-content-center" id="pagination"></ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<!-- Modal 彈出 QR Code -->
|
||||
<div class="modal fade" id="qrcodeModal" tabindex="-1" aria-labelledby="qrcodeModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-sm modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">開通 QR Code</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="關閉"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="qrcode"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bootstrap + QRCode.js -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/qrcodejs/qrcode.min.js"></script>
|
||||
|
||||
<script>
|
||||
const pageSize = 5;
|
||||
let currentPage = 1;
|
||||
let residents = [
|
||||
{ id: 1, name: "王小明", email: "xiaoming@example.com", phone: "0912-345-678" },
|
||||
{ id: 2, name: "林美麗", email: "meili@example.com", phone: "0987-654-321" },
|
||||
{ id: 3, name: "張大雄", email: "daxiong@example.com", phone: "0912-333-444" },
|
||||
{ id: 4, name: "李小龍", email: "dragon@example.com", phone: "0900-111-222" },
|
||||
{ id: 5, name: "周杰倫", email: "jay@example.com", phone: "0988-888-888" },
|
||||
{ id: 6, name: "蔡依林", email: "jolin@example.com", phone: "0977-777-777"},
|
||||
{ id: 7, name: "林志玲", email: "lin@example.com", phone: "0966-666-666" },
|
||||
{ id: 8, name: "王力宏", email: "leehom@example.com", phone: "0955-555-555" }
|
||||
];
|
||||
|
||||
function renderTable(data) {
|
||||
const tbody = document.getElementById("residentTable");
|
||||
tbody.innerHTML = "";
|
||||
|
||||
const start = (currentPage - 1) * pageSize;
|
||||
const pageData = data.slice(start, start + pageSize);
|
||||
|
||||
pageData.forEach(r => {
|
||||
const row = document.createElement("tr");
|
||||
row.innerHTML = `
|
||||
<td><input type="checkbox" class="row-checkbox" data-id="${r.id}"></td>
|
||||
<td>${r.id}</td>
|
||||
<td>${r.name}</td>
|
||||
<td>${r.email}</td>
|
||||
<td>${r.phone}</td>
|
||||
<td><button class="btn btn-success btn-sm" onclick="showQRCode('https://yourdomain.com/activate?id=${r.id}')">開通</button></td>
|
||||
`;
|
||||
tbody.appendChild(row);
|
||||
});
|
||||
|
||||
renderPagination(data.length);
|
||||
}
|
||||
|
||||
function renderPagination(totalItems) {
|
||||
const totalPages = Math.ceil(totalItems / pageSize);
|
||||
const pagination = document.getElementById("pagination");
|
||||
pagination.innerHTML = "";
|
||||
|
||||
for (let i = 1; i <= totalPages; i++) {
|
||||
const li = document.createElement("li");
|
||||
li.className = "page-item" + (i === currentPage ? " active" : "");
|
||||
li.innerHTML = `<a class="page-link" href="#" onclick="goToPage(${i})">${i}</a>`;
|
||||
pagination.appendChild(li);
|
||||
}
|
||||
}
|
||||
|
||||
function goToPage(page) {
|
||||
currentPage = page;
|
||||
search(); // 重新篩選並渲染
|
||||
}
|
||||
|
||||
function search() {
|
||||
const nameInput = document.getElementById("searchName").value.toLowerCase();
|
||||
const emailInput = document.getElementById("searchEmail").value.toLowerCase();
|
||||
|
||||
const filtered = residents.filter(r =>
|
||||
r.name.toLowerCase().includes(nameInput) &&
|
||||
r.email.toLowerCase().includes(emailInput)
|
||||
);
|
||||
|
||||
renderTable(filtered);
|
||||
}
|
||||
|
||||
function toggleAll(source) {
|
||||
const checkboxes = document.querySelectorAll(".row-checkbox");
|
||||
checkboxes.forEach(cb => cb.checked = source.checked);
|
||||
}
|
||||
|
||||
function deleteSelected() {
|
||||
if (!confirm("確定要刪除勾選的資料嗎?")) return;
|
||||
|
||||
const selected = document.querySelectorAll(".row-checkbox:checked");
|
||||
const idsToDelete = Array.from(selected).map(cb => parseInt(cb.dataset.id));
|
||||
|
||||
residents = residents.filter(r => !idsToDelete.includes(r.id));
|
||||
currentPage = 1;
|
||||
search();
|
||||
document.getElementById("selectAll").checked = false;
|
||||
}
|
||||
|
||||
function showQRCode(url) {
|
||||
const qrContainer = document.getElementById("qrcode");
|
||||
qrContainer.innerHTML = "";
|
||||
new QRCode(qrContainer, {
|
||||
text: url,
|
||||
width: 200,
|
||||
height: 200
|
||||
});
|
||||
|
||||
const modal = new bootstrap.Modal(document.getElementById("qrcodeModal"));
|
||||
modal.show();
|
||||
}
|
||||
|
||||
function scanResident() {
|
||||
alert("這裡可以接掃描裝置或開啟相機功能");
|
||||
// 若你想改成開 QRCode 掃描,可在這裡整合 JS 掃描工具
|
||||
}
|
||||
|
||||
// 初次載入
|
||||
search();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -5,12 +5,117 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>功能列</title>
|
||||
<style>
|
||||
html, body { height: 100%; margin: 0; padding: 0; overflow-x: hidden; overflow-y: auto; } /* Allow vertical scroll in sidebar */
|
||||
.sidebar { /* height: 100%; removed as body handles height */ }
|
||||
.sidebar img { display: block; margin: 20px auto; width: 60px; height: 60px; border-radius: 50%; }
|
||||
.sidebar ul { list-style: none; padding-left: 0; margin-top:0; }
|
||||
.sidebar ul li { padding: 12px 20px; color: #333; cursor: pointer; }
|
||||
.sidebar ul li:hover, .sidebar ul li.active { background-color: #e6f0f8; color: #007bff; }
|
||||
html, body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #f8f9fa;
|
||||
border-right: 1px solid #ddd;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.sidebar img {
|
||||
display: block;
|
||||
margin: 20px auto;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.sidebar ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.sidebar ul li {
|
||||
color: #333;
|
||||
cursor: pointer;
|
||||
padding: 12px 20px;
|
||||
transition: background 0.2s ease;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.sidebar ul li:hover,
|
||||
.sidebar ul li.active {
|
||||
background-color: #e6f0f8;
|
||||
color: #007bff;
|
||||
}
|
||||
|
||||
.has-submenu > .submenu-toggle {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.has-submenu ul {
|
||||
list-style: none;
|
||||
padding-left: 15px;
|
||||
margin: 0;
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
transition: max-height 0.3s ease, padding 0.3s ease;
|
||||
}
|
||||
|
||||
.has-submenu.open ul {
|
||||
padding-top: 5px;
|
||||
max-height: 200px;
|
||||
}
|
||||
|
||||
.has-submenu ul li {
|
||||
padding: 10px 20px;
|
||||
font-size: 16px;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
.has-submenu ul li:hover {
|
||||
background-color: #deeaf6;
|
||||
}
|
||||
|
||||
.submenu-arrow {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.badge {
|
||||
display: inline-block;
|
||||
min-width: 20px;
|
||||
padding: 2px 6px;
|
||||
margin-left: 8px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
background-color: red;
|
||||
border-radius: 10px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.sidebar ul li .li-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.sidebar ul li .li-content span {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@ -18,7 +123,23 @@
|
||||
<img src="https://cdn-icons-png.freepik.com/512/4873/4873262.png" alt="Logo" />
|
||||
<ul>
|
||||
<li class="active" onclick="requestNavigation('dashboard.html', this)">首頁</li>
|
||||
<li onclick="requestNavigation('Activation.html', this)">居民開通</li>
|
||||
|
||||
<li class="has-submenu">
|
||||
<div class="submenu-toggle" onclick="toggleSubmenu(this)">
|
||||
<span>住戶居民</span>
|
||||
<span class="submenu-arrow">▼</span>
|
||||
</div>
|
||||
<ul>
|
||||
<li onclick="requestNavigation('Activation.html', this)">
|
||||
<div class="li-content">
|
||||
<span>未開通居民</span>
|
||||
<span class="badge">8</span>
|
||||
</div>
|
||||
</li>
|
||||
<li onclick="requestNavigation('Activation.html', this)">居民列表</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li onclick="requestNavigation('some_page1.html', this)">出入管理</li>
|
||||
<li onclick="requestNavigation('some_page2.html', this)">緊急通報</li>
|
||||
<li onclick="requestNavigation('some_page3.html', this)">訊息通知</li>
|
||||
@ -26,26 +147,30 @@
|
||||
<li onclick="requestNavigation('some_page5.html', this)">佈告欄</li>
|
||||
<li onclick="requestNavigation('some_page6.html', this)">報表匯出</li>
|
||||
<li onclick="requestNavigation('some_page7.html', this)">設定</li>
|
||||
</ul>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function requestNavigation(url, clickedElement) {
|
||||
console.log('Sidebar: 發送導航請求 ->', url);
|
||||
// 向父視窗 (main.html) 發送訊息
|
||||
// 對於 file:/// 環境, targetOrigin 必須是 '*'
|
||||
// 在正式伺服器環境,應指定父視窗的確切來源 (e.g., 'http://yourdomain.com')
|
||||
parent.postMessage({ type: 'navigate', url: url }, '*');
|
||||
|
||||
// 更新側邊欄本地的 active class
|
||||
const listItems = document.querySelectorAll('.sidebar ul li');
|
||||
listItems.forEach(item => {
|
||||
item.classList.remove('active');
|
||||
});
|
||||
if (clickedElement) {
|
||||
const listItems = document.querySelectorAll('.sidebar ul > li');
|
||||
listItems.forEach(item => item.classList.remove('active'));
|
||||
if (!clickedElement.closest('.has-submenu')) {
|
||||
clickedElement.classList.add('active');
|
||||
}
|
||||
}
|
||||
|
||||
function toggleSubmenu(toggleElement) {
|
||||
const parentLi = toggleElement.closest('.has-submenu');
|
||||
parentLi.classList.toggle('open');
|
||||
|
||||
const arrow = toggleElement.querySelector('.submenu-arrow');
|
||||
if (arrow) {
|
||||
arrow.textContent = parentLi.classList.contains('open') ? '▲' : '▼';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
x
Reference in New Issue
Block a user