XNSim/XNSimPortal/components/user-management.js

645 lines
22 KiB
JavaScript

class UserManagement extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.users = [];
this.currentUser = null;
}
connectedCallback() {
this.render();
this.fetchUsers();
}
async fetchUsers() {
try {
const response = await fetch('/api/all-users');
const data = await response.json();
if (data.success) {
this.users = data.users.filter(user => user.id !== 1);
this.render();
} else {
console.error('获取用户列表失败:', data.message);
}
} catch (error) {
console.error('获取用户列表出错:', error);
}
}
showError(message) {
this.shadowRoot.querySelector('.error-message').textContent = message;
this.shadowRoot.querySelector('.error-message').style.display = 'block';
}
async handleEditInfo(userId) {
try {
const response = await fetch(`/api/user-info/${userId}`);
const data = await response.json();
if (data.success) {
this.currentUser = data.user;
this.showEditModal();
} else {
alert('获取用户信息失败: ' + data.message);
}
} catch (error) {
console.error('获取用户信息出错:', error);
alert('获取用户信息失败');
}
}
showEditModal() {
this.shadowRoot.querySelector('.modal').style.display = 'flex';
this.populateForm();
}
hideEditModal() {
this.shadowRoot.querySelector('.modal').style.display = 'none';
this.currentUser = null;
}
populateForm() {
const form = this.shadowRoot.querySelector('.edit-form');
form.username.value = this.currentUser.username || '';
form.full_name.value = this.currentUser.full_name || '';
form.email.value = this.currentUser.email || '';
form.phone.value = this.currentUser.phone || '';
form.department.value = this.currentUser.department || '';
form.position.value = this.currentUser.position || '';
}
async handleSaveUserInfo() {
const form = this.shadowRoot.querySelector('.edit-form');
const userInfo = {
full_name: form.full_name.value,
email: form.email.value,
phone: form.phone.value,
department: form.department.value,
position: form.position.value
};
try {
const response = await fetch('/api/update-user-info', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
userId: this.currentUser.id,
userInfo: userInfo
})
});
const data = await response.json();
if (data.success) {
alert('用户信息更新成功');
this.hideEditModal();
this.fetchUsers(); // 刷新用户列表
} else {
alert('用户信息更新失败: ' + data.message);
}
} catch (error) {
console.error('更新用户信息出错:', error);
alert('更新用户信息失败');
}
}
handleChangeAccessLevel(userId) {
this.currentUser = { id: userId };
this.showAccessModal();
}
showAccessModal() {
this.shadowRoot.querySelector('.access-modal').style.display = 'flex';
}
hideAccessModal() {
this.shadowRoot.querySelector('.access-modal').style.display = 'none';
this.currentUser = null;
}
async handleSaveAccessLevel() {
const form = this.shadowRoot.querySelector('.access-form');
const accessLevel = parseInt(form.access_level.value);
try {
const response = await fetch('/api/update-access-level', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
userId: this.currentUser.id,
accessLevel: accessLevel
})
});
const data = await response.json();
if (data.success) {
alert('权限级别更新成功');
this.hideAccessModal();
this.fetchUsers(); // 刷新用户列表
} else {
alert('权限级别更新失败: ' + data.message);
}
} catch (error) {
console.error('更新权限级别出错:', error);
alert('更新权限级别失败');
}
}
async handleResetPassword(userId) {
if (confirm('确定要重置该用户的密码吗?')) {
try {
const response = await fetch('/api/reset-password', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ userId: parseInt(userId) })
});
const data = await response.json();
if (data.success) {
alert('密码重置成功');
} else {
alert('密码重置失败: ' + data.message);
}
} catch (error) {
console.error('重置密码出错:', error);
alert('重置密码失败');
}
}
}
async handleDelete(userId) {
if (confirm('确定要删除该用户吗?此操作不可恢复!')) {
try {
const response = await fetch('/api/delete-user', {
method: 'DELETE',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ userId: parseInt(userId) })
});
const data = await response.json();
if (data.success) {
alert('用户删除成功');
// 重新获取用户列表
this.fetchUsers();
} else {
alert('用户删除失败: ' + data.message);
}
} catch (error) {
console.error('删除用户出错:', error);
alert('删除用户失败');
}
}
}
getAccessLevelName(level) {
const accessLevels = {
0: '访客',
1: '用户',
2: '开发人员',
3: '组长'
};
return accessLevels[level] || level;
}
render() {
this.shadowRoot.innerHTML = `
<style>
:host {
display: block;
height: 100%;
overflow: auto;
padding: 16px;
box-sizing: border-box;
}
.users-container {
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
padding: 16px;
height: 100%;
box-sizing: border-box;
}
.users-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid #e0e0e0;
}
.users-title {
font-size: 18px;
font-weight: bold;
color: #333;
}
.users-table {
width: 100%;
border-collapse: collapse;
table-layout: fixed;
}
.users-table th,
.users-table td {
padding: 12px;
text-align: left;
border-bottom: 1px solid #e0e0e0;
word-wrap: break-word;
}
.users-table th {
background-color: #f5f5f5;
font-weight: bold;
color: #333;
}
.users-table tr:hover {
background-color: #f9f9f9;
}
.col-id {
width: 8%;
}
.col-username {
width: 20%;
}
.col-fullname {
width: 25%;
}
.col-access {
width: 12%;
}
.col-actions {
width: 35%;
}
.error-message {
display: none;
color: #ff4d4f;
margin: 16px 0;
padding: 8px;
background-color: #fff2f0;
border: 1px solid #ffccc7;
border-radius: 4px;
}
.loading {
text-align: center;
padding: 20px;
color: #666;
}
.action-button {
padding: 6px 12px;
margin: 0 4px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 12px;
color: white;
transition: opacity 0.2s;
}
.edit-info {
background-color: #1890ff;
}
.change-access {
background-color: #52c41a;
}
.reset-password {
background-color: #faad14;
}
.delete {
background-color: #ff4d4f;
}
.action-button:hover {
opacity: 0.8;
}
.action-button:active {
opacity: 0.6;
}
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
justify-content: center;
align-items: center;
z-index: 1000;
}
.modal-content {
background-color: white;
border-radius: 8px;
padding: 24px;
width: 500px;
max-width: 90%;
max-height: 90%;
overflow-y: auto;
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid #e0e0e0;
}
.modal-title {
font-size: 18px;
font-weight: bold;
color: #333;
}
.close-button {
background: none;
border: none;
font-size: 20px;
cursor: pointer;
color: #999;
}
.close-button:hover {
color: #333;
}
.form-group {
margin-bottom: 16px;
}
.form-label {
display: block;
margin-bottom: 6px;
font-weight: bold;
color: #333;
}
.form-input {
width: 100%;
padding: 8px 12px;
border: 1px solid #d9d9d9;
border-radius: 4px;
font-size: 14px;
box-sizing: border-box;
}
.form-input:focus {
outline: none;
border-color: #1890ff;
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
}
.form-input:read-only {
background-color: #f5f5f5;
color: #666;
cursor: not-allowed;
}
.form-input:read-only:focus {
border-color: #d9d9d9;
box-shadow: none;
}
.modal-footer {
display: flex;
justify-content: flex-end;
gap: 12px;
margin-top: 24px;
padding-top: 16px;
border-top: 1px solid #e0e0e0;
}
.btn {
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
transition: opacity 0.2s;
}
.btn-primary {
background-color: #1890ff;
color: white;
}
.btn-secondary {
background-color: #f5f5f5;
color: #333;
border: 1px solid #d9d9d9;
}
.btn:hover {
opacity: 0.8;
}
.access-modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
justify-content: center;
align-items: center;
z-index: 1000;
}
.access-modal-content {
background-color: white;
border-radius: 8px;
padding: 24px;
width: 400px;
max-width: 90%;
}
.access-modal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid #e0e0e0;
}
.access-modal-title {
font-size: 18px;
font-weight: bold;
color: #333;
}
.access-close-button {
background: none;
border: none;
font-size: 20px;
cursor: pointer;
color: #999;
}
.access-close-button:hover {
color: #333;
}
.access-form-group {
margin-bottom: 16px;
}
.access-form-label {
display: block;
margin-bottom: 6px;
font-weight: bold;
color: #333;
}
.access-form-select {
width: 100%;
padding: 8px 12px;
border: 1px solid #d9d9d9;
border-radius: 4px;
font-size: 14px;
box-sizing: border-box;
background-color: white;
}
.access-form-select:focus {
outline: none;
border-color: #1890ff;
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
}
.access-modal-footer {
display: flex;
justify-content: flex-end;
gap: 12px;
margin-top: 24px;
padding-top: 16px;
border-top: 1px solid #e0e0e0;
}
</style>
<div class="users-container">
<div class="users-header">
<div class="users-title">用户管理</div>
</div>
<div class="error-message"></div>
${this.users.length === 0 ?
'<div class="loading">正在加载用户数据...</div>' :
`<table class="users-table">
<thead>
<tr>
<th class="col-id">ID</th>
<th class="col-username">用户名</th>
<th class="col-fullname">姓名</th>
<th class="col-access">权限等级</th>
<th class="col-actions">操作</th>
</tr>
</thead>
<tbody>
${this.users.map(user => `
<tr>
<td class="col-id">${user.id}</td>
<td class="col-username">${user.username}</td>
<td class="col-fullname">${user.full_name || '-'}</td>
<td class="col-access">${this.getAccessLevelName(user.access_level)}</td>
<td class="col-actions">
<button class="action-button edit-info" onclick="this.getRootNode().host.handleEditInfo(${user.id})">更改信息</button>
<button class="action-button change-access" onclick="this.getRootNode().host.handleChangeAccessLevel(${user.id})">调整权限</button>
<button class="action-button reset-password" onclick="this.getRootNode().host.handleResetPassword(${user.id})">重置密码</button>
<button class="action-button delete" onclick="this.getRootNode().host.handleDelete(${user.id})">删除</button>
</td>
</tr>
`).join('')}
</tbody>
</table>`
}
</div>
<!-- 编辑用户信息模态对话框 -->
<div class="modal">
<div class="modal-content">
<div class="modal-header">
<div class="modal-title">编辑用户信息</div>
<button class="close-button" onclick="this.getRootNode().host.hideEditModal()">&times;</button>
</div>
<form class="edit-form">
<div class="form-group">
<label class="form-label">用户名</label>
<input type="text" class="form-input" name="username" required readonly>
</div>
<div class="form-group">
<label class="form-label">姓名</label>
<input type="text" class="form-input" name="full_name">
</div>
<div class="form-group">
<label class="form-label">邮箱</label>
<input type="email" class="form-input" name="email">
</div>
<div class="form-group">
<label class="form-label">电话</label>
<input type="text" class="form-input" name="phone">
</div>
<div class="form-group">
<label class="form-label">部门</label>
<input type="text" class="form-input" name="department">
</div>
<div class="form-group">
<label class="form-label">职位</label>
<input type="text" class="form-input" name="position">
</div>
</form>
<div class="modal-footer">
<button class="btn btn-secondary" onclick="this.getRootNode().host.hideEditModal()">取消</button>
<button class="btn btn-primary" onclick="this.getRootNode().host.handleSaveUserInfo()">保存</button>
</div>
</div>
</div>
<!-- 调整权限级别模态对话框 -->
<div class="access-modal">
<div class="access-modal-content">
<div class="access-modal-header">
<div class="access-modal-title">调整权限级别</div>
<button class="access-close-button" onclick="this.getRootNode().host.hideAccessModal()">&times;</button>
</div>
<form class="access-form">
<div class="access-form-group">
<label class="access-form-label">权限级别</label>
<select class="access-form-select" name="access_level" required>
<option value="0">访客</option>
<option value="1">用户</option>
<option value="2">开发人员</option>
<option value="3">组长</option>
</select>
</div>
</form>
<div class="access-modal-footer">
<button class="btn btn-secondary" onclick="this.getRootNode().host.hideAccessModal()">取消</button>
<button class="btn btn-primary" onclick="this.getRootNode().host.handleSaveAccessLevel()">保存</button>
</div>
</div>
</div>
`;
}
}
customElements.define('user-management', UserManagement);