feat(wxapp): 实现分享功能并优化用户信息相关操作

- 新增分享功能处理逻辑,包括获取设置、记录分享次数和更新用户积分
- 优化用户信息获取和更新操作,提高代码复用性和可维护性
- 添加错题收藏功能,支持用户对错题进行收藏和取消收藏
- 重构部分代码,提高可读性和性能
This commit is contained in:
Basyc 2025-03-07 21:13:18 +08:00
parent 7ace7db5c5
commit 97a61189ea
3 changed files with 445 additions and 161 deletions

View File

@ -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"}

View File

@ -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):

View File

@ -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)