feat(wxapp): 实现分享功能并优化用户信息相关操作
- 新增分享功能处理逻辑,包括获取设置、记录分享次数和更新用户积分 - 优化用户信息获取和更新操作,提高代码复用性和可维护性 - 添加错题收藏功能,支持用户对错题进行收藏和取消收藏 - 重构部分代码,提高可读性和性能
This commit is contained in:
parent
7ace7db5c5
commit
97a61189ea
@ -1,10 +1,12 @@
|
||||
from fastapi import APIRouter, Depends, Request, Form, Body, UploadFile,File
|
||||
from fastapi import APIRouter, Depends, Request, Form, Body, UploadFile, File
|
||||
from fastapi.responses import PlainTextResponse
|
||||
from typing import Optional, Dict, Any
|
||||
from mooc.models.goouc_fullexam import ShareRecord
|
||||
from pydantic import BaseModel
|
||||
from sqlalchemy.orm import Session
|
||||
from mooc.db.database import get_db
|
||||
from mooc.crud.crud_goouc_fullexam_user import (
|
||||
CRUDFullExamUser,
|
||||
CRUDUserDoexam,
|
||||
CRUDUserExamAnswer,
|
||||
CRUDUserWrongPraction,
|
||||
@ -20,20 +22,21 @@ from mooc.models.goouc_fullexam_user import (
|
||||
)
|
||||
from mooc.core.config import settings
|
||||
from mooc.utils.wechat_client import wx_api
|
||||
from datetime import datetime
|
||||
from datetime import datetime, time
|
||||
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
|
||||
from mooc.crud.crud_goouc_fullexam import CRUDSetting, CRUDShareRecord, setting, xueshen
|
||||
from mooc.crud.crud_goouc_fullexam_user import full_exam_user, user_member, user_collection_praction
|
||||
|
||||
wxapp_router = APIRouter()
|
||||
|
||||
# 创建模块级别的日志记录器
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
class WxappRequest(BaseModel):
|
||||
uid: Optional[str] = None
|
||||
op: Optional[str] = None
|
||||
@ -53,6 +56,7 @@ class WxappRequest(BaseModel):
|
||||
return getattr(self, field_name)
|
||||
return self.data.get(field_name, default)
|
||||
|
||||
|
||||
@wxapp_router.post("/index")
|
||||
async def handle_wxapp_request(
|
||||
request: Request,
|
||||
@ -121,10 +125,18 @@ async def handle_wxapp_request(
|
||||
elif do == "UpdateHeadimg":
|
||||
return await handle_update_headimg(WxappRequest(**data), db)
|
||||
|
||||
# part 4编写
|
||||
|
||||
elif do == "Share":
|
||||
return await handle_share(WxappRequest(**data), int(i), db)
|
||||
elif do == "AddWrong":
|
||||
return await handle_add_wrong(WxappRequest(**data), db)
|
||||
elif do == "Feedback":
|
||||
return await handle_feedback(WxappRequest(**data), db)
|
||||
|
||||
return {"code": 404, "message": "接口未找到"}
|
||||
|
||||
|
||||
async def handle_update_headimg(data: WxappRequest, db: Session):
|
||||
"""处理更新用户头像的请求"""
|
||||
logger.info(f"处理更新头像请求: uid={data.uid},data={data}")
|
||||
@ -159,6 +171,7 @@ async def handle_update_headimg(data: WxappRequest, db: Session):
|
||||
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
|
||||
@ -254,6 +267,8 @@ async def handle_upload_image(data: WxappRequest, db: Session, file: UploadFile
|
||||
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):
|
||||
@ -270,6 +285,7 @@ def validate_phone(phone: str) -> bool:
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def handle_set_user_info(data: WxappRequest, db: Session):
|
||||
"""处理用户信息相关操作"""
|
||||
logger.info(f"处理用户信息请求: op={data.op}, uid={data.uid},data={data}")
|
||||
@ -348,6 +364,7 @@ async def handle_set_user_info(data: WxappRequest, db: Session):
|
||||
message=str(e)
|
||||
)
|
||||
|
||||
|
||||
# 获取用户信息
|
||||
async def get_user_info(uid: str, data: Dict[str, Any], db: Session) -> Dict[str, Any]:
|
||||
"""获取用户详细信息"""
|
||||
@ -445,6 +462,7 @@ async def get_user_info(uid: str, data: Dict[str, Any], db: Session) -> Dict[str
|
||||
|
||||
return {"info": info, "http": http}
|
||||
|
||||
|
||||
# 检查学生信息
|
||||
async def check_student(uid: str, data: Dict[str, Any], db: Session) -> Dict[str, Any]:
|
||||
"""检查学生信息是否存在"""
|
||||
@ -454,13 +472,10 @@ async def check_student(uid: str, data: Dict[str, Any], db: Session) -> Dict[str
|
||||
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,
|
||||
@ -481,6 +496,7 @@ async def check_student(uid: str, data: Dict[str, Any], db: Session) -> Dict[str
|
||||
|
||||
return {"list": student_info}
|
||||
|
||||
|
||||
# 获取验证码
|
||||
async def get_verification_code(uid: str, data: Dict[str, Any], db: Session) -> Dict[str, Any]:
|
||||
"""发送手机验证码"""
|
||||
@ -490,7 +506,6 @@ async def get_verification_code(uid: str, data: Dict[str, Any], db: Session) ->
|
||||
if not validate_phone(phone):
|
||||
raise ValueError("手机号有误")
|
||||
|
||||
|
||||
user = full_exam_user.get(db, int(uid))
|
||||
if not user:
|
||||
raise ValueError("用户不存在")
|
||||
@ -528,6 +543,7 @@ async def get_verification_code(uid: str, data: Dict[str, Any], db: Session) ->
|
||||
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]:
|
||||
"""验证手机验证码"""
|
||||
@ -601,6 +617,7 @@ async def check_verification_code(uid: str, data: Dict[str, Any], db: Session) -
|
||||
db.rollback()
|
||||
raise ValueError(f"更新手机号失败: {str(e)}")
|
||||
|
||||
|
||||
# 更新用户信息
|
||||
async def update_user_info(uid: str, data: Dict[str, Any], db: Session) -> Dict[str, Any]:
|
||||
"""更新用户基本信息"""
|
||||
@ -654,6 +671,7 @@ async def update_user_info(uid: str, data: Dict[str, Any], db: Session) -> Dict[
|
||||
db.rollback()
|
||||
raise ValueError(f"信息保存失败: {str(e)}")
|
||||
|
||||
|
||||
async def handle_exam_operation(
|
||||
data: WxappRequest,
|
||||
db: Session,
|
||||
@ -687,6 +705,7 @@ async def handle_exam_operation(
|
||||
"message": str(e)
|
||||
}
|
||||
|
||||
|
||||
async def handle_collection(
|
||||
data: WxappRequest,
|
||||
db: Session,
|
||||
@ -719,6 +738,7 @@ async def handle_collection(
|
||||
"message": str(e)
|
||||
}
|
||||
|
||||
|
||||
async def handle_wrong_question(
|
||||
data: WxappRequest,
|
||||
db: Session,
|
||||
@ -936,3 +956,128 @@ async def handle_login2(data: WxappRequest, db: Session):
|
||||
message=f"登录失败: {str(e)}",
|
||||
data=None
|
||||
)
|
||||
|
||||
|
||||
async def handle_share(
|
||||
data: WxappRequest,
|
||||
uniacid,
|
||||
db: Session,
|
||||
setting_mapper: CRUDSetting,
|
||||
sharing_mapper: CRUDShareRecord,
|
||||
user_mapping: CRUDFullExamUser
|
||||
):
|
||||
uid = int(data.uid)
|
||||
if not uid:
|
||||
return {"code": 1,
|
||||
"message": "传递的参数不存在",
|
||||
"data": "1001"}
|
||||
user_info = user_mapping.get_user_info(db, uniacid, uid)
|
||||
if not user_info:
|
||||
return {"code": 1,
|
||||
"message": "用户不存在",
|
||||
"data": "1001"}
|
||||
if user_info["status"] != 1:
|
||||
return {"code": 1,
|
||||
"message": "用户被禁用",
|
||||
"data": "1002"}
|
||||
|
||||
setting = setting_mapper.get_setting_1(db, uniacid)
|
||||
day_num = sharing_mapper.get_share_record_1(db, uniacid, uid)
|
||||
|
||||
if setting["shareupper"] == 0:
|
||||
data = {}
|
||||
if setting["share_integral"] != 0:
|
||||
if day_num:
|
||||
update = {
|
||||
"num": day_num["num"] + setting["share_integral"],
|
||||
"day": datetime.now().strftime("%Y-%m-%d"),
|
||||
"createtime": int(time.time())
|
||||
}
|
||||
result = sharing_mapper.update_share_record(db, update, day_num["id"], day_num["uid"])
|
||||
if result > 0:
|
||||
data["integral"] = user_info["integral"] + setting["share_integral"]
|
||||
res = user_mapping.update_user_info(db, data, user_info["id"])
|
||||
else:
|
||||
insert = {
|
||||
"uid": uid,
|
||||
"weid": uniacid,
|
||||
"num": setting["share_integral"],
|
||||
"istatus": 1,
|
||||
"day": datetime.now().strftime("%Y-%m-%d"),
|
||||
"createtime": int(time.time())
|
||||
}
|
||||
result = sharing_mapper.create(db, obj_in=insert)
|
||||
if result > 0:
|
||||
data["integral"] = user_info["integral"] + setting["share_integral"]
|
||||
res = user_mapping.update_user_info(db, data, user_info["id"])
|
||||
else:
|
||||
if setting["share_integral"] != 0:
|
||||
data = {}
|
||||
if day_num:
|
||||
if day_num["num"] < setting["shareupper"]:
|
||||
can_num = setting["shareupper"] - day_num["num"]
|
||||
if setting["share_integral"] <= can_num:
|
||||
update = {
|
||||
"num": day_num["num"] + setting["share_integral"],
|
||||
"day": datetime.now().strftime("%Y-%m-%d"),
|
||||
"createtime": int(time.time())
|
||||
}
|
||||
result = sharing_mapper.update_share_record(db, update, day_num["id"], day_num["uid"])
|
||||
if result:
|
||||
data["integral"] = user_info["integral"] + setting["share_integral"]
|
||||
res = user_mapping.update_user_info(db, data, user_info["id"])
|
||||
else:
|
||||
insert = {
|
||||
"uid": uid,
|
||||
"weid": uniacid,
|
||||
"num": setting["share_integral"],
|
||||
"istatus": 1,
|
||||
"day": datetime.now().strftime("%Y-%m-%d"),
|
||||
"createtime": int(time.time())
|
||||
}
|
||||
result = sharing_mapper.create(db, obj_in=insert)
|
||||
if result > 0:
|
||||
data["integral"] = user_info["integral"] + setting["share_integral"]
|
||||
res = user_mapping.update_user_info(db, data, user_info["id"])
|
||||
|
||||
if res:
|
||||
return {"status": 0, "message": "分享成功", "data": {"code": 1, "num": setting["share_integral"]}}
|
||||
else:
|
||||
return {"status": 1, "message": "分享失败", "data": {"code": 2}}
|
||||
|
||||
|
||||
async def handle_add_wrong(
|
||||
data: WxappRequest,
|
||||
uniacid,
|
||||
db: Session):
|
||||
uid = data.uid
|
||||
tid = data.data["tid"]
|
||||
test_type = data.data.get("test_type")
|
||||
iscollect = data.data.get("wrong_have")
|
||||
if not uid or not tid or not test_type or not iscollect:
|
||||
return {"code": 1, "message": "传递的参数不存在或失效", "data": "1001"}
|
||||
user_info = full_exam_user.get_user_info(db, uniacid, int(uid))
|
||||
if not user_info:
|
||||
return {"code": 1, "message": "用户不存在", "data": "1002"}
|
||||
if user_info["status"] != 1:
|
||||
return {"code": 1, "message": "用户被禁用", "data": "1003"}
|
||||
|
||||
have = user_collection_praction.get_user_collection_praction_1(db, uniacid, uid, tid)
|
||||
mess = 0
|
||||
if not have:
|
||||
insert = {
|
||||
"weid": uniacid,
|
||||
"uid": uid,
|
||||
"testid": tid,
|
||||
"test_type": test_type,
|
||||
"istatus": 1,
|
||||
"createtime": int(time.time())
|
||||
}
|
||||
res = user_collection_praction.create(db, obj_in=insert)
|
||||
mess = 1
|
||||
else:
|
||||
res = user_collection_praction.delete_user_collection_praction(db, uniacid, uid, tid)
|
||||
if res:
|
||||
return {"code": 0, "message": "操作成功", "data": mess}
|
||||
else:
|
||||
return {"code": 1, "message": "操作失败", "data": "1005"}
|
||||
|
@ -111,6 +111,7 @@ class CRUDPaperTest(CRUDBase[PaperTest, PaperTestCreate, PaperTestUpdate]):
|
||||
class CRUDPhonecode(CRUDBase[Phonecode, PhoneCodeCreate, PhoneCodeUpdate]):
|
||||
def get_phonecode(self, db: Session, phonecode_id: int):
|
||||
return self.get_by_field(db, "id", phonecode_id)
|
||||
|
||||
def get_latest_by_phone(self, db: Session, phone: str, weid: int):
|
||||
"""获取指定手机号的最新验证码记录"""
|
||||
return db.query(self.model).filter(
|
||||
@ -118,6 +119,7 @@ class CRUDPhonecode(CRUDBase[Phonecode, PhoneCodeCreate, PhoneCodeUpdate]):
|
||||
self.model.weid == weid
|
||||
).order_by(self.model.createtime.desc()).first()
|
||||
|
||||
|
||||
class CRUDQYear(CRUDBase[QYear, QYearCreate, QYearUpdate]):
|
||||
def get_qyear(self, db: Session, qyear_id: int):
|
||||
return self.get_by_field(db, "id", qyear_id)
|
||||
@ -132,11 +134,70 @@ class CRUDSetting(CRUDBase[Setting, SettingCreate, SettingUpdate]):
|
||||
def get_setting(self, db: Session, setting_id: int):
|
||||
return self.get_by_field(db, "id", setting_id)
|
||||
|
||||
def get_setting_1(self, session: Session, uniacid: int):
|
||||
# 执行查询并获取第一条结果
|
||||
result = session.query(
|
||||
self.model.share_integral,
|
||||
self.model.share_title,
|
||||
self.model.shareupper
|
||||
).filter(
|
||||
self.model.weid == uniacid
|
||||
).first()
|
||||
|
||||
# 将结果转换为字典格式
|
||||
if result:
|
||||
return {
|
||||
"share_integral": result[0],
|
||||
"share_title": result[1],
|
||||
"shareupper": result[2]
|
||||
}
|
||||
return {}
|
||||
|
||||
|
||||
class CRUDShareRecord(CRUDBase[ShareRecord, ShareRecordCreate, ShareRecordUpdate]):
|
||||
def get_share_record(self, db: Session, share_record_id: int):
|
||||
return self.get_by_field(db, "id", share_record_id)
|
||||
|
||||
def get_share_record_1(self, session: Session, uniacid: int, uid: int):
|
||||
# 生成当天日期字符串
|
||||
current_day = datetime.now().strftime("%Y-%m-%d")
|
||||
|
||||
# 构建查询并获取结果
|
||||
result = session.query(
|
||||
self.model.id,
|
||||
self.model.uid,
|
||||
self.model.num
|
||||
).filter(
|
||||
self.model.weid == uniacid,
|
||||
self.model.uid == uid,
|
||||
self.model.day == current_day
|
||||
).first()
|
||||
|
||||
# 转换结果类型
|
||||
# return result._asdict() if result else {} # 适用于 SQLAlchemy 2.x 的 Row 对象
|
||||
# 或者手动构建字典(兼容更多版本)
|
||||
return dict(zip(['id', 'uid', 'num'], result)) if result else {}
|
||||
|
||||
def update_share_record(
|
||||
self,
|
||||
session: Session,
|
||||
update_data: dict,
|
||||
record_id: int,
|
||||
user_id: int
|
||||
) -> int:
|
||||
try:
|
||||
# 执行更新操作
|
||||
affected_rows = session.query(self.model).filter(
|
||||
self.model.id == record_id,
|
||||
self.model.uid == user_id
|
||||
).update(update_data)
|
||||
session.commit()
|
||||
return affected_rows
|
||||
except Exception as e:
|
||||
session.rollback()
|
||||
print(f"更新失败: {str(e)}")
|
||||
return 0
|
||||
|
||||
|
||||
class CRUDsonSimple(CRUDBase[SonSimple, SonSimpleCreate, SonSimpleUpdate]):
|
||||
def get_son_simple(self, db: Session, son_simple_id: int):
|
||||
|
@ -98,6 +98,47 @@ class CRUDUserCollectionPraction(
|
||||
CRUDBase[UserCollectionPraction, UserCollectionPractionCreate, UserCollectionPractionUpdate]):
|
||||
def get_user_collection_praction(self, db: Session, user_collection_praction_id: int):
|
||||
return self.get_by_field(db, "id", user_collection_praction_id)
|
||||
def get_user_collection_praction_1(
|
||||
self,
|
||||
session: Session,
|
||||
uniacid: int,
|
||||
uid: int,
|
||||
testid: int
|
||||
) -> dict:
|
||||
result = session.query(
|
||||
self.model
|
||||
).filter(
|
||||
self.model.weid == uniacid,
|
||||
self.model.istatus == 1,
|
||||
self.model.uid == uid,
|
||||
self.model.testid == testid
|
||||
).first()
|
||||
|
||||
return result.__dict__ if result else {}
|
||||
|
||||
def delete_user_collection_praction(
|
||||
self,
|
||||
session: Session,
|
||||
uniacid: int,
|
||||
uid: int,
|
||||
testid: int
|
||||
) -> int:
|
||||
try:
|
||||
# 执行删除操作
|
||||
affected_rows = session.query(
|
||||
self.model
|
||||
).filter(
|
||||
self.model.weid == uniacid,
|
||||
self.model.uid == uid,
|
||||
self.model.testid == testid
|
||||
).delete()
|
||||
|
||||
session.commit()
|
||||
return affected_rows
|
||||
except Exception as e:
|
||||
session.rollback()
|
||||
print(f"删除失败: {str(e)}")
|
||||
return 0
|
||||
|
||||
|
||||
class CRUDUserGift(CRUDBase[UserGift, UserGiftCreate, UserGiftUpdate]):
|
||||
@ -134,10 +175,48 @@ class CRUDUserPool(CRUDBase[UserPool, UserPoolCreate, UserPoolUpdate]):
|
||||
def get_user_pool(self, db: Session, user_pool_id: int):
|
||||
return self.get_by_field(db, "id", user_pool_id)
|
||||
|
||||
|
||||
class CRUDFullExamUser(CRUDBase[FullExamUser, FullExamUserCreate, FullExamUserUpdate]):
|
||||
def get_full_exam_user(self, db: Session, full_exam_user_id: int):
|
||||
return self.get_by_field(db, "id", full_exam_user_id)
|
||||
|
||||
def get_user_info(self, session: Session, uniacid: int, uid: int):
|
||||
# 构建查询并获取第一条结果
|
||||
result = session.query(
|
||||
self.model.id,
|
||||
self.model.integral,
|
||||
self.model.status
|
||||
).filter(
|
||||
self.model.weid == uniacid,
|
||||
self.model.id == uid
|
||||
).first()
|
||||
|
||||
# 转换为字典格式
|
||||
fields = ["id", "integral", "status"]
|
||||
if result is not None:
|
||||
return dict(zip(fields, result))
|
||||
return {}
|
||||
|
||||
def update_user_info(
|
||||
self,
|
||||
session: Session,
|
||||
update_data: dict,
|
||||
user_id: int
|
||||
) -> int:
|
||||
try:
|
||||
# 执行更新操作
|
||||
affected_rows = session.query(self.model).filter(
|
||||
self.model.id == user_id
|
||||
).update(update_data)
|
||||
session.commit()
|
||||
return affected_rows
|
||||
except Exception as e:
|
||||
session.rollback()
|
||||
print(f"更新失败: {str(e)}")
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
def get_by_openid_and_weid(self, db: Session, openid: str, weid: int, istatus: int = 1):
|
||||
"""通过openid和weid获取用户"""
|
||||
return db.query(self.model).filter(
|
||||
@ -154,6 +233,7 @@ class CRUDFullExamUser(CRUDBase[FullExamUser, FullExamUserCreate, FullExamUserUp
|
||||
self.model.istatus == istatus
|
||||
).first()
|
||||
|
||||
|
||||
# 创建实例
|
||||
user_doexam = CRUDUserDoexam(UserDoexam)
|
||||
user_doother_exam_answer = CRUDUserDoOtherExamAnswer(UserDoOtherExamAnswer)
|
||||
@ -170,5 +250,3 @@ user_doother_exam = CRUDUserDoOtherExam(UserDootherExam)
|
||||
user_wrong_praction = CRUDUserWrongPraction(UserWrongPraction)
|
||||
user_pool = CRUDUserPool(UserPool)
|
||||
full_exam_user = CRUDFullExamUser(FullExamUser)
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user