2025-03-10 08:35:19 +08:00

375 lines
16 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 %}用户管理{% endblock %}
{% block content %}
<div class="container">
<!-- 标题和搜索框 -->
<div class="row mb-3">
<div class="col-md-6">
<h1 class="my-4">用户列表</h1>
</div>
<div class="col-md-6">
<div class="input-group mt-4">
<select class="form-select" id="queryMode">
<option value="uid">UID</option>
<option value="phone_number">手机号</option>
<option value="username">用户名</option>
<option value="email">邮箱</option>
</select>
<input type="text" class="form-control" id="queryValue" placeholder="搜索用户...">
<button class="btn btn-primary" type="button" onclick="performSearch()">搜索</button>
</div>
</div>
</div>
<p>当前用户总数:{{ total_users }}</p>
<table class="table table-striped table-bordered">
<thead class="thead-light">
<tr>
<th>用户ID</th>
<th>用户名</th>
<th>积分</th>
<th>性别</th>
<th>手机号</th>
<th>邮箱</th>
<th>用户类型</th>
<th>创建时间</th>
<th>更新时间</th>
<th>操作</th>
</tr>
</thead>
<tbody id="userTableBody">
{% for user in users %}
<tr>
<td>{{ user.user_id }}</td>
<td>{{ user.username }}</td>
<td>{{ user.points }}</td>
<td>{{ user.gender or '' }}</td>
<td>{{ user.phone_number or '' }}</td>
<td>{{ user.email or '' }}</td>
<td>{{ user.user_type }}</td>
<td>{{ user.created_at }}</td>
<td>{{ user.updated_at }}</td>
<td>
<button type="button" class="btn btn-info btn-sm"
onclick="openPointsModal('{{ user.user_id }}')">
调整积分
</button>
<!-- 更新按钮 -->
<button type="button" class="btn btn-primary btn-sm"
onclick="openUpdateModal('{{ user.user_id }}', '{{ user.username }}', '{{ user.email }}', '{{ user.phone_number or '' }}', '{{ user.gender or '' }}', '{{ user.user_type }}')">
更新
</button>
<!-- 重置密码按钮 -->
<button type="button" class="btn btn-warning btn-sm"
onclick="openResetPasswordModal('{{ user.user_id }}')">
重置密码
</button>
<button type="button" class="btn btn-success btn-sm"
onclick="openIssueCouponModal('{{ user.user_id }}')">
发放优惠券
</button>
<!-- 删除按钮 -->
<form action="{{ url_for('users.delete_user', page=page) }}" method="post" style="display:inline;">
<input type="hidden" name="uid" value="{{ user.user_id }}">
<button type="submit" class="btn btn-danger btn-sm" onclick="return confirm('确定删除该用户吗?');">
删除
</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<!-- 分页导航 -->
<nav aria-label="Page navigation">
<ul class="pagination">
{% if page > 1 %}
<li class="page-item">
<a class="page-link" href="{{ url_for('users.list_users', page=page - 1) }}">上一页</a>
</li>
{% else %}
<li class="page-item disabled">
<span class="page-link">上一页</span>
</li>
{% endif %}
{% for p in range(1, total_pages + 1) %}
<li class="page-item {% if p == page %}active{% endif %}">
<a class="page-link" href="{{ url_for('users.list_users', page=p) }}">{{ p }}</a>
</li>
{% endfor %}
{% if page < total_pages %}
<li class="page-item">
<a class="page-link" href="{{ url_for('users.list_users', page=page + 1) }}">下一页</a>
</li>
{% else %}
<li class="page-item disabled">
<span class="page-link">下一页</span>
</li>
{% endif %}
</ul>
</nav>
</div>
<!-- 更新用户模态框 -->
<div class="modal fade" id="updateUserModal" tabindex="-1" role="dialog"
aria-labelledby="updateUserModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<form action="{{ url_for('users.update_user', page=page) }}" method="post">
<div class="modal-header">
<h5 class="modal-title" id="updateUserModalLabel">更新用户信息</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<!-- uid, username, email, phone_number 保持原样 -->
<input type="hidden" id="update-uid" name="uid">
<div class="form-group">
<label for="update-username">用户名</label>
<input type="text" class="form-control" id="update-username" name="username">
</div>
<div class="form-group">
<label for="update-email">邮箱</label>
<input type="email" class="form-control" id="update-email" name="email">
</div>
<div class="form-group">
<label for="update-phone_number">手机号</label>
<input type="text" class="form-control" id="update-phone_number" name="phone_number">
</div>
<!-- 性别下拉male, female, other -->
<div class="form-group">
<label for="update-gender">性别</label>
<select class="form-control" id="update-gender" name="gender">
<option value="">请选择</option>
<option value="male">male</option>
<option value="female">female</option>
<option value="other">other</option>
</select>
</div>
<!-- 用户类型改为下拉选单player, admin -->
<div class="form-group">
<label for="update-user_type">用户类型</label>
<select class="form-control" id="update-user_type" name="user_type">
<option value="">请选择</option>
<option value="player">player</option>
<option value="admin">admin</option>
</select>
</div>
</div> <!-- end modal-body -->
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
<button type="submit" class="btn btn-primary">保存更改</button>
</div>
</form>
</div>
</div>
</div>
<!-- 重置密码模态框 -->
<div class="modal fade" id="resetPasswordModal" tabindex="-1" role="dialog"
aria-labelledby="resetPasswordModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<!-- 注意:此处提交的路由 'users.reset_password' 只是一个占位,目前没有实际的重置密码逻辑 -->
<form action="{{ url_for('users.reset_password', page=page) }}" method="post">
<div class="modal-header">
<h5 class="modal-title" id="resetPasswordModalLabel">重置密码</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<input type="hidden" id="reset-uid" name="uid">
<div class="form-group">
<label for="reset-password">新密码</label>
<input type="password" class="form-control" id="reset-password" name="password">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
<button type="submit" class="btn btn-primary">重置密码</button>
</div>
</form>
</div>
</div>
</div>
<!-- 添加积分调整模态框 -->
<div class="modal fade" id="pointsModal">
<div class="modal-dialog">
<div class="modal-content">
<form action="{{ url_for('users.adjust_points') }}" method="post">
<input type="hidden" name="uid" id="points-uid">
<div class="modal-body">
<div class="form-group">
<label>调整数值(正数为增加,负数为扣除)</label>
<input type="number" name="points" class="form-control" required>
</div>
<div class="form-group">
<label>调整原因</label>
<input type="text" name="reason" class="form-control" required value="管理员后台更改">
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">提交</button>
</div>
</form>
</div>
</div>
</div>
<div class="modal fade" id="issueCouponModal">
<div class="modal-dialog">
<div class="modal-content">
<form method="post" action="{{ url_for('users.issue_coupon') }}">
<input type="hidden" name="user_id" id="issue-user-id">
<div class="modal-header">
<h5 class="modal-title">发放优惠券</h5>
</div>
<div class="modal-body">
<div class="form-group">
<label>选择优惠券</label>
<select class="form-control" name="coupon_id" required>
<option value="">请选择优惠券</option>
{% for coupon in coupons %}
<option value="{{ coupon.coupon_id }}">{{ coupon.coupon_code }} - {{ coupon.discount_type }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
<button type="submit" class="btn btn-primary">发放</button>
</div>
</form>
</div>
</div>
</div>
<script>
function performSearch() {
const queryMode = document.getElementById("queryMode");
const queryValue = document.getElementById("queryValue").value.trim();
const tableBody = document.getElementById("userTableBody");
// 若搜索框为空,重新加载当前页面,等同于清空搜索
if (!queryValue) {
location.reload();
return;
}
fetch("/users/search", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
query_mode: queryMode.value,
query_value: queryValue
})
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.json();
})
.then(data => {
tableBody.innerHTML = "";
if (data.length === 0) {
tableBody.innerHTML =
`<tr><td colspan="9" class="text-center">未找到匹配的用户</td></tr>`;
return;
}
data.forEach(user => {
let row = `<tr>
<td>${user.user_id}</td>
<td>${user.username}</td>
<td>${user.points}</td>
<td>${user.gender || ''}</td>
<td>${user.phone_number || ''}</td>
<td>${user.email || ''}</td>
<td>${user.user_type}</td>
<td>${user.created_at}</td>
<td>${user.updated_at}</td>
<td>
<button type="button" class="btn btn-info btn-sm"
onclick="openPointsModal('${user.user_id}')">
调整积分
</button>
<button type="button" class="btn btn-primary btn-sm"
onclick="openUpdateModal('${user.user_id}', '${user.username}', '${user.email}', '${user.phone_number || ''}', '${user.gender || ''}', '${user.user_type}')">
更新
</button>
<button type="button" class="btn btn-warning btn-sm"
onclick="openResetPasswordModal('${user.user_id}')">
重置密码
</button>
<form action="{{ url_for('users.delete_user', page=page) }}" method="post" style="display:inline;">
<input type="hidden" name="uid" value="${user.user_id}">
<button type="submit" class="btn btn-danger btn-sm"
onclick="return confirm('确定删除该用户吗?');">
删除
</button>
</form>
</td>
</tr>`;
tableBody.innerHTML += row;
});
})
.catch(error => console.error("搜索用户失败:", error));
}
function openUpdateModal(uid, username, email, phone_number, gender, user_type) {
document.getElementById('update-uid').value = uid;
document.getElementById('update-username').value = username;
document.getElementById('update-email').value = email;
document.getElementById('update-phone_number').value = phone_number;
// 下拉选单初始化
// gender 可能是 "male", "female" 或 "other";若为空则使用 ""
let genderSelect = document.getElementById('update-gender');
genderSelect.value = gender || "";
// user_type 可能是 "player", "admin";若为空则使用 ""
let userTypeSelect = document.getElementById('update-user_type');
userTypeSelect.value = user_type || "";
$('#updateUserModal').modal('show');
}
function openResetPasswordModal(uid) {
document.getElementById('reset-uid').value = uid;
$('#resetPasswordModal').modal('show');
}
function openPointsModal(uid) {
document.getElementById('points-uid').value = uid;
$('#pointsModal').modal('show');
}
function openIssueCouponModal(userId) {
$('#issue-user-id').val(userId);
$('#issueCouponModal').modal('show');
}
// 监听优惠券选择变化
$('select[name="coupon_id"]').on('change', function() {
const selected = $(this).find('option:selected');
const quantity = selected.data('quantity') || 0;
$('#coupon-quantity-hint').text(`剩余库存: ${quantity}`);
});
</script>
{% endblock %}