数据管理页面的完善
This commit is contained in:
@@ -1,75 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="zh-CN">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>填写班级信息</title>
|
|
||||||
<style>
|
|
||||||
body { font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif; background: #f5f6fa; }
|
|
||||||
.container { max-width: 400px; margin: 15vh auto; padding: 24px; background: #fff; border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,0.08); }
|
|
||||||
h1 { font-size: 20px; margin: 0 0 16px; text-align: center; }
|
|
||||||
label { display:block; margin: 12px 0 6px; color:#333; }
|
|
||||||
input { width:100%; padding:10px 0px; border:1px solid #dcdde1; border-radius:6px; box-sizing: border-box; }
|
|
||||||
button { width:100%; margin-top:16px; padding:10px 12px; background:#2d8cf0; color:#fff; border:none; border-radius:6px; cursor:pointer; }
|
|
||||||
button:disabled { background:#9bbcf0; cursor:not-allowed; }
|
|
||||||
.error { color:#d93025; margin-top:10px; min-height:20px; font-size: 14px; }
|
|
||||||
.hint { color:#888; font-size:12px; margin-top:10px; }
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="container">
|
|
||||||
<h1>完善班级信息</h1>
|
|
||||||
<form id="classForm">
|
|
||||||
{% csrf_token %}
|
|
||||||
<input type="hidden" id="user_id" value="{{ user_id }}">
|
|
||||||
<label for="class_name">所在班级</label>
|
|
||||||
<input id="class_name" name="class_name" type="text" placeholder="例:2024级计算机专业1班" required />
|
|
||||||
<div class="hint">格式要求:XXXX级YY专业Z班(记得加“专业”两个字)</div>
|
|
||||||
<button id="submitBtn" type="submit">提交并进入登录页</button>
|
|
||||||
<div id="error" class="error"></div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
function getCookie(name){const v=`; ${document.cookie}`;const p=v.split(`; ${name}=`);if(p.length===2) return p.pop().split(';').shift();}
|
|
||||||
|
|
||||||
document.getElementById('classForm').addEventListener('submit', async (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
const err = document.getElementById('error');
|
|
||||||
err.textContent = '';
|
|
||||||
const className = document.getElementById('class_name').value.trim();
|
|
||||||
const userId = document.getElementById('user_id').value;
|
|
||||||
|
|
||||||
// 正则校验:2024级**专业*班
|
|
||||||
const pattern = /^\d{4}级.+专业\d+班$/;
|
|
||||||
if (!pattern.test(className)) {
|
|
||||||
err.textContent = '班级格式不正确,请重新输入(例:2024级计算机专业1班)';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const btn = document.getElementById('submitBtn');
|
|
||||||
btn.disabled = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const csrftoken = getCookie('csrftoken');
|
|
||||||
const resp = await fetch('/accounts/class-info/submit/', {
|
|
||||||
method: 'POST',
|
|
||||||
credentials: 'same-origin',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'X-CSRFToken': csrftoken || ''
|
|
||||||
},
|
|
||||||
body: JSON.stringify({ user_id: userId, class_name: className })
|
|
||||||
});
|
|
||||||
const data = await resp.json();
|
|
||||||
if (!resp.ok || !data.ok) {
|
|
||||||
throw new Error(data.message || '提交失败');
|
|
||||||
}
|
|
||||||
window.location.href = '/accounts/login/';
|
|
||||||
} catch (e) {
|
|
||||||
err.textContent = e.message || '发生错误';
|
|
||||||
} finally {
|
|
||||||
btn.disabled = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -12,7 +12,5 @@ urlpatterns = [
|
|||||||
path("register/", views.register_page, name="register"),
|
path("register/", views.register_page, name="register"),
|
||||||
path("register/submit/", views.register_submit, name="register_submit"),
|
path("register/submit/", views.register_submit, name="register_submit"),
|
||||||
path("email/send-code/", views.send_email_code, name="send_email_code"),
|
path("email/send-code/", views.send_email_code, name="send_email_code"),
|
||||||
path("class-info/", views.class_info_page, name="class_info"),
|
|
||||||
path("class-info/submit/", views.class_info_submit, name="class_info_submit"),
|
|
||||||
path("profile/", views.profile_page, name="profile"),
|
path("profile/", views.profile_page, name="profile"),
|
||||||
]
|
]
|
||||||
@@ -272,43 +272,7 @@ def register_submit(request):
|
|||||||
del request.session["email_verify"]
|
del request.session["email_verify"]
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
# 修改:注册成功后跳转到完善班级信息页面
|
return JsonResponse({"ok": True, "redirect_url": "/accounts/login/"})
|
||||||
return JsonResponse({"ok": True, "redirect_url": f"/accounts/class-info/?user_id={next_id}"})
|
|
||||||
|
|
||||||
@require_http_methods(["GET"])
|
|
||||||
@ensure_csrf_cookie
|
|
||||||
def class_info_page(request):
|
|
||||||
user_id = request.GET.get("user_id")
|
|
||||||
if not user_id:
|
|
||||||
return redirect("/accounts/register/")
|
|
||||||
return render(request, "accounts/class_info.html", {"user_id": user_id})
|
|
||||||
|
|
||||||
@require_http_methods(["POST"])
|
|
||||||
@csrf_protect
|
|
||||||
def class_info_submit(request):
|
|
||||||
try:
|
|
||||||
payload = json.loads(request.body.decode("utf-8"))
|
|
||||||
except json.JSONDecodeError:
|
|
||||||
return HttpResponseBadRequest("Invalid JSON")
|
|
||||||
|
|
||||||
user_id = payload.get("user_id")
|
|
||||||
class_name = (payload.get("class_name") or "").strip()
|
|
||||||
|
|
||||||
if not user_id or not class_name:
|
|
||||||
return HttpResponseBadRequest("Missing fields")
|
|
||||||
|
|
||||||
# 后端校验:2024级**专业*班
|
|
||||||
import re
|
|
||||||
pattern = r"^\d{4}级.+专业\d+班$"
|
|
||||||
if not re.match(pattern, class_name):
|
|
||||||
return JsonResponse({"ok": False, "message": "班级格式不正确"}, status=400)
|
|
||||||
|
|
||||||
# 更新用户信息,将班级信息存入 key 列表
|
|
||||||
ok = update_user_by_id(user_id, key=[class_name])
|
|
||||||
if not ok:
|
|
||||||
return JsonResponse({"ok": False, "message": "保存班级信息失败"}, status=500)
|
|
||||||
|
|
||||||
return JsonResponse({"ok": True})
|
|
||||||
|
|
||||||
@require_http_methods(["POST"])
|
@require_http_methods(["POST"])
|
||||||
@csrf_protect
|
@csrf_protect
|
||||||
|
|||||||
@@ -16,6 +16,9 @@
|
|||||||
table{width:100%;border-collapse:collapse;margin-top:20px}
|
table{width:100%;border-collapse:collapse;margin-top:20px}
|
||||||
th,td{border-bottom:1px solid #eee;padding:12px 8px;text-align:left;vertical-align:top}
|
th,td{border-bottom:1px solid #eee;padding:12px 8px;text-align:left;vertical-align:top}
|
||||||
th{background:#f8f9fa;font-weight:600}
|
th{background:#f8f9fa;font-weight:600}
|
||||||
|
.inner-table { width: 100%; margin: 0; border: 1px solid #e0e0e0; border-collapse: collapse; }
|
||||||
|
.inner-table th, .inner-table td { border: 1px solid #e0e0e0; padding: 6px; font-size: 12px; }
|
||||||
|
.inner-table th { background-color: #f9f9f9; }
|
||||||
img{max-width:120px;border:1px solid #eee;border-radius:6px;cursor:pointer}
|
img{max-width:120px;border:1px solid #eee;border-radius:6px;cursor:pointer}
|
||||||
.btn{padding:6px 10px;border:none;border-radius:6px;cursor:pointer;font-size:14px;margin:2px}
|
.btn{padding:6px 10px;border:none;border-radius:6px;cursor:pointer;font-size:14px;margin:2px}
|
||||||
.btn-primary{background:#1677ff;color:#fff}
|
.btn-primary{background:#1677ff;color:#fff}
|
||||||
@@ -86,7 +89,6 @@
|
|||||||
<table id="dataTable">
|
<table id="dataTable">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>ID</th>
|
|
||||||
<th>图片</th>
|
<th>图片</th>
|
||||||
<th>数据</th>
|
<th>数据</th>
|
||||||
<th>录入人</th>
|
<th>录入人</th>
|
||||||
@@ -320,18 +322,28 @@ function renderTable(data) {
|
|||||||
let displayData = item.data || '';
|
let displayData = item.data || '';
|
||||||
try {
|
try {
|
||||||
const parsed = JSON.parse(item.data);
|
const parsed = JSON.parse(item.data);
|
||||||
displayData = JSON.stringify(parsed, null, 2);
|
displayData = `
|
||||||
|
<table class="inner-table">
|
||||||
|
<tbody>
|
||||||
|
${Object.entries(parsed).map(([key, value]) => `
|
||||||
|
<tr>
|
||||||
|
<td>${escapeHtml(key)}</td>
|
||||||
|
<td>${escapeHtml(typeof value === 'object' ? JSON.stringify(value, null, 2) : value)}</td>
|
||||||
|
</tr>
|
||||||
|
`).join('')}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
`;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// 如果不是JSON,直接显示原字符串
|
displayData = `<pre style="white-space:pre-wrap; word-wrap:break-word; max-height: 100px; overflow-y: auto; font-size: 12px; margin: 0;">${escapeHtml(displayData)}</pre>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
row.innerHTML = `
|
row.innerHTML = `
|
||||||
<td style="max-width:140px; word-break:break-all; font-size: 12px;">${item._id || item.id || ''}</td>
|
|
||||||
<td>
|
<td>
|
||||||
<div style="display:flex;gap:6px;flex-wrap:wrap;">${buildImageCell(item)}</div>
|
<div style="display:flex;gap:6px;flex-wrap:wrap;">${buildImageCell(item)}</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<pre style="white-space:pre-wrap; word-wrap:break-word; max-height: 100px; overflow-y: auto; font-size: 12px; margin: 0;">${escapeHtml(displayData)}</pre>
|
${displayData}
|
||||||
</td>
|
</td>
|
||||||
<td style="font-size: 12px;">${item.writer_name || item.writer_id || ''}</td>
|
<td style="font-size: 12px;">${item.writer_name || item.writer_id || ''}</td>
|
||||||
<td>
|
<td>
|
||||||
|
|||||||
Reference in New Issue
Block a user