Files
vd_test_fixture/edc-web/app/templates/users.html
wangfq 322563dab0 feat: 用户登录/管理 + 操作日志模块
- tb_user 用户表、tb_log 日志表
- Flask-Login 认证(login/logout/权限装饰器)
- 用户管理页(admin 专有):增删改查、改密、角色设置
- 操作日志页:分页查询、按用户/类型筛选
- 测试操作区指令自动记录日志
- 所有页面加 @login_required 保护
- 默认管理员 admin/admin123(首次启动自动创建)
2026-05-28 13:58:19 +08:00

113 lines
4.1 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block title %}用户管理 - EDC 工装管理系统{% endblock %}
{% block content %}
<h2>用户管理</h2>
<div style="margin-bottom:16px;">
<button onclick="showAddForm()" class="btn-search">新增用户</button>
<div id="add-form" style="display:none;margin-top:12px;background:#fff;padding:16px;border-radius:8px;">
<label>用户名:<input type="text" id="new-username" style="margin:0 8px;"></label>
<label>密码:<input type="password" id="new-password" style="margin:0 8px;"></label>
<label>角色:
<select id="new-role" style="margin:0 8px;">
<option value="operator">operator</option>
<option value="admin">admin</option>
</select>
</label>
<button onclick="addUser()" class="btn-search">确认</button>
<button onclick="document.getElementById('add-form').style.display='none'" class="btn-export">取消</button>
</div>
</div>
<table>
<thead>
<tr>
<th>ID</th>
<th>用户名</th>
<th>角色</th>
<th>状态</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody id="user-tbody"></tbody>
</table>
{% endblock %}
{% block scripts %}
<script>
async function loadUsers() {
const resp = await fetch("/users/api/users");
const users = await resp.json();
const tbody = document.getElementById("user-tbody");
tbody.innerHTML = users.map(u => `
<tr>
<td>${u.id}</td>
<td>${u.username}</td>
<td>${u.role}</td>
<td>${u.is_active ? '启用' : '禁用'}</td>
<td>${u.create_time || '-'}</td>
<td>
<select onchange="updateUser(${u.id}, this, 'role')" data-field="role">
<option value="operator" ${u.role==='operator'?'selected':''}>operator</option>
<option value="admin" ${u.role==='admin'?'selected':''}>admin</option>
</select>
<select onchange="updateUser(${u.id}, this, 'is_active')" data-field="is_active">
<option value="1" ${u.is_active?'selected':''}>启用</option>
<option value="0" ${!u.is_active?'selected':''}>禁用</option>
</select>
<button onclick="resetPwd(${u.id})" class="btn-search" style="font-size:11px;">改密</button>
</td>
</tr>
`).join("");
}
function showAddForm() {
document.getElementById("add-form").style.display = "block";
document.getElementById("new-username").value = "";
document.getElementById("new-password").value = "";
}
async function addUser() {
const username = document.getElementById("new-username").value.trim();
const password = document.getElementById("new-password").value;
const role = document.getElementById("new-role").value;
if (!username || !password) { alert("用户名和密码不能为空"); return; }
const resp = await fetch("/users/api/users", {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({username, password, role}),
});
const data = await resp.json();
if (data.ok) { document.getElementById("add-form").style.display = "none"; loadUsers(); }
else { alert(data.error || "创建失败"); }
}
async function updateUser(id, el, field) {
const value = el.value;
const body = {};
body[field] = field === 'is_active' ? parseInt(value) : value;
await fetch(`/users/api/users/${id}`, {
method: "PUT",
headers: {"Content-Type": "application/json"},
body: JSON.stringify(body),
});
loadUsers();
}
async function resetPwd(id) {
const pwd = prompt("输入新密码至少6位");
if (!pwd || pwd.length < 6) { alert("密码至少6位"); return; }
await fetch(`/users/api/users/${id}`, {
method: "PUT",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({password: pwd}),
});
alert("密码已更新");
}
loadUsers();
</script>
{% endblock %}