plokmii commited on
Commit
d1f4cf7
·
verified ·
1 Parent(s): 8ea4c48

Upload templates/admin.html with huggingface_hub

Browse files
Files changed (1) hide show
  1. templates/admin.html +126 -0
templates/admin.html ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="zh-TW">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>後台管理</title>
7
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
8
+ </head>
9
+ <body>
10
+ <div class="container py-4" style="max-width: 1000px;">
11
+ <div class="d-flex justify-content-between align-items-center mb-3">
12
+ <h2 class="mb-0">後台管理</h2>
13
+ <div>
14
+ <a href="/" class="btn btn-dark btn-sm me-1">首頁</a>
15
+ <a href="/logout" class="btn btn-outline-secondary btn-sm">登出</a>
16
+ </div>
17
+ </div>
18
+
19
+ <h5>使用者管理</h5>
20
+ <table class="table table-bordered bg-white" style="font-size:.9rem;">
21
+ <thead class="table-light">
22
+ <tr>
23
+ <th>ID</th>
24
+ <th>姓名</th>
25
+ <th>Email</th>
26
+ <th>帳號</th>
27
+ <th>密碼</th>
28
+ <th>權限</th>
29
+ <th>註冊時間</th>
30
+ <th></th>
31
+ </tr>
32
+ </thead>
33
+ <tbody>
34
+ {% for u in users %}
35
+ <tr id="user-{{ u.id }}">
36
+ <td>{{ u.id }}</td>
37
+ <td id="name-{{ u.id }}">{{ u.display_name or '' }}</td>
38
+ <td id="email-{{ u.id }}">{{ u.username }}</td>
39
+ <td>{{ u.username }}</td>
40
+ <td>{{ u.password_plain or '***' }}</td>
41
+ <td>
42
+ <select class="form-select form-select-sm" style="width:120px;" id="role-{{ u.id }}">
43
+ <option value="user" {{ 'selected' if u.role == 'user' else '' }}>一般使用者</option>
44
+ <option value="admin" {{ 'selected' if u.role == 'admin' else '' }}>管理員</option>
45
+ </select>
46
+ </td>
47
+ <td>{{ u.created_at or '-' }}</td>
48
+ <td class="text-nowrap">
49
+ <button class="btn btn-sm btn-outline-primary me-1" onclick="editUser({{ u.id }})">Edit</button>
50
+ {% if u.username != username %}
51
+ <button class="btn btn-sm btn-outline-danger" onclick="deleteUser({{ u.id }}, '{{ u.username }}')">Del</button>
52
+ {% endif %}
53
+ </td>
54
+ </tr>
55
+ {% endfor %}
56
+ </tbody>
57
+ </table>
58
+ </div>
59
+
60
+ <!-- Edit Modal -->
61
+ <div class="modal fade" id="editModal" tabindex="-1">
62
+ <div class="modal-dialog modal-sm">
63
+ <div class="modal-content">
64
+ <div class="modal-header">
65
+ <h6 class="modal-title">編輯使用者</h6>
66
+ <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
67
+ </div>
68
+ <div class="modal-body">
69
+ <input type="hidden" id="editId">
70
+ <div class="mb-2">
71
+ <label class="form-label small">姓名</label>
72
+ <input type="text" class="form-control form-control-sm" id="editName">
73
+ </div>
74
+ <div class="mb-2">
75
+ <label class="form-label small">Email / 帳號</label>
76
+ <input type="text" class="form-control form-control-sm" id="editEmail">
77
+ </div>
78
+ <div class="mb-2">
79
+ <label class="form-label small">新密碼(空白=不修改)</label>
80
+ <input type="text" class="form-control form-control-sm" id="editPassword" placeholder="不修改請留空">
81
+ </div>
82
+ </div>
83
+ <div class="modal-footer">
84
+ <button type="button" class="btn btn-sm btn-secondary" data-bs-dismiss="modal">取消</button>
85
+ <button type="button" class="btn btn-sm btn-primary" onclick="saveUser()">儲存</button>
86
+ </div>
87
+ </div>
88
+ </div>
89
+ </div>
90
+
91
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
92
+ <script>
93
+ function deleteUser(id, name) {
94
+ if (!confirm('確定刪除帳號 ' + name + ' ?')) return;
95
+ fetch('/admin/delete_user/' + id, { method: 'POST' })
96
+ .then(r => r.json())
97
+ .then(d => { if (d.ok) document.getElementById('user-' + id).remove(); else alert('刪除失敗'); });
98
+ }
99
+
100
+ function editUser(id) {
101
+ document.getElementById('editId').value = id;
102
+ document.getElementById('editName').value = document.getElementById('name-' + id).textContent.trim();
103
+ document.getElementById('editEmail').value = document.getElementById('email-' + id).textContent.trim();
104
+ document.getElementById('editPassword').value = '';
105
+ new bootstrap.Modal(document.getElementById('editModal')).show();
106
+ }
107
+
108
+ function saveUser() {
109
+ const id = document.getElementById('editId').value;
110
+ const role = document.getElementById('role-' + id)?.value || 'user';
111
+ fetch('/admin/update_user/' + id, {
112
+ method: 'POST',
113
+ headers: {'Content-Type': 'application/json'},
114
+ body: JSON.stringify({
115
+ display_name: document.getElementById('editName').value.trim(),
116
+ username: document.getElementById('editEmail').value.trim(),
117
+ password: document.getElementById('editPassword').value,
118
+ role: role
119
+ })
120
+ })
121
+ .then(r => r.json())
122
+ .then(d => { if (d.ok) location.reload(); else alert('更新失敗: ' + (d.error || '')); });
123
+ }
124
+ </script>
125
+ </body>
126
+ </html>