Files
Genarrative/.hermes/skills/genarrative-profile-invite-flow/SKILL.md
历冰郁-hermes版 7e35231dfe
Some checks failed
CI / verify (pull_request) Has been cancelled
docs: sync genarrative shared skills
2026-05-08 17:39:49 +08:00

150 lines
7.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: genarrative-profile-invite-flow
description: 在 Genarrative 中排查或修改邀请码、邀请好友、首次登录后填写邀请码、我的页签邀请码兑换链路时使用。
version: 1.0.0
author: Hermes Agent
license: MIT
metadata:
hermes:
tags: [Genarrative, 邀请码, referral, auth, profile, query-params, 前端]
related_skills: []
---
# Genarrative 邀请码与邀请好友流程
用于排查或修改 Genarrative 的邀请码读取、填写、兑换、邀请中心与“我的”页签相关能力。
## 适用场景
- 判断 URL query 参数中的邀请码是否被读取。
- 修改邀请码填写入口、首次登录后引导或“我的”页签兑换入口。
- 排查邀请码预填、兑换、已填写状态、邀请好友复制链接。
- 修改邀请中心 API client 或前端 referral UI。
- 回答用户关于“邀请码在哪里填 / 从哪里配置 / query 是否支持”的问题。
## 先做代码核对,不要只凭旧记忆回答
邀请码流程近期发生过迁移:不要默认认为登录窗口可填写邀请码。回答前优先搜索并核对当前代码,尤其是:
```bash
cd <repo-root>
python3 - <<'PY'
from pathlib import Path
root=Path('src')
terms=['RegistrationInviteModal','readInviteCodeFromLocation','referralRedeemCode','redeemRpgProfileReferralInviteCode','邀请码','inviteCode']
for term in terms:
print('\n---', term)
for p in root.rglob('*'):
if p.is_file() and p.suffix in ['.ts', '.tsx']:
try:
txt=p.read_text('utf-8')
except Exception:
continue
if term in txt:
for i, line in enumerate(txt.splitlines(), 1):
if term in line:
print(f'{p}:{i}:{line.strip()[:180]}')
```
## 当前前端链路口径
### 1. AuthGate 中仍有旧 query 读取逻辑
文件:
- `src/components/auth/AuthGate.tsx`
重点函数 / 状态:
- `readInviteCodeFromLocation()`
- `pendingInviteCode`
- `showRegistrationInviteModal`
- `RegistrationInviteModal`
当前旧逻辑会读取:
- `?inviteCode=...`
- `?invite_code=...`
并把值清洗为大写字母数字形式。
### 2. 登录窗口本身不再填写邀请码
不要回答“登录窗口可填写邀请码”。当前登录弹窗 `LoginScreen` 只负责登录 / 注册账号;邀请码填写已迁移到登录后的流程。
### 3. 新版“我的”页签兑换入口在 RpgEntryHomeView
文件:
- `src/components/rpg-entry/RpgEntryHomeView.tsx`
重点常量 / 函数 / 状态:
- `PROFILE_INVITE_QUERY_KEYS`:新版 query 支持 `inviteCode` / `invite_code`
- `normalizeProfileInviteQueryCode()`:去掉非字母数字并转大写。
- `readProfileInviteCodeFromLocationSearch()`:从 `window.location.search` 读取并 normalize。
- `pendingProfileInviteCode`:组件初始化时读取 query 邀请码。
- `referralCenter`
- `referralRedeemCode`
- `setReferralRedeemCode`
- `openProfilePopupPanel('redeem')`
- `submitReferralRedeemCode()`
- `canShowReferralRedeemShortcut`
- `isWithinProfileInviteRedeemWindow(authUi?.user?.createdAt)`
UI 中“填邀请码”面板会使用 `referralRedeemCode` 作为输入值,并通过 `submitReferralRedeemCode()` 提交。当前新版实现会在首次打开“填邀请码”面板时用 `pendingProfileInviteCode` 预填输入框;例如 `/?inviteCode=spring-2026` 会预填为 `SPRING2026`
### 4. 新版兑换 API client
文件:
- `src/services/rpg-entry/rpgProfileClient.ts`
函数:
- `getRpgProfileReferralInviteCenter()` -> `GET /profile/referrals/invite-center`
- `redeemRpgProfileReferralInviteCode(inviteCode)` -> `POST /profile/referrals/redeem-code`
## 判断 query 参数是否真正接入新版流程
回答这类问题时要区分两层:
1. “是否存在旧 query 读取代码”:看 `AuthGate.tsx``readInviteCodeFromLocation()`
2. “query 是否接到新版填写入口”:看 `RpgEntryHomeView.tsx` 是否存在 `pendingProfileInviteCode` / `readProfileInviteCodeFromLocationSearch()`,以及打开 `openProfilePopupPanel('redeem')` 时是否把该值写回 `referralRedeemCode`
当前新版流程已经支持 `inviteCode` / `invite_code` query 预填“我的”页签的“填邀请码”弹窗;登录窗口仍不填写邀请码。
如果未来代码只看到 AuthGate 读 query但没有看到 `RpgEntryHomeView``referralRedeemCode` 从 query 初始化,就应回答:
> 代码里仍支持读取 `inviteCode` / `invite_code`,但新版“第一次登录后 / 我的页签”的填写入口未必已经完整接入该 query 值;需要继续把 query 值传入新版 profile referral redeem 流程。
## 修改建议顺序
如果要把 query 邀请码完整接入新版流程,建议按这个顺序做:
1. 先确定 query 参数规范:继续支持 `inviteCode` / `invite_code`,并统一 normalize。
2.`RpgEntryHomeView.tsx` 内用 `readProfileInviteCodeFromLocationSearch(window.location.search)` 初始化 `pendingProfileInviteCode`
3.`pendingProfileInviteCode` 初始化 `referralRedeemCode`,并在 `openProfilePopupPanel('redeem')` 时重新写回,避免关闭后再次打开被清空。
4. 如产品要求自动弹出:
-`pendingProfileInviteCode` 且未登录时,自动调用 `authUi?.openLoginModal()` 打开登录窗口;登录窗口仍不承接邀请码输入。
-`pendingProfileInviteCode` 且已登录时,自动将 `referralRedeemCode` 设为该 query 邀请码,并 `setProfilePopupPanel('redeem')` 直接打开“填邀请码”面板。
-`useRef` 记录是否已处理过当前 query避免组件重渲染或 `authUi` 对象变化导致重复弹窗。
- 当前项目实现已从“只预填、不自动弹”调整为上述行为。
5. 兑换成功后清理输入态;是否清理 URL query 需由产品决定,避免破坏分享链接归因。
6. 补测试覆盖:未登录访问带 query、已登录访问带 query 自动打开填写面板、我的页签手动打开、已填写邀请码、过期窗口、空/非法 query。当前已有 `RpgEntryHomeView.recharge.test.tsx` 覆盖:
- `invite query opens login modal for logged out users`
- `invite query opens redeem modal directly for logged in users`
- `profile redeem invite modal reads query invite code after login`
## 常见坑
1. 不要把旧 `RegistrationInviteModal` 误认为当前唯一入口。
2. 不要说“登录窗口可以填写邀请码”,除非当前代码重新把邀请码输入放回 `LoginScreen`
3. `AuthGate` 读到 query 不等于新版 `RpgEntryHomeView` 已经预填。
4. “第一次登录后”与“我的页签”可能是两个入口;修改时要同时检查自动引导和手动入口。
5. `canShowReferralRedeemShortcut` 受登录态、创建时间窗口、邀请中心初始化、已兑换状态共同影响。
6. 邀请码 URL 通常由 `inviteLinkPath` 生成,复制逻辑在 `copyInviteInfo()`,不要只改兑换入口而忘记分享链接格式。
## 参考资料
- `references/query-invite-code-flow-2026-05-07.md`:本次会话确认的邀请码 query 与新版 profile referral 入口关系。
## 验证标准
- 能明确回答当前 query 参数读取位置与参数名。
- 能区分旧 AuthGate 邀请弹窗与新版“我的”页签 referral redeem。
- 若实现改动,测试覆盖带 query 的登录后预填/弹窗行为,以及已填写邀请码时不再提示。