|
|
@@ -585,121 +585,223 @@ class UserService:
|
|
|
logger.error(f"❌ 更新用户UI状态失败: user_id={user_id}, error={e}")
|
|
|
return None
|
|
|
|
|
|
- async def register_with_phone(self, phone: str, username: str = "") -> Dict:
|
|
|
+ async def register_with_phone(self, phone: str, username: str = "", user_id: Optional[str] = None) -> Dict:
|
|
|
"""
|
|
|
使用手机号注册
|
|
|
|
|
|
Args:
|
|
|
phone: 手机号
|
|
|
username: 用户名(可选)
|
|
|
+ user_id: 可选的现有用户ID,如果提供则更新该用户而不是创建新用户
|
|
|
|
|
|
Returns:
|
|
|
用户信息字典
|
|
|
"""
|
|
|
try:
|
|
|
async with db_manager.get_session() as session:
|
|
|
- # 检查手机号是否已注册
|
|
|
+ # 检查手机号是否已被其他用户注册
|
|
|
result = await session.execute(
|
|
|
select(User).where(User.phone == phone)
|
|
|
)
|
|
|
- existing_user = result.scalar_one_or_none()
|
|
|
-
|
|
|
- if existing_user:
|
|
|
- raise ValueError("该手机号已被注册")
|
|
|
-
|
|
|
- # 生成用户ID和用户名
|
|
|
- user_id = str(uuid.uuid4())
|
|
|
- if not username or username.strip() == "":
|
|
|
- username = await self._generate_temp_username(session)
|
|
|
-
|
|
|
- user = User(
|
|
|
- user_id=user_id,
|
|
|
- username=username,
|
|
|
- phone=phone,
|
|
|
- user_type="registered",
|
|
|
- is_verified=True,
|
|
|
- registered_at=datetime.now(),
|
|
|
- current_background_image_id="default", # 设置默认背景图片
|
|
|
- )
|
|
|
- session.add(user)
|
|
|
- await session.flush() # 先 flush 确保 user 有 ID,但不提交事务
|
|
|
-
|
|
|
- # 初始化背景图片
|
|
|
- await self._init_user_background_image(session, user_id)
|
|
|
+ existing_phone_user = result.scalar_one_or_none()
|
|
|
|
|
|
- # 初始化头像(注册用户:默认头像 + 注册赠送头像)
|
|
|
- await self._init_user_avatar(session, user_id, user_type="registered")
|
|
|
+ if existing_phone_user:
|
|
|
+ # 如果提供了 user_id,检查是否是同一个用户
|
|
|
+ if user_id and existing_phone_user.user_id == user_id:
|
|
|
+ # 同一个用户,可能是重新注册,允许继续
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ raise ValueError("该手机号已被注册")
|
|
|
|
|
|
- await session.commit()
|
|
|
- await session.refresh(user)
|
|
|
+ # 如果提供了 user_id,使用现有用户
|
|
|
+ final_user_id = None
|
|
|
+ if user_id:
|
|
|
+ result = await session.execute(
|
|
|
+ select(User).where(User.user_id == user_id)
|
|
|
+ )
|
|
|
+ existing_user = result.scalar_one_or_none()
|
|
|
+
|
|
|
+ if not existing_user:
|
|
|
+ raise ValueError(f"用户ID {user_id} 不存在")
|
|
|
+
|
|
|
+ if existing_user.user_type == "registered":
|
|
|
+ raise ValueError("该用户已经注册过了")
|
|
|
+
|
|
|
+ # 更新现有用户
|
|
|
+ if not username or username.strip() == "":
|
|
|
+ # 如果用户已有用户名,保留;否则生成新用户名
|
|
|
+ if not existing_user.username or existing_user.username.strip() == "":
|
|
|
+ username = await self._generate_temp_username(session)
|
|
|
+ else:
|
|
|
+ username = existing_user.username
|
|
|
+
|
|
|
+ existing_user.phone = phone
|
|
|
+ existing_user.username = username
|
|
|
+ existing_user.user_type = "registered"
|
|
|
+ existing_user.is_verified = True
|
|
|
+ existing_user.registered_at = datetime.now()
|
|
|
+
|
|
|
+ user = existing_user
|
|
|
+ final_user_id = user_id
|
|
|
+ await session.flush()
|
|
|
+
|
|
|
+ # 如果用户还没有背景图片,初始化背景图片
|
|
|
+ if not existing_user.current_background_image_id or existing_user.current_background_image_id == "default":
|
|
|
+ await self._init_user_background_image(session, user_id)
|
|
|
+
|
|
|
+ # 初始化头像(注册用户:默认头像 + 注册赠送头像)
|
|
|
+ await self._init_user_avatar(session, user_id, user_type="registered")
|
|
|
+
|
|
|
+ await session.commit()
|
|
|
+ await session.refresh(user)
|
|
|
+ else:
|
|
|
+ # 创建新用户(原有逻辑)
|
|
|
+ new_user_id = str(uuid.uuid4())
|
|
|
+ if not username or username.strip() == "":
|
|
|
+ username = await self._generate_temp_username(session)
|
|
|
+
|
|
|
+ user = User(
|
|
|
+ user_id=new_user_id,
|
|
|
+ username=username,
|
|
|
+ phone=phone,
|
|
|
+ user_type="registered",
|
|
|
+ is_verified=True,
|
|
|
+ registered_at=datetime.now(),
|
|
|
+ current_background_image_id="default", # 设置默认背景图片
|
|
|
+ )
|
|
|
+ session.add(user)
|
|
|
+ await session.flush() # 先 flush 确保 user 有 ID,但不提交事务
|
|
|
+
|
|
|
+ final_user_id = new_user_id
|
|
|
+
|
|
|
+ # 初始化背景图片
|
|
|
+ await self._init_user_background_image(session, new_user_id)
|
|
|
+
|
|
|
+ # 初始化头像(注册用户:默认头像 + 注册赠送头像)
|
|
|
+ await self._init_user_avatar(session, new_user_id, user_type="registered")
|
|
|
+
|
|
|
+ await session.commit()
|
|
|
+ await session.refresh(user)
|
|
|
|
|
|
# 初始化 user_ui_states 的 current_avatar_id(注册用户优先使用注册赠送头像)
|
|
|
+ final_user_id = final_user_id if final_user_id else user.user_id
|
|
|
await self.upsert_user_ui_state(
|
|
|
- user_id=user_id,
|
|
|
+ user_id=final_user_id,
|
|
|
current_avatar_id=REGISTERED_AVATAR_ID
|
|
|
)
|
|
|
|
|
|
- logger.info(f"✅ 手机号注册成功: user_id={user_id}, phone={phone}")
|
|
|
+ logger.info(f"✅ 手机号注册成功: user_id={final_user_id}, phone={phone}")
|
|
|
return user.to_dict()
|
|
|
except Exception as e:
|
|
|
logger.error(f"❌ 手机号注册失败: {e}")
|
|
|
raise
|
|
|
|
|
|
- async def register_with_email(self, email: str, username: str = "") -> Dict:
|
|
|
+ async def register_with_email(self, email: str, username: str = "", user_id: Optional[str] = None) -> Dict:
|
|
|
"""
|
|
|
使用邮箱注册
|
|
|
|
|
|
Args:
|
|
|
email: 邮箱
|
|
|
username: 用户名(可选)
|
|
|
+ user_id: 可选的现有用户ID,如果提供则更新该用户而不是创建新用户
|
|
|
|
|
|
Returns:
|
|
|
用户信息字典
|
|
|
"""
|
|
|
try:
|
|
|
async with db_manager.get_session() as session:
|
|
|
- # 检查邮箱是否已注册
|
|
|
+ # 检查邮箱是否已被其他用户注册
|
|
|
result = await session.execute(
|
|
|
select(User).where(User.email == email)
|
|
|
)
|
|
|
- existing_user = result.scalar_one_or_none()
|
|
|
+ existing_email_user = result.scalar_one_or_none()
|
|
|
|
|
|
- if existing_user:
|
|
|
- raise ValueError("该邮箱已被注册")
|
|
|
+ if existing_email_user:
|
|
|
+ # 如果提供了 user_id,检查是否是同一个用户
|
|
|
+ if user_id and existing_email_user.user_id == user_id:
|
|
|
+ # 同一个用户,可能是重新注册,允许继续
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ raise ValueError("该邮箱已被注册")
|
|
|
|
|
|
- # 生成用户ID和用户名
|
|
|
- user_id = str(uuid.uuid4())
|
|
|
- if not username or username.strip() == "":
|
|
|
- username = await self._generate_temp_username(session)
|
|
|
-
|
|
|
- user = User(
|
|
|
- user_id=user_id,
|
|
|
- username=username,
|
|
|
- email=email,
|
|
|
- user_type="registered",
|
|
|
- is_verified=True,
|
|
|
- registered_at=datetime.now(),
|
|
|
- current_background_image_id="default", # 设置默认背景图片
|
|
|
- )
|
|
|
- session.add(user)
|
|
|
- await session.flush() # 先 flush 确保 user 有 ID,但不提交事务
|
|
|
-
|
|
|
- # 初始化背景图片
|
|
|
- await self._init_user_background_image(session, user_id)
|
|
|
-
|
|
|
- # 初始化头像(注册用户:默认头像 + 注册赠送头像)
|
|
|
- await self._init_user_avatar(session, user_id, user_type="registered")
|
|
|
-
|
|
|
- await session.commit()
|
|
|
- await session.refresh(user)
|
|
|
+ # 如果提供了 user_id,使用现有用户
|
|
|
+ final_user_id = None
|
|
|
+ if user_id:
|
|
|
+ result = await session.execute(
|
|
|
+ select(User).where(User.user_id == user_id)
|
|
|
+ )
|
|
|
+ existing_user = result.scalar_one_or_none()
|
|
|
+
|
|
|
+ if not existing_user:
|
|
|
+ raise ValueError(f"用户ID {user_id} 不存在")
|
|
|
+
|
|
|
+ if existing_user.user_type == "registered":
|
|
|
+ raise ValueError("该用户已经注册过了")
|
|
|
+
|
|
|
+ # 更新现有用户
|
|
|
+ if not username or username.strip() == "":
|
|
|
+ # 如果用户已有用户名,保留;否则生成新用户名
|
|
|
+ if not existing_user.username or existing_user.username.strip() == "":
|
|
|
+ username = await self._generate_temp_username(session)
|
|
|
+ else:
|
|
|
+ username = existing_user.username
|
|
|
+
|
|
|
+ existing_user.email = email
|
|
|
+ existing_user.username = username
|
|
|
+ existing_user.user_type = "registered"
|
|
|
+ existing_user.is_verified = True
|
|
|
+ existing_user.registered_at = datetime.now()
|
|
|
+
|
|
|
+ user = existing_user
|
|
|
+ final_user_id = user_id
|
|
|
+ await session.flush()
|
|
|
+
|
|
|
+ # 如果用户还没有背景图片,初始化背景图片
|
|
|
+ if not existing_user.current_background_image_id or existing_user.current_background_image_id == "default":
|
|
|
+ await self._init_user_background_image(session, user_id)
|
|
|
+
|
|
|
+ # 初始化头像(注册用户:默认头像 + 注册赠送头像)
|
|
|
+ await self._init_user_avatar(session, user_id, user_type="registered")
|
|
|
+
|
|
|
+ await session.commit()
|
|
|
+ await session.refresh(user)
|
|
|
+ else:
|
|
|
+ # 创建新用户(原有逻辑)
|
|
|
+ new_user_id = str(uuid.uuid4())
|
|
|
+ if not username or username.strip() == "":
|
|
|
+ username = await self._generate_temp_username(session)
|
|
|
+
|
|
|
+ user = User(
|
|
|
+ user_id=new_user_id,
|
|
|
+ username=username,
|
|
|
+ email=email,
|
|
|
+ user_type="registered",
|
|
|
+ is_verified=True,
|
|
|
+ registered_at=datetime.now(),
|
|
|
+ current_background_image_id="default", # 设置默认背景图片
|
|
|
+ )
|
|
|
+ session.add(user)
|
|
|
+ await session.flush() # 先 flush 确保 user 有 ID,但不提交事务
|
|
|
+
|
|
|
+ final_user_id = new_user_id
|
|
|
+
|
|
|
+ # 初始化背景图片
|
|
|
+ await self._init_user_background_image(session, new_user_id)
|
|
|
+
|
|
|
+ # 初始化头像(注册用户:默认头像 + 注册赠送头像)
|
|
|
+ await self._init_user_avatar(session, new_user_id, user_type="registered")
|
|
|
+
|
|
|
+ await session.commit()
|
|
|
+ await session.refresh(user)
|
|
|
|
|
|
# 初始化 user_ui_states 的 current_avatar_id(注册用户优先使用注册赠送头像)
|
|
|
+ final_user_id = final_user_id if final_user_id else user.user_id
|
|
|
await self.upsert_user_ui_state(
|
|
|
- user_id=user_id,
|
|
|
+ user_id=final_user_id,
|
|
|
current_avatar_id=REGISTERED_AVATAR_ID
|
|
|
)
|
|
|
|
|
|
- logger.info(f"✅ 邮箱注册成功: user_id={user_id}, email={email}")
|
|
|
+ logger.info(f"✅ 邮箱注册成功: user_id={final_user_id}, email={email}")
|
|
|
return user.to_dict()
|
|
|
except Exception as e:
|
|
|
logger.error(f"❌ 邮箱注册失败: {e}")
|
|
|
@@ -912,6 +1014,37 @@ class UserService:
|
|
|
except Exception as e:
|
|
|
logger.error(f"❌ 邮箱登录失败: {e}")
|
|
|
return None
|
|
|
+
|
|
|
+ async def check_user_exists_by_qq_openid(self, openid: str, unionid: Optional[str] = None) -> bool:
|
|
|
+ """
|
|
|
+ 检查QQ OpenID对应的用户是否存在
|
|
|
+
|
|
|
+ Args:
|
|
|
+ openid: QQ OpenID
|
|
|
+ unionid: QQ UnionID(可选)
|
|
|
+
|
|
|
+ Returns:
|
|
|
+ 用户是否存在
|
|
|
+ """
|
|
|
+ try:
|
|
|
+ async with db_manager.get_session() as session:
|
|
|
+ # 优先用 openid 查询
|
|
|
+ result = await session.execute(
|
|
|
+ select(User).where(User.qq_openid == openid)
|
|
|
+ )
|
|
|
+ existing_user = result.scalar_one_or_none()
|
|
|
+
|
|
|
+ # 如果未命中且拿到了 unionid,则尝试用 unionid 查询
|
|
|
+ if not existing_user and unionid:
|
|
|
+ union_result = await session.execute(
|
|
|
+ select(User).where(User.qq_unionid == unionid)
|
|
|
+ )
|
|
|
+ existing_user = union_result.scalar_one_or_none()
|
|
|
+
|
|
|
+ return existing_user is not None
|
|
|
+ except Exception as e:
|
|
|
+ logger.error(f"❌ 检查QQ用户是否存在失败: {e}")
|
|
|
+ return False
|
|
|
|
|
|
|
|
|
# 全局用户服务实例
|