diff --git a/.claude/settings.local.json b/.claude/settings.local.json
new file mode 100644
index 0000000..2f9ff20
--- /dev/null
+++ b/.claude/settings.local.json
@@ -0,0 +1,9 @@
+{
+ "permissions": {
+ "allow": [
+ "Bash(python -c \"import sys,json; d=json.load\\(sys.stdin\\); deps={**d.get\\('dependencies',{}\\), **d.get\\('devDependencies',{}\\)}; [print\\(f'{k}: {v}'\\) for k,v in deps.items\\(\\) if 'navigation' in k or 'tab' in k.lower\\(\\)]\")",
+ "Bash(npx tsc *)",
+ "Bash(echo \"EXIT: $?\")"
+ ]
+ }
+}
diff --git a/app.json b/app.json
index d84ab6c..dbbc8cb 100644
--- a/app.json
+++ b/app.json
@@ -7,14 +7,17 @@
"icon": "./assets/icon.png",
"userInterfaceStyle": "automatic",
"scheme": "withyou",
+ "splash": {
+ "image": "./assets/splash-icon.png",
+ "resizeMode": "contain",
+ "backgroundColor": "#ffffff"
+ },
"ios": {
"supportsTablet": true,
"infoPlist": {
"NSMicrophoneUsageDescription": "允许威友访问您的麦克风以进行语音通话",
"NSCameraUsageDescription": "允许威友访问您的相机以进行视频通话",
"UIBackgroundModes": [
- "fetch",
- "remote-notification",
"fetch",
"remote-notification",
"audio"
diff --git a/app/(app)/(tabs)/_layout.tsx b/app/(app)/(tabs)/_layout.tsx
index 95c57a0..d4e2844 100644
--- a/app/(app)/(tabs)/_layout.tsx
+++ b/app/(app)/(tabs)/_layout.tsx
@@ -1,8 +1,9 @@
import { useMemo, useCallback } from 'react';
-import { Platform, useWindowDimensions } from 'react-native';
+import { Platform, Pressable, useWindowDimensions } from 'react-native';
import { Tabs, usePathname } from 'expo-router';
import { MaterialCommunityIcons } from '@expo/vector-icons';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
+import type { PressableProps } from 'react-native';
import { useAppColors, shadows } from '../../../src/theme';
import { BREAKPOINTS } from '../../../src/hooks';
@@ -12,6 +13,16 @@ const TAB_BAR_HEIGHT = 56;
const TAB_BAR_FLOATING_MARGIN = 12;
const TAB_BAR_MARGIN = 20;
+const TabBarButton = ({ children, style, ...rest }: PressableProps) => (
+
+ {children}
+
+);
+
export default function TabsLayout() {
const colors = useAppColors();
const { width } = useWindowDimensions();
@@ -72,6 +83,7 @@ export default function TabsLayout() {
marginHorizontal: 2,
paddingVertical: 1,
},
+ tabBarButton: (props) => ,
tabBarShowLabel: true,
tabBarLabelStyle: { fontSize: 11, fontWeight: '600', marginTop: -1 },
}}
diff --git a/src/components/business/BlockEditor/ImageBlockView.tsx b/src/components/business/BlockEditor/ImageBlockView.tsx
index b7f1994..aff2f39 100644
--- a/src/components/business/BlockEditor/ImageBlockView.tsx
+++ b/src/components/business/BlockEditor/ImageBlockView.tsx
@@ -67,7 +67,7 @@ const styles = StyleSheet.create({
alignItems: 'center',
},
uploadingOverlay: {
- ...StyleSheet.absoluteFillObject,
+ ...StyleSheet.absoluteFill,
backgroundColor: 'rgba(0, 0, 0, 0.3)',
justifyContent: 'center',
alignItems: 'center',
diff --git a/src/components/business/VoteCard.tsx b/src/components/business/VoteCard.tsx
index 9705da1..df15e76 100644
--- a/src/components/business/VoteCard.tsx
+++ b/src/components/business/VoteCard.tsx
@@ -159,7 +159,7 @@ function createVoteCardStyles(colors: AppColors) {
fontSize: fontSizes.sm,
},
loadingOverlay: {
- ...StyleSheet.absoluteFillObject,
+ ...StyleSheet.absoluteFill,
backgroundColor: colors.background.paper + 'CC',
justifyContent: 'center',
alignItems: 'center',
diff --git a/src/components/call/CallScreen.tsx b/src/components/call/CallScreen.tsx
index 1063e49..17d03ea 100644
--- a/src/components/call/CallScreen.tsx
+++ b/src/components/call/CallScreen.tsx
@@ -267,12 +267,12 @@ const CallScreen: React.FC = () => {
const styles = StyleSheet.create({
container: {
- ...StyleSheet.absoluteFillObject,
+ ...StyleSheet.absoluteFill,
backgroundColor: '#1A1A2E',
zIndex: 9999,
},
background: {
- ...StyleSheet.absoluteFillObject,
+ ...StyleSheet.absoluteFill,
backgroundColor: '#1A1A2E',
},
topBar: {
@@ -334,7 +334,7 @@ const styles = StyleSheet.create({
letterSpacing: 0.3,
},
fullScreenVideo: {
- ...StyleSheet.absoluteFillObject,
+ ...StyleSheet.absoluteFill,
backgroundColor: '#1A1A2E',
},
localVideoContainer: {
diff --git a/src/components/call/CallScreen.web.tsx b/src/components/call/CallScreen.web.tsx
index 1c2b53c..d78610c 100644
--- a/src/components/call/CallScreen.web.tsx
+++ b/src/components/call/CallScreen.web.tsx
@@ -252,12 +252,12 @@ const CallScreen: React.FC = () => {
const styles = StyleSheet.create({
container: {
- ...StyleSheet.absoluteFillObject,
+ ...StyleSheet.absoluteFill,
backgroundColor: '#1A1A2E',
zIndex: 9999,
},
background: {
- ...StyleSheet.absoluteFillObject,
+ ...StyleSheet.absoluteFill,
backgroundColor: '#1A1A2E',
},
topBar: {
@@ -319,7 +319,7 @@ const styles = StyleSheet.create({
letterSpacing: 0.3,
},
fullScreenVideo: {
- ...StyleSheet.absoluteFillObject,
+ ...StyleSheet.absoluteFill,
backgroundColor: '#1A1A2E',
},
localVideoContainer: {
diff --git a/src/components/common/AdaptiveLayout.tsx b/src/components/common/AdaptiveLayout.tsx
index d6a145a..1bb6a37 100644
--- a/src/components/common/AdaptiveLayout.tsx
+++ b/src/components/common/AdaptiveLayout.tsx
@@ -346,7 +346,7 @@ const styles = StyleSheet.create({
flexDirection: 'row',
},
overlayTouchable: {
- ...StyleSheet.absoluteFillObject,
+ ...StyleSheet.absoluteFill,
},
overlay: {
flex: 1,
diff --git a/src/components/common/ImageGallery.tsx b/src/components/common/ImageGallery.tsx
index b6d755d..8fd9049 100644
--- a/src/components/common/ImageGallery.tsx
+++ b/src/components/common/ImageGallery.tsx
@@ -548,7 +548,7 @@ const styles = StyleSheet.create({
height: SCREEN_HEIGHT * 0.8,
},
errorContainer: {
- ...StyleSheet.absoluteFillObject,
+ ...StyleSheet.absoluteFill,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#000',
diff --git a/src/components/common/ImageGrid.tsx b/src/components/common/ImageGrid.tsx
index 402fedc..6ca29a8 100644
--- a/src/components/common/ImageGrid.tsx
+++ b/src/components/common/ImageGrid.tsx
@@ -148,7 +148,7 @@ function createImageGridStyles(colors: AppColors) {
backgroundColor: colors.background.disabled,
},
moreOverlay: {
- ...StyleSheet.absoluteFillObject,
+ ...StyleSheet.absoluteFill,
backgroundColor: 'rgba(0, 0, 0, 0.4)',
justifyContent: 'center',
alignItems: 'center',
@@ -390,10 +390,12 @@ export const ImageGrid: React.FC = ({
return (
{displayImages.map((image, index) => {
- const previewUrl = usePreview && displayMode
+ const mainUri = image.uri || image.url || '';
+ const previewForSmart = usePreview && displayMode
? getPreviewImageUrl(image as any, displayMode)
- : (image.uri || image.url || '');
-
+ : '';
+ const useSmartPreview = !!(usePreview && previewForSmart && mainUri && previewForSmart !== mainUri);
+
return (
= ({
]}
>
= ({
{displayImages.map((image, index) => {
const isLastVisible = index === displayImages.length - 1;
const showOverlay = isLastVisible && remainingCount > 0 && showMoreOverlay;
-
- const previewUrl = usePreview && displayMode
+
+ const mainUri = image.uri || image.url || '';
+ const previewForSmart = usePreview && displayMode
? getPreviewImageUrl(image as any, displayMode)
- : (image.uri || image.url || '');
+ : '';
+ const useSmartPreview = !!(usePreview && previewForSmart && mainUri && previewForSmart !== mainUri);
return (
= ({
]}
>
= ({
? image.width / image.height
: 1;
const height = itemWidth / aspectRatio;
-
- const previewUrl = usePreview && displayMode
+
+ const mainUri = image.uri || image.url || '';
+ const previewForSmart = usePreview && displayMode
? getPreviewImageUrl(image as any, displayMode)
- : (image.uri || image.url || '');
+ : '';
+ const useSmartPreview = !!(usePreview && previewForSmart && mainUri && previewForSmart !== mainUri);
return (
= ({
]}
>
= ({
if (isUpgradingFromPreview.current) {
return;
}
- setLoadState('loading');
+ // 已成功加载的图片不再回到loading状态(列表回收/re-render时onLoadStart可能重新触发)
+ setLoadState(prev => (prev === 'success' ? prev : 'loading'));
}, []);
// 处理加载完成
diff --git a/src/screens/create/CreatePostScreen.tsx b/src/screens/create/CreatePostScreen.tsx
index 7c8cc83..6ee176d 100644
--- a/src/screens/create/CreatePostScreen.tsx
+++ b/src/screens/create/CreatePostScreen.tsx
@@ -1045,7 +1045,7 @@ function createCreatePostStyles(colors: AppColors) {
height: '100%',
},
uploadingOverlay: {
- ...StyleSheet.absoluteFillObject,
+ ...StyleSheet.absoluteFill,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
justifyContent: 'center',
alignItems: 'center',
diff --git a/src/screens/home/HomeScreen.tsx b/src/screens/home/HomeScreen.tsx
index d7551ae..ba0cfe4 100644
--- a/src/screens/home/HomeScreen.tsx
+++ b/src/screens/home/HomeScreen.tsx
@@ -902,6 +902,7 @@ export const HomeScreen: React.FC = () => {
setShowSearch(false)}
+ homeTab={homeTab}
/>
);
diff --git a/src/screens/home/MarketView.tsx b/src/screens/home/MarketView.tsx
index aa9ff28..1dfb4c5 100644
--- a/src/screens/home/MarketView.tsx
+++ b/src/screens/home/MarketView.tsx
@@ -27,7 +27,7 @@ function createMarketStyles(colors: AppColors, gap: number, padding: number) {
},
listContent: {
paddingHorizontal: padding,
- paddingTop: gap / 2,
+ paddingTop: padding,
paddingBottom: 80,
},
});
diff --git a/src/screens/home/SearchScreen.tsx b/src/screens/home/SearchScreen.tsx
index 8d57b50..aee243c 100644
--- a/src/screens/home/SearchScreen.tsx
+++ b/src/screens/home/SearchScreen.tsx
@@ -18,34 +18,42 @@ import { useRouter } from 'expo-router';
import { MaterialCommunityIcons } from '@expo/vector-icons';
import { spacing, fontSizes, borderRadius, useAppColors, type AppColors } from '../../theme';
import { Post, User } from '../../types';
+import type { TradeItemDTO } from '../../types/trade';
import { useUserStore } from '../../stores';
import { postService, authService } from '../../services';
+import { tradeService } from '../../services/trade/tradeService';
import { postSyncService } from '@/services/post';
import { PostCard, TabBar, SearchBar } from '../../components/business';
+import { TradeCard } from '../../components/business/TradeCard/TradeCard';
import type { PostCardAction } from '../../components/business/PostCard';
import { Avatar, EmptyState, Text, ResponsiveGrid, Loading } from '../../components/common';
import * as hrefs from '../../navigation/hrefs';
import { useResponsive, useResponsiveSpacing, useResponsiveValue } from '../../hooks';
import { useCursorPagination } from '../../hooks/useCursorPagination';
-const TABS = ['帖子', '用户'];
+const SQUARE_TABS = ['帖子', '用户'];
+const MARKET_TABS = ['商品', '用户'];
const DEFAULT_PAGE_SIZE = 20;
// 与 TabsLayout 中的常量保持一致:tabBarHeight 56 + 上下浮动间距 12*2
const FLOATING_TAB_BAR_HEIGHT = 56 + 12 * 2;
-type SearchType = 'posts' | 'users';
+type SearchType = 'posts' | 'users' | 'trades';
interface SearchScreenProps {
onBack?: () => void;
+ homeTab?: 'square' | 'market';
}
-export const SearchScreen: React.FC = ({ onBack }) => {
+export const SearchScreen: React.FC = ({ onBack, homeTab = 'square' }) => {
const colors = useAppColors();
const styles = useMemo(() => createSearchScreenStyles(colors), [colors]);
const router = useRouter();
const insets = useSafeAreaInsets();
const history = useUserStore((state) => state.searchHistory);
const { addSearchHistory, clearSearchHistory } = useUserStore.getState();
+
+ const isMarket = homeTab === 'market';
+ const TABS = isMarket ? MARKET_TABS : SQUARE_TABS;
// 使用响应式 hook
const {
@@ -115,6 +123,10 @@ export const SearchScreen: React.FC = ({ onBack }) => {
const [userResults, setUserResults] = useState([]);
const [userLoading, setUserLoading] = useState(false);
+ // 市集搜索结果
+ const [tradeResults, setTradeResults] = useState([]);
+ const [tradeLoading, setTradeLoading] = useState(false);
+
const refreshRef = useRef(refresh);
refreshRef.current = refresh;
const resetRef = useRef(reset);
@@ -143,14 +155,21 @@ export const SearchScreen: React.FC = ({ onBack }) => {
try {
const searchType = getSearchType();
-
+
if (searchType === 'users') {
setUserLoading(true);
const usersResponse = await authService.searchUsers(trimmedKeyword, 1, 20);
setUserResults(usersResponse.list || []);
+ } else if (searchType === 'trades') {
+ setTradeLoading(true);
+ const tradeResponse = await tradeService.getTradeItems({ keyword: trimmedKeyword, page_size: DEFAULT_PAGE_SIZE });
+ setTradeResults(tradeResponse.list || []);
}
} catch (error) {
console.error('搜索失败:', error);
+ } finally {
+ setUserLoading(false);
+ setTradeLoading(false);
}
setHasSearched(true);
@@ -219,6 +238,13 @@ export const SearchScreen: React.FC = ({ onBack }) => {
// 获取当前搜索类型
const getSearchType = (): SearchType => {
+ if (isMarket) {
+ switch (activeIndex) {
+ case 0: return 'trades';
+ case 1: return 'users';
+ default: return 'trades';
+ }
+ }
switch (activeIndex) {
case 0: return 'posts';
case 1: return 'users';
@@ -426,18 +452,54 @@ export const SearchScreen: React.FC = ({ onBack }) => {
);
};
+ // 渲染市集搜索结果
+ const renderTradeResults = () => {
+ if (tradeResults.length === 0 && !tradeLoading) {
+ return (
+
+ );
+ }
+
+ return (
+ (
+
+ router.push(`/trade/${id}` as any)}
+ />
+
+ )}
+ keyExtractor={item => item.id}
+ contentContainerStyle={{ paddingVertical: responsiveGap, paddingBottom: listBottomInset }}
+ showsVerticalScrollIndicator={false}
+ ListFooterComponent={tradeLoading ? : null}
+ />
+ );
+ };
+
// 渲染搜索结果
const renderSearchResults = () => {
const searchType = getSearchType();
-
+
if (searchType === 'posts') {
return renderPostResults();
}
-
+
if (searchType === 'users') {
return renderUserResults();
}
-
+
+ if (searchType === 'trades') {
+ return renderTradeResults();
+ }
+
return null;
};
@@ -517,7 +579,7 @@ export const SearchScreen: React.FC = ({ onBack }) => {
value={searchText}
onChangeText={setSearchText}
onSubmit={handleSearch}
- placeholder="搜索帖子、用户"
+ placeholder={isMarket ? "搜索商品、用户" : "搜索帖子、用户"}
autoFocus
/>
@@ -548,7 +610,7 @@ export const SearchScreen: React.FC = ({ onBack }) => {
}
}}
variant="modern"
- icons={['file-document-outline', 'account-outline']}
+ icons={isMarket ? ['shopping-outline', 'account-outline'] : ['file-document-outline', 'account-outline']}
/>
diff --git a/src/screens/message/ChatScreen.tsx b/src/screens/message/ChatScreen.tsx
index e432f1e..ac8360a 100644
--- a/src/screens/message/ChatScreen.tsx
+++ b/src/screens/message/ChatScreen.tsx
@@ -27,11 +27,11 @@ import {
Platform,
TouchableOpacity,
BackHandler,
+ StatusBar,
} from 'react-native';
import { FlashList, ListRenderItem } from '@shopify/flash-list';
import { MaterialCommunityIcons } from '@expo/vector-icons';
import { useNavigation, useRouter } from 'expo-router';
-import { StatusBar } from 'expo-status-bar';
import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';
import { Text, ImageGallery, ImageGridItem } from '../../components/common';
import { useAppColors, useResolvedColorScheme } from '../../theme';
@@ -478,7 +478,7 @@ export const ChatScreen: React.FC = (props) => {
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
keyboardVerticalOffset={Platform.OS === 'ios' ? 0 : 0}
>
- {!props.isEmbedded && }
+ {!props.isEmbedded && }
{/* 顶部栏 */}
= ({
function createGroupInfoPanelStyles(colors: AppColors) {
return StyleSheet.create({
overlay: {
- ...StyleSheet.absoluteFillObject,
+ ...StyleSheet.absoluteFill,
backgroundColor: 'rgba(0, 0, 0, 0.3)',
zIndex: 100,
},
diff --git a/src/screens/message/components/ChatScreen/GroupInfoPanel.web.tsx b/src/screens/message/components/ChatScreen/GroupInfoPanel.web.tsx
index 306eac1..645ffd4 100644
--- a/src/screens/message/components/ChatScreen/GroupInfoPanel.web.tsx
+++ b/src/screens/message/components/ChatScreen/GroupInfoPanel.web.tsx
@@ -379,7 +379,7 @@ export const GroupInfoPanel: React.FC = ({
function createGroupInfoPanelStyles(colors: AppColors) {
return StyleSheet.create({
overlay: {
- ...StyleSheet.absoluteFillObject,
+ ...StyleSheet.absoluteFill,
backgroundColor: 'rgba(0, 0, 0, 0.35)',
zIndex: 100,
},
diff --git a/src/screens/message/components/ChatScreen/styles.ts b/src/screens/message/components/ChatScreen/styles.ts
index df4acc2..54c7925 100644
--- a/src/screens/message/components/ChatScreen/styles.ts
+++ b/src/screens/message/components/ChatScreen/styles.ts
@@ -551,7 +551,7 @@ export function createChatScreenStyles(colors: AppColors, dynamicStyles?: {
// 输入框@高亮
inputHighlightOverlay: {
- ...StyleSheet.absoluteFillObject,
+ ...StyleSheet.absoluteFill,
flexDirection: 'row',
flexWrap: 'wrap',
paddingTop: 8,
@@ -1072,7 +1072,7 @@ export function createChatScreenStyles(colors: AppColors, dynamicStyles?: {
// 遮罩层
overlay: {
- ...StyleSheet.absoluteFillObject,
+ ...StyleSheet.absoluteFill,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
alignItems: 'center',
justifyContent: 'center',
@@ -1142,7 +1142,7 @@ export function createChatScreenStyles(colors: AppColors, dynamicStyles?: {
justifyContent: 'flex-end',
},
manageModalBackdrop: {
- ...StyleSheet.absoluteFillObject,
+ ...StyleSheet.absoluteFill,
backgroundColor: 'rgba(0, 0, 0, 0.4)',
},
manageModalHandle: {
@@ -1165,7 +1165,7 @@ export function createChatScreenStyles(colors: AppColors, dynamicStyles?: {
borderColor: colors.chat.replyBorder,
},
stickerCheckOverlay: {
- ...StyleSheet.absoluteFillObject,
+ ...StyleSheet.absoluteFill,
backgroundColor: 'rgba(127, 182, 230, 0.14)',
alignItems: 'flex-end',
justifyContent: 'flex-start',
diff --git a/src/screens/profile/EditProfileScreen.tsx b/src/screens/profile/EditProfileScreen.tsx
index ed3f333..2de1621 100644
--- a/src/screens/profile/EditProfileScreen.tsx
+++ b/src/screens/profile/EditProfileScreen.tsx
@@ -68,7 +68,7 @@ function createEditProfileStyles(colors: AppColors) {
alignItems: 'center',
},
coverOverlay: {
- ...StyleSheet.absoluteFillObject,
+ ...StyleSheet.absoluteFill,
backgroundColor: 'rgba(0, 0, 0, 0.4)',
justifyContent: 'center',
alignItems: 'center',
diff --git a/src/screens/schedule/CourseDetailScreen.tsx b/src/screens/schedule/CourseDetailScreen.tsx
index fdaf7da..2d5f48e 100644
--- a/src/screens/schedule/CourseDetailScreen.tsx
+++ b/src/screens/schedule/CourseDetailScreen.tsx
@@ -198,7 +198,7 @@ const CourseDetailScreen: React.FC = () => {
return (
- router.back()} />
+ router.back()} />
);
@@ -207,7 +207,7 @@ const CourseDetailScreen: React.FC = () => {
return (
- router.back()} />
+ router.back()} />
diff --git a/src/screens/trade/CreateTradeScreen.tsx b/src/screens/trade/CreateTradeScreen.tsx
index e1a846b..58b7236 100644
--- a/src/screens/trade/CreateTradeScreen.tsx
+++ b/src/screens/trade/CreateTradeScreen.tsx
@@ -259,7 +259,7 @@ function createStyles(colors: AppColors) {
backgroundColor: colors.background.default,
},
uploadingOverlay: {
- ...StyleSheet.absoluteFillObject,
+ ...StyleSheet.absoluteFill,
backgroundColor: 'rgba(0,0,0,0.3)',
alignItems: 'center',
justifyContent: 'center',
diff --git a/src/stores/message/MessageManager.ts b/src/stores/message/MessageManager.ts
index 9a6ebc2..c95666b 100644
--- a/src/stores/message/MessageManager.ts
+++ b/src/stores/message/MessageManager.ts
@@ -208,7 +208,7 @@ class MessageManager {
return this.syncService.loadMoreMessages(conversationId, beforeSeq, limit);
}
- async fetchUnreadCount(): Promise<{ totalUnread: number; systemUnread: number }> {
+ async fetchUnreadCount(): Promise {
return this.syncService.fetchUnreadCount();
}
diff --git a/src/stores/message/services/MessageSyncService.ts b/src/stores/message/services/MessageSyncService.ts
index bb51339..d7da4fb 100644
--- a/src/stores/message/services/MessageSyncService.ts
+++ b/src/stores/message/services/MessageSyncService.ts
@@ -30,7 +30,7 @@ export class MessageSyncService implements IMessageSyncService {
/** 正在加载会话列表下一页 */
private loadingMoreConversations = false;
/** fetchUnreadCount 去重:复用 in-flight promise */
- private fetchUnreadCountPromise: Promise<{ totalUnread: number; systemUnread: number }> | null = null;
+ private fetchUnreadCountPromise: Promise | null = null;
constructor(
getCurrentUserId: () => string | null,
@@ -352,20 +352,19 @@ export class MessageSyncService implements IMessageSyncService {
/**
* 获取未读数(去重:复用 in-flight promise)
*/
- async fetchUnreadCount(): Promise<{ totalUnread: number; systemUnread: number }> {
+ async fetchUnreadCount(): Promise {
if (this.fetchUnreadCountPromise) {
return this.fetchUnreadCountPromise;
}
this.fetchUnreadCountPromise = this.doFetchUnreadCount();
try {
- const result = await this.fetchUnreadCountPromise;
- return result;
+ await this.fetchUnreadCountPromise;
} finally {
this.fetchUnreadCountPromise = null;
}
}
- private async doFetchUnreadCount(): Promise<{ totalUnread: number; systemUnread: number }> {
+ private async doFetchUnreadCount(): Promise {
const store = useMessageStore.getState();
try {
@@ -393,10 +392,8 @@ export class MessageSyncService implements IMessageSyncService {
// 服务端汇总未读为 0:不主动清零本地未读,等 fetchConversations 提供权威数据
// 避免后端缓存竞态导致的未读数抖动
- return { totalUnread, systemUnread };
} catch (error) {
console.error('[MessageSyncService] 获取未读数失败:', error);
- return { totalUnread: 0, systemUnread: 0 };
}
}