from fastapi import APIRouter, Depends, Request, Form, Body, UploadFile,File from fastapi.responses import PlainTextResponse 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, CRUDUserCollectionPraction, full_exam_user ) from mooc.models.goouc_fullexam_user import ( UserDoexam, UserExamAnswer, UserWrongPraction, UserCollectionPraction, FullExamUser ) 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 wxapp_router = APIRouter() # 创建模块级别的日志记录器 logger = get_logger(__name__) class WxappRequest(BaseModel): uid: Optional[str] = None op: Optional[str] = None m: Optional[str] = None data: Dict[str, Any] = {} 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) @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, db: Session = Depends(get_db), file: UploadFile = None ): # 获取表单数据 try: form_data = await request.form() logger.debug(f"Form data: {form_data}") # 将表单数据转换为字典 data = dict(form_data) # 检查是否包含上传文件 if "upfile" in form_data: file = form_data["upfile"] except Exception as e: logger.error(f"Error reading form data: {e}") # 如果没有表单数据,尝试读取JSON try: data = await request.json() logger.debug(f"JSON data: {data}") except Exception as e: logger.error(f"Error reading JSON: {e}") data = {} logger.debug(f"Final data: {data}") logger.debug(f"Query params: {request.query_params}") # 根据do参数处理不同的业务逻辑 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) 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": # 添加新的处理逻辑 return {"code": 0, "data": {"total": 100}, "message": "success"} elif do == "Index": # 添加首页处理逻辑 return {"code": 0, "data": {}, "message": "success"} elif do == "Advert": # 添加广告处理逻辑 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) return {"code": 404, "message": "接口未找到"} 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): """处理用户信息相关操作""" logger.info(f"处理用户信息请求: op={data.op}, uid={data.uid},data={data}") operations = { "getinfo": get_user_info, "checkStudent": check_student, "update": update_user_info, "getcode": get_verification_code, "checkcode": check_verification_code, } # 如果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) ) # 处理指定操作类型 operation = operations.get(data.op) logger.debug(f"operation: {operation}") if not operation: logger.warning(f"不支持的操作: {data.op}") return ResponseFactory.error( code=1, message=f"不支持的操作: {data.op}" ) try: # 处理特殊情况: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" ) except Exception as e: 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)}") 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, "message": f"Unsupported operation: {data.op}" } try: result = await operation(data.uid, data.data, db, user_doexam, user_exam_answer) return { "code": 0, "data": result, "message": "success" } except Exception as e: return { "code": 1, "message": str(e) } 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, "message": f"Unsupported operation: {data.op}" } try: result = await operation(data.uid, data.data, db, user_collection) return { "code": 0, "data": result, "message": "success" } except Exception as e: return { "code": 1, "message": str(e) } 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, "message": f"Unsupported operation: {data.op}" } try: result = await operation(data.uid, data.data, db, user_wrong_praction) return { "code": 0, "data": result, "message": "success" } except Exception as e: return { "code": 1, "message": str(e) } 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 )