Files
resume/templates/admin/users.html
T

258 lines
12 KiB
HTML

<div class="bg-white rounded-xl shadow-sm border border-slate-200 p-6">
<div class="flex items-center justify-between mb-6">
<div>
<h3 class="font-semibold text-slate-800 flex items-center gap-2">
<i class="fas fa-users text-purple-500"></i> 人员列表
</h3>
<p class="text-sm text-slate-500 mt-1">管理平台用户</p>
</div>
<button onclick="openAddUserModal()" class="btn btn-primary">
<i class="fas fa-plus"></i> 添加用户
</button>
</div>
<div class="mb-6 flex items-center gap-4">
<div class="relative flex-1 max-w-md">
<div class="absolute left-3 top-1/2 transform -translate-y-1/2 text-slate-400">
<i class="fas fa-search"></i>
</div>
<input type="text" id="searchInput" placeholder="搜索姓名或用户名..." class="w-full pl-10 pr-4 py-2.5 border-2 border-slate-200 rounded-xl focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition-all bg-white">
</div>
<button onclick="filterUsers()" class="btn btn-secondary">
<i class="fas fa-search"></i> 搜索
</button>
<button onclick="location.reload()" class="btn btn-secondary">
<i class="fas fa-redo"></i> 重置
</button>
</div>
<div class="overflow-x-auto">
<table class="table">
<thead>
<tr class="bg-slate-50 border-b border-slate-200">
<th class="text-left px-6 py-4 text-sm font-semibold text-slate-600">姓名</th>
<th class="text-left px-6 py-4 text-sm font-semibold text-slate-600">用户名</th>
<th class="text-left px-6 py-4 text-sm font-semibold text-slate-600">邮箱</th>
<th class="text-left px-6 py-4 text-sm font-semibold text-slate-600">手机号</th>
<th class="text-left px-6 py-4 text-sm font-semibold text-slate-600">创建时间</th>
<th class="text-left px-6 py-4 text-sm font-semibold text-slate-600 actions-col">操作</th>
</tr>
</thead>
<tbody>
{{ range .Users }}
<tr class="border-b border-slate-100 hover:bg-slate-50 transition-colors">
<td class="px-6 py-4">
<span class="font-medium text-slate-800">{{.Name}}</span>
</td>
<td class="px-6 py-4 text-slate-600">{{.Username}}</td>
<td class="px-6 py-4 text-slate-600">{{.Email}}</td>
<td class="px-6 py-4 text-slate-600">{{.Phone}}</td>
<td class="px-6 py-4 text-slate-500 text-sm">{{.CreatedAt}}</td>
<td class="px-6 py-4 actions-col">
<div class="btn-group">
<a href="{{$.AdminPath}}/user/{{.ID}}/resume" class="btn btn-primary btn-xs" title="简历">
<i class="fas fa-file-alt"></i> 简历
</a>
<a href="{{$.AdminPath}}/user/{{.ID}}/portfolio" class="btn btn-info btn-xs" title="作品集">
<i class="fas fa-folder-open"></i> 作品集
</a>
<a href="{{$.AdminPath}}/user/{{.ID}}/quiz" class="btn btn-purple btn-xs" title="面试题">
<i class="fas fa-question-circle"></i> 答题
</a>
<button onclick="editUser('{{.ID}}')" class="btn btn-warning btn-xs" title="编辑">
<i class="fas fa-edit"></i> 编辑
</button>
<button onclick="deleteUser('{{.ID}}')" class="btn btn-danger btn-xs" title="删除">
<i class="fas fa-trash"></i> 删除
</button>
</div>
</td>
</tr>
{{ else }}
<tr>
<td colspan="6" class="px-6 py-12 text-center text-slate-500">
<div class="w-16 h-16 mx-auto mb-4 rounded-full bg-slate-100 flex items-center justify-center">
<i class="fas fa-users text-slate-400 text-2xl"></i>
</div>
<p>暂无用户数据</p>
</td>
</tr>
{{ end }}
</tbody>
</table>
</div>
{{ if gt .TotalPages 1 }}
<div class="border-t border-slate-200 px-6 py-4 bg-slate-50 flex items-center justify-between">
<div class="text-sm text-slate-500">共 {{ .Total }} 条记录,第 {{ .Page }} / {{ .TotalPages }} 页</div>
<div class="flex items-center gap-2">
<a href="?page=1" class="btn btn-sm btn-slate {{ if eq .Page 1 }}opacity-50 cursor-not-allowed{{ end }}" {{ if eq .Page 1 }}onclick="return false"{{ end }}>
<i class="fas fa-chevron-left"></i>
<i class="fas fa-chevron-left"></i>
</a>
<a href="?page={{ if eq .Page 1 }}1{{ else }}{{ subtract .Page 1 }}{{ end }}" class="btn btn-sm btn-slate {{ if eq .Page 1 }}opacity-50 cursor-not-allowed{{ end }}" {{ if eq .Page 1 }}onclick="return false"{{ end }}>
<i class="fas fa-chevron-left"></i>
</a>
{{ range $i := to 1 $.TotalPages }}
{{ if or (eq $i 1) (eq $i $.TotalPages) (and (ge $i (subtract $.Page 2)) (le $i (add $.Page 2))) }}
<a href="?page={{ $i }}" class="btn btn-sm {{ if eq $i $.Page }}btn-primary{{ else }}btn-slate{{ end }}">{{ $i }}</a>
{{ else if and (eq $i 2) (gt (subtract $.Page 3) 1) }}
<span class="text-slate-400 px-2">...</span>
{{ else if and (eq $i (subtract $.TotalPages 1)) (lt (add $.Page 3) $.TotalPages) }}
<span class="text-slate-400 px-2">...</span>
{{ end }}
{{ end }}
<a href="?page={{ if eq .Page .TotalPages }}{{ .TotalPages }}{{ else }}{{ add .Page 1 }}{{ end }}" class="btn btn-sm btn-slate {{ if eq .Page .TotalPages }}opacity-50 cursor-not-allowed{{ end }}" {{ if eq .Page .TotalPages }}onclick="return false"{{ end }}>
<i class="fas fa-chevron-right"></i>
</a>
<a href="?page={{ .TotalPages }}" class="btn btn-sm btn-slate {{ if eq .Page .TotalPages }}opacity-50 cursor-not-allowed{{ end }}" {{ if eq .Page .TotalPages }}onclick="return false"{{ end }}>
<i class="fas fa-chevron-right"></i>
<i class="fas fa-chevron-right"></i>
</a>
</div>
</div>
{{ end }}
</div>
<div class="modal" id="userModal">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title" id="userModalTitle">
<i class="fas fa-user-plus text-blue-500"></i> 添加用户
</h3>
<div class="modal-close" onclick="closeUserModal()">
<i class="fas fa-times"></i>
</div>
</div>
<div class="modal-body">
<form id="userForm" onsubmit="saveUser(event)">
<input type="hidden" id="userId">
<div class="space-y-4">
<div>
<label class="form-label">姓名</label>
<input type="text" id="userName" class="form-input" required>
</div>
<div>
<label class="form-label">用户名</label>
<input type="text" id="userUsername" class="form-input" required>
</div>
<div>
<label class="form-label">邮箱</label>
<input type="email" id="userEmail" class="form-input" required>
</div>
<div>
<label class="form-label">手机号</label>
<input type="tel" id="userPhone" class="form-input">
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button onclick="closeUserModal()" class="btn btn-secondary">
<i class="fas fa-times"></i> 取消
</button>
<button type="submit" form="userForm" class="btn btn-primary">
<i class="fas fa-save"></i> 保存
</button>
</div>
</div>
</div>
<script>
function filterUsers() {
const searchTerm = document.getElementById('searchInput').value.toLowerCase();
const rows = document.querySelectorAll('table tbody tr');
rows.forEach(row => {
const name = row.querySelector('td:nth-child(1)')?.textContent.toLowerCase() || '';
const username = row.querySelector('td:nth-child(2)')?.textContent.toLowerCase() || '';
const email = row.querySelector('td:nth-child(3)')?.textContent.toLowerCase() || '';
const phone = row.querySelector('td:nth-child(4)')?.textContent.toLowerCase() || '';
if (name.includes(searchTerm) || username.includes(searchTerm) || email.includes(searchTerm) || phone.includes(searchTerm)) {
row.style.display = '';
} else {
row.style.display = 'none';
}
});
}
function openAddUserModal() {
document.getElementById('userModalTitle').innerHTML = '<i class="fas fa-user-plus text-blue-500"></i> 添加用户';
document.getElementById('userId').value = '';
document.getElementById('userName').value = '';
document.getElementById('userUsername').value = '';
document.getElementById('userEmail').value = '';
document.getElementById('userPhone').value = '';
document.getElementById('userModal').classList.add('active');
}
function closeUserModal() {
document.getElementById('userModal').classList.remove('active');
}
function editUser(id) {
fetch('/dashboard/api/user/' + id)
.then(response => response.json())
.then(res => {
const user = res.data || res;
document.getElementById('userModalTitle').innerHTML = '<i class="fas fa-user-edit text-yellow-500"></i> 编辑用户';
document.getElementById('userId').value = user.id || '';
document.getElementById('userName').value = user.name || '';
document.getElementById('userUsername').value = user.username || '';
document.getElementById('userEmail').value = user.email || '';
document.getElementById('userPhone').value = user.phone || '';
document.getElementById('userModal').classList.add('active');
})
.catch(error => {
console.error('Error:', error);
showCustomAlert('error', '错误', '获取用户信息失败');
});
}
function deleteUser(id) {
showCustomConfirm('确认删除', '确定要删除该用户吗?', function(confirmed) {
if (!confirmed) return;
fetch('/dashboard/api/user/' + id, { method: 'DELETE' })
.then(response => response.json())
.then(result => {
if (result.success) {
location.reload();
} else {
showCustomAlert('error', '错误', '删除失败:' + (result.message || '未知错误'));
}
})
.catch(error => {
console.error('Error:', error);
showCustomAlert('error', '错误', '删除失败');
});
});
}
function saveUser(event) {
event.preventDefault();
const id = document.getElementById('userId').value;
const data = {
name: document.getElementById('userName').value,
username: document.getElementById('userUsername').value,
email: document.getElementById('userEmail').value,
phone: document.getElementById('userPhone').value
};
const url = id ? '/dashboard/api/user/' + id : '/dashboard/api/user';
const method = id ? 'PUT' : 'POST';
fetch(url, {
method: method,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
})
.then(response => response.json())
.then(result => {
if (result.success) {
showCustomAlert('success', '成功', '保存成功');
closeUserModal();
setTimeout(() => location.reload(), 1500);
} else {
showCustomAlert('error', '错误', '保存失败:' + (result.message || '未知错误'));
}
})
.catch(error => {
console.error('Error:', error);
showCustomAlert('error', '错误', '保存失败');
});
}
</script>