index style

This commit is contained in:
Cai
2025-11-13 21:08:30 +08:00
parent 9dc81b1489
commit 7dc4714ae9
32 changed files with 26283 additions and 102 deletions

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

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; 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 { .course-card {
border: none; border: none;

View File

@@ -19,19 +19,9 @@ body {
} }
main { main {
flex: 1; 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 styles */
header { header {
@@ -88,25 +78,9 @@ main {
gap: 20px; 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 { .select-button {
display: block;
width: 100%;
padding: 10px;
background-color: #2575fc;
color: white;
border: none; border: none;
cursor: pointer; cursor: pointer;
font-size: 16px; font-size: 16px;
@@ -115,11 +89,6 @@ main {
.course-card:hover { .course-card:hover {
transform: translateY(-10px); /* 提升效果 */ transform: translateY(-10px); /* 提升效果 */
} }
.course-card img {
width: 100%;
height: 261px;
object-fit: cover;
}
.course-card h3 { .course-card h3 {
padding: 15px; padding: 15px;
@@ -139,9 +108,6 @@ main {
} }
.selected-button { .selected-button {
display: block;
width: 100%;
padding: 10px;
background-color: #8a8b8c; background-color: #8a8b8c;
color: white; color: white;
border: none; border: none;

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

View File

@@ -10,6 +10,7 @@
<!-- Font Awesome 图标 --> <!-- 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="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/cdnback/all.min.css">
<link rel="stylesheet" href="/static/css/search-section.css">
<link rel="stylesheet" href="/static/css/dashboard.css"> <link rel="stylesheet" href="/static/css/dashboard.css">
</head> </head>
<body> <body>

View File

@@ -4,14 +4,11 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>华实学伴 - 专业的在线学习平台</title> <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"> <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/cdnback/all.min.css">
<link rel="stylesheet" href="/static/css/dashboard.css"> <link rel="stylesheet" href="/static/css/dashboard.css">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script> <link rel="stylesheet" href="/static/css/search-section.css">
<script src="/static/cdnback/js/bootstrap.bundle.min.js"></script>
</head> </head>
<body> <body>

View File

@@ -3,8 +3,14 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>课程选择主页</title> <title>课程选择主页</title>
<link rel="stylesheet" href="/static/css/footer.css"> <script src="/static/cdnback/jquery.min.js"></script>
<link rel="stylesheet" href="/static/css/index.css">
<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> </head>
<body> <body>
{% include 'navbar.html' %} {% include 'navbar.html' %}
@@ -30,17 +36,42 @@
<div class="course-selection"> <div class="course-selection">
<h2>课程列表</h2> <h2>课程列表</h2>
<div class="course-list"> <div class="course-cards" id="course-cards">
{% for course in courses_data %} {% for course in courses_data %}
<div class="course-card" onclick="show_course_details('{{ course._id }}')"> <!-- <div class="course-card" onclick="show_course_details('{{ course._id }}')">
<img src="{{ course.image_url }}" alt="{{ course.course_name }}"> <img src="{{ course.image_url }}" alt="{{ course.course_name }}">
<h3>{{ course.name }}</h3> <h3>{{ course.name }}</h3>
<p>{{ course.description }}</p> <p>{{ course.description }}</p>
{% if course._id in selected_courses %} {% if course._id in selected_courses %}
<button class="selected-button">已选择</button> <button class="selected-button">已选择</button>
{% else %} {% else %}
<button class="select-button" data-course-id="{{course._id}}">选择课程</button> <button class="select-button" data-course-id="{{course._id}}">选择课程</button>
{% endif %} {% 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> </div>
{% endfor %} {% endfor %}
@@ -53,7 +84,7 @@
</body> </body>
<script> <script>
window.appData = { window.appData = {
user_selected_courses: JSON.parse(`{{selected_courses}}`.replace(/&#34;/g, "\"")) user_selected_courses: JSON.parse(`{{selected_courses}}`.replace(/&#39;/g, "\""))
} }
</script> </script>
<script src="/static/js/index.js"></script> <script src="/static/js/index.js"></script>

View File

@@ -1,8 +1,5 @@
<link rel="stylesheet" href="/static/css/navbar.css"> <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/cdnback/all.min.css">
<link rel="stylesheet" href="/static/css/dashboard.css"> <link rel="stylesheet" href="/static/css/dashboard.css">
<header class="navbar"> <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 from ..auth.decorators import require_role
bp = Blueprint("auth", __name__) 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") @bp.get("/register")
def 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).