6 Commits

Author SHA1 Message Date
Cai
7dc4714ae9 index style 2025-11-13 21:08:30 +08:00
Cai
9dc81b1489 Merge branch 'main' into feature/paste_detecte_new 2025-11-13 20:18:39 +08:00
0cf1896b5b paste detecte new 2025-11-05 19:00:02 +08:00
a45e5f6f37 Merge branch 'main' into czh 2025-10-29 20:18:12 +08:00
ad2de51a55 some chage 2025-10-29 20:16:10 +08:00
293cc24ac5 some change 2025-10-28 13:11:44 +08:00
37 changed files with 27219 additions and 111 deletions

500
Html/.log

File diff suppressed because one or more lines are too long

View File

@@ -57,9 +57,14 @@ def realtime_response(config: dict, realtime_action: dict) -> None:
# emit('paste_detected', paste_data)
#判断一下,如果粘帖内容过多就发送,后期可加入更多条件判断
if bb.pasted_content and len(bb.pasted_content) > 250:
chatmanager.ase_client.send("pasted_detected_in", {"file_path": file_path, "content": bb.pasted_content})
if bb.pasted_content and len(bb.pasted_content) > 200:
print(f"粘贴内容 : {bb.pasted_content[:100]}...")
print(f"ready to send")
try:
result = chatmanager.ase_client.send_text("pasted_detected_in", bb.pasted_content)
print(f"Send result: {result}")
except Exception as e:
print(f"Error sending: {e}")
elif rtype == "fileEdit":
file_path = realtime_action.get("filePath")

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,327 @@
/*!
* Bootstrap Reboot v4.4.1 (https://getbootstrap.com/)
* Copyright 2011-2019 The Bootstrap Authors
* Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/
*,
*::before,
*::after {
box-sizing: border-box;
}
html {
font-family: sans-serif;
line-height: 1.15;
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
article, aside, figcaption, figure, footer, header, hgroup, main, nav, section {
display: block;
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #212529;
text-align: left;
background-color: #fff;
}
[tabindex="-1"]:focus:not(:focus-visible) {
outline: 0 !important;
}
hr {
box-sizing: content-box;
height: 0;
overflow: visible;
}
h1, h2, h3, h4, h5, h6 {
margin-top: 0;
margin-bottom: 0.5rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title],
abbr[data-original-title] {
text-decoration: underline;
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
border-bottom: 0;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: .5rem;
margin-left: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 80%;
}
sub,
sup {
position: relative;
font-size: 75%;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -.25em;
}
sup {
top: -.5em;
}
a {
color: #007bff;
text-decoration: none;
background-color: transparent;
}
a:hover {
color: #0056b3;
text-decoration: underline;
}
a:not([href]) {
color: inherit;
text-decoration: none;
}
a:not([href]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
font-size: 1em;
}
pre {
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
}
figure {
margin: 0 0 1rem;
}
img {
vertical-align: middle;
border-style: none;
}
svg {
overflow: hidden;
vertical-align: middle;
}
table {
border-collapse: collapse;
}
caption {
padding-top: 0.75rem;
padding-bottom: 0.75rem;
color: #6c757d;
text-align: left;
caption-side: bottom;
}
th {
text-align: inherit;
}
label {
display: inline-block;
margin-bottom: 0.5rem;
}
button {
border-radius: 0;
}
button:focus {
outline: 1px dotted;
outline: 5px auto -webkit-focus-ring-color;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
input {
overflow: visible;
}
button,
select {
text-transform: none;
}
select {
word-wrap: normal;
}
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
button:not(:disabled),
[type="button"]:not(:disabled),
[type="reset"]:not(:disabled),
[type="submit"]:not(:disabled) {
cursor: pointer;
}
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
padding: 0;
border-style: none;
}
input[type="radio"],
input[type="checkbox"] {
box-sizing: border-box;
padding: 0;
}
input[type="date"],
input[type="time"],
input[type="datetime-local"],
input[type="month"] {
-webkit-appearance: listbox;
}
textarea {
overflow: auto;
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
display: block;
width: 100%;
max-width: 100%;
padding: 0;
margin-bottom: .5rem;
font-size: 1.5rem;
line-height: inherit;
color: inherit;
white-space: normal;
}
progress {
vertical-align: baseline;
}
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
[type="search"] {
outline-offset: -2px;
-webkit-appearance: none;
}
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
summary {
display: list-item;
cursor: pointer;
}
template {
display: none;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.css.map */

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,8 @@
/*!
* Bootstrap Reboot v4.4.1 (https://getbootstrap.com/)
* Copyright 2011-2019 The Bootstrap Authors
* Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]){color:inherit;text-decoration:none}a:not([href]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}
/*# sourceMappingURL=bootstrap-reboot.min.css.map */

