Merge remote-tracking branch 'origin/main' into zhutt
# Conflicts: # main.py
This commit is contained in:
+5
-7
@@ -9,8 +9,7 @@ router = APIRouter()
|
||||
|
||||
@router.get(
|
||||
path="/consultants",
|
||||
tags=['顾问管理模块']
|
||||
)
|
||||
tags=['顾问管理模块'],summary='顾问模糊分页查询')
|
||||
def read_consultants(
|
||||
db: Session = Depends(get_db),
|
||||
page:int=1,
|
||||
@@ -22,7 +21,7 @@ def read_consultants(
|
||||
|
||||
|
||||
|
||||
@router.post("/consultants", response_model=ConsultantResponse,tags=['顾问管理模块'])
|
||||
@router.post("/consultants", response_model=ConsultantResponse,tags=['顾问管理模块'],summary='顾问增加')
|
||||
def create_consultant(
|
||||
obj_in: ConsultantCreate,
|
||||
db: Session = Depends(get_db)
|
||||
@@ -30,7 +29,7 @@ def create_consultant(
|
||||
return dao_consultant.create_consultant(db, obj_in)
|
||||
|
||||
|
||||
@router.get("/consultants/{id}", response_model=ConsultantResponse,tags=['顾问管理模块'])
|
||||
@router.get("/consultants/{id}", response_model=ConsultantResponse,tags=['顾问管理模块'],summary='顾问查询')
|
||||
def read_consultant(id: int, db: Session = Depends(get_db)):
|
||||
res = dao_consultant.get_consultant_by_id(db, cid=id)
|
||||
if res is None:
|
||||
@@ -41,8 +40,7 @@ def read_consultant(id: int, db: Session = Depends(get_db)):
|
||||
@router.put(
|
||||
path="/consultants/{id}",
|
||||
response_model=ConsultantResponse,
|
||||
tags=['顾问管理模块']
|
||||
)
|
||||
tags=['顾问管理模块'],summary='顾问更新')
|
||||
def update_consultant(
|
||||
id: int,
|
||||
obj_in: ConsultantUpdate,
|
||||
@@ -57,7 +55,7 @@ def update_consultant(
|
||||
|
||||
|
||||
|
||||
@router.delete("/consultants/{id}", response_model=ConsultantResponse,tags=['顾问管理模块'])
|
||||
@router.delete("/consultants/{id}", response_model=ConsultantResponse,tags=['顾问管理模块'],summary='顾问删除')
|
||||
def delete_consultant(id: int, db: Session = Depends(get_db)):
|
||||
res = dao_consultant.delete_consultant(db, cid=id)
|
||||
if res is None:
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.orm import Session
|
||||
from core.database import get_db
|
||||
from dao.employment import (
|
||||
create_employment,
|
||||
get_employment_by_id,
|
||||
get_employment_by_student_id,
|
||||
get_employment_list,
|
||||
update_employment,
|
||||
delete_employment_logic
|
||||
)
|
||||
from schemas.employment import (
|
||||
EmploymentCreate,
|
||||
EmploymentUpdate,
|
||||
EmploymentResponse
|
||||
)
|
||||
|
||||
employment_router = APIRouter(prefix="/employments", tags=["就业管理模块"])
|
||||
|
||||
|
||||
@employment_router.post("/", response_model=EmploymentResponse, summary="新增就业信息")
|
||||
def add_employment(body: EmploymentCreate, db: Session = Depends(get_db)):
|
||||
"""
|
||||
新增就业信息
|
||||
- 一个学生只能保存一条就业记录
|
||||
- student_id必须在学生表student_info_detail中真实存在
|
||||
"""
|
||||
res = create_employment(db, body)
|
||||
if res is None:
|
||||
raise HTTPException(status_code=500, detail="新增失败,学生id不存在或该学生已有就业记录")
|
||||
return res
|
||||
|
||||
|
||||
@employment_router.get("/students/{student_id}", response_model=EmploymentResponse, summary="查询指定学生的就业信息")
|
||||
def query_student_employment(student_id: int, db: Session = Depends(get_db)):
|
||||
"""根据学生id获取对应就业记录"""
|
||||
record = get_employment_by_student_id(db, student_id)
|
||||
if not record:
|
||||
raise HTTPException(status_code=404, detail="未找到该学生的就业信息")
|
||||
return record
|
||||
|
||||
|
||||
@employment_router.get("/", summary="就业信息列表,支持筛选")
|
||||
def query_employment_list(
|
||||
company_name: str | None = Query(None, description="公司名称模糊查询"),
|
||||
salary_min: float | None = Query(None, description="最低薪资"),
|
||||
salary_max: float | None = Query(None, description="最高薪资"),
|
||||
skip: int = Query(0, ge=0, description="偏移量"),
|
||||
limit: int = Query(20, ge=1, le=100, description="每页条数"),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
# 调用dao列表查询,拿到数据字典列表和总条数
|
||||
data_list, total = get_employment_list(db, company_name, salary_min, salary_max, skip, limit)
|
||||
return {"total": total, "data": data_list}
|
||||
|
||||
|
||||
@employment_router.get("/{eid}", response_model=EmploymentResponse, summary="根据id查询就业详情")
|
||||
def query_employment_detail(eid: int, db: Session = Depends(get_db)):
|
||||
"""根据就业主键id查询单条就业记录"""
|
||||
record = get_employment_by_id(db, eid)
|
||||
if not record:
|
||||
raise HTTPException(status_code=404, detail="就业记录不存在或已被逻辑删除")
|
||||
return record
|
||||
|
||||
|
||||
@employment_router.put("/{eid}", response_model=EmploymentResponse, summary="修改就业信息")
|
||||
def edit_employment(eid: int, body: EmploymentUpdate, db: Session = Depends(get_db)):
|
||||
"""修改就业记录,只传想要修改的字段即可"""
|
||||
res = update_employment(db, eid, body)
|
||||
if res is None:
|
||||
raise HTTPException(status_code=404, detail="修改失败,记录不存在")
|
||||
return res
|
||||
|
||||
|
||||
@employment_router.delete("/{eid}", summary="逻辑删除就业记录")
|
||||
def logic_delete_employment(eid: int, db: Session = Depends(get_db)):
|
||||
"""执行逻辑删除,is_deleted置1,不会真正删除数据库行"""
|
||||
ok = delete_employment_logic(db, eid)
|
||||
if not ok:
|
||||
raise HTTPException(status_code=404, detail="删除失败,记录不存在")
|
||||
# 删除成功返回提示字典
|
||||
return {"code": 200, "msg": "逻辑删除成功"}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.orm import Session
|
||||
from core.database import get_db
|
||||
from dao.score import post_score_dao, update_score_dao, get_score_dao, delete_score_dao, exist_student_exam_dao
|
||||
from schemas.score import ScoreCreate, ScoreUpdate, ScorePageResp
|
||||
|
||||
scores_router = APIRouter(prefix="/scores", tags=["成绩接口"])
|
||||
|
||||
|
||||
@scores_router.post("", summary="新增成绩接口")
|
||||
def create_score(req: ScoreCreate, db: Session = Depends(get_db)):
|
||||
# 业务校验:联合唯一
|
||||
if exist_student_exam_dao(req.student_id, req.exam_seq, db):
|
||||
raise HTTPException(status_code=400, detail="该学生本次考试成绩已存在,不能重复录入")
|
||||
|
||||
ok = post_score_dao(req.model_dump(), db)
|
||||
if not ok:
|
||||
raise HTTPException(status_code=400, detail="新增成绩失败,请检查学生id是否存在")
|
||||
return {"msg": "新增成功"}
|
||||
|
||||
|
||||
@scores_router.get("", response_model=ScorePageResp, summary="查询成绩接口")
|
||||
def list_score(
|
||||
score_id: int|None=None,
|
||||
student_id: int |None=None,
|
||||
exam_seq: int|None=None,
|
||||
page: int = Query(1, ge=1),
|
||||
page_size: int = Query(10, ge=1, le=100),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
total, data_list = get_score_dao(score_id, student_id, exam_seq, page, page_size, db)
|
||||
return {"total": total, "data": data_list}
|
||||
|
||||
|
||||
@scores_router.put("{score_id}", summary="更新成绩接口")
|
||||
def modify_score(score_id: int, req: ScoreUpdate, db: Session = Depends(get_db)):
|
||||
update_dict = req.model_dump(exclude_unset=True)
|
||||
if not update_dict:
|
||||
raise HTTPException(status_code=400, detail="没有传入任何修改字段")
|
||||
ok = update_score_dao(score_id, db, update_dict)
|
||||
if not ok:
|
||||
raise HTTPException(status_code=400, detail="修改失败,记录不存在或已删除")
|
||||
return {"msg": "修改成功"}
|
||||
|
||||
|
||||
@scores_router.delete("{score_id}", summary="删除成绩接口")
|
||||
def remove_score(score_id: int, db: Session = Depends(get_db)):
|
||||
ok = delete_score_dao(score_id, db)
|
||||
if not ok:
|
||||
raise HTTPException(status_code=400, detail="删除失败,记录不存在或已删除")
|
||||
return {"msg": "逻辑删除成功"}
|
||||
+62
-7
@@ -1,16 +1,17 @@
|
||||
from fastapi import APIRouter,HTTPException,Depends
|
||||
from DoubaoTeam.core.database import get_db
|
||||
from DoubaoTeam.models.student import Student
|
||||
from DoubaoTeam.models.score import Score
|
||||
from DoubaoTeam.dao.statistics import *
|
||||
from DoubaoTeam.schemas.common import SuccessResponse
|
||||
from core.database import get_db
|
||||
from models.employment import Employment
|
||||
from models.student import Student
|
||||
from models.score import Score
|
||||
from dao.statistics import *
|
||||
from schemas.common import SuccessResponse
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
|
||||
statistics_router=APIRouter()
|
||||
statistics_router=APIRouter(tags=['statistics'])
|
||||
|
||||
|
||||
@statistics_router.get("/scores/age-over-30",response_model=SuccessResponse)
|
||||
@statistics_router.get("/students/age-over-30",response_model=SuccessResponse)
|
||||
def api_age_over_thirty(db:Session=Depends(get_db)):
|
||||
try:
|
||||
age_over_thirty_list=age_over_thirty(Student,db)
|
||||
@@ -26,3 +27,57 @@ def api_gender_count(db:Session=Depends(get_db)):
|
||||
except NoExist as e:
|
||||
raise HTTPException(status_code=404,detail=str(e))
|
||||
|
||||
@statistics_router.get("/scores/all-above-80",response_model=SuccessResponse)
|
||||
def all_above_eighty(db:Session=Depends(get_db)):
|
||||
try:
|
||||
result = score_over_eighty(Score,Student,db)
|
||||
return SuccessResponse(status_code=200,msg=result)
|
||||
except NoExist as e:
|
||||
raise HTTPException(status_code=404,detail=str(e))
|
||||
|
||||
@statistics_router.get("/scores/fail-more-than-two",response_model=SuccessResponse)
|
||||
def fail_two(db:Session=Depends(get_db)):
|
||||
try:
|
||||
result = twice_error(Score,Student,db)
|
||||
return SuccessResponse(status_code=200,msg=result)
|
||||
except NoExist as e:
|
||||
raise HTTPException(status_code=404,detail=str(e))
|
||||
|
||||
@statistics_router.get("/scores/class-average",response_model=SuccessResponse)
|
||||
def class_average(db:Session=Depends(get_db)):
|
||||
try:
|
||||
result = avg_class(Score,Student,db)
|
||||
return SuccessResponse(status_code=200,msg=result)
|
||||
except NoExist as e:
|
||||
raise HTTPException(status_code=404,detail=str(e))
|
||||
|
||||
|
||||
@statistics_router.get("/employments/top5-salary",response_model=SuccessResponse)
|
||||
def top_salary(db:Session=Depends(get_db)):
|
||||
try:
|
||||
result=max_salary(Student,Employment,db)
|
||||
return SuccessResponse(status_code=200,msg=result)
|
||||
except NoExist as e:
|
||||
raise HTTPException(status_code=404,detail=str(e))
|
||||
|
||||
@statistics_router.get("/employments/student-duration",response_model=SuccessResponse)
|
||||
def employ_time(db:Session=Depends(get_db)):
|
||||
try:
|
||||
result = student_market(Employment,db)
|
||||
return SuccessResponse(status_code=200,msg=result)
|
||||
except NoExist as e:
|
||||
raise HTTPException(status_code=404,detail=str(e))
|
||||
|
||||
@statistics_router.get("/employments/class-average-duration",response_model=SuccessResponse)
|
||||
def avg_employ_time(db:Session=Depends(get_db)):
|
||||
try:
|
||||
result = avg_emptime(Employment,Student,db)
|
||||
return SuccessResponse(status_code=200,msg=result)
|
||||
except NoExist as e:
|
||||
raise HTTPException(status_code=404,detail=str(e))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+89
-7
@@ -1,14 +1,96 @@
|
||||
from fastapi import APIRouter,Depends,HTTPException
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
from dao.student import *
|
||||
from schemas.student import StudentCreate
|
||||
|
||||
from core.database import get_db
|
||||
from schemas.student import StudentCreate, StudentUpdate
|
||||
from dao import student as student_dao
|
||||
student_router = APIRouter()
|
||||
|
||||
@student_router.post("/student")
|
||||
def create_student(request:StudentCreate,db:Session,create = Depends(create_students)):
|
||||
@student_router.post("",summary='添加学生')
|
||||
def create_student(request:StudentCreate,db:Session = Depends(get_db)):
|
||||
d = request.model_dump()
|
||||
r = create_students(d,db)
|
||||
r = student_dao.create_students(d,db)
|
||||
if not r:
|
||||
raise HTTPException(status_code=500,detail='服务器繁忙,请稍后添加!')
|
||||
return {'code':200,'detail':"添加学生成功"}
|
||||
return {'code':200,'detail':"添加学生成功"}
|
||||
|
||||
@student_router.put("/{id}", summary="修改学生")
|
||||
def update_student(
|
||||
id: int,
|
||||
request: StudentUpdate,
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
# 只取前端真正传来的字段
|
||||
# 例如只传 age,就只修改 age
|
||||
data = request.model_dump(exclude_unset=True)
|
||||
|
||||
student = student_dao.update_student(id, data, db)
|
||||
|
||||
# None 表示学生不存在
|
||||
if student is None:
|
||||
raise HTTPException(status_code=404, detail="学生不存在")
|
||||
|
||||
# False 表示操作数据库失败
|
||||
if student is False:
|
||||
raise HTTPException(status_code=500, detail="修改学生失败")
|
||||
|
||||
return {
|
||||
"code": 200,
|
||||
"detail": "修改学生成功",
|
||||
"data": student,
|
||||
}
|
||||
|
||||
@student_router.get("", summary="查询学生列表")
|
||||
def get_students(
|
||||
# 三个查询条件都可以不传
|
||||
student_no: str | None = None,
|
||||
student_name: str | None = None,
|
||||
class_id: int | None = None,
|
||||
# 获取本次请求使用的数据库连接
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
# 调用 DAO 查询数据库
|
||||
students = student_dao.get_students(
|
||||
db=db,
|
||||
student_no=student_no,
|
||||
student_name=student_name,
|
||||
class_id=class_id,
|
||||
)
|
||||
|
||||
return {
|
||||
"code": 200,
|
||||
"detail": "查询成功",
|
||||
"total": len(students),
|
||||
"data": students,
|
||||
}
|
||||
|
||||
@student_router.get("/{id}", summary="查询学生详情")
|
||||
def get_student(id: int, db: Session = Depends(get_db)):
|
||||
# 根据路径中的 ID 查询学生
|
||||
student = student_dao.get_student_by_id(id, db)
|
||||
|
||||
if not student:
|
||||
# 404 表示请求的数据不存在
|
||||
raise HTTPException(status_code=404, detail="学生不存在")
|
||||
|
||||
return {
|
||||
"code": 200,
|
||||
"detail": "查询成功",
|
||||
"data": student,
|
||||
}
|
||||
|
||||
@student_router.delete("/{id}", summary="逻辑删除学生")
|
||||
def delete_student(id: int, db: Session = Depends(get_db)):
|
||||
student = student_dao.delete_student(id, db)
|
||||
|
||||
# None 表示不存在,或者以前已经删除
|
||||
if student is None:
|
||||
raise HTTPException(status_code=404, detail="学生不存在或已经删除")
|
||||
|
||||
if student is False:
|
||||
raise HTTPException(status_code=500, detail="删除学生失败")
|
||||
|
||||
return {
|
||||
"code": 200,
|
||||
"detail": "删除学生成功",
|
||||
}
|
||||
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
from typing import List
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
from core import database
|
||||
from core.database import get_db
|
||||
from schemas.teacher import TeacherOut, TeacherCreate, TeacherUpdate, ClassTeachersCreate, ClassTeacherOut
|
||||
# 导入dao层所有函数
|
||||
from models.teacher import Teacher
|
||||
from models.class_teacher import ClassTeachers
|
||||
from dao.teacher import (
|
||||
get_teacher_list,
|
||||
get_teacher_by_id,
|
||||
create_teacher,
|
||||
update_teacher,
|
||||
delete_teacher,
|
||||
get_class_teacher_by_class_id,
|
||||
create_class_teacher,
|
||||
update_class_teacher_full,
|
||||
delete_class_teacher
|
||||
)
|
||||
|
||||
router = APIRouter(prefix="/teacher", tags=["老师管理模块"])
|
||||
|
||||
#============================老师表===============================
|
||||
@router.get("/list", response_model=List[TeacherOut])
|
||||
def api_get_teacher_list(db: Session = Depends(get_db)):
|
||||
"""
|
||||
GET 查询全部有效老师列表
|
||||
:param db: 数据库会话,Depends自动注入
|
||||
:return: List[TeacherOut] 老师列表,使用TeacherOut做响应格式化
|
||||
"""
|
||||
return get_teacher_list(db)
|
||||
|
||||
@router.get("/{teacher_id}", response_model=TeacherOut)
|
||||
def api_get_teacher_by_id(teacher_id: int,db: Session = Depends(get_db)):
|
||||
"""
|
||||
根据老师主键ID查询单个有效老师
|
||||
:param teacher_id: int 老师表主键ID
|
||||
:param db: Session 数据库会话对象,依赖注入自动获取
|
||||
:return: TeacherOut 老师详情信息
|
||||
"""
|
||||
return get_teacher_by_id(db,teacher_id)
|
||||
@router.post("", response_model=TeacherOut, summary="新增老师")
|
||||
def api_create_teacher(obj: TeacherCreate, db: Session = Depends(get_db)):
|
||||
"""
|
||||
新增老师记录,自动校验姓名、编号唯一性,并自动生成老师业务编号
|
||||
:param obj: TeacherCreate Pydantic模型,前端提交新增老师表单数据
|
||||
:param db: Session 数据库会话对象,依赖注入自动获取
|
||||
:return: TeacherOut 新增成功后的老师完整信息
|
||||
"""
|
||||
return create_teacher(db, obj)
|
||||
@router.put("/{teacher_id}", response_model=TeacherOut, summary="修改老师信息(局部更新)")
|
||||
def api_update_teacher(teacher_id: int, obj: TeacherUpdate, db: Session = Depends(get_db)):
|
||||
"""
|
||||
修改老师信息,支持局部更新,仅更新前端传入的字段
|
||||
:param teacher_id: int 需要修改的老师主键ID
|
||||
:param obj: TeacherUpdate Pydantic模型,前端提交待修改字段
|
||||
:param db: Session 数据库会话对象,依赖注入自动获取
|
||||
:return: TeacherOut 更新后的老师完整信息
|
||||
"""
|
||||
db_teacher = get_teacher_by_id(db, teacher_id)
|
||||
if not db_teacher:
|
||||
raise HTTPException(status_code=404, detail="老师不存在或已删除!")
|
||||
result = update_teacher(db, teacher_id, obj)
|
||||
return result
|
||||
@router.delete("/{teacher_id}", summary="逻辑删除老师")
|
||||
def api_delete_teacher(teacher_id: int, db: Session = Depends(get_db)):
|
||||
"""
|
||||
逻辑删除老师,存在有效班级带班关系时禁止删除
|
||||
:param teacher_id: int 需要删除的老师主键ID
|
||||
:param db: Session 数据库会话对象,依赖注入自动获取
|
||||
:return: dict 操作成功提示
|
||||
"""
|
||||
result = delete_teacher(db, teacher_id)
|
||||
if not result:
|
||||
raise HTTPException(status_code=404, detail="老师不存在或已删除!")
|
||||
return {"msg": "老师逻辑删除成功"}
|
||||
|
||||
# ===================== 班级老师关联路由组 =====================
|
||||
class_teacher_router = APIRouter(prefix="/class-teacher", tags=["班级老师分配管理模块"])
|
||||
|
||||
@class_teacher_router.get("/class/{class_id}", response_model=List[ClassTeacherOut], summary="根据班级ID查询该班级所有带班老师")
|
||||
def api_get_class_teacher_by_class_id(class_id: int, db: Session = Depends(get_db)):
|
||||
"""
|
||||
根据班级主键ID,查询该班级全部有效的班级-老师绑定记录
|
||||
:param class_id: int 班级表主键ID
|
||||
:param db: Session 数据库会话对象,依赖注入自动获取
|
||||
:return: List[ClassTeachersOut] 班级老师关联记录列表
|
||||
"""
|
||||
return get_class_teacher_by_class_id(db, class_id)
|
||||
|
||||
@class_teacher_router.post("", response_model=ClassTeacherOut, summary="分配老师到班级,新增班级老师关联记录")
|
||||
def api_create_class_teacher(obj: ClassTeachersCreate, db: Session = Depends(get_db)):
|
||||
"""
|
||||
新增班级与老师的绑定关系,做重复性校验与老师有效性校验
|
||||
:param obj: ClassTeachersCreate Pydantic模型,前端提交class_id、teacher_id、role
|
||||
:param db: Session 数据库会话对象,依赖注入自动获取
|
||||
:return: ClassTeachersOut 新增成功后的班级老师关联记录
|
||||
"""
|
||||
return create_class_teacher(db, obj)
|
||||
|
||||
@class_teacher_router.put("/{rel_id}", response_model=ClassTeacherOut, summary="更新班级老师绑定关系")
|
||||
def api_update_class_teacher_full(rel_id: int, obj: ClassTeachersCreate, db: Session = Depends(get_db)):
|
||||
"""
|
||||
修改班级老师中间表记录,支持修改class_id、teacher_id、role;自动校验老师有效性、三元组合唯一性
|
||||
:param rel_id: int class_teachers中间表主键ID(待修改的关联记录id)
|
||||
:param obj: ClassTeachersCreate Pydantic模型,前端提交新的class_id、teacher_id、role
|
||||
:param db: Session 数据库会话对象,依赖注入自动获取
|
||||
:return: ClassTeachersOut 更新后的班级老师关联记录
|
||||
"""
|
||||
result = update_class_teacher_full(db, rel_id, obj)
|
||||
if not result:
|
||||
raise HTTPException(status_code=404, detail="班级老师关联记录不存在!")
|
||||
return result
|
||||
|
||||
@class_teacher_router.delete("/{rel_id}", summary="逻辑删除班级老师带班关联")
|
||||
def api_delete_class_teacher(rel_id: int, db: Session = Depends(get_db)):
|
||||
"""
|
||||
逻辑删除班级老师绑定关系,修改is_deleted标记为1,非物理删除
|
||||
:param rel_id: int class_teachers中间表主键ID
|
||||
:param db: Session 数据库会话对象,依赖注入自动获取
|
||||
:return: dict 操作成功提示
|
||||
"""
|
||||
result = delete_class_teacher(db, rel_id)
|
||||
if not result:
|
||||
raise HTTPException(status_code=404, detail="班级老师关联记录不存在!")
|
||||
return {"msg": "解除班级带班关系成功"}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user