Skip to content
This repository was archived by the owner on Oct 17, 2023. It is now read-only.

Commit 94336c0

Browse files
authoredOct 7, 2023
Add files via upload
1 parent a7bfd06 commit 94336c0

31 files changed

+705
-0
lines changed
 

‎vadamecum/app.py

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from flask import Flask
2+
from models import db
3+
import views
4+
5+
app = Flask(__name__)
6+
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///students.db'
7+
app.config['SECRET_KEY'] = 'secret key'
8+
db.init_app(app)
9+
10+
11+
@app.route("/")
12+
def index():
13+
return views.index()
14+
15+
16+
@app.route("/login", methods=['GET', 'POST'])
17+
def login():
18+
return views.login()
19+
20+
21+
@app.route('/api/students/edit/<int:id>', methods=['POST'])
22+
def edit_student(id):
23+
return views.edit_student(id)
24+
25+
26+
27+
@app.route('/api/students/delete/<int:id>', methods=['DELETE'])
28+
def delete_student(id):
29+
return views.delete_student(id)
30+
31+
32+
33+
if __name__ == "__main__":
34+
app.run(debug=True)

‎vadamecum/forms.py

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from flask_wtf import FlaskForm # 导入FlaskForm类,这是WTForms集成到Flask中的表单基类
2+
from wtforms import StringField, SubmitField, IntegerField # 导入我们需要的表单字段类,这里导入了字符串字段和提交按钮字段
3+
from wtforms.validators import DataRequired # 导入验证器类DataRequired,用于对字段进行必填验证
4+
5+
6+
class LoginForm(FlaskForm):
7+
csrf_enabled = False
8+
user = StringField('User', validators=[DataRequired()])
9+
password = StringField('Password', validators=[DataRequired()])
10+
submit = SubmitField('Submit')
11+
12+
13+
class MainForm(FlaskForm):
14+
csrf_enabled = False
15+
id = IntegerField('Id', validators=[DataRequired()])
16+
username = StringField('UserName', validators=[DataRequired()])
17+
college = StringField('College', validators=[DataRequired()])
18+
major = StringField('Major', validators=[DataRequired()])
19+
grade = IntegerField('Grade', validators=[DataRequired()])
20+
submit = SubmitField('Submit')
21+
22+

‎vadamecum/instance/students.db

444 KB
Binary file not shown.

‎vadamecum/models.py

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from flask_sqlalchemy import SQLAlchemy
2+
3+
db = SQLAlchemy()
4+
5+
6+
class Students(db.Model):
7+
__tablename__ = "students"
8+
index = db.Column(db.Integer, primary_key=True, autoincrement=True)
9+
id = db.Column(db.Integer, unique=True, nullable=False)
10+
username = db.Column(db.String(5), unique=True, nullable=False)
11+
college = db.Column(db.String(20), nullable=False)
12+
major = db.Column(db.String(30), nullable=False)
13+
grade = db.Column(db.String(4), nullable=False)
14+
15+
editing = db.Column(db.Boolean, default=False)
16+
17+
ix_name = db.Index('ix_students_username', 'username', unique=True)
18+
ix_id = db.Index('ix_students_id', 'id', unique=True)
19+
20+
def __repr__(self):
21+
return f'<Student {self.username}>'
22+
23+
24+
class User(db.Model):
25+
__tablename__ = "user"
26+
index = db.Column(db.Integer, primary_key=True, autoincrement=True)
27+
user = db.Column(db.String(10), unique=True, nullable=False)
28+
password = db.Column(db.String(18), nullable=False)
29+
30+
ix_user = db.Index('ix_user_user', 'user', unique=True)

‎vadamecum/requirements.txt

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
flask~=2.3.3
2+
flask_sqlalchemy~=3.1.1
3+
SQLAlchemy~=2.0.21
4+
WTForms~=3.0.1
5+
bcrypt~=4.0.1

‎vadamecum/static/images/icons/QQ.svg

+1
Loading
Loading
Loading
+1
Loading
Loading
+7
Loading
Loading
+1
Loading
Loading
Loading
Loading
Loading
+1
Loading
Loading
Loading
+49
Loading
+47
Loading
463 KB
Loading

‎vadamecum/static/scripts/login.js

Whitespace-only changes.

‎vadamecum/static/scripts/main.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const selectAll = document.querySelector("#select-all");
2+
3+
// 监听change事件
4+
selectAll.addEventListener('change', (e) => {
5+
// 获取所有选择框
6+
const items = document.querySelectorAll("input[type=checkbox]");
7+
8+
// 设置checked状态
9+
items.forEach(item => {
10+
item.checked = e.target.checked;
11+
})
12+
})
13+
14+

