mergeok
This commit is contained in:
@@ -12,8 +12,10 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
});
|
||||
socket.on('connect', function () {
|
||||
console.log('Connected to server');
|
||||
socket.emit('login', JSON.stringify(data));
|
||||
OpenIframe();
|
||||
socket.emit('login',JSON.stringify(data));
|
||||
});
|
||||
socket.on('open-iframe', function(data) {
|
||||
OpenIframe();
|
||||
});
|
||||
// 监听来自服务器的消息
|
||||
socket.on('message', function (data) {
|
||||
@@ -24,29 +26,18 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
// 滚动到最新消息
|
||||
document.getElementById('chatbox').scrollTop = document.getElementById('chatbox').scrollHeight;
|
||||
});
|
||||
|
||||
//监听来自服务器的消息
|
||||
/*socket.on('VoiceMessage', function(data) {
|
||||
console.log("Received voice answer message:", data);
|
||||
socket.on('message-hint', function(data){
|
||||
console.log('get message-hint');
|
||||
|
||||
// 显示服务器的回复消息
|
||||
const VoiceMessage = document.createElement('div');
|
||||
VoiceMessage.className = 'chat-message server-message';
|
||||
VoiceMessage.innerHTML = `
|
||||
<div><b>华实君:</b></div>
|
||||
${marked.parse(data)}
|
||||
`;
|
||||
//插入与滚动
|
||||
document.getElementById('chatbox').appendChild(VoiceMessage);
|
||||
|
||||
const serverMessage = document.createElement('div');
|
||||
serverMessage.innerHTML = `<div id="hint-title"><b>提示</b></div><div id="hint-message" class="chat-message server-message"> ${data}</div>`;
|
||||
document.getElementById('chatbox').appendChild(serverMessage);
|
||||
// 滚动到最新消息
|
||||
document.getElementById('chatbox').scrollTop = document.getElementById('chatbox').scrollHeight;
|
||||
});*/
|
||||
//监听来自服务器的语音识别消息
|
||||
socket.on('VoiceMessage', function (data) {
|
||||
console.log("Received voice message I sent from server:", data);
|
||||
//将语音转文字显示在输入框中
|
||||
document.getElementById('messageInput').value = data;
|
||||
});
|
||||
|
||||
socket.on('request_function', function (data) {
|
||||
socket.on('request_function', function(data){
|
||||
try {
|
||||
console.log("request_function", data);
|
||||
if (typeof data === 'string') {
|
||||
|
||||
@@ -22,7 +22,6 @@ function show_user_data(user_data, course_brief_data_list){
|
||||
}
|
||||
}
|
||||
function openCourseProgress(courseId) {
|
||||
console.log(courseId)
|
||||
const course = courseData[courseId];
|
||||
if (!course) return;
|
||||
fetch(`/dashboard/get_course_progress`, {
|
||||
@@ -33,7 +32,7 @@ function openCourseProgress(courseId) {
|
||||
body: JSON.stringify({course_id: courseId})
|
||||
}).then(response => response.json())
|
||||
.then(data => {
|
||||
console.log(data)
|
||||
// console.log(data)
|
||||
/*
|
||||
course_last_study_date: "2025-09-06"
|
||||
course_put_in_date: "2025-09-06"
|
||||
@@ -75,31 +74,36 @@ function openCourseProgress(courseId) {
|
||||
const subChapterItem = document.createElement('li');//课时层级
|
||||
subChapterItem.classList.add('sub-chapter-item');
|
||||
subChapterItem.textContent = subChapter.lesson_name;
|
||||
console.log('-------------------')
|
||||
console.log(course)
|
||||
// 查找学生进度
|
||||
lesson_score_text_content = ""
|
||||
for(let i = 0; i < course.lesson_processs.length; i++) {
|
||||
if (course.lesson_processs[i][2] == subChapter.lesson_name && course.lesson_processs[i][1] == chapter.chapter_name) {//确定lesson_id对应正确
|
||||
///////////////////////////////////////////
|
||||
//这里之后要做lesson的各个step的进度和得分
|
||||
////////////////////////////////////////////
|
||||
|
||||
console.log('-------------------')
|
||||
console.log(course.lesson_processs[i][0])
|
||||
lesson_chapters_progress = course.lesson_processs[i][0];//寻找对应的每一个章节的进度
|
||||
for (let j=0; j<lesson_chapters_progress.length;j++){
|
||||
chapter_progress = lesson_chapters_progress[j]
|
||||
if(chapter_progress.title == subChapter){
|
||||
subChapterItem.textContent += ("(已"+(chapter_progress.is_rebuttal?"申辩" : "完成")+" 得分"+ (chapter_progress.is_rebuttal?chapter_progress.rebuttal_score : chapter_progress.score) +")");
|
||||
}
|
||||
}
|
||||
if (course.lesson_processs[i][0].length === 1) {
|
||||
subChapterItem.classList.add('completed');
|
||||
if (course.lesson_processs[i].length<=3){break;}
|
||||
for (let j =0; j< course.lesson_processs[i][3].length;j++){
|
||||
if (isObject(course.lesson_processs[i][3][j]))course.lesson_processs[i][3][j]=course.lesson_processs[i][3][j]['data']
|
||||
lesson_score_text_content+=course.lesson_processs[i][3][j]+';'
|
||||
}
|
||||
// console.log('-------------------')
|
||||
// subChapterItem.textContent +=
|
||||
// console.log(course.lesson_processs[i][0])
|
||||
// lesson_chapters_progress = course.lesson_processs[i][0];//寻找对应的每一个章节的进度
|
||||
// for (let j=0; j<lesson_chapters_progress.length;j++){
|
||||
// chapter_progress = lesson_chapters_progress[j]
|
||||
// if(chapter_progress.title == subChapter){
|
||||
// subChapterItem.textContent += ("(已"+(chapter_progress.is_rebuttal?"申辩" : "完成")+" 得分"+ (chapter_progress.is_rebuttal?chapter_progress.rebuttal_score : chapter_progress.score) +")");
|
||||
// }
|
||||
// }
|
||||
// if (course.lesson_processs[i][0].length === 1) {
|
||||
// subChapterItem.classList.add('completed');
|
||||
// }
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lesson_score_text_content!=""){lesson_score_text_content = ' ('+lesson_score_text_content+')'}
|
||||
subChapterItem.textContent+=lesson_score_text_content
|
||||
// 添加点击事件跳转到学习页面
|
||||
subChapterItem.addEventListener('click', () => {
|
||||
const courseId = encodeURIComponent(course._id); // 对课程名称进行编码
|
||||
@@ -136,3 +140,7 @@ function closeCourseProgress() {
|
||||
// 关闭滑出卡片
|
||||
document.getElementById('courseProgress').classList.remove('open');
|
||||
}
|
||||
|
||||
function isObject(value) {
|
||||
return Object.prototype.toString.call(value) === '[object Object]';
|
||||
}
|
||||
@@ -8,7 +8,11 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
const email = document.getElementById('email').value;
|
||||
const password = document.getElementById('password').value;
|
||||
const confirmPassword = document.getElementById('confirm-password').value;
|
||||
|
||||
const u = validateLinuxUsername(username);
|
||||
if (!u.ok) {
|
||||
alert(u.error);
|
||||
return;
|
||||
}
|
||||
if (password !== confirmPassword) {
|
||||
alert('密码和确认密码不一致');
|
||||
return;
|
||||
@@ -36,4 +40,36 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
alert('注册失败');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// 校验 Linux 用户名
|
||||
function validateLinuxUsername(name) {
|
||||
// 基本字符规则:^[a-z_][a-z0-9_-]*[$]?$
|
||||
const basic = /^[a-z_][a-z0-9_-]*[$]?$/;
|
||||
|
||||
if (typeof name !== 'string' || name.length === 0) {
|
||||
return { ok: false, error: '用户名不能为空' };
|
||||
}
|
||||
// 长度限制(常见系统为 <= 32)
|
||||
if (name.length > 32) {
|
||||
return { ok: false, error: '用户名长度不能超过 32 个字符' };
|
||||
}
|
||||
if (!basic.test(name)) {
|
||||
return {
|
||||
ok: false,
|
||||
error:
|
||||
'用户名需以小写字母或下划线开头,仅包含小写字母、数字、下划线、连字符,允许以 $ 结尾'
|
||||
};
|
||||
}
|
||||
// 可选:避免纯数字用户名(多数系统不推荐)
|
||||
if (/^[0-9]+$/.test(name)) {
|
||||
return { ok: false, error: '用户名不能为纯数字' };
|
||||
}
|
||||
// 可选:避免使用保留名
|
||||
const reserved = new Set(['root', 'daemon', 'bin', 'sys', 'sync', 'games', 'man']);
|
||||
if (reserved.has(name)) {
|
||||
return { ok: false, error: '该用户名为系统保留名,请更换' };
|
||||
}
|
||||
|
||||
return { ok: true };
|
||||
}
|
||||
27
Html/apps/static/js/register_field_tip.js
Normal file
27
Html/apps/static/js/register_field_tip.js
Normal file
@@ -0,0 +1,27 @@
|
||||
(function () {
|
||||
let usernameInput = document.getElementById('username');
|
||||
if (!usernameInput){
|
||||
usernameInput = document.getElementById('teacher-username');
|
||||
}
|
||||
const tip = document.getElementById('username-tip');
|
||||
|
||||
function showTip() {
|
||||
tip.classList.add('is-visible');
|
||||
tip.setAttribute('aria-hidden', 'false');
|
||||
}
|
||||
function hideTip() {
|
||||
tip.classList.remove('is-visible');
|
||||
tip.setAttribute('aria-hidden', 'true');
|
||||
}
|
||||
|
||||
usernameInput.addEventListener('focus', showTip);
|
||||
usernameInput.addEventListener('blur', hideTip);
|
||||
|
||||
// 当用户点击提示框自身时不影响(比如复制文本)
|
||||
tip.addEventListener('mousedown', e => e.preventDefault());
|
||||
|
||||
// 可选:输入时也显示(防止因某些浏览器失焦导致闪烁)
|
||||
usernameInput.addEventListener('input', () => {
|
||||
if (document.activeElement === usernameInput) showTip();
|
||||
});
|
||||
})();
|
||||
@@ -8,7 +8,11 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
const email = document.getElementById('teacher-email').value;
|
||||
const password = document.getElementById('teacher-password').value;
|
||||
const confirmPassword = document.getElementById('teacher-confirm-password').value;
|
||||
|
||||
const u = validateLinuxUsername(username);
|
||||
if (!u.ok) {
|
||||
alert(u.error);
|
||||
return;
|
||||
}
|
||||
// 检查密码和确认密码是否一致
|
||||
if (password !== confirmPassword) {
|
||||
alert('密码和确认密码不一致');
|
||||
@@ -39,3 +43,35 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// 校验 Linux 用户名
|
||||
function validateLinuxUsername(name) {
|
||||
// 基本字符规则:^[a-z_][a-z0-9_-]*[$]?$
|
||||
const basic = /^[a-z_][a-z0-9_-]*[$]?$/;
|
||||
|
||||
if (typeof name !== 'string' || name.length === 0) {
|
||||
return { ok: false, error: '用户名不能为空' };
|
||||
}
|
||||
// 长度限制(常见系统为 <= 32)
|
||||
if (name.length > 32) {
|
||||
return { ok: false, error: '用户名长度不能超过 32 个字符' };
|
||||
}
|
||||
if (!basic.test(name)) {
|
||||
return {
|
||||
ok: false,
|
||||
error:
|
||||
'用户名需以小写字母或下划线开头,仅包含小写字母、数字、下划线、连字符,允许以 $ 结尾'
|
||||
};
|
||||
}
|
||||
// 可选:避免纯数字用户名(多数系统不推荐)
|
||||
if (/^[0-9]+$/.test(name)) {
|
||||
return { ok: false, error: '用户名不能为纯数字' };
|
||||
}
|
||||
// 可选:避免使用保留名
|
||||
const reserved = new Set(['root', 'daemon', 'bin', 'sys', 'sync', 'games', 'man']);
|
||||
if (reserved.has(name)) {
|
||||
return { ok: false, error: '该用户名为系统保留名,请更换' };
|
||||
}
|
||||
|
||||
return { ok: true };
|
||||
}
|
||||
Reference in New Issue
Block a user