This commit is contained in:
@@ -39,8 +39,8 @@
|
|||||||
.msg.success { color: #166534; }
|
.msg.success { color: #166534; }
|
||||||
|
|
||||||
/* 图片放大模态框 */
|
/* 图片放大模态框 */
|
||||||
.image-modal { position: fixed; inset: 0; background: rgba(0,0,0,0.8); display: none; align-items: center; justify-content: center; z-index: 2000; }
|
.image-modal { position: fixed; inset: 0; background: rgba(0,0,0,0.8); display: none; align-items: center; justify-content: center; z-index: 2000; overflow: hidden; }
|
||||||
.image-modal-content { max-width: 90%; max-height: 90%; border-radius: 8px; }
|
.image-modal-content { max-width: 90%; max-height: 90%; border-radius: 8px; transform-origin: center center; cursor: grab; user-select: none; }
|
||||||
.image-modal-close { position: absolute; top: 20px; right: 30px; color: white; font-size: 40px; font-weight: bold; cursor: pointer; }
|
.image-modal-close { position: absolute; top: 20px; right: 30px; color: white; font-size: 40px; font-weight: bold; cursor: pointer; }
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
@@ -79,7 +79,6 @@
|
|||||||
</form>
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if subpage == "password" %}
|
{% if subpage == "password" %}
|
||||||
{% if permission_name != "管理员" and not profile_user.manage_key %}
|
|
||||||
<form id="pwdForm">
|
<form id="pwdForm">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="newPassword">新密码</label>
|
<label for="newPassword">新密码</label>
|
||||||
@@ -92,9 +91,6 @@
|
|||||||
<button type="submit" class="btn">保存</button>
|
<button type="submit" class="btn">保存</button>
|
||||||
<div id="pwdMsg" class="msg"></div>
|
<div id="pwdMsg" class="msg"></div>
|
||||||
</form>
|
</form>
|
||||||
{% else %}
|
|
||||||
<div class="msg error">无权限</div>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if subpage == "registration-code" %}
|
{% if subpage == "registration-code" %}
|
||||||
<form id="rcForm">
|
<form id="rcForm">
|
||||||
@@ -138,9 +134,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div style="display:flex; gap:12px; flex-wrap:wrap;">
|
<div style="display:flex; gap:12px; flex-wrap:wrap;">
|
||||||
<a class="btn" href="{% url 'accounts:profile_username' %}">修改用户名</a>
|
<a class="btn" href="{% url 'accounts:profile_username' %}">修改用户名</a>
|
||||||
{% if permission_name != "管理员" and not profile_user.manage_key %}
|
|
||||||
<a class="btn" href="{% url 'accounts:profile_password' %}">修改密码</a>
|
<a class="btn" href="{% url 'accounts:profile_password' %}">修改密码</a>
|
||||||
{% endif %}
|
|
||||||
<a class="btn" href="{% url 'accounts:profile_registration_code' %}">替换注册码</a>
|
<a class="btn" href="{% url 'accounts:profile_registration_code' %}">替换注册码</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -194,20 +188,114 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 图片放大功能
|
// 图片放大功能
|
||||||
|
let modalScale = 1;
|
||||||
|
let modalTranslateX = 0;
|
||||||
|
let modalTranslateY = 0;
|
||||||
|
let modalDragging = false;
|
||||||
|
let modalDragStartX = 0;
|
||||||
|
let modalDragStartY = 0;
|
||||||
|
let modalDragOriginX = 0;
|
||||||
|
let modalDragOriginY = 0;
|
||||||
|
|
||||||
|
function applyModalTransform() {
|
||||||
|
const modalImg = document.getElementById('modalImg');
|
||||||
|
modalImg.style.transform = `translate(${modalTranslateX}px, ${modalTranslateY}px) scale(${modalScale})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetModalTransform() {
|
||||||
|
modalScale = 1;
|
||||||
|
modalTranslateX = 0;
|
||||||
|
modalTranslateY = 0;
|
||||||
|
applyModalTransform();
|
||||||
|
}
|
||||||
|
|
||||||
|
function clampScale(next) {
|
||||||
|
if (next < 0.2) return 0.2;
|
||||||
|
if (next > 5) return 5;
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
function openModal(src) {
|
function openModal(src) {
|
||||||
const modal = document.getElementById('imageModal');
|
const modal = document.getElementById('imageModal');
|
||||||
const modalImg = document.getElementById('modalImg');
|
const modalImg = document.getElementById('modalImg');
|
||||||
modal.style.display = "flex";
|
modal.style.display = "flex";
|
||||||
modalImg.src = src;
|
modalImg.src = src;
|
||||||
|
resetModalTransform();
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeModal() {
|
function closeModal() {
|
||||||
document.getElementById('imageModal').style.display = "none";
|
document.getElementById('imageModal').style.display = "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
window.onclick = function(event) {
|
const modalEl = document.getElementById('imageModal');
|
||||||
const modal = document.getElementById('imageModal');
|
const modalImgEl = document.getElementById('modalImg');
|
||||||
if (event.target == modal) closeModal();
|
if (modalEl && modalImgEl) {
|
||||||
|
modalEl.addEventListener('click', (e) => {
|
||||||
|
if (e.target === modalEl) closeModal();
|
||||||
|
});
|
||||||
|
|
||||||
|
modalImgEl.addEventListener('mousedown', (e) => {
|
||||||
|
if (e.button !== 0) return;
|
||||||
|
e.preventDefault();
|
||||||
|
modalDragging = true;
|
||||||
|
modalDragStartX = e.clientX;
|
||||||
|
modalDragStartY = e.clientY;
|
||||||
|
modalDragOriginX = modalTranslateX;
|
||||||
|
modalDragOriginY = modalTranslateY;
|
||||||
|
modalImgEl.style.cursor = 'grabbing';
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('mousemove', (e) => {
|
||||||
|
if (!modalDragging) return;
|
||||||
|
const dx = e.clientX - modalDragStartX;
|
||||||
|
const dy = e.clientY - modalDragStartY;
|
||||||
|
modalTranslateX = modalDragOriginX + dx;
|
||||||
|
modalTranslateY = modalDragOriginY + dy;
|
||||||
|
applyModalTransform();
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('mouseup', () => {
|
||||||
|
if (!modalDragging) return;
|
||||||
|
modalDragging = false;
|
||||||
|
modalImgEl.style.cursor = 'grab';
|
||||||
|
});
|
||||||
|
|
||||||
|
modalEl.addEventListener('wheel', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const rect = modalImgEl.getBoundingClientRect();
|
||||||
|
const cx = e.clientX - rect.left - rect.width / 2;
|
||||||
|
const cy = e.clientY - rect.top - rect.height / 2;
|
||||||
|
const nextScale = clampScale(modalScale * (e.deltaY < 0 ? 1.1 : 0.9));
|
||||||
|
const ratio = nextScale / modalScale;
|
||||||
|
modalTranslateX = (modalTranslateX - cx) * ratio + cx;
|
||||||
|
modalTranslateY = (modalTranslateY - cy) * ratio + cy;
|
||||||
|
modalScale = nextScale;
|
||||||
|
applyModalTransform();
|
||||||
|
}, { passive: false });
|
||||||
|
|
||||||
|
modalImgEl.addEventListener('touchstart', (e) => {
|
||||||
|
if (e.touches.length !== 1) return;
|
||||||
|
const t = e.touches[0];
|
||||||
|
modalDragging = true;
|
||||||
|
modalDragStartX = t.clientX;
|
||||||
|
modalDragStartY = t.clientY;
|
||||||
|
modalDragOriginX = modalTranslateX;
|
||||||
|
modalDragOriginY = modalTranslateY;
|
||||||
|
}, { passive: true });
|
||||||
|
|
||||||
|
modalImgEl.addEventListener('touchmove', (e) => {
|
||||||
|
if (!modalDragging || e.touches.length !== 1) return;
|
||||||
|
const t = e.touches[0];
|
||||||
|
const dx = t.clientX - modalDragStartX;
|
||||||
|
const dy = t.clientY - modalDragStartY;
|
||||||
|
modalTranslateX = modalDragOriginX + dx;
|
||||||
|
modalTranslateY = modalDragOriginY + dy;
|
||||||
|
applyModalTransform();
|
||||||
|
}, { passive: true });
|
||||||
|
|
||||||
|
modalImgEl.addEventListener('touchend', () => {
|
||||||
|
modalDragging = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const pwdForm = document.getElementById('pwdForm');
|
const pwdForm = document.getElementById('pwdForm');
|
||||||
|
|||||||
@@ -289,40 +289,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="main-content">
|
<div class="main-content">
|
||||||
{% if is_student %}
|
|
||||||
<div class="card">
|
|
||||||
<div class="header"><h2>修改密码</h2></div>
|
|
||||||
<form id="selfPwdForm">
|
|
||||||
<input type="hidden" id="selfUserId" name="user_id" value="{{ user_id }}">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="password">新密码</label>
|
|
||||||
<input type="password" id="password" name="password" required>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="confirmPassword">确认密码</label>
|
|
||||||
<input type="password" id="confirmPassword" name="confirmPassword" required>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="btn btn-primary">保存</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
{% if is_tutor %}
|
|
||||||
<div class="card">
|
|
||||||
<div class="header"><h2>修改本人密码</h2></div>
|
|
||||||
<form id="selfPwdForm">
|
|
||||||
<input type="hidden" id="selfUserId" name="user_id" value="{{ user_id }}">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="password">新密码</label>
|
|
||||||
<input type="password" id="password" name="password" required>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="confirmPassword">确认密码</label>
|
|
||||||
<input type="password" id="confirmPassword" name="confirmPassword" required>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="btn btn-primary">保存</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<h2>用户管理</h2>
|
<h2>用户管理</h2>
|
||||||
@@ -356,7 +322,6 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 添加/编辑用户模态框 -->
|
<!-- 添加/编辑用户模态框 -->
|
||||||
@@ -971,30 +936,6 @@
|
|||||||
// 页面加载时获取用户列表
|
// 页面加载时获取用户列表
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
initKeyFilter();
|
initKeyFilter();
|
||||||
const selfForm = document.getElementById('selfPwdForm');
|
|
||||||
if (selfForm) {
|
|
||||||
selfForm.addEventListener('submit', async (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
const uid = document.getElementById('selfUserId').value;
|
|
||||||
const pwd = document.getElementById('password').value;
|
|
||||||
const cpwd = document.getElementById('confirmPassword').value;
|
|
||||||
if (pwd !== cpwd) { showNotification('密码和确认密码不匹配', false); return; }
|
|
||||||
if ((pwd || '').length < 6) { showNotification('密码长度至少为6位', false); return; }
|
|
||||||
try {
|
|
||||||
const csrftoken = getCookie('csrftoken');
|
|
||||||
const resp = await fetch(`/elastic/users/${uid}/update/`, {
|
|
||||||
method: 'POST', credentials: 'same-origin',
|
|
||||||
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrftoken || '' },
|
|
||||||
body: JSON.stringify({ password: pwd })
|
|
||||||
});
|
|
||||||
const result = await resp.json();
|
|
||||||
if (resp.ok && result.status === 'success') { showNotification('修改成功'); }
|
|
||||||
else { showNotification(result.message || '操作失败', false); }
|
|
||||||
} catch (error) {
|
|
||||||
showNotification('保存失败', false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const tbody = document.getElementById('usersTableBody');
|
const tbody = document.getElementById('usersTableBody');
|
||||||
if (tbody) {
|
if (tbody) {
|
||||||
const select = document.getElementById('keyFilter');
|
const select = document.getElementById('keyFilter');
|
||||||
|
|||||||
Reference in New Issue
Block a user