‎vadamecum/static/styles/login.css

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
body {
2+
background-color: #1d74b2;
3+
}

‎vadamecum/static/styles/main.css

+243
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
.page-container {
2+
display: grid;
3+
grid-template-columns: 150px 1fr; /* 定义两列,sidebar 和 main */
4+
grid-template-rows: 50px 1fr; /* 定义两行,header 和 主体 */
5+
grid-template-areas:
6+
"header header"
7+
"sidebar main";
8+
margin: 0;
9+
}
10+
11+
12+
.header {
13+
display: grid;
14+
grid-area: header;
15+
grid-template-columns: 20px 120px 1fr 200px 20px;
16+
grid-template-areas: ". div . ul .";
17+
background-color: #1d74b2;
18+
color: #fff;
19+
position: fixed;
20+
top: 0;
21+
left: 0;
22+
width: 100%;
23+
z-index: 100;
24+
25+
align-items: center;
26+
height: 50px;
27+
}
28+
29+
.header div {
30+
display: grid;
31+
grid-area: div;
32+
grid-template-columns: 1fr 2fr;
33+
align-items: center;
34+
}
35+
36+
.header ul {
37+
display: grid;
38+
grid-area: ul;
39+
grid-template-columns: 30px 30px 30px 30px;
40+
grid-column-gap: 20px;
41+
align-items: center;
42+
list-style-type: none;
43+
padding: 0;
44+
}
45+
46+
47+
.header ul img {
48+
width: 25px;
49+
}
50+
51+
52+
/* sidebar样式 */
53+
.sidebar {
54+
grid-area: sidebar;
55+
width: 150px;
56+
background-color: #223142;
57+
color: #fff;
58+
position: fixed;
59+
top: 40px; /* 调整top值以适应header的高度 */
60+
left: 0;
61+
height: 100%;
62+
}
63+
64+
.sidebar ul {
65+
list-style: none;
66+
padding: 0;
67+
}
68+
69+
.sidebar li {
70+
padding: 10px;
71+
}
72+
73+
.sidebar a {
74+
text-decoration: none;
75+
color: #fff;
76+
display: block;
77+
}
78+
79+
.sidebar a:hover {
80+
background-color: #555;
81+
}
82+
83+
/* 主要内容区域样式 */
84+
.main {
85+
grid-area: main;
86+
display: grid;
87+
grid-template-columns: 20px 1fr 10px;
88+
grid-template-areas:
89+
"block block block"
90+
"title title title"
91+
"table-action table-action table-action"
92+
"left-margin table right-margin";
93+
}
94+
95+
.left-margin {
96+
grid-area: left-margin;
97+
}
98+
99+
.right-margin {
100+
grid-area: right-margin;
101+
}
102+
103+
.block {
104+
grid-area: block;
105+
height: 28px;
106+
}
107+
.title {
108+
grid-area: title;
109+
background-color: #e9e9e9;
110+
font-size: 12px;
111+
padding: 10px 20px;
112+
}
113+
114+
.title h3 {
115+
float: left;
116+
font-size: 1.17em;
117+
color: #333;
118+
font-weight: 400;
119+
margin: 0;
120+
}
121+
122+
123+
/* table acton */
124+
.table-actions {
125+
grid-area: table-action;
126+
display: grid;
127+
grid-template-columns: 1fr 1fr 1fr;
128+
align-items: center;
129+
margin-bottom: 10px;
130+
}
131+
132+
133+
.search-box {
134+
display: grid;
135+
grid-template-columns: 30px 90px 125px 20px;
136+
grid-template-areas: "span span box icon";
137+
}
138+
139+
.search-box span {
140+
grid-area: span;
141+
font-size: 8px;
142+
padding: 5px 0;
143+
margin-top: 15px;
144+
}
145+
146+
.search-input {
147+
grid-area: box;
148+
background-color: #fff;
149+
border: 1px solid #ddd;
150+
border-right-width: 0;
151+
color: #666;
152+
font-size: 12px;
153+
height: 26px;
154+
width: 125px;
155+
padding-left: 5px;
156+
padding-right: 0;
157+
border-radius: 2px;
158+
margin-top: 15px;
159+
}
160+
161+
.search-icon {
162+
grid-area: icon;
163+
align-items: center;
164+
background: url("../images/icons/search.svg") no-repeat center;
165+
border: 1px solid #ddd;
166+
border-left-width: 0;
167+
border-radius: 2px;
168+
cursor: pointer;
169+
height: 30px;
170+
margin-top: 15px;
171+
}
172+
173+
.btn-group {
174+
display: grid;
175+
grid-template-columns: 1fr 1fr 1fr 1fr;
176+
column-gap: 10px;
177+
margin-right: 20px;
178+
margin-top: 15px;
179+
}
180+
181+
.btn-group a {
182+
display: inline-block;
183+
margin-right: 5px;
184+
padding: 4px 20px;
185+
background: #fff;
186+
height: 20px;
187+
border: 1px solid #ddd;
188+
font-size: 15px;
189+
color: #89949b;
190+
text-align: center;
191+
cursor: pointer;
192+
transition: all .4s ease 0s;
193+
border-radius: 2px;
194+
}
195+
196+
.data-action {
197+
198+
}
199+
200+
.data-action a {
201+
text-decoration: none;
202+
color: #08c;
203+
display: inline-block;
204+
margin-right: 5px;
205+
white-space: nowrap;
206+
word-break: normal;
207+
cursor: pointer;
208+
}
209+
210+
211+
.table {
212+
grid-area: table;
213+
-webkit-border-horizontal-spacing: 0;
214+
-webkit-border-vertical-spacing: 0;
215+
table-layout: fixed;
216+
width: 100%;
217+
}
218+
219+
220+
.table tr {
221+
display: grid;
222+
grid-template-columns: 1fr 1fr 3fr 3fr 1fr 1fr 1fr;
223+
}
224+
225+
.table th {
226+
font-size: 15px;
227+
background-color: #4c5366;
228+
color: #fff;
229+
padding: 7px 6px;
230+
font-weight: 400
231+
}
232+
233+
234+
.table td {
235+
color: #666;
236+
font-size: 15px;
237+
border-bottom: 1px;
238+
padding: 10px 6px;
239+
word-wrap: break-word;
240+
transition: all .4s ease 0s;
241+
overflow: hidden;
242+
text-align: center;
243+
}