File diff suppressed because one or more lines are too long

10224
Html/apps/static/cdnback/css/bootstrap.css vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4521
Html/apps/static/cdnback/js/bootstrap.js vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -336,18 +336,6 @@ body {
margin-left: 0.75rem;
}
/* 搜索区域 */
.search-section {
padding: 0;
}
.search-container {
background-color: white;
border-radius: 12px;
padding: 1.5rem;
box-shadow: var(--card-shadow);
}
/* 课程卡片样式 */
.course-card {
border: none;

View File

@@ -19,19 +19,9 @@ body {
}
main {
flex: 1;
padding: 0 20px;
}
/* 搜索区域 */
.search-section {
padding: 0;
}
.search-container {
background-color: white;
border-radius: 12px;
padding: 1.5rem;
box-shadow: var(--card-shadow);
}
/* Header styles */
header {
@@ -88,25 +78,9 @@ main {
gap: 20px;
}
.course-card {
background-color: white;
display: flex;
flex-direction: column;
border-radius: 8px;
width: 300px;
height: 400px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
overflow: hidden;
transition: transform 0.3s ease;
margin: 0px;
}
.select-button {
display: block;
width: 100%;
padding: 10px;
background-color: #2575fc;
color: white;
border: none;
cursor: pointer;
font-size: 16px;
@@ -115,11 +89,6 @@ main {
.course-card:hover {
transform: translateY(-10px); /* 提升效果 */
}
.course-card img {
width: 100%;
height: 261px;
object-fit: cover;
}
.course-card h3 {
padding: 15px;
@@ -139,9 +108,6 @@ main {
}
.selected-button {
display: block;
width: 100%;
padding: 10px;
background-color: #8a8b8c;
color: white;
border: none;

View File

@@ -0,0 +1,281 @@
:root {
--primary-blue: #6A9FB5;
--secondary-blue: #8BB4C5;
--light-blue: #E1F0F7;
--accent-blue: #4A7B9D;
--text-dark: #2C3E50;
--text-light: #7F8C8D;
--card-shadow: 0 4px 12px rgba(106, 159, 181, 0.15);
}
/* 学习路径区域 */
.learning-path-section {
background: linear-gradient(135deg, var(--light-blue), #D4E9F2);
padding: 2rem 0;
border-radius: 0 0 20px 20px;
margin-bottom: 2rem;
}
.section-title {
color: var(--accent-blue);
font-weight: 600;
margin-bottom: 1.5rem;
position: relative;
padding-bottom: 0.5rem;
font-size: 28px;
}
.section-title:after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 60px;
height: 3px;
background-color: var(--primary-blue);
border-radius: 2px;
}
/* 专业选择器 */
.major-selector {
position: relative;
margin-bottom: 2rem;
}
.major-selector label {
font-weight: 600;
color: var(--accent-blue);
margin-bottom: 0.5rem;
display: block;
}
.major-selector select {
appearance: none;
background-color: white;
border: 2px solid var(--primary-blue);
border-radius: 8px;
padding: 0.75rem 1.5rem;
font-size: 1rem;
color: var(--text-dark);
width: 100%;
max-width: 300px;
cursor: pointer;
transition: all 0.3s ease;
}
.major-selector select:focus {
outline: none;
box-shadow: 0 0 0 3px rgba(106, 159, 181, 0.3);
border-color: var(--accent-blue);
}
.major-selector::after {
content: '\f078';
font-family: 'Font Awesome 5 Free';
font-weight: 900;
position: absolute;
top: 50%;
right: 1rem;
transform: translateY(-50%);
pointer-events: none;
color: var(--primary-blue);
}
/* 学习路径流程图 */
.path-flow {
background-color: white;
border-radius: 12px;
padding: 2rem;
box-shadow: var(--card-shadow);
overflow-x: auto;
position: relative;
}
.path-container {
display: flex;
min-width: 900px;
position: relative;
}
.path-step {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
position: relative;
padding: 0 1rem;
}
.step-connector {
position: absolute;
top: 40px;
left: -50%;
width: 100%;
height: 2px;
background-color: var(--primary-blue);
z-index: 1;
}
.step-node {
width: 80px;
height: 80px;
border-radius: 50%;
background-color: var(--light-blue);
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 1rem;
position: relative;
z-index: 2;
transition: all 0.3s ease;
cursor: pointer;
}
.step-node:hover {
transform: scale(1.05);
background-color: var(--primary-blue);
}
.step-node:hover .step-icon {
color: white;
}
.step-icon {
font-size: 1.8rem;
color: var(--accent-blue);
}
.step-content {
text-align: center;
width: 100%;
}
.step-title {
font-weight: 600;
margin-bottom: 0.5rem;
color: var(--accent-blue);
}
.step-courses {
font-size: 0.9rem;
color: var(--text-light);
margin-bottom: 0.5rem;
}
.step-progress {
height: 6px;
background-color: #e9ecef;
border-radius: 3px;
overflow: hidden;
margin-bottom: 0.5rem;
}
.step-progress-bar {
height: 100%;
background-color: var(--primary-blue);
border-radius: 3px;
transition: width 0.5s ease;
}
.step-status {
font-size: 0.8rem;
color: var(--text-light);
}
/* 阶段状态样式 */
.step-completed .step-node {
background-color: var(--primary-blue);
}
.step-completed .step-icon {
color: white;
}
.step-active .step-node {
background-color: var(--accent-blue);
box-shadow: 0 0 0 4px rgba(74, 123, 157, 0.3);
}
.step-active .step-icon {
color: white;
}
/* 课程详情面板 */
.course-panel {
display: none;
background-color: white;
border-radius: 12px;
padding: 1.5rem;
box-shadow: var(--card-shadow);
margin-top: 1.5rem;
}
.course-panel.active {
display: block;
}
.panel-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1rem;
padding-bottom: 0.5rem;
border-bottom: 1px solid #e9ecef;
}
.panel-title {
font-weight: 600;
color: var(--accent-blue);
margin: 0;
}
.close-panel {
background: none;
border: none;
font-size: 1.2rem;
color: var(--text-light);
cursor: pointer;
}
.course-list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 1rem;
}
.course-item {
display: flex;
align-items: center;
padding: 0.75rem;
border-radius: 8px;
border: 1px solid #e9ecef;
transition: all 0.3s ease;
}
.course-item:hover {
border-color: var(--primary-blue);
box-shadow: 0 2px 8px rgba(106, 159, 181, 0.15);
}
.course-check {
margin-right: 0.75rem;
color: #28a745;
}
.course-info {
flex: 1;
}
.course-name {
font-weight: 500;
margin-bottom: 0.25rem;
}
.course-duration {
font-size: 0.8rem;
color: var(--text-light);
}
.course-action {
margin-left: 0.75rem;
}

View File

@@ -1,12 +1,8 @@
/* 页眉导航栏 */
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #2575fc;
color: rgb(235, 235, 235);
border-radius: 10px;
margin-bottom: 30px;
background: linear-gradient(135deg, var(--primary-blue), var(--accent-blue));
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
padding: 0.8rem 1rem;
}
.navbar .logo h1 {

View File

@@ -0,0 +1,12 @@
/* 搜索区域 */
.search-section {
padding: 0;
}
.search-container {
background-color: white;
border-radius: 12px;
padding: 1.5rem;
box-shadow: var(--card-shadow);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 738 KiB

View File

@@ -6,37 +6,36 @@ function show_course_details(course_id){
window.location.href = '/course/' + course_id
}
document.addEventListener('DOMContentLoaded', function() {
const selectButtons = document.querySelectorAll('.select-button');
selectButtons.forEach(button => {
button.addEventListener('click', function(event) {
event.stopPropagation(); // 阻止事件冒泡
const courseId = this.getAttribute('data-course-id');
fetch(`/select_course`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': '{{ csrf_token() }}' // 如果使用 CSRF 保护
},
body: JSON.stringify({ course_id: courseId })
})
.then(response => response.json())
.then(data => {
if (data.success) {
// 更新按钮样式或显示消息
this.classList.remove('select-button');
this.classList.add('selected-button');
this.textContent = '选择';
alert('选择课程成功');
} else {
alert('选择课程失败');
}
})
.catch(error => {
console.error('Error:', error);
alert('选择课程失败');
});
});
function on_click_select_course(event){
event.stopPropagation(); // 阻止事件冒泡
const courseId = event.currentTarget.getAttribute('data-course-id');
if (event.currentTarget.classList.contains("selected-button")) {alert('课程已选择'); return;}
fetch(`/select_course`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': '{{ csrf_token() }}' // 如果使用 CSRF 保护
},
body: JSON.stringify({ course_id: courseId })
})
.then(response => response.json())
.then(data => {
if (data.success) {
// 更新按钮样式或显示消息
this.classList.remove('select-button');
this.classList.add('selected-button');
this.textContent = '已选择';
alert('选择课程成功');
} else {
alert('选择课程失败');
}
})
.catch(error => {
console.error('Error:', error);
alert('选择课程失败');
});
}
document.addEventListener('DOMContentLoaded', function() {
});

View File

@@ -0,0 +1,30 @@
// 1. 点击学习阶段节点,显示对应课程面板
document.querySelectorAll('.step-node').forEach((node) => {
node.addEventListener('click', function () {
// 隐藏所有面板
document.querySelectorAll('.course-panel').forEach(panel => {
panel.classList.remove('active');
});
// 获取当前阶段名称匹配面板ID
const stepTitle = this.closest('.path-step').querySelector('.step-title').textContent;
const panelId = stepTitle.toLowerCase().replace(' ', '-') + '-panel';
const targetPanel = document.getElementById(panelId);
// 显示对应面板(若存在)
if (targetPanel) {
targetPanel.classList.add('active');
}
});
});
// 2. 关闭课程面板
document.querySelectorAll('.close-panel').forEach(button => {
button.addEventListener('click', function () {
this.closest('.course-panel').classList.remove('active');
});
});
// 3. 切换专业方向(可扩展为动态更新学习路径)
document.getElementById('majorSelect').addEventListener('change', function () {
const selectedMajor = this.options[this.selectedIndex].text;
// 实际项目中可替换为AJAX请求加载对应专业的学习路径
});

View File

@@ -10,6 +10,7 @@
<!-- Font Awesome 图标 -->
<!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"> -->
<link rel="stylesheet" href="/static/cdnback/all.min.css">
<link rel="stylesheet" href="/static/css/search-section.css">
<link rel="stylesheet" href="/static/css/dashboard.css">
</head>
<body>

View File

@@ -4,16 +4,16 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>华实学伴 - 专业的在线学习平台</title>
<!-- Bootstrap 5 CSS -->
<!-- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"> -->
<link href="/static/cdnback/bootstrap.min.css" rel="stylesheet">
<!-- Font Awesome 图标 -->
<!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"> -->
<link rel="stylesheet" href="/static/cdnback/all.min.css">
<link rel="stylesheet" href="/static/css/dashboard.css">
<link rel="stylesheet" href="/static/css/search-section.css">
<script src="/static/cdnback/js/bootstrap.bundle.min.js"></script>
</head>
<body>
{% include 'navbar.html' %} <!-- 引入navbar.html -->
{% include 'learning-path.html' %} <!-- 引入learning-path.html -->
<section class="search-section">
<div class="container">
<div class="row justify-content-center">

View File

@@ -3,8 +3,14 @@
<head>
<meta charset="UTF-8">
<title>课程选择主页</title>
<link rel="stylesheet" href="/static/css/footer.css">
<link rel="stylesheet" href="/static/css/index.css">
<script src="/static/cdnback/jquery.min.js"></script>
<link href="/static/cdnback/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="/static/cdnback/all.min.css">
<link rel="stylesheet" href="/static/css/dashboard.css">
<link rel="stylesheet" href="/static/css/search-section.css">
<script src="/static/cdnback/js/bootstrap.bundle.min.js"></script>
<link rel="stylesheet" href="/static/css/index.css">
</head>
<body>
{% include 'navbar.html' %}
@@ -30,17 +36,42 @@
<div class="course-selection">
<h2>课程列表</h2>
<div class="course-list">
<div class="course-cards" id="course-cards">
{% for course in courses_data %}
<div class="course-card" onclick="show_course_details('{{ course._id }}')">
<img src="{{ course.image_url }}" alt="{{ course.course_name }}">
<h3>{{ course.name }}</h3>
<p>{{ course.description }}</p>
{% if course._id in selected_courses %}
<button class="selected-button">已选择</button>
{% else %}
<button class="select-button" data-course-id="{{course._id}}">选择课程</button>
{% endif %}
<!-- <div class="course-card" onclick="show_course_details('{{ course._id }}')">
<img src="{{ course.image_url }}" alt="{{ course.course_name }}">
<h3>{{ course.name }}</h3>
<p>{{ course.description }}</p>
{% if course._id in selected_courses %}
<button class="selected-button">已选择</button>
{% else %}
<button class="select-button" data-course-id="{{course._id}}">选择课程</button>
{% endif %}
</div> -->
<div class="col-md-6 col-lg-4">
<div class="course-card card h-100" onclick="openCourseProgress('{{course._id}}')">
<img src="{{course.image_url}}"
class="course-img" alt="课程封面">
<div class="card-body d-flex flex-column">
<span class="course-category">算法设计</span>
<h5 class="course-title">{{course.name}}</h5>
<p class="course-instructor">{{course.description}}</p>
<div class="course-meta">
<span><i class="far fa-user me-1"></i> 初级</span>
<span class="course-rating"><i class="fas fa-star"></i> 4.7</span>
</div>
<div class="mt-auto d-grid gap-2 d-md-flex">
<button class="btn btn-view flex-fill" onclick="btn_view(event,'{{course._id}}')"><i class="far fa-eye me-1"></i> 课程</button>
{% if course._id in selected_courses %}
<button class="btn btn-process flex-fill selected-button" data-course-id="{{course._id}}">已选课</button>
{% else %}
<button class="btn btn-process flex-fill select-button" onclick="on_click_select_course(event)" data-course-id="{{course._id}}">选择课程</button>
{% endif %}
</div>
</div>
</div>
</div>
{% endfor %}
@@ -53,7 +84,7 @@
</body>
<script>
window.appData = {
user_selected_courses: JSON.parse(`{{selected_courses}}`.replace(/&#34;/g, "\""))
user_selected_courses: JSON.parse(`{{selected_courses}}`.replace(/&#39;/g, "\""))
}
</script>
<script src="/static/js/index.js"></script>

View File

@@ -0,0 +1,145 @@
<link rel="stylesheet" href="/static/css/learning-path.css">
<!-- 学习路径区域 -->
<section class="learning-path-section">
<div class="container">
<h2 class="section-title">学习路径</h2>
<!-- 专业选择器 -->
<div class="major-selector">
<label for="majorSelect">选择专业方向:</label>
<select class="form-select" id="majorSelect">
<option value="computer">计算机科学与技术</option>
<option value="data">数据科学与大数据</option>
<option value="business">工商管理</option>
<option value="design">艺术设计</option>
<option value="language">语言文学</option>
</select>
</div>
<!-- 学习路径流程图 -->
<div class="path-flow">
<div class="path-container">
<!-- 阶段1已完成 -->
<div class="path-step step-completed">
<div class="step-connector"></div>
<div class="step-node">
<i class="fas fa-code step-icon"></i>
</div>
<div class="step-content">
<div class="step-title">编程基础</div>
<div class="step-courses">3门课程</div>
<div class="step-progress">
<div class="step-progress-bar" style="width: 100%"></div>
</div>
<div class="step-status">已完成</div>
</div>
</div>
<!-- 阶段2已完成 -->
<div class="path-step step-completed">
<div class="step-connector"></div>
<div class="step-node">
<i class="fas fa-project-diagram step-icon"></i>
</div>
<div class="step-content">
<div class="step-title">数据结构</div>
<div class="step-courses">2门课程</div>
<div class="step-progress">
<div class="step-progress-bar" style="width: 100%"></div>
</div>
<div class="step-status">已完成</div>
</div>
</div>
<!-- 阶段3进行中 -->
<div class="path-step step-active">
<div class="step-connector"></div>
<div class="step-node">
<i class="fas fa-brain step-icon"></i>
</div>
<div class="step-content">
<div class="step-title">算法设计</div>
<div class="step-courses">3门课程</div>
<div class="step-progress">
<div class="step-progress-bar" style="width: 67%"></div>
</div>
<div class="step-status">进行中</div>
</div>
</div>
<!-- 阶段4未开始 -->
<div class="path-step">
<div class="step-connector"></div>
<div class="step-node">
<i class="fas fa-database step-icon"></i>
</div>
<div class="step-content">
<div class="step-title">数据库原理</div>
<div class="step-courses">2门课程</div>
<div class="step-progress">
<div class="step-progress-bar" style="width: 0%"></div>
</div>
<div class="step-status">未开始</div>
</div>
</div>
<!-- 阶段5未开始 -->
<div class="path-step">
<div class="step-connector"></div>
<div class="step-node">
<i class="fas fa-laptop-code step-icon"></i>
</div>
<div class="step-content">
<div class="step-title">Web开发</div>
<div class="step-courses">5门课程</div>
<div class="step-progress">
<div class="step-progress-bar" style="width: 0%"></div>
</div>
<div class="step-status">未开始</div>
</div>
</div>
</div>
<!-- 课程详情面板(默认隐藏,点击阶段显示) -->
<div class="course-panel" id="algorithm-panel">
<div class="panel-header">
<h3 class="panel-title">算法设计 - 课程列表</h3>
<button class="close-panel"><i class="fas fa-times"></i></button>
</div>
<div class="course-list">
<div class="course-item">
<i class="fas fa-check-circle course-check"></i>
<div class="course-info">
<div class="course-name">算法基础与复杂度分析</div>
<div class="course-duration">12课时</div>
</div>
<div class="course-action">
<button class="btn btn-sm btn-primary">继续学习</button>
</div>
</div>
<div class="course-item">
<i class="fas fa-check-circle course-check"></i>
<div class="course-info">
<div class="course-name">排序与搜索算法</div>
<div class="course-duration">15课时</div>
</div>
<div class="course-action">
<button class="btn btn-sm btn-primary">继续学习</button>
</div>
</div>
<div class="course-item">
<i class="far fa-circle course-check"></i>
<div class="course-info">
<div class="course-name">动态规划与贪心算法</div>
<div class="course-duration">18课时</div>
</div>
<div class="course-action">
<button class="btn btn-sm btn-outline-primary">开始学习</button>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="/static/js/learning-path.js"></script>
</section>

View File

@@ -1,8 +1,5 @@
<link rel="stylesheet" href="/static/css/navbar.css">
<!-- Bootstrap 5 CSS -->
<!-- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"> -->
<!-- Font Awesome 图标 -->
<!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"> -->
<link rel="stylesheet" href="/static/cdnback/all.min.css">
<link rel="stylesheet" href="/static/css/dashboard.css">
<header class="navbar">

View File

@@ -4,6 +4,10 @@ from ..services.auth_service import register_user, login_user, logout_user
from ..auth.decorators import require_role
bp = Blueprint("auth", __name__)
# 将/favicon.ico重定向到/static/favicon.ico
@bp.route('/favicon.ico')
def redirect_favicon():
return redirect(url_for('static', filename='favicon.ico'))
@bp.get("/register")
def register():

2
Html/nohup.out Normal file
View File

@@ -0,0 +1,2 @@
[2025-11-13 20:27:29,577] INFO in __init__: Shutting down gracefully (2)...
[2025-11-13 20:27:29,578] INFO in __init__: Cleanup finished (2).