Merge remote-tracking branch 'origin/master'
Some checks failed
CI / verify (push) Has been cancelled
Some checks failed
CI / verify (push) Has been cancelled
This commit is contained in:
@@ -32,6 +32,7 @@ import {
|
||||
liftAuthRiskBlock,
|
||||
loginWithPhoneCode,
|
||||
logoutAllAuthSessions,
|
||||
redeemRegistrationInviteCode,
|
||||
sendPhoneLoginCode,
|
||||
startWechatLogin,
|
||||
updateAuthProfile,
|
||||
@@ -93,6 +94,7 @@ describe('authService', () => {
|
||||
loginMethod: 'password',
|
||||
bindingStatus: 'active',
|
||||
wechatBound: false,
|
||||
createdAt: '2026-05-01T00:00:00.000Z',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -129,6 +131,7 @@ describe('authService', () => {
|
||||
loginMethod: 'password',
|
||||
bindingStatus: 'active',
|
||||
wechatBound: false,
|
||||
createdAt: '2026-05-01T00:00:00.000Z',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -216,6 +219,7 @@ describe('authService', () => {
|
||||
loginMethod: 'phone',
|
||||
bindingStatus: 'active',
|
||||
wechatBound: false,
|
||||
createdAt: '2026-05-01T00:00:00.000Z',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -245,6 +249,42 @@ describe('authService', () => {
|
||||
expect(window.dispatchEvent).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('redeems registration invite code after authenticated new account login', async () => {
|
||||
apiClientMocks.requestJson.mockResolvedValue({
|
||||
center: {
|
||||
inviteCode: 'SY12345678',
|
||||
inviteLinkPath: '/?inviteCode=SY12345678',
|
||||
invitedCount: 1,
|
||||
rewardedInviteCount: 1,
|
||||
todayInviterRewardCount: 0,
|
||||
todayInviterRewardRemaining: 3,
|
||||
rewardPoints: 30,
|
||||
hasRedeemedCode: true,
|
||||
boundInviterUserId: 'user_inviter',
|
||||
boundAt: '2026-05-01T00:00:00Z',
|
||||
updatedAt: '2026-05-01T00:00:00Z',
|
||||
},
|
||||
inviteeRewardGranted: true,
|
||||
inviterRewardGranted: true,
|
||||
inviteeBalanceAfter: 30,
|
||||
inviterBalanceAfter: 30,
|
||||
});
|
||||
|
||||
const response = await redeemRegistrationInviteCode(' spring-2026 ');
|
||||
|
||||
expect(response.inviteeRewardGranted).toBe(true);
|
||||
expect(apiClientMocks.requestJson).toHaveBeenCalledWith(
|
||||
'/api/profile/referrals/redeem-code',
|
||||
expect.objectContaining({
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
inviteCode: 'SPRING2026',
|
||||
}),
|
||||
}),
|
||||
'填写邀请码失败',
|
||||
);
|
||||
});
|
||||
|
||||
it('stores renewed access token after wechat bind activation', async () => {
|
||||
apiClientMocks.requestJson.mockResolvedValue({
|
||||
token: 'jwt-wechat-bind-token',
|
||||
@@ -258,6 +298,7 @@ describe('authService', () => {
|
||||
loginMethod: 'wechat',
|
||||
bindingStatus: 'active',
|
||||
wechatBound: true,
|
||||
createdAt: '2026-05-01T00:00:00.000Z',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -280,6 +321,7 @@ describe('authService', () => {
|
||||
loginMethod: 'phone',
|
||||
bindingStatus: 'active',
|
||||
wechatBound: false,
|
||||
createdAt: '2026-05-01T00:00:00.000Z',
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import type {
|
||||
LogoutResponse,
|
||||
PublicUserSearchResponse,
|
||||
} from '../../packages/shared/src/contracts/auth';
|
||||
import type { RedeemProfileReferralInviteCodeResponse } from '../../packages/shared/src/contracts/runtime';
|
||||
import {
|
||||
ApiClientError,
|
||||
type ApiRequestOptions,
|
||||
@@ -177,6 +178,20 @@ export async function loginWithPhoneCode(
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function redeemRegistrationInviteCode(inviteCode: string) {
|
||||
return requestJson<RedeemProfileReferralInviteCodeResponse>(
|
||||
'/api/profile/referrals/redeem-code',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
inviteCode: normalizeInviteCodeInput(inviteCode),
|
||||
}),
|
||||
},
|
||||
'填写邀请码失败',
|
||||
);
|
||||
}
|
||||
|
||||
export async function bindWechatPhone(phone: string, code: string) {
|
||||
const response = await requestJson<AuthWechatBindPhoneResponse>(
|
||||
'/api/auth/wechat/bind-phone',
|
||||
|
||||
@@ -136,7 +136,7 @@ export async function updatePuzzleRunPause(
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用正式拼图道具,服务端负责扣除陶泥币并更新运行态。
|
||||
* 使用正式拼图道具,服务端负责扣除光点并更新运行态。
|
||||
*/
|
||||
export async function usePuzzleRuntimeProp(
|
||||
runId: string,
|
||||
|
||||
@@ -99,7 +99,7 @@ export async function deletePuzzleWork(profileId: string) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 领取当前用户名下拼图作品的整数陶泥币激励。
|
||||
* 领取当前用户名下拼图作品的整数光点激励。
|
||||
*/
|
||||
export async function claimPuzzleWorkPointIncentive(profileId: string) {
|
||||
return requestJson<PuzzleWorkMutationResponse>(
|
||||
|
||||
Reference in New Issue
Block a user