‎vadamecum/students.xls

273 KB
Binary file not shown.

‎vadamecum/templates/index.html

+139
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
<!doctype html>
2+
<html lang="zh">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width" />
6+
<title>学生信息管理系统</title>
7+
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
8+
<link rel="stylesheet" href="../static/styles/main.css">
9+
</head>
10+
<body class="page-container">
11+
12+
<header class="header">
13+
<div>
14+
<img src="../static/images/logos/logo.svg" alt="logo not found" style="width: 20px">
15+
<img src="../static/images/logos/hduhelp.svg" alt="logo not found" style="width: 60px">
16+
</div>
17+
<ul>
18+
<li><img src="../static/images/icons/wechat-fill.svg" alt="wechat" /></li>
19+
<li><img src="../static/images/icons/QQ.svg" alt="QQ" ></li>
20+
<li><img src="../static/images/icons/github-fill.svg" alt="github" ></li>
21+
<li><img src="../static/images/icons/user-fill.svg" alt="manager" ></li>
22+
</ul>
23+
</header>
24+
25+
<div class="sidebar">
26+
<ul>
27+
<li><a href="#">首页</a></li>
28+
<li><a href="#">学生列表</a></li>
29+
<li><a href="#">成绩管理</a></li>
30+
<li><a href="#">课程表</a></li>
31+
</ul>
32+
</div>
33+
34+
<div class="main">
35+
<!-- 这里放置您的主要内容 -->
36+
<div class="block"></div>
37+
38+
<div class="title"><h3>学生信息管理</h3></div>
39+
40+
<div class="table-actions">
41+
42+
<div class="search-box">
43+
<span></span>
44+
<span>查找学生信息:</span>
45+
<input type="text" placeholder="搜索学号、姓名..." class="search-input">
46+
<input type="button" class="search-icon">
47+
</div>
48+
49+
<div class="filterBtn">
50+
<button>筛选</button>
51+
</div>
52+
53+
<div class="btn-group">
54+
<a style="background-color: #59cba0;color: #fff">新增</a>
55+
<a>导入</a>
56+
<a>导出</a>
57+
<a>删除</a>
58+
</div>
59+
</div>
60+
61+
<div class="left-margin"></div>
62+
<table class="table">
63+
<thead>
64+
<tr>
65+
<th>学号</th>
66+
<th>姓名</th>
67+
<th>学院</th>
68+
<th>专业</th>
69+
<th>年级</th>
70+
<th>操作</th>
71+
<th><input type="checkbox" id="select-all"></th>
72+
</tr>
73+
</thead>
74+
75+
<tbody>
76+
{% for student in students %}
77+
<tr>
78+
{% if not student.editing %}
79+
<td>
80+
<input value="{{student.id}}">
81+
</td>
82+
{% else %}
83+
<td>{{student.id}}</td>
84+
{% endif %}
85+
86+
{% if not student.editing %}
87+
<td>
88+
<input value="{{student.username}}">
89+
</td>
90+
{% else %}
91+
<td>{{student.username}}</td>
92+
{% endif %}
93+
94+
{% if not student.editing %}
95+
<td>
96+
<input value="{{student.college}}">
97+
</td>
98+
{% else %}
99+
<td style="white-space: nowrap">{{student.college}}</td>
100+
{% endif %}
101+
102+
{% if not student.college %}
103+
<td>
104+
<input value="{{student.major}}">
105+
</td>
106+
{% else %}
107+
<td style="white-space: nowrap">{{student.major}}</td>
108+
{% endif %}
109+
110+
{% if not student.editing %}
111+
<td>
112+
<input value="{{student.grade}}">
113+
</td>
114+
{% else %}
115+
<td>{{student.grade}}</td>
116+
{% endif %}
117+
118+
<td class="data-action">
119+
<a class="edit-btn">编辑</a>
120+
<a class="delete-btn">删除</a>
121+
</td>
122+
<td><input type="checkbox" class="check"></td>
123+
</tr>
124+
{% endfor %}
125+
</tbody>
126+
</table>
127+
<div class="right-margin"></div>
128+
129+
<nav aria-label="Page navigation">
130+
{% for page in students.iter_pages() %}
131+
<a href="{{ url_for('index', page=page) }}">{{ page }}</a>
132+
{% endfor %}
133+
</nav>
134+
</div>
135+
136+
<script src="../static/scripts/main.js"></script>
137+
138+
</body>
139+
</html>

