2025-03-04 20:36:52 +08:00
|
|
|
|
from fastapi import APIRouter, Depends, Request, Form, Body, UploadFile,File
|
|
|
|
|
from fastapi.responses import PlainTextResponse
|
2025-01-15 20:26:58 +08:00
|
|
|
|
from typing import Optional, Dict, Any
|
|
|
|
|
from pydantic import BaseModel
|
|
|
|
|
from sqlalchemy.orm import Session
|
|
|
|
|
from mooc.db.database import get_db
|
|
|
|
|
from mooc.crud.crud_goouc_fullexam_user import (
|
|
|
|
|
CRUDUserDoexam,
|
|
|
|
|
CRUDUserExamAnswer,
|
|
|
|
|
CRUDUserWrongPraction,
|
2025-03-04 20:36:52 +08:00
|
|
|
|
CRUDUserCollectionPraction,
|
|
|
|
|
full_exam_user
|
2025-01-15 20:26:58 +08:00
|
|
|
|
)
|
|
|
|
|
from mooc.models.goouc_fullexam_user import (
|
|
|
|
|
UserDoexam,
|
|
|
|
|
UserExamAnswer,
|
|
|
|
|
UserWrongPraction,
|
2025-03-04 20:36:52 +08:00
|
|
|
|
UserCollectionPraction,
|
|
|
|
|
FullExamUser
|
2025-01-15 20:26:58 +08:00
|
|
|
|
)
|
2025-03-04 20:36:52 +08:00
|
|
|
|
from mooc.core.config import settings
|
|
|
|
|
from mooc.utils.wechat_client import wx_api
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
import os
|
|
|
|
|
from mooc.core.logger import get_logger
|
|
|
|
|
import httpx
|
|
|
|
|
from mooc.core.response import ResponseFactory
|
|
|
|
|
import re
|
|
|
|
|
from mooc.crud.crud_goouc_fullexam import setting, xueshen
|
|
|
|
|
from mooc.crud.crud_goouc_fullexam_user import full_exam_user, user_member
|
2025-01-15 20:26:58 +08:00
|
|
|
|
|
|
|
|
|
wxapp_router = APIRouter()
|
|
|
|
|
|
2025-03-04 20:36:52 +08:00
|
|
|
|
# 创建模块级别的日志记录器
|
|
|
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
2025-01-15 20:26:58 +08:00
|
|
|
|
class WxappRequest(BaseModel):
|
|
|
|
|
uid: Optional[str] = None
|
|
|
|
|
op: Optional[str] = None
|
|
|
|
|
m: Optional[str] = None
|
|
|
|
|
data: Dict[str, Any] = {}
|
2025-03-04 20:36:52 +08:00
|
|
|
|
code: Optional[str] = None
|
|
|
|
|
|
|
|
|
|
# 启用额外字段支持
|
|
|
|
|
model_config = {
|
|
|
|
|
"extra": "allow" # 允许存储模型中未定义的字段
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# 添加一个方法便于获取任意字段,带默认值
|
|
|
|
|
def get_field(self, field_name: str, default=None):
|
|
|
|
|
"""获取字段值,优先从直接属性获取,然后从data字典获取"""
|
|
|
|
|
if hasattr(self, field_name):
|
|
|
|
|
return getattr(self, field_name)
|
|
|
|
|
return self.data.get(field_name, default)
|
2025-01-15 20:26:58 +08:00
|
|
|
|
|
|
|
|
|
@wxapp_router.post("/index")
|
|
|
|
|
async def handle_wxapp_request(
|
|
|
|
|
request: Request,
|
|
|
|
|
i: str,
|
|
|
|
|
t: Optional[str] = None,
|
|
|
|
|
v: Optional[str] = None,
|
|
|
|
|
c: Optional[str] = "entry",
|
|
|
|
|
a: Optional[str] = "wxapp",
|
|
|
|
|
do: Optional[str] = None,
|
2025-03-04 20:36:52 +08:00
|
|
|
|
db: Session = Depends(get_db),
|
|
|
|
|
file: UploadFile = None
|
2025-01-15 20:26:58 +08:00
|
|
|
|
):
|
|
|
|
|
# 获取表单数据
|
|
|
|
|
try:
|
|
|
|
|
form_data = await request.form()
|
2025-03-04 20:36:52 +08:00
|
|
|
|
logger.debug(f"Form data: {form_data}")
|
2025-01-15 20:26:58 +08:00
|
|
|
|
# 将表单数据转换为字典
|
|
|
|
|
data = dict(form_data)
|
2025-03-04 20:36:52 +08:00
|
|
|
|
|
|
|
|
|
# 检查是否包含上传文件
|
|
|
|
|
if "upfile" in form_data:
|
|
|
|
|
file = form_data["upfile"]
|
2025-01-15 20:26:58 +08:00
|
|
|
|
except Exception as e:
|
2025-03-04 20:36:52 +08:00
|
|
|
|
logger.error(f"Error reading form data: {e}")
|
2025-01-15 20:26:58 +08:00
|
|
|
|
# 如果没有表单数据,尝试读取JSON
|
|
|
|
|
try:
|
|
|
|
|
data = await request.json()
|
2025-03-04 20:36:52 +08:00
|
|
|
|
logger.debug(f"JSON data: {data}")
|
2025-01-15 20:26:58 +08:00
|
|
|
|
except Exception as e:
|
2025-03-04 20:36:52 +08:00
|
|
|
|
logger.error(f"Error reading JSON: {e}")
|
2025-01-15 20:26:58 +08:00
|
|
|
|
data = {}
|
|
|
|
|
|
2025-03-04 20:36:52 +08:00
|
|
|
|
logger.debug(f"Final data: {data}")
|
|
|
|
|
logger.debug(f"Query params: {request.query_params}")
|
2025-01-15 20:26:58 +08:00
|
|
|
|
|
|
|
|
|
# 根据do参数处理不同的业务逻辑
|
2025-03-04 20:36:52 +08:00
|
|
|
|
if do == "login2":
|
|
|
|
|
# 针对login2,直接传递表单数据
|
|
|
|
|
if "code" in data:
|
|
|
|
|
return await handle_login2(WxappRequest(code=data.get("code"),
|
|
|
|
|
data=data), db)
|
|
|
|
|
else:
|
|
|
|
|
# 如果没有code,仍然尝试正常处理
|
|
|
|
|
return await handle_login2(WxappRequest(**data), db)
|
|
|
|
|
elif do == "Setuserinfo":
|
|
|
|
|
return await handle_set_user_info(WxappRequest(**data), db)
|
2025-01-15 20:26:58 +08:00
|
|
|
|
elif do == "ExamOperation":
|
|
|
|
|
return await handle_exam_operation(WxappRequest(**data), db, user_doexam, user_exam_answer)
|
|
|
|
|
elif do == "Collection":
|
|
|
|
|
return await handle_collection(WxappRequest(**data), db, user_collection)
|
|
|
|
|
elif do == "WrongQuestion":
|
|
|
|
|
return await handle_wrong_question(WxappRequest(**data), db, user_wrong_praction)
|
|
|
|
|
elif do == "TotalqNum":
|
|
|
|
|
# 添加新的处理逻辑
|
2025-03-04 20:36:52 +08:00
|
|
|
|
return {"code": 0, "data": {"total": 100}, "message": "success"}
|
2025-01-15 20:26:58 +08:00
|
|
|
|
elif do == "Index":
|
|
|
|
|
# 添加首页处理逻辑
|
2025-03-04 20:36:52 +08:00
|
|
|
|
return {"code": 0, "data": {}, "message": "success"}
|
2025-01-15 20:26:58 +08:00
|
|
|
|
elif do == "Advert":
|
|
|
|
|
# 添加广告处理逻辑
|
2025-03-04 20:36:52 +08:00
|
|
|
|
return {"code": 0, "data": [], "message": "success"}
|
|
|
|
|
elif do == "uploadImage":
|
|
|
|
|
if not file:
|
|
|
|
|
return ResponseFactory.error(code=400, message="缺少上传文件")
|
|
|
|
|
return await handle_upload_image(WxappRequest(**data), db, file)
|
|
|
|
|
elif do == "UpdateHeadimg":
|
|
|
|
|
return await handle_update_headimg(WxappRequest(**data), db)
|
|
|
|
|
|
|
|
|
|
|
2025-01-15 20:26:58 +08:00
|
|
|
|
|
2025-03-04 20:36:52 +08:00
|
|
|
|
return {"code": 404, "message": "接口未找到"}
|
2025-01-15 20:26:58 +08:00
|
|
|
|
|
2025-03-04 20:36:52 +08:00
|
|
|
|
async def handle_update_headimg(data: WxappRequest, db: Session):
|
|
|
|
|
"""处理更新用户头像的请求"""
|
|
|
|
|
logger.info(f"处理更新头像请求: uid={data.uid},data={data}")
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# 验证必要参数
|
|
|
|
|
uid = data.uid
|
|
|
|
|
# headimg = data.data.get("headimg")
|
|
|
|
|
|
|
|
|
|
# if not uid or not headimg:
|
|
|
|
|
# logger.error("参数不足: uid或headimg缺失")
|
|
|
|
|
# return ResponseFactory.error(code=1, message="传递的参数不存在", data="1001")
|
|
|
|
|
|
|
|
|
|
# 获取用户对象,包含weid条件
|
|
|
|
|
user = full_exam_user.get_by_id_and_weid(db, int(uid), settings.WECHAT_UNIACID)
|
|
|
|
|
if not user:
|
|
|
|
|
logger.error(f"用户不存在: uid={uid}")
|
|
|
|
|
return ResponseFactory.error(code=1, message="用户不存在", data="error")
|
|
|
|
|
logger.debug(f"用户信息: {user.headimg}")
|
|
|
|
|
# 更新用户头像
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
update_data = {"headimg": data.headimg}
|
|
|
|
|
full_exam_user.update(db, db_obj=user, obj_in=update_data)
|
|
|
|
|
logger.info(f"头像更新成功: uid={uid}, headimg={data.headimg}")
|
|
|
|
|
return ResponseFactory.success(data="ok", message="ok")
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"头像更新失败: {str(e)}")
|
|
|
|
|
return ResponseFactory.error(code=1, message="error", data="error")
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.exception(f"处理更新头像请求过程中发生异常: {str(e)}")
|
|
|
|
|
return ResponseFactory.error(code=1, message=str(e), data="error")
|
|
|
|
|
|
|
|
|
|
async def handle_upload_image(data: WxappRequest, db: Session, file: UploadFile = File(...)):
|
|
|
|
|
"""处理图片上传功能"""
|
|
|
|
|
import os
|
|
|
|
|
import time
|
|
|
|
|
import random
|
|
|
|
|
import string
|
|
|
|
|
import shutil
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
logger.info(f"处理图片上传请求: uid={data.uid}, module={data.m}")
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# 定义允许的图片类型
|
|
|
|
|
allowed_types = [
|
|
|
|
|
"image/jpg", "image/jpeg", "image/png",
|
|
|
|
|
"image/pjpeg", "image/gif", "image/bmp", "image/x-png"
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
# 最大文件大小(2MB)
|
|
|
|
|
max_file_size = 2000000
|
|
|
|
|
|
|
|
|
|
# 检查文件是否存在
|
|
|
|
|
if not file:
|
|
|
|
|
logger.error("图片不存在!")
|
|
|
|
|
return ResponseFactory.error(code=400, message="图片不存在!")
|
|
|
|
|
|
|
|
|
|
# 检查文件内容类型
|
|
|
|
|
content_type = file.content_type
|
|
|
|
|
if content_type not in allowed_types:
|
|
|
|
|
logger.error(f"文件类型不符: {content_type}")
|
|
|
|
|
return ResponseFactory.error(code=400, message=f"文件类型不符: {content_type}")
|
|
|
|
|
|
|
|
|
|
# 读取文件内容以检查大小
|
|
|
|
|
contents = await file.read()
|
|
|
|
|
if len(contents) > max_file_size:
|
|
|
|
|
logger.error(f"文件太大: {len(contents)} bytes")
|
|
|
|
|
return ResponseFactory.error(code=400, message="文件太大!")
|
|
|
|
|
|
|
|
|
|
# 重置文件位置指针
|
|
|
|
|
await file.seek(0)
|
|
|
|
|
|
|
|
|
|
# 获取上传目标文件夹路径
|
|
|
|
|
module_name = data.m or "default"
|
|
|
|
|
|
|
|
|
|
# 使用绝对路径并确保目录存在
|
|
|
|
|
destination_folder = os.path.join(settings.UPLOAD_IMG_DIR, module_name)
|
|
|
|
|
logger.debug(f"上传目标文件夹: {destination_folder}")
|
|
|
|
|
|
|
|
|
|
# 确保目标目录存在
|
|
|
|
|
Path(destination_folder).mkdir(parents=True, exist_ok=True)
|
|
|
|
|
|
|
|
|
|
# 创建更安全的随机文件名 (时间戳 + 随机数)
|
|
|
|
|
current_time = int(time.time())
|
|
|
|
|
random_string = ''.join(random.choices(string.digits + string.ascii_lowercase, k=8))
|
|
|
|
|
file_extension = os.path.splitext(file.filename)[1].lower() # 转为小写以增加一致性
|
|
|
|
|
|
|
|
|
|
# 验证扩展名安全性
|
|
|
|
|
safe_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp']
|
|
|
|
|
if file_extension not in safe_extensions:
|
|
|
|
|
file_extension = '.jpg' # 默认使用安全扩展名
|
|
|
|
|
|
|
|
|
|
filename = f"{current_time}_{random_string}{file_extension}"
|
|
|
|
|
|
|
|
|
|
# 完整的保存路径
|
|
|
|
|
file_path = os.path.join(destination_folder, filename)
|
|
|
|
|
logger.debug(f"文件将保存至: {file_path}")
|
|
|
|
|
|
|
|
|
|
# 保存文件
|
|
|
|
|
with open(file_path, "wb") as buffer:
|
|
|
|
|
shutil.copyfileobj(file.file, buffer)
|
|
|
|
|
|
|
|
|
|
# 检查文件是否成功保存
|
|
|
|
|
if not os.path.exists(file_path):
|
|
|
|
|
logger.error(f"文件保存失败: {file_path}")
|
|
|
|
|
return ResponseFactory.error(code=500, message="文件保存失败")
|
|
|
|
|
|
|
|
|
|
# 构建文件URL路径
|
|
|
|
|
url_module_path = module_name.replace('\\', '/')
|
|
|
|
|
|
|
|
|
|
# 使用相对路径作为存储路径
|
|
|
|
|
relative_path = f"{url_module_path}/{filename}"
|
|
|
|
|
|
|
|
|
|
# 构建完整的外网访问URL
|
|
|
|
|
# 方法1: 使用BASE_URL配置构建绝对URL
|
|
|
|
|
absolute_url = f"{settings.BASE_URL}{settings.ATTACH_URL}{relative_path}"
|
|
|
|
|
|
|
|
|
|
logger.info(f"文件上传成功: {absolute_url}")
|
|
|
|
|
|
|
|
|
|
# 直接返回完整URL字符串
|
|
|
|
|
return PlainTextResponse(content=absolute_url)
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.exception(f"文件上传过程中发生异常: {str(e)}")
|
|
|
|
|
# 直接返回错误消息字符串
|
|
|
|
|
return str(e)
|
|
|
|
|
def validate_phone(phone: str) -> bool:
|
|
|
|
|
# 基础格式验证
|
|
|
|
|
if not re.match(r"^1(3\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\d|9[0-35-9])\d{8}$", phone):
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
# 特殊号段白名单
|
|
|
|
|
special_prefix = ["191", "192", "197"] # 根据实际情况更新
|
|
|
|
|
if any(phone.startswith(p) for p in special_prefix):
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
# 虚拟运营商号段二次验证
|
|
|
|
|
if phone.startswith(("170", "171", "172")):
|
|
|
|
|
return validate_virtual_operator(phone) # 调用专用验证接口
|
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
async def handle_set_user_info(data: WxappRequest, db: Session):
|
2025-01-15 20:26:58 +08:00
|
|
|
|
"""处理用户信息相关操作"""
|
2025-03-04 20:36:52 +08:00
|
|
|
|
logger.info(f"处理用户信息请求: op={data.op}, uid={data.uid},data={data}")
|
|
|
|
|
|
2025-01-15 20:26:58 +08:00
|
|
|
|
operations = {
|
|
|
|
|
"getinfo": get_user_info,
|
2025-03-04 20:36:52 +08:00
|
|
|
|
"checkStudent": check_student,
|
2025-01-15 20:26:58 +08:00
|
|
|
|
"update": update_user_info,
|
2025-03-04 20:36:52 +08:00
|
|
|
|
"getcode": get_verification_code,
|
|
|
|
|
"checkcode": check_verification_code,
|
2025-01-15 20:26:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-03-04 20:36:52 +08:00
|
|
|
|
# 如果op为空,则默认执行更新用户信息操作
|
|
|
|
|
if not data.op:
|
|
|
|
|
logger.info(f"未指定操作类型,默认执行更新用户信息: uid={data.uid}")
|
|
|
|
|
try:
|
|
|
|
|
# 直接从请求对象中获取数据
|
|
|
|
|
update_data = {}
|
|
|
|
|
if hasattr(data, "name"):
|
|
|
|
|
update_data["name"] = data.name
|
|
|
|
|
if hasattr(data, "phone") and data.phone != "null":
|
|
|
|
|
update_data["phone"] = data.phone
|
|
|
|
|
|
|
|
|
|
# 添加请求中的其他字段
|
|
|
|
|
for field in ["student_id", "id_card", "school", "level"]:
|
|
|
|
|
if hasattr(data, field):
|
|
|
|
|
update_data["field"] = getattr(data, field)
|
|
|
|
|
|
|
|
|
|
logger.debug(f"更新用户数据: {update_data}")
|
|
|
|
|
result = await update_user_info(data.uid, update_data, db)
|
|
|
|
|
return ResponseFactory.success(
|
|
|
|
|
data=result,
|
|
|
|
|
message="更新成功"
|
|
|
|
|
)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.exception(f"更新用户信息时发生异常: {str(e)}")
|
|
|
|
|
return ResponseFactory.error(
|
|
|
|
|
code=1,
|
|
|
|
|
message=str(e)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# 处理指定操作类型
|
2025-01-15 20:26:58 +08:00
|
|
|
|
operation = operations.get(data.op)
|
2025-03-04 20:36:52 +08:00
|
|
|
|
logger.debug(f"operation: {operation}")
|
2025-01-15 20:26:58 +08:00
|
|
|
|
if not operation:
|
2025-03-04 20:36:52 +08:00
|
|
|
|
logger.warning(f"不支持的操作: {data.op}")
|
|
|
|
|
return ResponseFactory.error(
|
|
|
|
|
code=1,
|
|
|
|
|
message=f"不支持的操作: {data.op}"
|
|
|
|
|
)
|
2025-01-15 20:26:58 +08:00
|
|
|
|
|
|
|
|
|
try:
|
2025-03-04 20:36:52 +08:00
|
|
|
|
# 处理特殊情况:getcode操作需要直接获取phone属性
|
|
|
|
|
if data.op == "getcode":
|
|
|
|
|
# 确保将phone从对象属性传递到data字典
|
|
|
|
|
data_dict = dict(data.data) if data.data else {} # 复制现有数据
|
|
|
|
|
|
|
|
|
|
# 从对象中获取phone属性
|
|
|
|
|
if hasattr(data, "phone"):
|
|
|
|
|
data_dict["phone"] = data.phone
|
|
|
|
|
|
|
|
|
|
result = await operation(data.uid, data_dict, db)
|
|
|
|
|
else:
|
|
|
|
|
# 其他操作保持原样
|
|
|
|
|
result = await operation(data.uid, data.data, db)
|
|
|
|
|
|
|
|
|
|
logger.debug(f"result: {result}")
|
|
|
|
|
return ResponseFactory.success(
|
|
|
|
|
data=result,
|
|
|
|
|
message="success"
|
|
|
|
|
)
|
2025-01-15 20:26:58 +08:00
|
|
|
|
except Exception as e:
|
2025-03-04 20:36:52 +08:00
|
|
|
|
logger.exception(f"处理用户信息时发生异常: {str(e)}")
|
|
|
|
|
return ResponseFactory.error(
|
|
|
|
|
code=1,
|
|
|
|
|
message=str(e)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# 获取用户信息
|
|
|
|
|
async def get_user_info(uid: str, data: Dict[str, Any], db: Session) -> Dict[str, Any]:
|
|
|
|
|
"""获取用户详细信息"""
|
|
|
|
|
logger.debug(f"获取用户信息: uid={uid},data={data}")
|
|
|
|
|
if not uid:
|
|
|
|
|
raise ValueError("用户ID不存在")
|
|
|
|
|
|
|
|
|
|
# 从请求获取协议和域名
|
|
|
|
|
protocol = "https://" # 在实际部署中可能需要根据请求头判断
|
|
|
|
|
domain_name = "yourdomain.com" # 这里需要从请求中获取
|
|
|
|
|
http = f"{protocol}{domain_name}"
|
|
|
|
|
|
|
|
|
|
# 获取用户基本信息 - 已经使用CRUD方法
|
|
|
|
|
user = full_exam_user.get_by_fields(db, {"id": int(uid), "weid": settings.WECHAT_UNIACID, "istatus": 1})
|
|
|
|
|
if not user or user.istatus != 1:
|
|
|
|
|
raise ValueError("用户不存在或已被删除")
|
|
|
|
|
|
|
|
|
|
# 构建用户信息字典
|
|
|
|
|
info = {
|
|
|
|
|
"id": user.id,
|
|
|
|
|
"nickname": user.nickname,
|
|
|
|
|
"headimg": user.headimg,
|
|
|
|
|
"name": user.name,
|
|
|
|
|
"phone": user.phone,
|
|
|
|
|
"grade": user.gradeid,
|
|
|
|
|
"ismember": user.ismember,
|
|
|
|
|
"member_endtime": None,
|
|
|
|
|
"nativeplace": user.nativeplace,
|
|
|
|
|
"integral": user.integral,
|
|
|
|
|
"student_id": user.student_id,
|
|
|
|
|
"id_card": user.id_card,
|
|
|
|
|
"school": user.school,
|
|
|
|
|
"level": user.level,
|
|
|
|
|
"openid": user.openid
|
|
|
|
|
}
|
|
|
|
|
logger.debug(f"用户信息: {info}")
|
|
|
|
|
|
|
|
|
|
# 检查会员是否过期
|
|
|
|
|
current_time = int(datetime.now().timestamp())
|
|
|
|
|
if user.ismember == 1 and user.member_endtime and int(user.member_endtime) < current_time:
|
|
|
|
|
# 更新会员状态为非会员 - 使用CRUD方法
|
|
|
|
|
full_exam_user.update(db, db_obj=user, obj_in={"ismember": 2})
|
|
|
|
|
info["ismember"] = 2
|
|
|
|
|
|
|
|
|
|
# 格式化会员到期时间
|
|
|
|
|
if user.member_endtime:
|
|
|
|
|
info["member_endtime"] = datetime.fromtimestamp(int(user.member_endtime)).strftime("%Y-%m-%d")
|
|
|
|
|
|
|
|
|
|
# 获取系统设置 - 使用CRUD替代原始SQL
|
|
|
|
|
system_setting = setting.get_by_fields(db, {"weid": user.weid})
|
|
|
|
|
|
|
|
|
|
# 默认用户信息状态为完整
|
|
|
|
|
is_ok = 1
|
|
|
|
|
|
|
|
|
|
# 检查用户信息是否完整
|
|
|
|
|
if system_setting and system_setting.info_status == 1:
|
|
|
|
|
if not user.phone or not user.name:
|
|
|
|
|
is_ok = 2
|
|
|
|
|
|
|
|
|
|
# 添加系统设置信息
|
|
|
|
|
if system_setting:
|
|
|
|
|
info["IOS"] = system_setting.IOS
|
|
|
|
|
info["customer_service"] = system_setting.customer_service
|
|
|
|
|
|
|
|
|
|
# 检查会员系统是否开启 - 使用CRUD替代原始SQL
|
|
|
|
|
member_setting = user_member.get_by_fields(db, {
|
|
|
|
|
"weid": user.weid,
|
|
|
|
|
"istatus": 1
|
|
|
|
|
})
|
|
|
|
|
info["is_open"] = member_setting.status if member_setting else 0
|
|
|
|
|
|
|
|
|
|
# 用户信息完整性状态
|
|
|
|
|
info["is_ok"] = is_ok
|
|
|
|
|
|
|
|
|
|
# 默认学生信息
|
|
|
|
|
info["stu_have"] = 2
|
|
|
|
|
info["student_id"] = 0
|
|
|
|
|
info["xuesheng_id"] = 0
|
|
|
|
|
|
|
|
|
|
# 如果用户有姓名和手机号,检查是否是学生 - 使用CRUD替代原始SQL
|
|
|
|
|
if user.phone and user.name:
|
|
|
|
|
student = xueshen.get_by_fields(db, {
|
|
|
|
|
"weid": user.weid,
|
|
|
|
|
"name": user.name,
|
|
|
|
|
"phone": user.phone
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
if student:
|
|
|
|
|
info["student_id"] = student.student_name
|
|
|
|
|
info["xuesheng_id"] = student.xuesheng_id
|
|
|
|
|
info["stu_have"] = 1
|
|
|
|
|
|
|
|
|
|
# 检查是否绑定微信
|
|
|
|
|
info["is_bind"] = 1 if user.openid else 0
|
|
|
|
|
|
|
|
|
|
return {"info": info, "http": http}
|
|
|
|
|
|
|
|
|
|
# 检查学生信息
|
|
|
|
|
async def check_student(uid: str, data: Dict[str, Any], db: Session) -> Dict[str, Any]:
|
|
|
|
|
"""检查学生信息是否存在"""
|
|
|
|
|
phone = data.get("phone")
|
|
|
|
|
name = data.get("name")
|
|
|
|
|
|
|
|
|
|
if not phone or not name:
|
|
|
|
|
raise ValueError("传递的参数不存在")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
user = full_exam_user.get(db, int(uid))
|
|
|
|
|
if not user:
|
|
|
|
|
raise ValueError("用户不存在")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
student = xueshen.get_by_fields(db, {
|
|
|
|
|
"weid": user.weid,
|
|
|
|
|
"name": name,
|
|
|
|
|
"phone": phone
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
if not student:
|
|
|
|
|
raise ValueError("学生信息不存在")
|
|
|
|
|
|
|
|
|
|
# 将结果转换为字典
|
|
|
|
|
student_info = {
|
|
|
|
|
"xuesheng_id": student.xuesheng_id,
|
|
|
|
|
"name": student.name,
|
|
|
|
|
"phone": student.phone,
|
|
|
|
|
"student_name": student.student_name,
|
|
|
|
|
"sex": student.sex
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {"list": student_info}
|
|
|
|
|
|
|
|
|
|
# 获取验证码
|
|
|
|
|
async def get_verification_code(uid: str, data: Dict[str, Any], db: Session) -> Dict[str, Any]:
|
|
|
|
|
"""发送手机验证码"""
|
|
|
|
|
phone = data.get("phone")
|
|
|
|
|
|
|
|
|
|
# 验证手机号
|
|
|
|
|
if not validate_phone(phone):
|
|
|
|
|
raise ValueError("手机号有误")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
user = full_exam_user.get(db, int(uid))
|
|
|
|
|
if not user:
|
|
|
|
|
raise ValueError("用户不存在")
|
|
|
|
|
|
|
|
|
|
# 使用CRUD替代SQL查询系统配置
|
|
|
|
|
system_config = setting.get_by_fields(db, {"weid": user.weid})
|
|
|
|
|
|
|
|
|
|
# 生成4位随机验证码
|
|
|
|
|
import random
|
|
|
|
|
code = ''.join(random.choices('0123456789', k=4))
|
|
|
|
|
|
|
|
|
|
# 发送验证码 - 这里需要替换为实际的短信发送逻辑
|
|
|
|
|
try:
|
|
|
|
|
# 假设这是成功发送
|
|
|
|
|
send_result = {"Code": "OK"}
|
|
|
|
|
|
|
|
|
|
if send_result["Code"] == "OK":
|
|
|
|
|
# 保存验证码记录
|
|
|
|
|
|
|
|
|
|
from mooc.schemas.goouc_fullexam import PhoneCodeCreate
|
|
|
|
|
|
|
|
|
|
phone_code_data = PhoneCodeCreate(
|
|
|
|
|
phone=phone,
|
|
|
|
|
code=int(code), # 确保代码和模型匹配
|
|
|
|
|
createtime=int(datetime.now().timestamp()),
|
|
|
|
|
weid=user.weid
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
phone_code.create(db, obj_in=phone_code_data)
|
|
|
|
|
|
|
|
|
|
return {"status": 1}
|
|
|
|
|
else:
|
|
|
|
|
raise ValueError(f"发送失败: {send_result.get('Message', '未知错误')}")
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"发送验证码失败: {str(e)}")
|
|
|
|
|
raise ValueError(f"发送验证码失败: {str(e)}")
|
|
|
|
|
|
|
|
|
|
# 检查验证码
|
|
|
|
|
async def check_verification_code(uid: str, data: Dict[str, Any], db: Session) -> Dict[str, Any]:
|
|
|
|
|
"""验证手机验证码"""
|
|
|
|
|
input_code = data.get("code", "").strip()
|
|
|
|
|
phone = data.get("phone")
|
|
|
|
|
|
|
|
|
|
if not input_code or not phone:
|
|
|
|
|
raise ValueError("传递的参数不存在")
|
|
|
|
|
|
|
|
|
|
# 获取最新的验证码记录
|
|
|
|
|
from sqlalchemy import text
|
|
|
|
|
code_query = text("""
|
|
|
|
|
SELECT * FROM ims_goouc_fullexam_phonecode
|
|
|
|
|
WHERE weid = :weid AND phone = :phone
|
|
|
|
|
ORDER BY createtime DESC LIMIT 1
|
|
|
|
|
""")
|
|
|
|
|
|
|
|
|
|
user = full_exam_user.get(db, int(uid))
|
|
|
|
|
if not user:
|
|
|
|
|
raise ValueError("用户不存在")
|
|
|
|
|
|
|
|
|
|
code_record = db.execute(code_query, {
|
|
|
|
|
"weid": user.weid,
|
|
|
|
|
"phone": phone
|
|
|
|
|
}).fetchone()
|
|
|
|
|
|
|
|
|
|
if not code_record:
|
|
|
|
|
raise ValueError("验证码不存在")
|
|
|
|
|
|
|
|
|
|
# 检查验证码是否过期(5分钟有效期)
|
|
|
|
|
current_time = int(datetime.now().timestamp())
|
|
|
|
|
if code_record.createtime + 300 < current_time:
|
|
|
|
|
raise ValueError("验证码已过期")
|
|
|
|
|
|
|
|
|
|
# 验证码是否正确
|
|
|
|
|
if str(code_record.code) != input_code:
|
|
|
|
|
raise ValueError("验证码错误")
|
|
|
|
|
|
|
|
|
|
# 使用CRUD检查手机号是否已绑定其他账号
|
|
|
|
|
other_users = full_exam_user.get_multi_by_fields(db, {
|
|
|
|
|
"weid": user.weid,
|
|
|
|
|
"phone": phone
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
# 过滤掉当前用户
|
|
|
|
|
other_users = [u for u in other_users if u.id != int(uid)]
|
|
|
|
|
|
|
|
|
|
if other_users:
|
|
|
|
|
raise ValueError("该手机号已绑定其他账号!")
|
|
|
|
|
|
|
|
|
|
# 更新用户手机号
|
|
|
|
|
try:
|
|
|
|
|
# 使用CRUD更新用户手机号
|
|
|
|
|
full_exam_user.update(db, db_obj=user, obj_in={"phone": phone})
|
|
|
|
|
|
|
|
|
|
# 如果用户有姓名,尝试更新学生信息
|
|
|
|
|
if user.name:
|
|
|
|
|
# 查找学生记录
|
|
|
|
|
student = xueshen.get_by_fields(db, {
|
|
|
|
|
"weid": user.weid,
|
|
|
|
|
"name": user.name
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
# 如果找到学生记录,更新其手机号
|
|
|
|
|
if student:
|
|
|
|
|
xueshen.update(db, db_obj=student, obj_in={"phone": phone})
|
|
|
|
|
|
|
|
|
|
return {"status": "success"}
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"更新手机号失败: {str(e)}")
|
|
|
|
|
db.rollback()
|
|
|
|
|
raise ValueError(f"更新手机号失败: {str(e)}")
|
|
|
|
|
|
|
|
|
|
# 更新用户信息
|
|
|
|
|
async def update_user_info(uid: str, data: Dict[str, Any], db: Session) -> Dict[str, Any]:
|
|
|
|
|
"""更新用户基本信息"""
|
|
|
|
|
if not uid:
|
|
|
|
|
raise ValueError("传递的参数不存在")
|
|
|
|
|
|
|
|
|
|
# 获取用户
|
|
|
|
|
user = full_exam_user.get_by_id_and_weid(db, int(uid), settings.WECHAT_UNIACID)
|
|
|
|
|
if not user or user.istatus != 1:
|
|
|
|
|
raise ValueError("非法用户ID")
|
|
|
|
|
|
|
|
|
|
# 需要更新的字段
|
|
|
|
|
update_data = {}
|
|
|
|
|
|
|
|
|
|
# 姓名字段
|
|
|
|
|
if "name" in data:
|
|
|
|
|
update_data["name"] = data.get("name", "").strip()
|
|
|
|
|
|
|
|
|
|
# 处理其他可能需要更新的字段
|
|
|
|
|
fields = ["student_id", "id_card", "school", "level", "phone"]
|
|
|
|
|
for field in fields:
|
|
|
|
|
if field in data and data.get(field) != "null":
|
|
|
|
|
update_data[field] = data.get(field)
|
|
|
|
|
|
|
|
|
|
# 如果没有要更新的数据
|
|
|
|
|
if not update_data:
|
|
|
|
|
return {"status": 0, "message": "没有提供要更新的数据"}
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# 更新用户信息
|
|
|
|
|
full_exam_user.update(db, db_obj=user, obj_in=update_data)
|
|
|
|
|
|
|
|
|
|
# 如果更新了姓名,并且用户有手机号,则尝试更新学生信息
|
|
|
|
|
if "name" in update_data and user.phone:
|
|
|
|
|
from sqlalchemy import text
|
|
|
|
|
update_student_query = text("""
|
|
|
|
|
UPDATE ims_goouc_fullexam_xuesheng
|
|
|
|
|
SET name = :name
|
|
|
|
|
WHERE weid = :weid AND phone = :phone
|
|
|
|
|
""")
|
|
|
|
|
|
|
|
|
|
db.execute(update_student_query, {
|
|
|
|
|
"name": update_data["name"],
|
|
|
|
|
"weid": user.weid,
|
|
|
|
|
"phone": user.phone
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return {"status": 1, "message": "信息保存成功"}
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"更新用户信息失败: {str(e)}")
|
|
|
|
|
db.rollback()
|
|
|
|
|
raise ValueError(f"信息保存失败: {str(e)}")
|
2025-01-15 20:26:58 +08:00
|
|
|
|
|
|
|
|
|
async def handle_exam_operation(
|
|
|
|
|
data: WxappRequest,
|
|
|
|
|
db: Session,
|
|
|
|
|
user_doexam: CRUDUserDoexam,
|
|
|
|
|
user_exam_answer: CRUDUserExamAnswer
|
|
|
|
|
):
|
|
|
|
|
"""处理考试相关操作"""
|
|
|
|
|
operations = {
|
|
|
|
|
"submit": submit_exam,
|
|
|
|
|
"get_history": get_exam_history,
|
|
|
|
|
"get_detail": get_exam_detail,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
operation = operations.get(data.op)
|
|
|
|
|
if not operation:
|
|
|
|
|
return {
|
|
|
|
|
"code": 1,
|
2025-03-04 20:36:52 +08:00
|
|
|
|
"message": f"Unsupported operation: {data.op}"
|
2025-01-15 20:26:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
result = await operation(data.uid, data.data, db, user_doexam, user_exam_answer)
|
|
|
|
|
return {
|
|
|
|
|
"code": 0,
|
|
|
|
|
"data": result,
|
2025-03-04 20:36:52 +08:00
|
|
|
|
"message": "success"
|
2025-01-15 20:26:58 +08:00
|
|
|
|
}
|
|
|
|
|
except Exception as e:
|
|
|
|
|
return {
|
|
|
|
|
"code": 1,
|
2025-03-04 20:36:52 +08:00
|
|
|
|
"message": str(e)
|
2025-01-15 20:26:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async def handle_collection(
|
|
|
|
|
data: WxappRequest,
|
|
|
|
|
db: Session,
|
|
|
|
|
user_collection: CRUDUserCollectionPraction
|
|
|
|
|
):
|
|
|
|
|
"""处理收藏相关操作"""
|
|
|
|
|
operations = {
|
|
|
|
|
"add": add_collection,
|
|
|
|
|
"remove": remove_collection,
|
|
|
|
|
"list": list_collections,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
operation = operations.get(data.op)
|
|
|
|
|
if not operation:
|
|
|
|
|
return {
|
|
|
|
|
"code": 1,
|
2025-03-04 20:36:52 +08:00
|
|
|
|
"message": f"Unsupported operation: {data.op}"
|
2025-01-15 20:26:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
result = await operation(data.uid, data.data, db, user_collection)
|
|
|
|
|
return {
|
|
|
|
|
"code": 0,
|
|
|
|
|
"data": result,
|
2025-03-04 20:36:52 +08:00
|
|
|
|
"message": "success"
|
2025-01-15 20:26:58 +08:00
|
|
|
|
}
|
|
|
|
|
except Exception as e:
|
|
|
|
|
return {
|
|
|
|
|
"code": 1,
|
2025-03-04 20:36:52 +08:00
|
|
|
|
"message": str(e)
|
2025-01-15 20:26:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async def handle_wrong_question(
|
|
|
|
|
data: WxappRequest,
|
|
|
|
|
db: Session,
|
|
|
|
|
user_wrong_praction: CRUDUserWrongPraction
|
|
|
|
|
):
|
|
|
|
|
"""处理错题相关操作"""
|
|
|
|
|
operations = {
|
|
|
|
|
"add": add_wrong_question,
|
|
|
|
|
"remove": remove_wrong_question,
|
|
|
|
|
"list": list_wrong_questions,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
operation = operations.get(data.op)
|
|
|
|
|
if not operation:
|
|
|
|
|
return {
|
|
|
|
|
"code": 1,
|
2025-03-04 20:36:52 +08:00
|
|
|
|
"message": f"Unsupported operation: {data.op}"
|
2025-01-15 20:26:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
result = await operation(data.uid, data.data, db, user_wrong_praction)
|
|
|
|
|
return {
|
|
|
|
|
"code": 0,
|
|
|
|
|
"data": result,
|
2025-03-04 20:36:52 +08:00
|
|
|
|
"message": "success"
|
2025-01-15 20:26:58 +08:00
|
|
|
|
}
|
|
|
|
|
except Exception as e:
|
|
|
|
|
return {
|
|
|
|
|
"code": 1,
|
2025-03-04 20:36:52 +08:00
|
|
|
|
"message": str(e)
|
2025-01-15 20:26:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-03-04 20:36:52 +08:00
|
|
|
|
|
|
|
|
|
async def handle_login2(data: WxappRequest, db: Session):
|
|
|
|
|
"""处理微信小程序登录2"""
|
|
|
|
|
logger.info(f"处理登录请求: {data.uid}")
|
|
|
|
|
try:
|
|
|
|
|
# 修改这里,查找code的位置
|
|
|
|
|
# 首先检查data.data中是否有code
|
|
|
|
|
code = data.data.get("code") if isinstance(data.data, dict) else None
|
|
|
|
|
|
|
|
|
|
# 如果在data.data中没有找到code,尝试直接从data对象获取
|
|
|
|
|
if not code and hasattr(data, "code"):
|
|
|
|
|
code = data.code
|
|
|
|
|
|
|
|
|
|
logger.debug(f"登录请求数据: {data}")
|
|
|
|
|
|
|
|
|
|
if not code:
|
|
|
|
|
logger.warning(f"登录失败: code为空 - UID: {data.uid}")
|
|
|
|
|
return {
|
|
|
|
|
"code": 1,
|
|
|
|
|
"message": "code值获取失败",
|
|
|
|
|
"data": {"message": "code值获取失败"}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# 调用微信API获取openid和session_key
|
|
|
|
|
logger.debug(f"开始调用微信API: code={code}")
|
|
|
|
|
wx_info = await wx_api.code2session(code)
|
|
|
|
|
logger.debug(f"微信API返回结果: {wx_info}")
|
|
|
|
|
except httpx.ConnectTimeout:
|
|
|
|
|
# 特别处理连接超时错误
|
|
|
|
|
logger.error("连接微信服务器超时,请检查网络连接")
|
|
|
|
|
return {
|
|
|
|
|
"code": 1,
|
|
|
|
|
"message": "连接微信服务器超时,请稍后再试",
|
|
|
|
|
"data": {"message": "网络连接问题,无法连接到微信服务器"}
|
|
|
|
|
}
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"微信API调用失败: {str(e)}", exc_info=True)
|
|
|
|
|
return {
|
|
|
|
|
"code": 1,
|
|
|
|
|
"message": "获取用户信息失败",
|
|
|
|
|
"data": {"message": str(e)}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# 检查是否有错误
|
|
|
|
|
if wx_info.get("errcode") == 4001:
|
|
|
|
|
return {
|
|
|
|
|
"code": 1,
|
|
|
|
|
"message": "获取用户信息失败",
|
|
|
|
|
"data": {"message": wx_info.get("errmessage")}
|
|
|
|
|
}
|
|
|
|
|
# 确保weid是整数
|
|
|
|
|
try:
|
|
|
|
|
weid = int(settings.WECHAT_UNIACID)
|
|
|
|
|
except ValueError:
|
|
|
|
|
# 如果无法转换为整数,使用默认值
|
|
|
|
|
logger.warning(f"WECHAT_UNIACID '{settings.WECHAT_UNIACID}' 无法转换为整数,使用默认值1")
|
|
|
|
|
weid = 1
|
|
|
|
|
|
|
|
|
|
# 查询用户 - 注意这里是用openid和weid查询
|
|
|
|
|
users = full_exam_user.get_by_openid_and_weid(
|
|
|
|
|
db,
|
|
|
|
|
wx_info["openid"],
|
|
|
|
|
weid # 使用整数weid
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
info_status = 2 # 默认状态
|
|
|
|
|
|
|
|
|
|
# 构建用户数据
|
|
|
|
|
current_time = int(datetime.now().timestamp())
|
|
|
|
|
user_data = {
|
|
|
|
|
"openid": wx_info["openid"],
|
|
|
|
|
"nickname": data.data.get("nickName"),
|
|
|
|
|
"nativeplace": f"{data.data.get('province')},{data.data.get('city')}",
|
|
|
|
|
"headimg": data.data.get("avatarUrl"),
|
|
|
|
|
"unionid": wx_info.get("unionid"),
|
|
|
|
|
"createtime": current_time,
|
|
|
|
|
"weid": weid, # 现在weid已定义
|
|
|
|
|
"last_login_time": current_time,
|
|
|
|
|
"h5_openid": wx_info["openid"]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if not users:
|
|
|
|
|
logger.debug(f"用户不存在,创建新用户: {user_data}")
|
|
|
|
|
# 创建新用户 - 使用CRUD实例
|
|
|
|
|
try:
|
|
|
|
|
logger.debug(f"创建新用户: {user_data}")
|
|
|
|
|
# 使用UserMemberCreate schema需要导入
|
|
|
|
|
from mooc.schemas.goouc_fullexam_user import FullExamUserCreate
|
|
|
|
|
|
|
|
|
|
# 转换为schema对象
|
|
|
|
|
user_create_schema = FullExamUserCreate(**user_data)
|
|
|
|
|
|
|
|
|
|
# 使用CRUD实例创建用户
|
|
|
|
|
new_user = full_exam_user.create(db, obj_in=user_create_schema)
|
|
|
|
|
uid = new_user.id
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"创建新用户失败: {e}")
|
|
|
|
|
return {
|
|
|
|
|
"code": 1,
|
|
|
|
|
"message": "用户数据插入失败",
|
|
|
|
|
"data": str(e)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# 处理二维码生成
|
|
|
|
|
try:
|
|
|
|
|
logger.debug(f"开始生成二维码")
|
|
|
|
|
access_token = await wx_api.get_access_token()
|
|
|
|
|
|
|
|
|
|
# 创建二维码目录
|
|
|
|
|
qrcode_path = "../addons/goouc_fullexam/Qrcode/"
|
|
|
|
|
if not os.path.exists(qrcode_path):
|
|
|
|
|
os.makedirs(qrcode_path, mode=0o777, exist_ok=True)
|
|
|
|
|
|
|
|
|
|
filename = f"qrcode_{uid}.jpg"
|
|
|
|
|
|
|
|
|
|
# 生成二维码并保存
|
|
|
|
|
res = await wx_api.save_unlimited_qrcode(
|
|
|
|
|
uid,
|
|
|
|
|
qrcode_path,
|
|
|
|
|
filename,
|
|
|
|
|
access_token
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if res:
|
|
|
|
|
# 更新用户二维码路径 - 使用CRUD实例
|
|
|
|
|
from mooc.schemas.goouc_fullexam_user import FullExamUserUpdate
|
|
|
|
|
|
|
|
|
|
update_data = {"qrcode": os.path.join(qrcode_path, filename)}
|
|
|
|
|
update_schema = FullExamUserUpdate(**update_data)
|
|
|
|
|
|
|
|
|
|
# 使用CRUD实例更新用户
|
|
|
|
|
full_exam_user.update(db, db_obj=new_user, obj_in=update_schema)
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"生成二维码错误: {e}")
|
|
|
|
|
return {
|
|
|
|
|
"code": 1,
|
|
|
|
|
"message": "生成二维码错误了",
|
|
|
|
|
"data": str(e)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
logger.debug(f"用户存在,更新用户信息: {users}")
|
|
|
|
|
# 检查用户状态
|
|
|
|
|
if users.status != 1:
|
|
|
|
|
return {
|
|
|
|
|
"code": 1,
|
|
|
|
|
"message": "您已被禁用,请联系管理员处理~",
|
|
|
|
|
"data": users
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# 更新用户信息 - 使用CRUD实例
|
|
|
|
|
try:
|
|
|
|
|
logger.debug(f"开始更新用户信息: {user_data}")
|
|
|
|
|
from mooc.schemas.goouc_fullexam_user import FullExamUserUpdate
|
|
|
|
|
|
|
|
|
|
update_schema = FullExamUserUpdate(**user_data)
|
|
|
|
|
full_exam_user.update(db, db_obj=users, obj_in=update_schema)
|
|
|
|
|
|
|
|
|
|
uid = users.id
|
|
|
|
|
if users.phone:
|
|
|
|
|
info_status = 1
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"更新用户信息失败: {e}")
|
|
|
|
|
return {
|
|
|
|
|
"code": 1,
|
|
|
|
|
"message": "更新用户信息失败",
|
|
|
|
|
"data": str(e)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logger.info(f"登录成功,用户ID: {uid}, 状态: {info_status}")
|
|
|
|
|
|
|
|
|
|
return ResponseFactory.success(
|
|
|
|
|
data={"uid": uid, "info_status": info_status, "info": {"uid": uid, "info_status": info_status}},
|
|
|
|
|
message="登录成功"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.exception(f"登录过程发生未处理异常: {str(e)}")
|
|
|
|
|
return ResponseFactory.error(
|
|
|
|
|
code=1,
|
|
|
|
|
message=f"登录失败: {str(e)}",
|
|
|
|
|
data=None
|
|
|
|
|
)
|