v0.1测试
This commit is contained in:
11
backend/routes/__init__.py
Normal file
11
backend/routes/__init__.py
Normal file
@@ -0,0 +1,11 @@
|
||||
# ===========================================
|
||||
# 班级操行分管理系统 - 后端服务
|
||||
#
|
||||
# 开发者: Canglan
|
||||
# 联系方式: admin@sea-studio.top
|
||||
# 版权归属: Sea Network Technology Studio
|
||||
# 许可证: MIT License
|
||||
#
|
||||
# 版权所有 © Sea Network Technology Studio
|
||||
# ===========================================
|
||||
|
||||
64
backend/routes/admin.py
Normal file
64
backend/routes/admin.py
Normal file
@@ -0,0 +1,64 @@
|
||||
# ===========================================
|
||||
# 班级操行分管理系统 - 管理端路由
|
||||
#
|
||||
# 开发者: Canglan
|
||||
# 联系方式: admin@sea-studio.top
|
||||
# 版权归属: Sea Network Technology Studio
|
||||
# 许可证: MIT License
|
||||
#
|
||||
# 版权所有 © Sea Network Technology Studio
|
||||
# ===========================================
|
||||
|
||||
# 在 admin.py 中修改导入接口
|
||||
|
||||
@router.post("/students/import")
|
||||
async def import_students(
|
||||
request: Request,
|
||||
file: UploadFile = File(...)
|
||||
):
|
||||
"""
|
||||
批量导入学生(JSON格式)
|
||||
初始操行分默认为60分
|
||||
"""
|
||||
user = await get_current_user(request)
|
||||
|
||||
# 检查权限(仅班主任)
|
||||
is_teacher = await PermissionChecker.check_is_teacher(user["user_id"])
|
||||
if not is_teacher:
|
||||
return error_response(message="仅班主任可导入学生", code=403)
|
||||
|
||||
# 检查文件大小
|
||||
file_size = 0
|
||||
content = await file.read()
|
||||
file_size = len(content)
|
||||
|
||||
if file_size > settings.MAX_UPLOAD_SIZE:
|
||||
return error_response(message=f"文件大小不能超过{settings.MAX_UPLOAD_SIZE // 1024 // 1024}MB")
|
||||
|
||||
# 检查文件扩展名
|
||||
filename = file.filename or ""
|
||||
extension = filename.split('.')[-1].lower() if '.' in filename else ''
|
||||
if extension not in settings.ALLOWED_EXTENSIONS:
|
||||
return error_response(message=f"不支持的文件类型,仅支持 {', '.join(settings.ALLOWED_EXTENSIONS)}")
|
||||
|
||||
# 解析JSON
|
||||
try:
|
||||
import json
|
||||
data = json.loads(content.decode('utf-8'))
|
||||
students = data.get("students", [])
|
||||
except json.JSONDecodeError as e:
|
||||
return error_response(message=f"JSON格式错误: {str(e)}")
|
||||
except UnicodeDecodeError:
|
||||
return error_response(message="文件编码错误,请使用UTF-8编码")
|
||||
|
||||
if not students:
|
||||
return error_response(message="文件中没有学生数据")
|
||||
|
||||
# 导入学生(初始操行分60分)
|
||||
result = await AdminService.import_students(
|
||||
students=students,
|
||||
operator_id=user["user_id"],
|
||||
initial_points=60
|
||||
)
|
||||
|
||||
return success_response(data=result, message=f"导入完成: 成功{result['success_count']}人,失败{result['failed_count']}人")
|
||||
100
backend/routes/auth.py
Normal file
100
backend/routes/auth.py
Normal file
@@ -0,0 +1,100 @@
|
||||
# ===========================================
|
||||
# 班级操行分管理系统 - 后端服务
|
||||
#
|
||||
# 开发者: Canglan
|
||||
# 联系方式: admin@sea-studio.top
|
||||
# 版权归属: Sea Network Technology Studio
|
||||
# 许可证: MIT License
|
||||
#
|
||||
# 版权所有 © Sea Network Technology Studio
|
||||
# ===========================================
|
||||
|
||||
from fastapi import APIRouter, Request, HTTPException
|
||||
from typing import Dict, Any
|
||||
|
||||
from schemas.auth import LoginRequest, ChangePasswordRequest
|
||||
from services.auth_service import AuthService
|
||||
from middleware.permission import get_current_user
|
||||
from utils.response import success_response, error_response, unauthorized_response
|
||||
from utils.logger import get_logger
|
||||
|
||||
router = APIRouter()
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
@router.post("/login")
|
||||
async def login(request: LoginRequest, http_request: Request):
|
||||
"""
|
||||
用户登录
|
||||
"""
|
||||
# 获取客户端IP
|
||||
client_ip = http_request.client.host
|
||||
|
||||
result = await AuthService.login(
|
||||
username=request.username,
|
||||
password=request.password,
|
||||
ip=client_ip
|
||||
)
|
||||
|
||||
if result["success"]:
|
||||
return success_response(
|
||||
data={
|
||||
"token": result["token"],
|
||||
"user_id": result["user_id"],
|
||||
"username": result["username"],
|
||||
"real_name": result["real_name"],
|
||||
"user_type": result["user_type"],
|
||||
"need_change_password": result["need_change_password"],
|
||||
"redirect": result["redirect"]
|
||||
},
|
||||
message="登录成功"
|
||||
)
|
||||
else:
|
||||
return error_response(message=result["message"], code=401)
|
||||
|
||||
|
||||
@router.post("/logout")
|
||||
async def logout(request: Request):
|
||||
"""
|
||||
用户登出
|
||||
"""
|
||||
user = await get_current_user(request)
|
||||
result = await AuthService.logout(user["user_id"])
|
||||
|
||||
if result["success"]:
|
||||
return success_response(message="登出成功")
|
||||
else:
|
||||
return error_response(message=result["message"])
|
||||
|
||||
|
||||
@router.post("/change-password")
|
||||
async def change_password(request: Request, req: ChangePasswordRequest):
|
||||
"""
|
||||
修改密码
|
||||
"""
|
||||
user = await get_current_user(request)
|
||||
|
||||
result = await AuthService.change_password(
|
||||
user_id=user["user_id"],
|
||||
old_password=req.old_password,
|
||||
new_password=req.new_password
|
||||
)
|
||||
|
||||
if result["success"]:
|
||||
return success_response(message="密码修改成功,请重新登录")
|
||||
else:
|
||||
return error_response(message=result["message"])
|
||||
|
||||
|
||||
@router.get("/me")
|
||||
async def get_current_user_info(request: Request):
|
||||
"""
|
||||
获取当前用户信息
|
||||
"""
|
||||
user = await get_current_user(request)
|
||||
|
||||
# 获取用户详细信息
|
||||
from services.auth_service import AuthService
|
||||
user_info = await AuthService.get_user_info(user["user_id"])
|
||||
|
||||
return success_response(data=user_info)
|
||||
69
backend/routes/debug.py
Normal file
69
backend/routes/debug.py
Normal file
@@ -0,0 +1,69 @@
|
||||
# ===========================================
|
||||
# 班级操行分管理系统 - 后端服务
|
||||
#
|
||||
# 开发者: Canglan
|
||||
# 联系方式: admin@sea-studio.top
|
||||
# 版权归属: Sea Network Technology Studio
|
||||
# 许可证: MIT License
|
||||
#
|
||||
# 版权所有 © Sea Network Technology Studio
|
||||
# ===========================================
|
||||
|
||||
from fastapi import APIRouter, Request, HTTPException
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional
|
||||
|
||||
from config import settings
|
||||
from services.admin_service import AdminService
|
||||
from utils.response import success_response, error_response
|
||||
from utils.logger import get_logger
|
||||
|
||||
router = APIRouter()
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
class AddAdminDebugRequest(BaseModel):
|
||||
"""添加管理员请求"""
|
||||
username: str
|
||||
password: str
|
||||
real_name: str
|
||||
role_type: str # 班主任/班长/科代表/考勤委员/劳动委员
|
||||
class_id: int
|
||||
subject_id: Optional[int] = None
|
||||
|
||||
|
||||
@router.post(settings.DEBUG_PATH)
|
||||
async def debug_add_admin(request: Request, req: AddAdminDebugRequest):
|
||||
"""
|
||||
调试入口 - 添加第一批管理员
|
||||
注意:此接口仅用于首次部署,使用后建议注释掉此路由
|
||||
"""
|
||||
# 检查是否已存在管理员
|
||||
from models.user import UserModel
|
||||
existing = await UserModel.get_by_username(req.username)
|
||||
if existing:
|
||||
return error_response(message="用户名已存在")
|
||||
|
||||
# 创建管理员账号
|
||||
result = await AdminService.add_admin(
|
||||
username=req.username,
|
||||
real_name=req.real_name,
|
||||
password=req.password,
|
||||
role_type=req.role_type,
|
||||
class_id=req.class_id,
|
||||
subject_id=req.subject_id,
|
||||
operator_id=0 # 系统添加
|
||||
)
|
||||
|
||||
if result["success"]:
|
||||
logger.info(f"调试入口创建管理员: {req.username} ({req.role_type})")
|
||||
return success_response(
|
||||
data={
|
||||
"username": req.username,
|
||||
"password": req.password,
|
||||
"role_type": req.role_type
|
||||
},
|
||||
message=f"管理员 {req.username} 创建成功"
|
||||
)
|
||||
else:
|
||||
return error_response(message=result["message"])
|
||||
66
backend/routes/parent.py
Normal file
66
backend/routes/parent.py
Normal file
@@ -0,0 +1,66 @@
|
||||
# ===========================================
|
||||
# 班级操行分管理系统 - 后端服务
|
||||
#
|
||||
# 开发者: Canglan
|
||||
# 联系方式: admin@sea-studio.top
|
||||
# 版权归属: Sea Network Technology Studio
|
||||
# 许可证: MIT License
|
||||
#
|
||||
# 版权所有 © Sea Network Technology Studio
|
||||
# ===========================================
|
||||
|
||||
from fastapi import APIRouter, Request, Query
|
||||
from typing import Optional
|
||||
|
||||
from middleware.permission import get_current_user
|
||||
from services.parent_service import ParentService
|
||||
from utils.response import success_response, error_response
|
||||
from utils.logger import get_logger
|
||||
|
||||
router = APIRouter()
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
@router.get("/child/conduct")
|
||||
async def get_child_conduct(request: Request):
|
||||
"""
|
||||
获取子女操行分(仅总分)
|
||||
"""
|
||||
user = await get_current_user(request)
|
||||
|
||||
if user["user_type"] != "parent":
|
||||
return error_response(message="仅限家长访问", code=403)
|
||||
|
||||
result = await ParentService.get_child_conduct(user["user_id"])
|
||||
|
||||
return success_response(data=result)
|
||||
|
||||
|
||||
@router.get("/child/homework")
|
||||
async def get_child_homework(request: Request):
|
||||
"""
|
||||
获取子女作业情况
|
||||
"""
|
||||
user = await get_current_user(request)
|
||||
|
||||
if user["user_type"] != "parent":
|
||||
return error_response(message="仅限家长访问", code=403)
|
||||
|
||||
result = await ParentService.get_child_homework(user["user_id"])
|
||||
|
||||
return success_response(data=result)
|
||||
|
||||
|
||||
@router.get("/child/attendance")
|
||||
async def get_child_attendance(request: Request):
|
||||
"""
|
||||
获取子女考勤记录
|
||||
"""
|
||||
user = await get_current_user(request)
|
||||
|
||||
if user["user_type"] != "parent":
|
||||
return error_response(message="仅限家长访问", code=403)
|
||||
|
||||
result = await ParentService.get_child_attendance(user["user_id"])
|
||||
|
||||
return success_response(data=result)
|
||||
120
backend/routes/student.py
Normal file
120
backend/routes/student.py
Normal file
@@ -0,0 +1,120 @@
|
||||
# ===========================================
|
||||
# 班级操行分管理系统 - 后端服务
|
||||
#
|
||||
# 开发者: Canglan
|
||||
# 联系方式: admin@sea-studio.top
|
||||
# 版权归属: Sea Network Technology Studio
|
||||
# 许可证: MIT License
|
||||
#
|
||||
# 版权所有 © Sea Network Technology Studio
|
||||
# ===========================================
|
||||
|
||||
from fastapi import APIRouter, Request, Query
|
||||
from typing import Optional
|
||||
|
||||
from middleware.permission import get_current_user
|
||||
from services.student_service import StudentService
|
||||
from utils.response import success_response, error_response
|
||||
from utils.logger import get_logger
|
||||
|
||||
router = APIRouter()
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
@router.get("/conduct/{student_id}")
|
||||
async def get_conduct_history(
|
||||
request: Request,
|
||||
student_id: int,
|
||||
limit: int = Query(50, ge=1, le=200),
|
||||
offset: int = Query(0, ge=0)
|
||||
):
|
||||
"""
|
||||
获取学生操行分历史
|
||||
"""
|
||||
user = await get_current_user(request)
|
||||
|
||||
# 权限检查:只能查看自己的信息(学生)或同班(管理员)
|
||||
if user["user_type"] == "student" and user["student_id"] != student_id:
|
||||
return error_response(message="无权查看其他学生信息", code=403)
|
||||
|
||||
result = await StudentService.get_conduct_history(
|
||||
student_id=student_id,
|
||||
limit=limit,
|
||||
offset=offset
|
||||
)
|
||||
|
||||
return success_response(data=result)
|
||||
|
||||
|
||||
@router.get("/homework/{student_id}")
|
||||
async def get_homework_status(request: Request, student_id: int):
|
||||
"""
|
||||
获取学生作业情况
|
||||
"""
|
||||
user = await get_current_user(request)
|
||||
|
||||
# 权限检查
|
||||
if user["user_type"] == "student" and user["student_id"] != student_id:
|
||||
return error_response(message="无权查看其他学生信息", code=403)
|
||||
|
||||
result = await StudentService.get_homework_status(student_id)
|
||||
|
||||
return success_response(data=result)
|
||||
|
||||
|
||||
@router.get("/attendance/{student_id}")
|
||||
async def get_attendance_records(
|
||||
request: Request,
|
||||
student_id: int,
|
||||
month: Optional[str] = None
|
||||
):
|
||||
"""
|
||||
获取学生考勤记录
|
||||
"""
|
||||
user = await get_current_user(request)
|
||||
|
||||
# 权限检查
|
||||
if user["user_type"] == "student" and user["student_id"] != student_id:
|
||||
return error_response(message="无权查看其他学生信息", code=403)
|
||||
|
||||
result = await StudentService.get_attendance_records(
|
||||
student_id=student_id,
|
||||
month=month
|
||||
)
|
||||
|
||||
return success_response(data=result)
|
||||
|
||||
|
||||
@router.get("/ranking")
|
||||
async def get_ranking(
|
||||
request: Request,
|
||||
class_id: Optional[int] = None,
|
||||
limit: int = Query(50, ge=1, le=100)
|
||||
):
|
||||
"""
|
||||
获取操行分排行榜
|
||||
"""
|
||||
user = await get_current_user(request)
|
||||
|
||||
result = await StudentService.get_ranking(
|
||||
user_id=user["user_id"],
|
||||
class_id=class_id,
|
||||
limit=limit
|
||||
)
|
||||
|
||||
return success_response(data=result)
|
||||
|
||||
|
||||
@router.get("/my-info")
|
||||
async def get_my_info(request: Request):
|
||||
"""
|
||||
获取当前学生个人信息
|
||||
"""
|
||||
user = await get_current_user(request)
|
||||
|
||||
if user["user_type"] != "student":
|
||||
return error_response(message="仅限学生访问", code=403)
|
||||
|
||||
result = await StudentService.get_student_info(user["student_id"])
|
||||
|
||||
return success_response(data=result)
|
||||
105
backend/routes/subject.py
Normal file
105
backend/routes/subject.py
Normal file
@@ -0,0 +1,105 @@
|
||||
# ===========================================
|
||||
# 班级操行分管理系统 - 后端服务
|
||||
#
|
||||
# 开发者: Canglan
|
||||
# 联系方式: admin@sea-studio.top
|
||||
# 版权归属: Sea Network Technology Studio
|
||||
# 许可证: MIT License
|
||||
#
|
||||
# 版权所有 © Sea Network Technology Studio
|
||||
# ===========================================
|
||||
|
||||
from fastapi import APIRouter, Request, Query
|
||||
from typing import Optional
|
||||
|
||||
from middleware.permission import get_current_user, PermissionChecker
|
||||
from services.subject_service import SubjectService
|
||||
from schemas.subject import CreateSubjectRequest, UpdateSubjectRequest
|
||||
from utils.response import success_response, error_response
|
||||
from utils.logger import get_logger
|
||||
|
||||
router = APIRouter()
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
@router.get("/list")
|
||||
async def get_subjects(
|
||||
request: Request,
|
||||
is_active: Optional[bool] = None
|
||||
):
|
||||
"""
|
||||
获取科目列表
|
||||
"""
|
||||
user = await get_current_user(request)
|
||||
|
||||
result = await SubjectService.get_subjects(is_active=is_active)
|
||||
|
||||
return success_response(data=result)
|
||||
|
||||
|
||||
@router.post("/create")
|
||||
async def create_subject(request: Request, req: CreateSubjectRequest):
|
||||
"""
|
||||
创建科目(班主任)
|
||||
"""
|
||||
user = await get_current_user(request)
|
||||
|
||||
is_teacher = await PermissionChecker.check_is_teacher(user["user_id"])
|
||||
if not is_teacher:
|
||||
return error_response(message="仅班主任可创建科目", code=403)
|
||||
|
||||
result = await SubjectService.create_subject(
|
||||
subject_name=req.subject_name,
|
||||
subject_code=req.subject_code,
|
||||
sort_order=req.sort_order
|
||||
)
|
||||
|
||||
if result["success"]:
|
||||
return success_response(data=result, message="科目创建成功")
|
||||
else:
|
||||
return error_response(message=result["message"])
|
||||
|
||||
|
||||
@router.put("/update/{subject_id}")
|
||||
async def update_subject(
|
||||
request: Request,
|
||||
subject_id: int,
|
||||
req: UpdateSubjectRequest
|
||||
):
|
||||
"""
|
||||
更新科目(班主任)
|
||||
"""
|
||||
user = await get_current_user(request)
|
||||
|
||||
is_teacher = await PermissionChecker.check_is_teacher(user["user_id"])
|
||||
if not is_teacher:
|
||||
return error_response(message="仅班主任可更新科目", code=403)
|
||||
|
||||
result = await SubjectService.update_subject(
|
||||
subject_id=subject_id,
|
||||
**req.dict(exclude_none=True)
|
||||
)
|
||||
|
||||
if result["success"]:
|
||||
return success_response(message="科目更新成功")
|
||||
else:
|
||||
return error_response(message=result["message"])
|
||||
|
||||
|
||||
@router.delete("/delete/{subject_id}")
|
||||
async def delete_subject(request: Request, subject_id: int):
|
||||
"""
|
||||
删除科目(软删除,班主任)
|
||||
"""
|
||||
user = await get_current_user(request)
|
||||
|
||||
is_teacher = await PermissionChecker.check_is_teacher(user["user_id"])
|
||||
if not is_teacher:
|
||||
return error_response(message="仅班主任可删除科目", code=403)
|
||||
|
||||
result = await SubjectService.delete_subject(subject_id)
|
||||
|
||||
if result["success"]:
|
||||
return success_response(message="科目已禁用")
|
||||
else:
|
||||
return error_response(message=result["message"])
|
||||
Reference in New Issue
Block a user