This commit is contained in:
Caikecheng
2025-10-13 19:53:00 +08:00
53 changed files with 1360 additions and 129620 deletions

View File

@@ -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') {

View File

@@ -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]';
}

View File

@@ -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 };
}

View 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();
});
})();

View File

@@ -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 };
}