|
|
@@ -223,6 +223,11 @@ function getLocalizedInboxContent(
|
|
|
return item.content_en || item.content || item.content_zh || '';
|
|
|
}
|
|
|
|
|
|
+/** 纯通知类站内信(无能量石领取):普通消息通知 + A/B 实验通知 */
|
|
|
+function isDisplayOnlyInboxNotice(type: string): boolean {
|
|
|
+ return type === 'news_notice' || type === 'ab_notice';
|
|
|
+}
|
|
|
+
|
|
|
export const ChatBotPage = () => {
|
|
|
const { t: tCommon, i18n } = useTranslation('common');
|
|
|
const { t: tProfile } = useTranslation('profile');
|
|
|
@@ -550,15 +555,20 @@ export const ChatBotPage = () => {
|
|
|
setPendingInboxGiftDetail(null);
|
|
|
setShowInboxGiftModal(true);
|
|
|
setLoadingInboxGiftDetail(true);
|
|
|
+ // 纯通知无领取流程:展示即标记已读,避免下次进页重复弹窗
|
|
|
+ const markRead = isDisplayOnlyInboxNotice(item.type);
|
|
|
try {
|
|
|
- const detailRes = await getUserInboxMessageDetail(userId, item.id, false);
|
|
|
+ const detailRes = await getUserInboxMessageDetail(userId, item.id, markRead);
|
|
|
if (detailRes?.success && detailRes.data) {
|
|
|
setPendingInboxGiftDetail(detailRes.data);
|
|
|
}
|
|
|
+ if (markRead) {
|
|
|
+ await loadInboxUnreadBadge(userId);
|
|
|
+ }
|
|
|
} finally {
|
|
|
setLoadingInboxGiftDetail(false);
|
|
|
}
|
|
|
- }, []);
|
|
|
+ }, [loadInboxUnreadBadge]);
|
|
|
|
|
|
const advanceInboxGiftQueueOrContinue = useCallback(
|
|
|
(userId?: string | null) => {
|
|
|
@@ -583,12 +593,24 @@ export const ChatBotPage = () => {
|
|
|
|
|
|
const closeInboxGiftModalAndContinue = useCallback(() => {
|
|
|
const userId = getUserId();
|
|
|
+ const currentMessage = pendingInboxGiftMessage;
|
|
|
setShowInboxGiftModal(false);
|
|
|
setPendingInboxGiftDetail(null);
|
|
|
setLoadingInboxGiftDetail(false);
|
|
|
setClaimingInboxGift(false);
|
|
|
+
|
|
|
+ // 关闭时兜底标记已读(详情请求失败/未完成时避免下次重复弹)
|
|
|
+ if (userId && currentMessage && isDisplayOnlyInboxNotice(currentMessage.type)) {
|
|
|
+ void getUserInboxMessageDetail(userId, currentMessage.id, true)
|
|
|
+ .then(() => loadInboxUnreadBadge(userId))
|
|
|
+ .finally(() => {
|
|
|
+ advanceInboxGiftQueueOrContinue(userId);
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
advanceInboxGiftQueueOrContinue(userId);
|
|
|
- }, [advanceInboxGiftQueueOrContinue]);
|
|
|
+ }, [advanceInboxGiftQueueOrContinue, loadInboxUnreadBadge, pendingInboxGiftMessage]);
|
|
|
|
|
|
const closeInboxRewardModalAndContinue = useCallback(() => {
|
|
|
const userId = getUserId();
|
|
|
@@ -2336,28 +2358,44 @@ export const ChatBotPage = () => {
|
|
|
// 对话能量石数量(顶部状态)
|
|
|
fetchConversationStoneCount(userId);
|
|
|
|
|
|
- getUserInboxMessages(userId, {
|
|
|
- page: 1,
|
|
|
- page_size: 20,
|
|
|
- message_type: 'energy_gift',
|
|
|
- })
|
|
|
- .then((res) => {
|
|
|
+ // 能量石未领取 + 消息通知/A/B 通知未读:进页依次弹窗(样式一致;通知仅展示无领取)
|
|
|
+ Promise.all([
|
|
|
+ getUserInboxMessages(userId, {
|
|
|
+ page: 1,
|
|
|
+ page_size: 20,
|
|
|
+ message_type: 'energy_gift',
|
|
|
+ }),
|
|
|
+ getUserInboxMessages(userId, {
|
|
|
+ page: 1,
|
|
|
+ page_size: 20,
|
|
|
+ message_type: 'news_notice',
|
|
|
+ }),
|
|
|
+ getUserInboxMessages(userId, {
|
|
|
+ page: 1,
|
|
|
+ page_size: 20,
|
|
|
+ message_type: 'ab_notice',
|
|
|
+ }),
|
|
|
+ ])
|
|
|
+ .then(([giftRes, noticeRes, abNoticeRes]) => {
|
|
|
const pendingGiftItems =
|
|
|
- res.data?.items
|
|
|
- .filter((item) => Number(item.claim_status) !== 1)
|
|
|
- .sort((a, b) => {
|
|
|
- const timeA = a.created_at ? new Date(a.created_at).getTime() : 0;
|
|
|
- const timeB = b.created_at ? new Date(b.created_at).getTime() : 0;
|
|
|
- return timeB - timeA;
|
|
|
- }) ?? [];
|
|
|
- if (pendingGiftItems.length === 0) {
|
|
|
+ giftRes.data?.items.filter((item) => Number(item.claim_status) !== 1) ?? [];
|
|
|
+ const pendingNoticeItems = [
|
|
|
+ ...(noticeRes.data?.items ?? []),
|
|
|
+ ...(abNoticeRes.data?.items ?? []),
|
|
|
+ ].filter((item) => Number(item.read_status) === 0);
|
|
|
+ const pendingInboxItems = [...pendingGiftItems, ...pendingNoticeItems].sort((a, b) => {
|
|
|
+ const timeA = a.created_at ? new Date(a.created_at).getTime() : 0;
|
|
|
+ const timeB = b.created_at ? new Date(b.created_at).getTime() : 0;
|
|
|
+ return timeB - timeA;
|
|
|
+ });
|
|
|
+ if (pendingInboxItems.length === 0) {
|
|
|
startPostInboxFlow(userId);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- const [firstGift, ...restGifts] = pendingGiftItems;
|
|
|
- setPendingInboxGiftQueue(restGifts);
|
|
|
- void showInboxGiftMessage(userId, firstGift);
|
|
|
+ const [firstMessage, ...restMessages] = pendingInboxItems;
|
|
|
+ setPendingInboxGiftQueue(restMessages);
|
|
|
+ void showInboxGiftMessage(userId, firstMessage);
|
|
|
})
|
|
|
.catch(() => {
|
|
|
startPostInboxFlow(userId);
|
|
|
@@ -5061,47 +5099,57 @@ export const ChatBotPage = () => {
|
|
|
: `${isZh ? '亲爱的:' : 'Dear:'} ${getStorage(STORAGE_KEYS.USER_NAME) || tCommon('userDefault')}\n${pendingInboxGiftDetail ? getLocalizedInboxContent(pendingInboxGiftDetail, i18n.language) : ''}`}
|
|
|
</div>
|
|
|
|
|
|
- <div
|
|
|
- style={{
|
|
|
- position: 'relative',
|
|
|
- width: px2vmin(44, 'v2'),
|
|
|
- height: px2vmin(44, 'v2'),
|
|
|
- margin: `${px2vmin(16, 'v2')} auto 0`,
|
|
|
- }}
|
|
|
- >
|
|
|
- <img
|
|
|
- src={talkEnergyStoneImg}
|
|
|
- alt=""
|
|
|
- draggable={false}
|
|
|
- style={{
|
|
|
- width: '100%',
|
|
|
- height: '100%',
|
|
|
- objectFit: 'contain',
|
|
|
- display: 'block',
|
|
|
- }}
|
|
|
- />
|
|
|
- <span
|
|
|
+ {isDisplayOnlyInboxNotice(pendingInboxGiftMessage.type) ? null : (
|
|
|
+ <div
|
|
|
style={{
|
|
|
- position: 'absolute',
|
|
|
- right: px2vmin(2, 'v2'),
|
|
|
- bottom: px2vmin(2, 'v2'),
|
|
|
- color: '#F5F3F0',
|
|
|
- fontSize: px2vmin(11, 'v2'),
|
|
|
- lineHeight: px2vmin(11, 'v2'),
|
|
|
- fontWeight: 500,
|
|
|
+ position: 'relative',
|
|
|
+ width: px2vmin(44, 'v2'),
|
|
|
+ height: px2vmin(44, 'v2'),
|
|
|
+ margin: `${px2vmin(16, 'v2')} auto 0`,
|
|
|
}}
|
|
|
>
|
|
|
- {`X${pendingInboxGiftMessage.energy_stone_amount}`}
|
|
|
- </span>
|
|
|
- </div>
|
|
|
+ <img
|
|
|
+ src={talkEnergyStoneImg}
|
|
|
+ alt=""
|
|
|
+ draggable={false}
|
|
|
+ style={{
|
|
|
+ width: '100%',
|
|
|
+ height: '100%',
|
|
|
+ objectFit: 'contain',
|
|
|
+ display: 'block',
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ <span
|
|
|
+ style={{
|
|
|
+ position: 'absolute',
|
|
|
+ right: px2vmin(2, 'v2'),
|
|
|
+ bottom: px2vmin(2, 'v2'),
|
|
|
+ color: '#F5F3F0',
|
|
|
+ fontSize: px2vmin(11, 'v2'),
|
|
|
+ lineHeight: px2vmin(11, 'v2'),
|
|
|
+ fontWeight: 500,
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {`X${pendingInboxGiftMessage.energy_stone_amount}`}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
|
|
|
<button
|
|
|
type="button"
|
|
|
data-sfx-ignore
|
|
|
onClick={() => {
|
|
|
+ if (isDisplayOnlyInboxNotice(pendingInboxGiftMessage.type)) {
|
|
|
+ closeInboxGiftModalAndContinue();
|
|
|
+ return;
|
|
|
+ }
|
|
|
void handleClaimInboxGift();
|
|
|
}}
|
|
|
- disabled={claimingInboxGift || loadingInboxGiftDetail}
|
|
|
+ disabled={
|
|
|
+ isDisplayOnlyInboxNotice(pendingInboxGiftMessage.type)
|
|
|
+ ? loadingInboxGiftDetail
|
|
|
+ : claimingInboxGift || loadingInboxGiftDetail
|
|
|
+ }
|
|
|
style={{
|
|
|
margin: `${px2vmin(16, 'v2')} auto 0`,
|
|
|
width: px2vmin(210),
|
|
|
@@ -5111,11 +5159,29 @@ export const ChatBotPage = () => {
|
|
|
background: `url(${secondaryDefaultButton}) center/cover no-repeat`,
|
|
|
color: '#F5F3F0',
|
|
|
fontSize: px2vmin(16, 'v2'),
|
|
|
- cursor: claimingInboxGift || loadingInboxGiftDetail ? 'default' : 'pointer',
|
|
|
- opacity: claimingInboxGift || loadingInboxGiftDetail ? 0.6 : 1,
|
|
|
+ cursor: isDisplayOnlyInboxNotice(pendingInboxGiftMessage.type)
|
|
|
+ ? loadingInboxGiftDetail
|
|
|
+ ? 'default'
|
|
|
+ : 'pointer'
|
|
|
+ : claimingInboxGift || loadingInboxGiftDetail
|
|
|
+ ? 'default'
|
|
|
+ : 'pointer',
|
|
|
+ opacity: isDisplayOnlyInboxNotice(pendingInboxGiftMessage.type)
|
|
|
+ ? loadingInboxGiftDetail
|
|
|
+ ? 0.6
|
|
|
+ : 1
|
|
|
+ : claimingInboxGift || loadingInboxGiftDetail
|
|
|
+ ? 0.6
|
|
|
+ : 1,
|
|
|
}}
|
|
|
>
|
|
|
- {isZh ? '领取奖励' : 'Claim reward'}
|
|
|
+ {isDisplayOnlyInboxNotice(pendingInboxGiftMessage.type)
|
|
|
+ ? isZh
|
|
|
+ ? '知道了'
|
|
|
+ : 'Got it'
|
|
|
+ : isZh
|
|
|
+ ? '领取奖励'
|
|
|
+ : 'Claim reward'}
|
|
|
</button>
|
|
|
</div>
|
|
|
</>
|