‎vadamecum/templates/login.html

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<!DOCTYPE HTML>
2+
<html lang = "zh-CN">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width" />
6+
<title>用户登录界面</title>
7+
<link rel="stylesheet" href="../static/styles/login.css">
8+
</head>
9+
<body>
10+
<div id="app">
11+
<div>
12+
<ul>
13+
<li>
14+
<a href="https://www.hduhelp.cn" target="_blank" >杭州官网</a>
15+
</li>
16+
<li>
17+
<a href="https://www.i.hdu.cn" target="_blank" >智慧杭电</a>
18+
</li>
19+
<li>
20+
<a href="https://www.webvpn.edu.hdu.cn" target="_blank" >杭电vpn</a>
21+
</li>
22+
</ul>
23+
<div>
24+
<form method="post" action="{{ url_for('login') }}">
25+
<div class="logo">
26+
<img src="../static/images/logos/logo.svg" alt="logo not found">
27+
</div>
28+
<span></span>
29+
<div class="logo">
30+
<img src="../static/images/logos/hduhelp.svg" alt="logo not found">
31+
</div>
32+
{{ form.hidden_tag() }}
33+
<label for="user">Email</label>
34+
<input type="text" id="user" name="user">
35+
<label for="password">Password</label>
36+
<input type="password" id="password" name="password">
37+
{% with messages = get_flashed_messages() %}
38+
{% if messages %}
39+
<ul class=flashes>
40+
{% for message in messages %}
41+
<li>{{ message }}</li>
42+
{% endfor %}
43+
</ul>
44+
{% endif %}
45+
{% endwith %}
46+
<button type="submit">submit</button>
47+
<div>
48+
<label>
49+
<input type="checkbox">
50+
<span></span>
51+
记住密码
52+
</label>
53+
<span style="display:inline-block;position: relative;cursor: pointer;">
54+
忘记密码
55+
<p>
56+
<span></span>
57+
请联系管理员qq:2742518001
58+
</p>
59+
</span>
60+
</div>
61+
</form>
62+
</div>
63+
</div>
64+
</div>
65+
</body>
66+
</html>

‎vadamecum/views.py

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from flask import request, render_template, redirect, url_for, flash
2+
from forms import LoginForm, MainForm
3+
from models import Students, User
4+
5+
6+
def index():
7+
page = request.args.get('page', 1, type=int)
8+
students = Students.query.order_by(Students.id).paginate(page=page, per_page=20)
9+
return render_template('index.html', students=students)
10+
11+
12+
def login():
13+
form = LoginForm()
14+
if request.method == 'POST':
15+
if form.validate_on_submit(): # 调用validate_on_submit()进行表单验证
16+
user = User.query.filter_by(user=form.user.data).first()
17+
if user and user.password == form.password.data:
18+
return redirect(url_for('index'))
19+
else:
20+
flash('无效的用户名或密码')
21+
return render_template('login.html', form=form)
22+
23+
24+
def edit_student(id):
25+
form = MainForm()
26+
if request.method == 'POST':
27+
if form.validate_on_submit():
28+
data = Students.query.filter_by(id=form.id.data).first()
29+
data.username = form.username.data
30+
data.college = form.college.data
31+
data.major = form.major.data
32+
data.grade = form.grade.data

0 commit comments

Comments
 (0)
This repository has been archived.