diff --git a/lover/__pycache__/models.cpython-314.pyc b/lover/__pycache__/models.cpython-314.pyc
index 712cc9c..9144147 100644
Binary files a/lover/__pycache__/models.cpython-314.pyc and b/lover/__pycache__/models.cpython-314.pyc differ
diff --git a/lover/migrations/add_invite_code_fields.sql b/lover/migrations/add_invite_code_fields.sql
new file mode 100644
index 0000000..cb94fcb
--- /dev/null
+++ b/lover/migrations/add_invite_code_fields.sql
@@ -0,0 +1,18 @@
+-- 添加邀请码相关字段
+ALTER TABLE nf_user
+ADD COLUMN invite_code VARCHAR(10) UNIQUE COMMENT '我的邀请码',
+ADD COLUMN invited_by VARCHAR(10) COMMENT '被谁邀请(邀请码)',
+ADD COLUMN invite_count INT DEFAULT 0 COMMENT '邀请人数',
+ADD COLUMN invite_reward_total DECIMAL(10,2) DEFAULT 0.00 COMMENT '邀请奖励总额';
+
+-- 为已有用户生成邀请码(6位随机字符)
+UPDATE nf_user
+SET invite_code = CONCAT(
+ SUBSTRING('ABCDEFGHJKLMNPQRSTUVWXYZ23456789', FLOOR(1 + RAND() * 32), 1),
+ SUBSTRING('ABCDEFGHJKLMNPQRSTUVWXYZ23456789', FLOOR(1 + RAND() * 32), 1),
+ SUBSTRING('ABCDEFGHJKLMNPQRSTUVWXYZ23456789', FLOOR(1 + RAND() * 32), 1),
+ SUBSTRING('ABCDEFGHJKLMNPQRSTUVWXYZ23456789', FLOOR(1 + RAND() * 32), 1),
+ SUBSTRING('ABCDEFGHJKLMNPQRSTUVWXYZ23456789', FLOOR(1 + RAND() * 32), 1),
+ SUBSTRING('ABCDEFGHJKLMNPQRSTUVWXYZ23456789', FLOOR(1 + RAND() * 32), 1)
+)
+WHERE invite_code IS NULL;
diff --git a/lover/models.py b/lover/models.py
index e7b0111..28b1f06 100644
--- a/lover/models.py
+++ b/lover/models.py
@@ -31,6 +31,11 @@ class User(Base):
owned_outfit_ids = Column(JSON)
owned_voice_ids = Column(JSON)
vip_endtime = Column(BigInteger, default=0)
+ # 邀请码相关
+ invite_code = Column(String(10), unique=True)
+ invited_by = Column(String(10))
+ invite_count = Column(Integer, default=0)
+ invite_reward_total = Column(DECIMAL(10, 2), default=0.00)
class VoiceLibrary(Base):
diff --git a/lover/routers/__pycache__/config.cpython-314.pyc b/lover/routers/__pycache__/config.cpython-314.pyc
index 69aea36..e494acc 100644
Binary files a/lover/routers/__pycache__/config.cpython-314.pyc and b/lover/routers/__pycache__/config.cpython-314.pyc differ
diff --git a/lover/routers/config.py b/lover/routers/config.py
index 1382e25..7e568f7 100644
--- a/lover/routers/config.py
+++ b/lover/routers/config.py
@@ -492,3 +492,144 @@ def save_cloned_voice(
except Exception as e:
db.rollback()
raise HTTPException(status_code=500, detail=f"保存失败: {str(e)}")
+
+
+
+# ===== 邀请码相关 =====
+
+class InviteInfoResponse(BaseModel):
+ invite_code: str
+ invite_count: int
+ invite_reward_total: float
+ invite_url: str
+
+ model_config = ConfigDict(from_attributes=True)
+
+
+class InviteRewardRequest(BaseModel):
+ invite_code: str
+
+ model_config = ConfigDict(from_attributes=True)
+
+
+def _generate_invite_code() -> str:
+ """生成6位邀请码(不含易混淆字符)"""
+ import random
+ import string
+ chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789' # 去掉 0O1I 等易混淆字符
+ return ''.join(random.choice(chars) for _ in range(6))
+
+
+@router.get("/invite/info", response_model=ApiResponse[InviteInfoResponse])
+def get_invite_info(
+ db: Session = Depends(get_db),
+ user: AuthedUser = Depends(get_current_user),
+):
+ """
+ 获取用户的邀请信息
+ """
+ user_row = db.query(User).filter(User.id == user.id).first()
+ if not user_row:
+ raise HTTPException(status_code=404, detail="用户不存在")
+
+ # 如果没有邀请码,生成一个
+ if not user_row.invite_code:
+ while True:
+ code = _generate_invite_code()
+ # 检查是否重复
+ existing = db.query(User).filter(User.invite_code == code).first()
+ if not existing:
+ user_row.invite_code = code
+ db.add(user_row)
+ db.flush()
+ break
+
+ # 生成邀请链接(这里使用简单的格式,实际可以是 H5 页面链接)
+ invite_url = f"https://your-domain.com/register?invite={user_row.invite_code}"
+
+ return success_response(
+ InviteInfoResponse(
+ invite_code=user_row.invite_code,
+ invite_count=user_row.invite_count or 0,
+ invite_reward_total=float(user_row.invite_reward_total or 0),
+ invite_url=invite_url
+ )
+ )
+
+
+@router.post("/invite/apply", response_model=ApiResponse[dict])
+def apply_invite_code(
+ payload: InviteRewardRequest,
+ db: Session = Depends(get_db),
+ user: AuthedUser = Depends(get_current_user),
+):
+ """
+ 新用户使用邀请码(注册后调用)
+ """
+ user_row = db.query(User).filter(User.id == user.id).with_for_update().first()
+ if not user_row:
+ raise HTTPException(status_code=404, detail="用户不存在")
+
+ # 检查是否已经使用过邀请码
+ if user_row.invited_by:
+ raise HTTPException(status_code=400, detail="您已经使用过邀请码")
+
+ # 不能使用自己的邀请码
+ if user_row.invite_code == payload.invite_code:
+ raise HTTPException(status_code=400, detail="不能使用自己的邀请码")
+
+ # 查找邀请人
+ inviter = db.query(User).filter(User.invite_code == payload.invite_code).with_for_update().first()
+ if not inviter:
+ raise HTTPException(status_code=404, detail="邀请码不存在")
+
+ # 奖励金额配置
+ INVITER_REWARD = 10.00 # 邀请人获得10金币
+ INVITEE_REWARD = 5.00 # 被邀请人获得5金币
+
+ # 给邀请人发放奖励
+ inviter.money = float(inviter.money or 0) + INVITER_REWARD
+ inviter.invite_count = (inviter.invite_count or 0) + 1
+ inviter.invite_reward_total = float(inviter.invite_reward_total or 0) + INVITER_REWARD
+ db.add(inviter)
+
+ # 记录邀请人的金币日志
+ db.add(
+ UserMoneyLog(
+ user_id=inviter.id,
+ money=Decimal(str(INVITER_REWARD)),
+ before=Decimal(str(float(inviter.money) - INVITER_REWARD)),
+ after=Decimal(str(inviter.money)),
+ memo=f"邀请新用户奖励",
+ createtime=int(time.time()),
+ )
+ )
+
+ # 给被邀请人发放奖励
+ user_row.money = float(user_row.money or 0) + INVITEE_REWARD
+ user_row.invited_by = payload.invite_code
+ db.add(user_row)
+
+ # 记录被邀请人的金币日志
+ db.add(
+ UserMoneyLog(
+ user_id=user.id,
+ money=Decimal(str(INVITEE_REWARD)),
+ before=Decimal(str(float(user_row.money) - INVITEE_REWARD)),
+ after=Decimal(str(user_row.money)),
+ memo=f"使用邀请码奖励",
+ createtime=int(time.time()),
+ )
+ )
+
+ try:
+ db.flush()
+ except IntegrityError:
+ db.rollback()
+ raise HTTPException(status_code=409, detail="操作失败,请重试")
+
+ return success_response({
+ "message": f"邀请码使用成功!您获得了{INVITEE_REWARD}金币",
+ "reward": INVITEE_REWARD,
+ "balance": float(user_row.money)
+ })
diff --git a/xuniYou/pages/login/index.vue b/xuniYou/pages/login/index.vue
index efb8ef0..08825dd 100644
--- a/xuniYou/pages/login/index.vue
+++ b/xuniYou/pages/login/index.vue
@@ -32,6 +32,19 @@
🔧 开发模式:只需输入手机号即可登录
+
+
+
+
+
+
+
+
+ ✅ 使用邀请码可获得5金币奖励
+
+
+
+
+ 扫描二维码获取邀请码
+
+
+ 长按保存二维码分享给好友
+
+
+
+ 邀请规则
+ • 分享邀请码或二维码给好友
+ • 好友扫码或输入邀请码注册
+ • 您获得10金币,好友获得5金币
+ • 金币可用于购买会员、音色等