Compare commits
36 Commits
a2be2f6378
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| dbeeb4d25a | |||
| 58c4b85e6a | |||
| b6fc41994e | |||
| 1a08ba460c | |||
| 692631e395 | |||
| 1174b225a7 | |||
| ded28f6a1e | |||
| 4e64fb2422 | |||
| eb074e5dd5 | |||
| 6ef3faf149 | |||
| 9b519f4650 | |||
| d6bef5812b | |||
| 8e8fccbb1a | |||
| 237f0acf8d | |||
| 44ce96c7d9 | |||
| dae0ce21be | |||
| a94dc7b415 | |||
| ca44cf0eaa | |||
| 18c3968e59 | |||
| 5ce9ee1b1e | |||
| 2596680c3a | |||
| ff030444e4 | |||
| e14688471a | |||
| c554d2d7af | |||
| 9296b70ac3 | |||
| cff2b66bc0 | |||
| 9d68073dd5 | |||
| 894d075d55 | |||
| 8021f15e58 | |||
| b5461dbff4 | |||
| aab814a23a | |||
| c0d0e43e73 | |||
| 3e79a22956 | |||
| ca55d9d2fd | |||
| e655b72a5c | |||
| e75cce4dc9 |
@@ -0,0 +1,2 @@
|
|||||||
|
import views
|
||||||
|
|
||||||
|
|||||||
60
app/static/js/get_teacher_attendance_table.js
Normal file
60
app/static/js/get_teacher_attendance_table.js
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
layui.use(['laypage', 'element', 'jquery', 'dropdown'], function () {
|
||||||
|
var laypage = layui.laypage;
|
||||||
|
var $ = layui.jquery;
|
||||||
|
|
||||||
|
function renderTable(page) {
|
||||||
|
$.get('/api/get-teacher-attendance-table?page=' + page, function (response) {
|
||||||
|
var $tbody = $('#attendanceTable tbody');
|
||||||
|
$tbody.empty(); // 清空表格内容
|
||||||
|
|
||||||
|
response.data.forEach(function (item) {
|
||||||
|
var $row = $('<tr></tr>');
|
||||||
|
$row.append(`<td>${item.course_id}</td>`);
|
||||||
|
$row.append(`<td>${item.course_name}</td>`);
|
||||||
|
$row.append(`<td>${item.class_name}</td>`);
|
||||||
|
$row.append(`<td>${item.major}</td>`);
|
||||||
|
$row.append(`<td><div class="layui-btn-container">
|
||||||
|
<button type="button" class="layui-btn btn-sign-in"
|
||||||
|
data-course-id="${item.course_id}"
|
||||||
|
data-course-name="${item.course_name}"
|
||||||
|
data-class-name = "${item.class_name}"
|
||||||
|
data-major-id = "${item.major_id}"
|
||||||
|
>签到</button>
|
||||||
|
</div>
|
||||||
|
</td>`)
|
||||||
|
$tbody.append($row);
|
||||||
|
});
|
||||||
|
|
||||||
|
laypage.render({
|
||||||
|
elem: 'pagination',
|
||||||
|
count: response.count,
|
||||||
|
limit: 10,
|
||||||
|
curr: page,
|
||||||
|
jump: function (obj, first) {
|
||||||
|
if (!first) {
|
||||||
|
renderTable(obj.curr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 为动态生成的按钮添加点击事件
|
||||||
|
$(document).on('click', '.btn-sign-in', function () {
|
||||||
|
var courseId = $(this).data('course-id'); // 获取课程ID
|
||||||
|
var courseName = $(this).data('course-name'); // 获取课程名
|
||||||
|
var className = $(this).data('class-name'); // 获取课程名
|
||||||
|
var majorId = $(this).data('major-id'); // 获取课程名
|
||||||
|
// console.log(courseId,courseName,className,majorId)
|
||||||
|
// 向后端发送POST请求
|
||||||
|
$.post('/api/teacher-sign-in', {
|
||||||
|
course_id: courseId,
|
||||||
|
course_name: courseName,
|
||||||
|
class_name: className,
|
||||||
|
major_id:majorId
|
||||||
|
}, function (response) {
|
||||||
|
layer.msg(response.msg);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
renderTable(1); // 初始加载第一页
|
||||||
|
});
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
src="//unpkg.com/outeres@0.0.10/img/layui/icon-v2.png"
|
src="//unpkg.com/outeres@0.0.10/img/layui/icon-v2.png"
|
||||||
class="layui-nav-img"
|
class="layui-nav-img"
|
||||||
/>
|
/>
|
||||||
{{ session.nickname }}
|
{{ session.name }}
|
||||||
</a>
|
</a>
|
||||||
<dl class="layui-nav-child">
|
<dl class="layui-nav-child">
|
||||||
<dd><a href="/home/profile">资料</a></dd> <!-- 修改这里的href指向/profile -->
|
<dd><a href="/home/profile">资料</a></dd> <!-- 修改这里的href指向/profile -->
|
||||||
|
|||||||
@@ -55,10 +55,10 @@
|
|||||||
<!-- 表头 -->
|
<!-- 表头 -->
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>课程名称</th>
|
|
||||||
<th>课程代码</th>
|
<th>课程代码</th>
|
||||||
<th>学分</th>
|
<th>课程名称</th>
|
||||||
<th>班级专业</th>
|
<th>班级</th>
|
||||||
|
<th>专业</th>
|
||||||
<th>签到</th>
|
<th>签到</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@@ -74,50 +74,8 @@
|
|||||||
<script src="/static/layui.js"></script>
|
<script src="/static/layui.js"></script>
|
||||||
<script src="/static/js/menu.js"></script>
|
<script src="/static/js/menu.js"></script>
|
||||||
<script src="/static/js/logout.js"></script>
|
<script src="/static/js/logout.js"></script>
|
||||||
|
<script src="/static/js/get_teacher_attendance_table.js"></script>
|
||||||
<script>
|
<script>
|
||||||
layui.use(['laypage', 'element', 'jquery', 'dropdown'], function () {
|
|
||||||
var laypage = layui.laypage;
|
|
||||||
var $ = layui.jquery;
|
|
||||||
|
|
||||||
function renderTable(page) {
|
|
||||||
// 发送GET请求到服务器端点
|
|
||||||
$.get('/api/get-teacher-attendance-table?page=' + page, function (response) {
|
|
||||||
var $tbody = $('#attendanceTable tbody');
|
|
||||||
$tbody.empty(); // 清空表格内容
|
|
||||||
|
|
||||||
// 遍历返回的数据数组
|
|
||||||
response.data.forEach(function (item) {
|
|
||||||
// 创建新的行并填充数据
|
|
||||||
var $row = $('<tr></tr>');
|
|
||||||
$row.append(`<td>${item.course_name}</td>`);
|
|
||||||
$row.append(`<td>${item.course_code}</td>`);
|
|
||||||
$row.append(`<td>${item.credits}</td>`);
|
|
||||||
$row.append(`<td>${item.class_name + item.major}</td>`);
|
|
||||||
$row.append(`<td><div class="layui-btn-container">
|
|
||||||
<button type="button" class="layui-btn">签到</button>
|
|
||||||
</div>
|
|
||||||
</td>`)
|
|
||||||
$tbody.append($row);
|
|
||||||
|
|
||||||
});
|
|
||||||
// 渲染分页控件
|
|
||||||
laypage.render({
|
|
||||||
elem: 'pagination', // 分页容器的id
|
|
||||||
count: response.count, // 总条数
|
|
||||||
limit: 10, // 每页显示条数
|
|
||||||
curr: page, // 当前页
|
|
||||||
jump: function (obj, first) {
|
|
||||||
if (!first) { // 首次不执行
|
|
||||||
renderTable(obj.curr); // 根据页码加载数据
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始加载第一页
|
|
||||||
renderTable(1);
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
src="//unpkg.com/outeres@0.0.10/img/layui/icon-v2.png"
|
src="//unpkg.com/outeres@0.0.10/img/layui/icon-v2.png"
|
||||||
class="layui-nav-img"
|
class="layui-nav-img"
|
||||||
/>
|
/>
|
||||||
{{ session.nickname }}
|
{{ session.name }}
|
||||||
</a>
|
</a>
|
||||||
<dl class="layui-nav-child">
|
<dl class="layui-nav-child">
|
||||||
<dd><a href="/home/profile">资料</a></dd> <!-- 修改这里的href指向/profile -->
|
<dd><a href="/home/profile">资料</a></dd> <!-- 修改这里的href指向/profile -->
|
||||||
|
|||||||
@@ -64,6 +64,7 @@
|
|||||||
data: data.field, // 表单数据
|
data: data.field, // 表单数据
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
success: function (response) {
|
success: function (response) {
|
||||||
|
console.log(response)
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
window.location.href = '/attendance-reminder'; // 或者你的成功页面
|
window.location.href = '/attendance-reminder'; // 或者你的成功页面
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
43
app/tests/ReceiveExcelTest.py
Normal file
43
app/tests/ReceiveExcelTest.py
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import unittest
|
||||||
|
import os
|
||||||
|
|
||||||
|
from app.views import *
|
||||||
|
from werkzeug.datastructures import FileStorage # 用于创建测试文件
|
||||||
|
|
||||||
|
class ReceiveExcelTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
app.testing = True # 设置 Flask 应用为测试模式
|
||||||
|
self.client = app.test_client()
|
||||||
|
# 创建一个测试用的Excel文件或使用一个真实的Excel文件路径
|
||||||
|
self.test_file_path = 'template.xlsx'
|
||||||
|
|
||||||
|
def test_receive_excel_no_file(self):
|
||||||
|
# 测试没有文件时的情况
|
||||||
|
response = self.client.post('/api/receive-excel')
|
||||||
|
self.assertEqual(response.status_code, 400)
|
||||||
|
self.assertEqual(response.get_json(), {"error": "No file part"})
|
||||||
|
|
||||||
|
def test_receive_excel_with_file(self):
|
||||||
|
# 模拟已登录用户
|
||||||
|
with self.client.session_transaction() as sess:
|
||||||
|
sess['number'] = 'X202301000001'
|
||||||
|
|
||||||
|
# 使用 FileStorage 创建测试文件对象
|
||||||
|
data = {
|
||||||
|
'file': (open(self.test_file_path, 'rb'), self.test_file_path)
|
||||||
|
}
|
||||||
|
# 发送 POST 请求到 /api/receive-excel
|
||||||
|
response = self.client.post('/api/receive-excel', data=data, content_type='multipart/form-data')
|
||||||
|
|
||||||
|
# 验证返回的状态码和响应
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertEqual(response.get_json(), {"message": "File successfully processed"})
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
# 清理测试用的文件或数据
|
||||||
|
if os.path.exists(self.test_file_path):
|
||||||
|
os.remove(self.test_file_path)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
39
app/tests/StudentSignInTest.py
Normal file
39
app/tests/StudentSignInTest.py
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import unittest
|
||||||
|
|
||||||
|
from app.views import *
|
||||||
|
from unittest.mock import patch
|
||||||
|
from flask import session
|
||||||
|
|
||||||
|
|
||||||
|
class StudentSignInTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
# 设置 Flask 测试模式
|
||||||
|
app.testing = True
|
||||||
|
self.client = app.test_client()
|
||||||
|
|
||||||
|
@patch('db.database_manager.DatabaseManager.update_sign_in_info')
|
||||||
|
def test_student_sign_in(self, mock_update_sign_in_info):
|
||||||
|
# 模拟已登录用户
|
||||||
|
with self.client.session_transaction() as sess:
|
||||||
|
sess['number'] = 'X202301000001'
|
||||||
|
|
||||||
|
# 模拟数据库操作
|
||||||
|
mock_update_sign_in_info.return_value = 1 # 假设成功更新签到信息
|
||||||
|
|
||||||
|
# 发送 POST 请求到/api/student-sign-in
|
||||||
|
response = self.client.post('/api/student-sign-in', data={
|
||||||
|
'course_name': '计算机导论',
|
||||||
|
'course_id': '2',
|
||||||
|
'student_number': 'X202301000001',
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
# 验证返回的状态码和JSON数据
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
json_data = response.get_json()
|
||||||
|
self.assertEqual(json_data, {"msg": "ok", "data": "签到成功!"})
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
37
app/tests/TeacherSignInTest.py
Normal file
37
app/tests/TeacherSignInTest.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import unittest
|
||||||
|
|
||||||
|
from app.views import *
|
||||||
|
from unittest.mock import patch
|
||||||
|
from flask import session
|
||||||
|
|
||||||
|
class TeacherSignInTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
# 设置 Flask 测试模式
|
||||||
|
app.testing = True
|
||||||
|
self.client = app.test_client()
|
||||||
|
|
||||||
|
@patch('db.database_manager.DatabaseManager.update_sign_in_info')
|
||||||
|
def test_teacher_sign_in(self, mock_teacher_sign_in):
|
||||||
|
# 模拟已登录用户
|
||||||
|
with self.client.session_transaction() as sess:
|
||||||
|
sess['number'] = 'X202301000001'
|
||||||
|
|
||||||
|
# 模拟数据库操作的返回值
|
||||||
|
mock_teacher_sign_in.return_value = {"msg": "当前班级专业没有学生'"}
|
||||||
|
|
||||||
|
# 发送 POST 请求到/api/teacher-sign-in
|
||||||
|
response = self.client.post('/api/teacher-sign-in', data={
|
||||||
|
'course_id': '123',
|
||||||
|
'course_name': 'Test Course',
|
||||||
|
'class_name': 'TestClass',
|
||||||
|
'major_id': '456'
|
||||||
|
})
|
||||||
|
|
||||||
|
# 验证返回的状态码和数据
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
json_data = response.get_json()
|
||||||
|
self.assertEqual(json_data, {"msg": "当前班级专业没有学生"})
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
73
app/tests/TestGetHtml.py
Normal file
73
app/tests/TestGetHtml.py
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import unittest
|
||||||
|
|
||||||
|
from app.views import *
|
||||||
|
|
||||||
|
|
||||||
|
class HtmlTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
app.testing = True # 设置 Flask 应用为测试模式
|
||||||
|
self.client = app.test_client() # 创建一个测试客户端
|
||||||
|
|
||||||
|
def test_get_course_info(self):
|
||||||
|
# 测试 GET 请求
|
||||||
|
response = self.client.get('/course-info')
|
||||||
|
|
||||||
|
# 验证响应状态码
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
# 验证响应的Content-Type头部值
|
||||||
|
self.assertIn('text/html', response.content_type)
|
||||||
|
|
||||||
|
def test_get_attendance(self):
|
||||||
|
# 测试 GET 请求
|
||||||
|
response = self.client.get('/attendance')
|
||||||
|
|
||||||
|
# 验证响应状态码
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
# 验证响应的Content-Type头部值
|
||||||
|
self.assertIn('text/html', response.content_type)
|
||||||
|
|
||||||
|
def test_get_announcement(self):
|
||||||
|
# 测试 GET 请求
|
||||||
|
response = self.client.get('/announcement')
|
||||||
|
|
||||||
|
# 验证响应状态码
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
# 验证响应的Content-Type头部值
|
||||||
|
self.assertIn('text/html', response.content_type)
|
||||||
|
|
||||||
|
def test_get_attendance_reminder(self):
|
||||||
|
# 测试 GET 请求
|
||||||
|
response = self.client.get('/attendance-reminder')
|
||||||
|
|
||||||
|
# 验证响应状态码
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
# 验证响应的Content-Type头部值
|
||||||
|
self.assertIn('text/html', response.content_type)
|
||||||
|
|
||||||
|
def test_get_course_category(self):
|
||||||
|
# 测试 GET 请求
|
||||||
|
response = self.client.get('/course-category')
|
||||||
|
|
||||||
|
# 验证响应状态码
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
# 验证响应的Content-Type头部值
|
||||||
|
self.assertIn('text/html', response.content_type)
|
||||||
|
|
||||||
|
def test_get_attendance_teacher(self):
|
||||||
|
# 测试 GET 请求
|
||||||
|
response = self.client.get('/attendance-teacher')
|
||||||
|
|
||||||
|
# 验证响应状态码
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
# 验证响应的Content-Type头部值
|
||||||
|
self.assertIn('text/html', response.content_type)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
44
app/tests/TestGetMenu.py
Normal file
44
app/tests/TestGetMenu.py
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import unittest
|
||||||
|
|
||||||
|
from app.views import *
|
||||||
|
from flask import session
|
||||||
|
from unittest.mock import patch # 如果需要模拟数据库方法
|
||||||
|
|
||||||
|
|
||||||
|
class MenuAPITestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
app.testing = True # 设置 Flask 应用为测试模式
|
||||||
|
self.client = app.test_client() # 创建一个测试客户端
|
||||||
|
self.expected_menu = [
|
||||||
|
{"name": "课程类别", "path": "/course-category"},
|
||||||
|
{"name": "课程信息", "path": "/course-info"},
|
||||||
|
{"name": "课程签到", "path": "/attendance-teacher"},
|
||||||
|
{"name": "签到提醒", "path": "/attendance-reminder"}
|
||||||
|
]
|
||||||
|
|
||||||
|
def test_menu_no_login(self):
|
||||||
|
# 测试未登录情况下请求API
|
||||||
|
response = self.client.get('/api/menu')
|
||||||
|
self.assertEqual(response.status_code, 401)
|
||||||
|
self.assertEqual(response.get_json(), [])
|
||||||
|
|
||||||
|
def test_login(self):
|
||||||
|
with self.client:
|
||||||
|
self.client.post('/login', data=dict(
|
||||||
|
number='G0001',
|
||||||
|
password='1'
|
||||||
|
))
|
||||||
|
|
||||||
|
# 确认登录后session中有数据
|
||||||
|
self.assertIn('role', session)
|
||||||
|
|
||||||
|
# 执行logout
|
||||||
|
response = self.client.get('/api/menu')
|
||||||
|
print(response.get_json())
|
||||||
|
# 确认响应是重定向到登录页面
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertEqual(self.expected_menu,response.get_json())
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
45
app/tests/TestLogin.py
Normal file
45
app/tests/TestLogin.py
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import unittest
|
||||||
|
|
||||||
|
from app.views import *
|
||||||
|
from db.database_manager import DatabaseManager # 确保你可以导入DatabaseManager
|
||||||
|
|
||||||
|
class LoginTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
# 设置 Flask 测试模式
|
||||||
|
app.testing = True
|
||||||
|
self.client = app.test_client()
|
||||||
|
|
||||||
|
def test_login_get(self):
|
||||||
|
# 测试 GET 请求返回登录页面
|
||||||
|
response = self.client.get('/login')
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertIn('text/html', response.content_type)
|
||||||
|
|
||||||
|
def test_successful_login_post(self):
|
||||||
|
# 测试有效的登录 POST 请求
|
||||||
|
with self.client:
|
||||||
|
response = self.client.post('/login', data={
|
||||||
|
'number': 'G0001',
|
||||||
|
'password': '1'
|
||||||
|
})
|
||||||
|
# 根据你的应用逻辑调整断言
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
def test_invalid_login_post(self):
|
||||||
|
# 测试无效的登录 POST 请求
|
||||||
|
response = self.client.post('/login', data={
|
||||||
|
'number': 'admin',
|
||||||
|
'password': 'admin'
|
||||||
|
})
|
||||||
|
# 将返回的数据解析为JSON
|
||||||
|
json_data = response.get_json()
|
||||||
|
|
||||||
|
# 确认JSON响应中的值
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertFalse(json_data['success'])
|
||||||
|
self.assertEqual(json_data['message'], "无效的用户名或密码")
|
||||||
|
|
||||||
|
# 运行测试
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
34
app/tests/TestLogout.py
Normal file
34
app/tests/TestLogout.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import unittest
|
||||||
|
|
||||||
|
from app.views import *
|
||||||
|
|
||||||
|
class LogoutTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
# 设置 Flask 测试模式
|
||||||
|
app.testing = True
|
||||||
|
self.client = app.test_client()
|
||||||
|
|
||||||
|
def test_logout(self):
|
||||||
|
# 先登录,确保 session 是设置的
|
||||||
|
with self.client:
|
||||||
|
self.client.post('/login', data=dict(
|
||||||
|
number='G0001',
|
||||||
|
password='1'
|
||||||
|
))
|
||||||
|
|
||||||
|
# 确认登录后session中有数据
|
||||||
|
self.assertIn('number', session)
|
||||||
|
|
||||||
|
# 执行logout
|
||||||
|
response = self.client.get('/logout')
|
||||||
|
|
||||||
|
# 确认 session 被清空
|
||||||
|
self.assertNotIn('number', session)
|
||||||
|
|
||||||
|
# 确认响应是重定向到登录页面
|
||||||
|
self.assertEqual(response.status_code, 302)
|
||||||
|
self.assertTrue(response.location.endswith('/login'))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
53
app/views.py
53
app/views.py
@@ -1,19 +1,21 @@
|
|||||||
import os
|
import os
|
||||||
import openpyxl as openpyxl
|
import logging
|
||||||
|
|
||||||
|
# 第三方库
|
||||||
|
import openpyxl
|
||||||
from flask import Flask, redirect, url_for, render_template, session, jsonify, request, send_file
|
from flask import Flask, redirect, url_for, render_template, session, jsonify, request, send_file
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
# 应用内部模块
|
||||||
from utils.time_utils import check_now_time
|
from utils.time_utils import check_now_time
|
||||||
|
from utils.parse_table import parse_table
|
||||||
from utils.allowed_files import allowed_excel
|
from utils.allowed_files import allowed_excel
|
||||||
from db.connection import MySQLPool
|
from db.connection import MySQLPool
|
||||||
from config import SECRET_KEY
|
|
||||||
from db.database_manager import DatabaseManager
|
from db.database_manager import DatabaseManager
|
||||||
from models.Student import Student
|
from models.Student import Student
|
||||||
from models.Teacher import Teacher
|
from models.Teacher import Teacher
|
||||||
from models.User import User
|
from models.User import User
|
||||||
import logging
|
from config import SECRET_KEY, LOGGING_CONFIG, FILE_PATH
|
||||||
from config import LOGGING_CONFIG
|
|
||||||
from config import FILE_PATH
|
|
||||||
from datetime import datetime
|
|
||||||
import datetime
|
|
||||||
|
|
||||||
app = Flask(__name__, static_folder='static')
|
app = Flask(__name__, static_folder='static')
|
||||||
app.secret_key = SECRET_KEY # 从配置文件设置
|
app.secret_key = SECRET_KEY # 从配置文件设置
|
||||||
@@ -87,7 +89,7 @@ def login():
|
|||||||
db_manager = DatabaseManager()
|
db_manager = DatabaseManager()
|
||||||
|
|
||||||
result = db_manager.valid_login(number, password) # 获取验证结果
|
result = db_manager.valid_login(number, password) # 获取验证结果
|
||||||
|
print(result)
|
||||||
# 确保用户已验证且活跃(未被禁用)
|
# 确保用户已验证且活跃(未被禁用)
|
||||||
if result['valid'] and result['status'] == 1:
|
if result['valid'] and result['status'] == 1:
|
||||||
# 登录成功
|
# 登录成功
|
||||||
@@ -95,7 +97,7 @@ def login():
|
|||||||
session['role'] = check_identity(number)
|
session['role'] = check_identity(number)
|
||||||
session['name'] = result['name']
|
session['name'] = result['name']
|
||||||
return jsonify(success=True, message="登录成功")
|
return jsonify(success=True, message="登录成功")
|
||||||
elif not result['status']:
|
elif not result.get('status'):
|
||||||
# 用户被禁用的情况
|
# 用户被禁用的情况
|
||||||
return jsonify(success=False, message="账户已被禁用")
|
return jsonify(success=False, message="账户已被禁用")
|
||||||
else:
|
else:
|
||||||
@@ -245,6 +247,7 @@ def get_current_teacher_courses():
|
|||||||
# 获取所有课程数据
|
# 获取所有课程数据
|
||||||
db_manager = DatabaseManager()
|
db_manager = DatabaseManager()
|
||||||
all_course_data = db_manager.get_current_teacher_courses(number)
|
all_course_data = db_manager.get_current_teacher_courses(number)
|
||||||
|
print(all_course_data)
|
||||||
logging.info(f"all_course_data: {all_course_data}")
|
logging.info(f"all_course_data: {all_course_data}")
|
||||||
# 计算分页的起始和结束索引
|
# 计算分页的起始和结束索引
|
||||||
start = (page - 1) * limit
|
start = (page - 1) * limit
|
||||||
@@ -273,6 +276,7 @@ def download_template():
|
|||||||
|
|
||||||
@app.route('/api/receive-excel', methods=['POST'])
|
@app.route('/api/receive-excel', methods=['POST'])
|
||||||
def receive_excel():
|
def receive_excel():
|
||||||
|
number = session.get('number')
|
||||||
# 检查是否有文件在请求中
|
# 检查是否有文件在请求中
|
||||||
if 'file' not in request.files:
|
if 'file' not in request.files:
|
||||||
return jsonify({"error": "No file part"}), 400
|
return jsonify({"error": "No file part"}), 400
|
||||||
@@ -287,9 +291,10 @@ def receive_excel():
|
|||||||
if file and allowed_excel(file.filename):
|
if file and allowed_excel(file.filename):
|
||||||
try:
|
try:
|
||||||
# 使用 openpyxl 读取文件内容
|
# 使用 openpyxl 读取文件内容
|
||||||
workbook = openpyxl.load_workbook(file)
|
data = parse_table(file, number)
|
||||||
# TODO: 在这里处理你的Excel文件,例如读取数据
|
db_manager = DatabaseManager()
|
||||||
print(workbook)
|
result = db_manager.insert_into_class_student(data)
|
||||||
|
print(result)
|
||||||
return jsonify({"message": "File successfully processed"}), 200
|
return jsonify({"message": "File successfully processed"}), 200
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return jsonify({"error": str(e)}), 500
|
return jsonify({"error": str(e)}), 500
|
||||||
@@ -315,7 +320,8 @@ def get_course_name():
|
|||||||
return jsonify({"msg": "用户未登录或编号不可用", "data": None})
|
return jsonify({"msg": "用户未登录或编号不可用", "data": None})
|
||||||
|
|
||||||
# 获取今天是星期几
|
# 获取今天是星期几
|
||||||
day_of_week = datetime.date.today().weekday() + 1
|
now = datetime.now()
|
||||||
|
day_of_week = now.weekday() + 1
|
||||||
|
|
||||||
# 如果是周末
|
# 如果是周末
|
||||||
if not (1 <= day_of_week <= 5):
|
if not (1 <= day_of_week <= 5):
|
||||||
@@ -358,7 +364,8 @@ def student_get_today_courses():
|
|||||||
return jsonify({"msg": "用户未登录或编号不可用", "data": None})
|
return jsonify({"msg": "用户未登录或编号不可用", "data": None})
|
||||||
|
|
||||||
# 获取今天是星期几
|
# 获取今天是星期几
|
||||||
day_of_week = datetime.date.today().weekday() + 1
|
now = datetime.now() # 获取当前时间
|
||||||
|
day_of_week = now.weekday() + 1
|
||||||
|
|
||||||
# 如果是周末
|
# 如果是周末
|
||||||
if not (1 <= day_of_week <= 5):
|
if not (1 <= day_of_week <= 5):
|
||||||
@@ -374,5 +381,23 @@ def student_get_today_courses():
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/api/teacher-sign-in', methods=['POST'])
|
||||||
|
def teacher_sign_in():
|
||||||
|
teacher_number = session.get('number')
|
||||||
|
course_id = request.form['course_id']
|
||||||
|
course_name = request.form['course_name']
|
||||||
|
class_name = request.form['class_name']
|
||||||
|
major_id = request.form['major_id']
|
||||||
|
|
||||||
|
now = datetime.now()
|
||||||
|
date = now.strftime("%Y年%m月%d日%H:%M")
|
||||||
|
status = "出勤"
|
||||||
|
print(f"course_id: {course_id},course_name: {course_name},class_name: {class_name},major_id: {major_id}")
|
||||||
|
|
||||||
|
db_manager = DatabaseManager()
|
||||||
|
data = db_manager.teacher_sign_in(course_id, course_name, class_name, major_id, date, status, teacher_number)
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run(debug=True)
|
app.run(debug=True)
|
||||||
|
|||||||
@@ -31,6 +31,22 @@ class DatabaseManager:
|
|||||||
cursor.close()
|
cursor.close()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
def executemany(self, query, params_list):
|
||||||
|
conn = self.pool.get_connection()
|
||||||
|
try:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.executemany(query, params_list) # 使用executemany代替execute
|
||||||
|
conn.commit() # 提交事务
|
||||||
|
return cursor.rowcount # 返回受影响的行数
|
||||||
|
except Exception as e:
|
||||||
|
# 可以在这里添加错误处理逻辑,例如打印错误日志、回滚事务等
|
||||||
|
print("An error occurred: ", e)
|
||||||
|
conn.rollback()
|
||||||
|
return None
|
||||||
|
finally:
|
||||||
|
cursor.close()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
def user_exists(self, phone_number):
|
def user_exists(self, phone_number):
|
||||||
sql = "SELECT 1 FROM user WHERE number=%s LIMIT 1"
|
sql = "SELECT 1 FROM user WHERE number=%s LIMIT 1"
|
||||||
result = self.fetch(sql, (phone_number,))
|
result = self.fetch(sql, (phone_number,))
|
||||||
@@ -61,7 +77,7 @@ class DatabaseManager:
|
|||||||
return {'valid': True, 'status': status, 'name': name}
|
return {'valid': True, 'status': status, 'name': name}
|
||||||
|
|
||||||
# 密码不匹配或用户不存在,返回登录失败
|
# 密码不匹配或用户不存在,返回登录失败
|
||||||
return {'valid': False}
|
return {'valid': False, 'status': True}
|
||||||
|
|
||||||
def get_menu(self, role):
|
def get_menu(self, role):
|
||||||
sql = "SELECT menu_name,path FROM menu_items WHERE role=%s ORDER BY `order`"
|
sql = "SELECT menu_name,path FROM menu_items WHERE role=%s ORDER BY `order`"
|
||||||
@@ -76,12 +92,14 @@ class DatabaseManager:
|
|||||||
def get_current_teacher_courses(self, teacher_number):
|
def get_current_teacher_courses(self, teacher_number):
|
||||||
# 使用INNER JOIN连接teacher_class_course表和course表
|
# 使用INNER JOIN连接teacher_class_course表和course表
|
||||||
sql = """
|
sql = """
|
||||||
SELECT
|
SELECT
|
||||||
|
c.course_id,
|
||||||
c.course_name,
|
c.course_name,
|
||||||
c.course_code,
|
c.course_code,
|
||||||
c.credits,
|
c.credits,
|
||||||
tcc.class_name,
|
tcc.class_name,
|
||||||
m.major
|
m.major,
|
||||||
|
m.major_id
|
||||||
FROM
|
FROM
|
||||||
teacher_class_course tcc
|
teacher_class_course tcc
|
||||||
JOIN
|
JOIN
|
||||||
@@ -93,8 +111,34 @@ WHERE
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# 执行查询并返回结果
|
# 执行查询并返回结果
|
||||||
result = self.fetch(sql, (teacher_number,))
|
class_student_sql = """SELECT course_id, course_name,class_name,major,major_id,major FROM class_student where teacher_number = %s;"""
|
||||||
return result
|
result1 = self.fetch(sql, (teacher_number,))
|
||||||
|
result2 = self.fetch(class_student_sql, (teacher_number))
|
||||||
|
|
||||||
|
data = []
|
||||||
|
# 遍历第一个结果集
|
||||||
|
if result1:
|
||||||
|
for row in result1:
|
||||||
|
data.append({
|
||||||
|
"course_id": row['course_id'],
|
||||||
|
"course_name": row['course_name'],
|
||||||
|
"class_name": row['class_name'],
|
||||||
|
"major_id": row['major_id'],
|
||||||
|
"major": row['major']
|
||||||
|
})
|
||||||
|
|
||||||
|
# 遍历第二个结果集
|
||||||
|
if result2:
|
||||||
|
for row in result2:
|
||||||
|
data.append({
|
||||||
|
"course_id": row['course_id'],
|
||||||
|
"course_name": row['course_name'],
|
||||||
|
"class_name": row['class_name'],
|
||||||
|
"major_id": row['major_id'],
|
||||||
|
"major": row['major']
|
||||||
|
})
|
||||||
|
# 返回包含两个结果集信息的data列表
|
||||||
|
return data
|
||||||
|
|
||||||
def get_course_type(self):
|
def get_course_type(self):
|
||||||
sql = "SELECT course_name, course_type FROM course"
|
sql = "SELECT course_name, course_type FROM course"
|
||||||
@@ -128,18 +172,22 @@ WHERE
|
|||||||
return self.execute(sql, data)
|
return self.execute(sql, data)
|
||||||
|
|
||||||
def get_course_name(self, student_number, day_of_week, period_id):
|
def get_course_name(self, student_number, day_of_week, period_id):
|
||||||
|
print(f"student_number: {student_number}, day_of_week: {day_of_week}, period_id: {period_id}")
|
||||||
# 从student表获取class_name
|
# 从student表获取class_name
|
||||||
sql_student = "SELECT class_name FROM student WHERE student_number = %s;"
|
sql_student = "SELECT class_name FROM student WHERE student_number = %s;"
|
||||||
class_name = self.fetch(sql_student, (student_number,))[0]['class_name']
|
class_name = self.fetch(sql_student, (student_number,))[0]['class_name']
|
||||||
|
|
||||||
# 使用class_name和day_of_week从schedule表获取course_id
|
# 使用class_name和day_of_week从schedule表获取course_id
|
||||||
sql_schedule = "SELECT course_id, FROM schedule WHERE day_of_week = %s AND class_name = %s AND period_id = %s;"
|
sql_schedule = "SELECT course_id FROM schedule WHERE day_of_week = %s AND class_name = %s AND period_id = %s;"
|
||||||
course_id = self.fetch(sql_schedule, (day_of_week, class_name, period_id))
|
course_id = self.fetch(sql_schedule, (day_of_week, class_name, period_id))
|
||||||
|
print(f"course_id: {course_id}")
|
||||||
|
id = course_id[0]['course_id']
|
||||||
|
print(f"id: {id}")
|
||||||
# 对于每一个course_id,从course表中查询course_name
|
# 对于每一个course_id,从course表中查询course_name
|
||||||
sql_course = "SELECT course_name FROM course WHERE course_id = %s;"
|
sql_course = "SELECT course_name FROM course WHERE course_id = %s;"
|
||||||
course_name = self.fetch(sql_course, (course_id['course_id'],))
|
course_name = self.fetch(sql_course, (id,))[0]['course_name']
|
||||||
data = {"course_name": course_name, "course_id": course_id}
|
print(f"course_name: {course_name}")
|
||||||
|
data = {"course_name": course_name, "course_id": id}
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def update_sign_in_info(self, student_number, course_id, course_name, date, status):
|
def update_sign_in_info(self, student_number, course_id, course_name, date, status):
|
||||||
@@ -189,3 +237,63 @@ WHERE
|
|||||||
time = get_time_by_ids(id)
|
time = get_time_by_ids(id)
|
||||||
data.append({"course_name": course_name, "time": time})
|
data.append({"course_name": course_name, "time": time})
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
def teacher_sign_in(self, course_id, course_name, class_name, major_id, date, status, teacher_number):
|
||||||
|
class_student_sql = "SELECT student_number FROM class_student WHERE teacher_number = %s AND major_id = %s AND class_name = %s"
|
||||||
|
class_student_result = self.fetch(class_student_sql, (teacher_number, major_id, class_name))
|
||||||
|
|
||||||
|
student_sql = "SELECT student_number FROM student WHERE class_name = %s AND major_id = %s;"
|
||||||
|
student_sql_result = self.fetch(student_sql, (class_name, major_id))
|
||||||
|
|
||||||
|
values_list = []
|
||||||
|
# 检查是否有学生编号被返回
|
||||||
|
if student_sql_result:
|
||||||
|
for student in student_sql_result:
|
||||||
|
# 对于每个学生编号,创建一条记录的值元组
|
||||||
|
student_number = student['student_number']
|
||||||
|
values_list.append((student_number, course_id, course_name, date, status))
|
||||||
|
|
||||||
|
if class_student_result:
|
||||||
|
for class_student in class_student_result:
|
||||||
|
# 注意这里变量名已经修改为class_student
|
||||||
|
student_number = class_student['student_number']
|
||||||
|
values_list.append((student_number, course_id, course_name, date, status))
|
||||||
|
|
||||||
|
# 如果没有任何学生编号,返回相应的消息
|
||||||
|
if not values_list:
|
||||||
|
return {"msg": "当前班级专业没有学生"}
|
||||||
|
|
||||||
|
# 构建一次性插入多条记录的SQL语句
|
||||||
|
attendance_sql = "INSERT INTO attendance_record (student_number, course_id, course_name, date, status) VALUES (%s, %s, %s, %s, %s)"
|
||||||
|
|
||||||
|
# 使用executemany一次性插入多条记录
|
||||||
|
result = self.executemany(attendance_sql, values_list)
|
||||||
|
print(f"Inserted rows: {result}")
|
||||||
|
|
||||||
|
return {"msg": "班级签到成功,签到人数:" + str(result)}
|
||||||
|
|
||||||
|
def insert_into_class_student(self, class_students):
|
||||||
|
try:
|
||||||
|
values_list = [
|
||||||
|
(
|
||||||
|
cs['teacher_number'],
|
||||||
|
cs['class_name'],
|
||||||
|
cs['student_name'],
|
||||||
|
cs['student_number'],
|
||||||
|
cs['course_id'],
|
||||||
|
cs['course_name'],
|
||||||
|
cs['major_id'],
|
||||||
|
cs['major']
|
||||||
|
)
|
||||||
|
for cs in class_students
|
||||||
|
]
|
||||||
|
|
||||||
|
sql = """INSERT INTO class_student
|
||||||
|
(teacher_number, class_name, student_name, student_number, course_id, course_name, major_id, major)
|
||||||
|
VALUES (%s, %s, %s, %s, %s, %s, %s, %s)"""
|
||||||
|
result = self.executemany(sql, values_list)
|
||||||
|
return {"inserted_rows": result}
|
||||||
|
except Exception as e:
|
||||||
|
# 这里应根据实际情况记录日志或返回错误信息
|
||||||
|
print(f"An error occurred: {e}")
|
||||||
|
return {"error": str(e)}
|
||||||
|
|||||||
Binary file not shown.
210
mysql.sql
210
mysql.sql
@@ -1,18 +1,3 @@
|
|||||||
CREATE TABLE user
|
|
||||||
(
|
|
||||||
user_id INT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
name VARCHAR(50) NOT NULL,
|
|
||||||
number VARCHAR(15) NOT NULL UNIQUE,
|
|
||||||
password VARCHAR(255) NOT NULL,
|
|
||||||
status BOOLEAN NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO user (name, number, password, identity, status)
|
|
||||||
VALUES ('学生', '1', '$2b$12$okY88GrzlUHb/Ox1ENwtqeBUnE0bgMOCPy.UKmFaTnu3El7EYX8Em', 'student', TRUE),
|
|
||||||
('老师', '2', '$2b$12$okY88GrzlUHb/Ox1ENwtqeBUnE0bgMOCPy.UKmFaTnu3El7EYX8Em', 'teacher', TRUE);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE menu_items
|
CREATE TABLE menu_items
|
||||||
(
|
(
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
@@ -27,11 +12,8 @@ INSERT INTO menu_items (menu_name, role, path, `order`)
|
|||||||
VALUES ('课程信息', 'student', '/course-info', 1),
|
VALUES ('课程信息', 'student', '/course-info', 1),
|
||||||
('课程签到', 'student', '/attendance', 2),
|
('课程签到', 'student', '/attendance', 2),
|
||||||
('公告信息', 'student', '/announcement', 3),
|
('公告信息', 'student', '/announcement', 3),
|
||||||
('签到提醒', 'student', '/attendance-reminder', 4);
|
('签到提醒', 'student', '/attendance-reminder', 4),
|
||||||
|
('课程类别', 'teacher', '/course-category', 1),
|
||||||
|
|
||||||
INSERT INTO menu_items (menu_name, role, path, `order`)
|
|
||||||
VALUES ('课程类别', 'teacher', '/course-category', 1),
|
|
||||||
('课程信息', 'teacher', '/course-info', 2),
|
('课程信息', 'teacher', '/course-info', 2),
|
||||||
('课程签到', 'teacher', '/attendance-teacher', 3),
|
('课程签到', 'teacher', '/attendance-teacher', 3),
|
||||||
('签到提醒', 'teacher', '/attendance-reminder', 4);
|
('签到提醒', 'teacher', '/attendance-reminder', 4);
|
||||||
@@ -79,7 +61,6 @@ VALUES ('大学计算机基础', 'CF001', '必修', 3, '介绍计算机基础知
|
|||||||
('离散数学导论', 'IDTM01', '必修', 3, '介绍离散数学的基础知识和应用'),
|
('离散数学导论', 'IDTM01', '必修', 3, '介绍离散数学的基础知识和应用'),
|
||||||
('计算机网络', 'CN002', '必修', 4, '学习计算机网络的基础理论和协议');
|
('计算机网络', 'CN002', '必修', 4, '学习计算机网络的基础理论和协议');
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE attendance_record
|
CREATE TABLE attendance_record
|
||||||
(
|
(
|
||||||
record_id INT AUTO_INCREMENT PRIMARY KEY,
|
record_id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
@@ -90,6 +71,61 @@ CREATE TABLE attendance_record
|
|||||||
status VARCHAR(20)
|
status VARCHAR(20)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE time_period
|
||||||
|
(
|
||||||
|
period_id INT AUTO_INCREMENT UNIQUE,
|
||||||
|
period_name VARCHAR(10),
|
||||||
|
start_time TIME,
|
||||||
|
end_time TIME,
|
||||||
|
PRIMARY KEY (period_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO time_period (period_name, start_time, end_time)
|
||||||
|
VALUES ('一、二节', '08:00:00', '09:30:00'),
|
||||||
|
('三、四节', '10:00:00', '11:30:00'),
|
||||||
|
('五、六节', '14:30:00', '16:00:00'),
|
||||||
|
('七、八节', '16:30:00', '18:00:00');
|
||||||
|
|
||||||
|
CREATE TABLE class_student (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
teacher_number VARCHAR(20) NOT NULL,
|
||||||
|
class_name VARCHAR(20) NOT NULL , -- 班级
|
||||||
|
student_name VARCHAR(50) NOT NULL , -- 姓名
|
||||||
|
student_number VARCHAR(20) NOT NULL UNIQUE, -- 学号
|
||||||
|
course_id INT NOT NULL , -- 课程ID
|
||||||
|
course_name VARCHAR(100) NOT NULL , -- 课程名称
|
||||||
|
major_id VARCHAR(20) NOT NULL,
|
||||||
|
major VARCHAR(255) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE user
|
||||||
|
(
|
||||||
|
user_id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
name VARCHAR(50) NOT NULL,
|
||||||
|
number VARCHAR(15) NOT NULL UNIQUE,
|
||||||
|
password VARCHAR(255) NOT NULL,
|
||||||
|
status BOOLEAN NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO user (name, number, password, status) VALUES
|
||||||
|
('教师1','G0001','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
||||||
|
('教师2','G0002','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
||||||
|
('教师3','G0003','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
||||||
|
('教师4','G0004','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
||||||
|
('学生1','X202301000001','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
||||||
|
('学生2','X202301000002','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
||||||
|
('学生3','X202301000003','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
||||||
|
('学生4','X202301000004','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
||||||
|
('学生5','X202301000005','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
||||||
|
('学生6','X202301000006','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
||||||
|
('学生7','X202301000007','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
||||||
|
('学生8','X202301000008','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
||||||
|
('学生9','X202301000009','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
||||||
|
('学生10','X2023010000010','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
||||||
|
('学生11','X2023010000011','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE),
|
||||||
|
('学生12','X2023010000012','$2b$12$COT85R.ice41B/ofAra2ZewTe1En3ZhF6CBKOv2WScTcy.jQAhEVO',TRUE);
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE major
|
CREATE TABLE major
|
||||||
(
|
(
|
||||||
@@ -117,27 +153,20 @@ CREATE TABLE student
|
|||||||
FOREIGN KEY (major_id) REFERENCES major (major_id)
|
FOREIGN KEY (major_id) REFERENCES major (major_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
INSERT INTO student (user_id, student_number, student_name, class_id)
|
INSERT INTO student (user_id, student_number, student_name, class_name,major_id)
|
||||||
VALUES (5,'王伟', 202300001000, 1),
|
VALUES
|
||||||
(6,'李娜', 202300001001, 1),
|
(5,'X202301000001','学生1','2023级01班','000'),
|
||||||
(7,'张伟', 202300001002, 1),
|
(6,'X202301000002','学生2','2023级01班','000'),
|
||||||
(8,'刘洋', 202300001003, 1),
|
(7,'X202301000003','学生3','2023级01班','000'),
|
||||||
(9,'陈敏', 202300001004, 1),
|
(8,'X202301000004','学生4','2023级01班','000'),
|
||||||
(10,'杨静', 202300001005, 2),
|
(9,'X202302000005','学生5','2023级02班','000'),
|
||||||
(11,'赵媛媛', 202300001006, 2),
|
(10,'X202302000006','学生6','2023级02班','000'),
|
||||||
(12,'黄进', 202300001007, 2),
|
(11,'X202302000007','学生7','2023级02班','000'),
|
||||||
(13,'周杰', 202300001008, 2),
|
(12,'X202302000008','学生8','2023级02班','000'),
|
||||||
(14,'吴琳', 202300001009, 2),
|
(13,'X202303000009','学生9','2023级03班','001'),
|
||||||
(15,'徐涛', 202300001010, 3),
|
(14,'X202303000010','学生10','2023级03班','001'),
|
||||||
(16,'孙怡', 202300001011, 3),
|
(15,'X202303000011','学生11','2023级03班','001'),
|
||||||
(17,'朱元璋', 202300001012, 3),
|
(16,'X202303000012','学生12','2023级03班','001');
|
||||||
(18,'马云', 202300001013, 3),
|
|
||||||
(19,'胡雪', 202300001014, 3),
|
|
||||||
(20,'郭敬明', 202300001015, 4),
|
|
||||||
(21,'林芳', 202300001016, 4),
|
|
||||||
(22,'段誉', 202300001017, 4),
|
|
||||||
(23,'曹操', 202300001018, 4),
|
|
||||||
(24,'刘备', 202300001019, 4);
|
|
||||||
|
|
||||||
CREATE TABLE teacher
|
CREATE TABLE teacher
|
||||||
(
|
(
|
||||||
@@ -149,11 +178,11 @@ CREATE TABLE teacher
|
|||||||
FOREIGN KEY (user_id) REFERENCES user (user_id)
|
FOREIGN KEY (user_id) REFERENCES user (user_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
INSERT INTO teacher (name, user_id)
|
INSERT INTO teacher (name, user_id,teacher_number)
|
||||||
VALUES ('教师1', 1),
|
VALUES ('教师1', 1,'G0001'),
|
||||||
('教师2', 2),
|
('教师2', 2,'G0002'),
|
||||||
('教师3', 3),
|
('教师3', 3,'G0003'),
|
||||||
('教师4', 4);
|
('教师4', 4,'G0004');
|
||||||
|
|
||||||
CREATE TABLE major_course
|
CREATE TABLE major_course
|
||||||
(
|
(
|
||||||
@@ -188,11 +217,14 @@ CREATE TABLE teacher_class_course
|
|||||||
);
|
);
|
||||||
|
|
||||||
INSERT INTO teacher_class_course(teacher_number, course_id, class_name,major_id) VALUES
|
INSERT INTO teacher_class_course(teacher_number, course_id, class_name,major_id) VALUES
|
||||||
('G0000',1,'2023级01班','000'),
|
('G0001',1,'2023级01班','000'),
|
||||||
('G0000',3,'2023级01班','000'),
|
('G0001',3,'2023级01班','000'),
|
||||||
('G0001',2,'2023级01班','000'),
|
('G0002',2,'2023级02班','000'),
|
||||||
('G0001',4,'2023级01班','000');
|
('G0002',4,'2023级02班','000'),
|
||||||
|
('G0001',1,'2023级02班','000'),
|
||||||
|
('G0001',3,'2023级02班','000'),
|
||||||
|
('G0002',2,'2023级03班','001'),
|
||||||
|
('G0002',4,'2023级03班','001');
|
||||||
|
|
||||||
CREATE TABLE schedule
|
CREATE TABLE schedule
|
||||||
(
|
(
|
||||||
@@ -210,39 +242,45 @@ CREATE TABLE schedule
|
|||||||
|
|
||||||
|
|
||||||
INSERT INTO schedule (day_of_week, period_id, teacher_number, class_name, course_id) VALUES
|
INSERT INTO schedule (day_of_week, period_id, teacher_number, class_name, course_id) VALUES
|
||||||
(1,1,'G0000','2023级01班',1),
|
(1,1,'G0001','2023级01班',1),
|
||||||
(1,2,'G0000','2023级01班',3),
|
(1,2,'G0001','2023级01班',3),
|
||||||
(1,3,'G0001','2023级01班',2),
|
(1,3,'G0002','2023级01班',2),
|
||||||
(1,4,'G0001','2023级01班',4),
|
(1,4,'G0002','2023级01班',4),
|
||||||
(2,1,'G0001','2023级01班',4),
|
(2,1,'G0001','2023级01班',1),
|
||||||
(2,2,'G0001','2023级01班',2),
|
(2,2,'G0001','2023级01班',3),
|
||||||
(2,3,'G0000','2023级01班',1),
|
(2,3,'G0002','2023级01班',2),
|
||||||
(2,4,'G0000','2023级01班',3),
|
(2,4,'G0002','2023级01班',4),
|
||||||
(3,1,'G0000','2023级01班',1),
|
(3,1,'G0001','2023级01班',1),
|
||||||
(3,2,'G0000','2023级01班',3),
|
(3,2,'G0001','2023级01班',3),
|
||||||
(3,3,'G0001','2023级01班',2),
|
(3,3,'G0002','2023级01班',2),
|
||||||
(3,4,'G0001','2023级01班',4),
|
(3,4,'G0002','2023级01班',4),
|
||||||
(4,1,'G0001','2023级01班',4),
|
(4,1,'G0001','2023级01班',1),
|
||||||
(4,2,'G0001','2023级01班',2),
|
(4,2,'G0001','2023级01班',3),
|
||||||
(4,3,'G0000','2023级01班',1),
|
(4,3,'G0002','2023级01班',2),
|
||||||
(4,4,'G0000','2023级01班',3),
|
(4,4,'G0002','2023级01班',4),
|
||||||
(5,1,'G0000','2023级01班',1),
|
(5,1,'G0001','2023级01班',1),
|
||||||
(5,2,'G0000','2023级01班',3),
|
(5,2,'G0001','2023级01班',3),
|
||||||
(5,3,'G0001','2023级01班',2),
|
(5,3,'G0002','2023级01班',2),
|
||||||
(5,4,'G0001','2023级01班',4);
|
(5,4,'G0002','2023级01班',4),
|
||||||
|
(1,1,'G0002','2023级03班',2),
|
||||||
|
(1,2,'G0002','2023级03班',4),
|
||||||
|
(1,3,'G0001','2023级02班',1),
|
||||||
|
(1,4,'G0001','2023级02班',3),
|
||||||
|
(2,1,'G0002','2023级02班',2),
|
||||||
|
(2,2,'G0002','2023级02班',4),
|
||||||
|
(2,3,'G0001','2023级02班',1),
|
||||||
|
(2,4,'G0001','2023级02班',3),
|
||||||
|
(3,1,'G0002','2023级03班',2),
|
||||||
|
(3,2,'G0002','2023级03班',4),
|
||||||
|
(3,3,'G0001','2023级02班',1),
|
||||||
|
(3,4,'G0001','2023级02班',3),
|
||||||
|
(4,1,'G0002','2023级02班',2),
|
||||||
|
(4,2,'G0002','2023级02班',4),
|
||||||
|
(4,3,'G0001','2023级02班',1),
|
||||||
|
(4,4,'G0001','2023级02班',3),
|
||||||
|
(5,1,'G0002','2023级03班',2),
|
||||||
|
(5,2,'G0002','2023级03班',4),
|
||||||
|
(5,3,'G0001','2023级02班',1),
|
||||||
|
(5,4,'G0001','2023级02班',3);
|
||||||
|
|
||||||
CREATE TABLE time_period
|
|
||||||
(
|
|
||||||
period_id INT AUTO_INCREMENT UNIQUE,
|
|
||||||
period_name VARCHAR(10),
|
|
||||||
start_time TIME,
|
|
||||||
end_time TIME,
|
|
||||||
PRIMARY KEY (period_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO time_period (period_name, start_time, end_time)
|
|
||||||
VALUES ('一、二节', '08:00:00', '09:30:00'),
|
|
||||||
('三、四节', '10:00:00', '11:30:00'),
|
|
||||||
('五、六节', '14:30:00', '16:00:00'),
|
|
||||||
('七、八节', '16:30:00', '18:00:00');
|
|
||||||
|
|
||||||
|
|||||||
BIN
requirements.txt
BIN
requirements.txt
Binary file not shown.
30
utils/parse_table.py
Normal file
30
utils/parse_table.py
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
from openpyxl import load_workbook
|
||||||
|
|
||||||
|
|
||||||
|
def parse_table(file_path, number):
|
||||||
|
# 加载Excel工作簿
|
||||||
|
work_book = load_workbook(file_path)
|
||||||
|
|
||||||
|
# 选择工作簿中的第一个工作表
|
||||||
|
sheet = work_book.active
|
||||||
|
|
||||||
|
# 创建一个列表来存储所有行的数据
|
||||||
|
data = []
|
||||||
|
|
||||||
|
# 从第二行开始遍历(假设第一行是标题行)
|
||||||
|
for row in sheet.iter_rows(min_row=2, values_only=True):
|
||||||
|
# 创建一个字典来存储每行的数据
|
||||||
|
row_data = {
|
||||||
|
"teacher_number": number,
|
||||||
|
"class_name": row[0], # 班级
|
||||||
|
"student_name": row[1], # 姓名
|
||||||
|
"student_number": row[2], # 学号
|
||||||
|
"course_id": row[3], # 课程id
|
||||||
|
"course_name": row[4], # 课程
|
||||||
|
"major_id": row[5], # 专业代码
|
||||||
|
"major": row[6]
|
||||||
|
}
|
||||||
|
data.append(row_data)
|
||||||
|
|
||||||
|
# 返回解析后的数据
|
||||||
|
return data
|
||||||
Reference in New Issue
Block a user