This commit is contained in:
imeepos
2026-01-28 19:05:25 +08:00
parent 7f84a348a7
commit 6fc87d59de
5 changed files with 369 additions and 103 deletions

View File

@@ -25,6 +25,9 @@ import { useTemplateFilter } from '@/hooks/use-template-filter'
import { useUserBalance } from '@/hooks/use-user-balance' import { useUserBalance } from '@/hooks/use-user-balance'
import { useTemplateLike, useTemplateFavorite } from '@/hooks' import { useTemplateLike, useTemplateFavorite } from '@/hooks'
import { useTemplateSocialStore } from '@/stores/templateSocialStore' import { useTemplateSocialStore } from '@/stores/templateSocialStore'
import { root } from '@repo/core'
import { TemplateSocialController } from '@repo/sdk'
import { handleError } from '@/hooks/use-error'
const NUM_COLUMNS = 3 const NUM_COLUMNS = 3
const HORIZONTAL_PADDING = 16 const HORIZONTAL_PADDING = 16
@@ -108,6 +111,21 @@ export default function HomeScreen() {
} }
}, [params.categoryId]) }, [params.categoryId])
// 同步模板的点赞数量到 store用于初始化 store 中的数据)
useEffect(() => {
if (filteredTemplates.length > 0) {
const likeCountMap: Record<string, number> = {}
filteredTemplates.forEach(template => {
if (template.id && 'likeCount' in template && template.likeCount !== undefined) {
likeCountMap[template.id] = template.likeCount
}
})
if (Object.keys(likeCountMap).length > 0) {
setLikeCountStates(likeCountMap)
}
}
}, [filteredTemplates, setLikeCountStates])
// 状态判断 - 使用 useMemo 缓存 // 状态判断 - 使用 useMemo 缓存
// 统一 loading 状态:只要有任何一个在加载,就显示 loading // 统一 loading 状态:只要有任何一个在加载,就显示 loading
const isLoading = useMemo(() => const isLoading = useMemo(() =>
@@ -154,35 +172,72 @@ export default function HomeScreen() {
}), [router]) }), [router])
// 使用 Store 中的点赞/收藏状态 // 使用 Store 中的点赞/收藏状态
const { setLiked, setFavorited } = useTemplateSocialStore() const { setLiked, setFavorited, incrementLikeCount, decrementLikeCount, setLikeCountStates } = useTemplateSocialStore()
// 获取 social controller
const getSocialController = useCallback(() => {
return root.get(TemplateSocialController)
}, [])
// 点赞处理 // 点赞处理
const handleLike = useCallback((id: string) => { const handleLike = useCallback(async (id: string) => {
const currentState = setLiked(id, true) // 乐观更新 setLiked(id, true) // 乐观更新状态
// TODO: 调用 API incrementLikeCount(id) // 乐观更新数量
console.log('Like template:', id) try {
}, [setLiked]) const social = getSocialController()
await handleError(() => social.like({ templateId: id }))
console.log('Liked template:', id)
} catch (e) {
// 失败时回滚状态
setLiked(id, false)
decrementLikeCount(id)
console.error('Like failed:', e)
}
}, [setLiked, incrementLikeCount, decrementLikeCount, getSocialController])
// 取消点赞处理 // 取消点赞处理
const handleUnlike = useCallback((id: string) => { const handleUnlike = useCallback(async (id: string) => {
const currentState = setLiked(id, false) // 乐观更新 setLiked(id, false) // 乐观更新状态
// TODO: 调用 API decrementLikeCount(id) // 乐观更新数量
console.log('Unlike template:', id) try {
}, [setLiked]) const social = getSocialController()
await handleError(() => social.unlike({ templateId: id }))
console.log('Unliked template:', id)
} catch (e) {
// 失败时回滚状态
setLiked(id, true)
incrementLikeCount(id)
console.error('Unlike failed:', e)
}
}, [setLiked, incrementLikeCount, decrementLikeCount, getSocialController])
// 收藏处理 // 收藏处理
const handleFavorite = useCallback((id: string) => { const handleFavorite = useCallback(async (id: string) => {
const currentState = setFavorited(id, true) // 乐观更新 setFavorited(id, true) // 乐观更新
// TODO: 调用 API try {
console.log('Favorite template:', id) const social = getSocialController()
}, [setFavorited]) await handleError(() => social.favorite({ templateId: id }))
console.log('Favorited template:', id)
} catch (e) {
// 失败时回滚状态
setFavorited(id, false)
console.error('Favorite failed:', e)
}
}, [setFavorited, getSocialController])
// 取消收藏处理 // 取消收藏处理
const handleUnfavorite = useCallback((id: string) => { const handleUnfavorite = useCallback(async (id: string) => {
const currentState = setFavorited(id, false) // 乐观更新 setFavorited(id, false) // 乐观更新
// TODO: 调用 API try {
console.log('Unfavorite template:', id) const social = getSocialController()
}, [setFavorited]) await handleError(() => social.unfavorite({ templateId: id }))
console.log('Unfavorited template:', id)
} catch (e) {
// 失败时回滚状态
setFavorited(id, true)
console.error('Unfavorite failed:', e)
}
}, [setFavorited, getSocialController])
// 渲染模板卡片 // 渲染模板卡片
const renderTemplateItem = useCallback(({ item }: { item: typeof filteredTemplates[0] }) => { const renderTemplateItem = useCallback(({ item }: { item: typeof filteredTemplates[0] }) => {
@@ -200,6 +255,7 @@ export default function HomeScreen() {
onPress={handleTemplatePress} onPress={handleTemplatePress}
liked={'isLiked' in item ? item.isLiked : undefined} liked={'isLiked' in item ? item.isLiked : undefined}
favorited={'isFavorited' in item ? item.isFavorited : undefined} favorited={'isFavorited' in item ? item.isFavorited : undefined}
likeCount={'likeCount' in item ? item.likeCount : undefined}
onLike={handleLike} onLike={handleLike}
onUnlike={handleUnlike} onUnlike={handleUnlike}
onFavorite={handleFavorite} onFavorite={handleFavorite}

View File

@@ -18,6 +18,9 @@ import ErrorState from '@/components/ErrorState'
import LoadingState from '@/components/LoadingState' import LoadingState from '@/components/LoadingState'
import { useUserFavorites } from '@/hooks/use-user-favorites' import { useUserFavorites } from '@/hooks/use-user-favorites'
import { useTemplateSocialStore } from '@/stores/templateSocialStore' import { useTemplateSocialStore } from '@/stores/templateSocialStore'
import { root } from '@repo/core'
import { TemplateSocialController } from '@repo/sdk'
import { handleError } from '@/hooks/use-error'
const NUM_COLUMNS = 2 const NUM_COLUMNS = 2
const HORIZONTAL_PADDING = 16 const HORIZONTAL_PADDING = 16
@@ -36,7 +39,7 @@ export default function FavoritesScreen() {
const router = useRouter() const router = useRouter()
// 使用 Store 中的点赞/收藏状态 // 使用 Store 中的点赞/收藏状态
const { setLiked, setFavorited } = useTemplateSocialStore() const { setLiked, setFavorited, incrementLikeCount, decrementLikeCount } = useTemplateSocialStore()
// 获取收藏列表 // 获取收藏列表
const { const {
@@ -86,27 +89,56 @@ export default function FavoritesScreen() {
}) })
}, [router]) }, [router])
// 点赞/取消点赞处理 // 获取 social controller
const handleLike = useCallback((id: string) => { const getSocialController = useCallback(() => {
setLiked(id, true) return root.get(TemplateSocialController)
console.log('Like template:', id) }, [])
}, [setLiked])
const handleUnlike = useCallback((id: string) => { // 点赞/取消点赞处理
const handleLike = useCallback(async (id: string) => {
setLiked(id, true)
incrementLikeCount(id)
try {
const social = getSocialController()
await handleError(() => social.like({ templateId: id }))
} catch (e) {
setLiked(id, false)
decrementLikeCount(id)
}
}, [setLiked, incrementLikeCount, decrementLikeCount, getSocialController])
const handleUnlike = useCallback(async (id: string) => {
setLiked(id, false) setLiked(id, false)
console.log('Unlike template:', id) decrementLikeCount(id)
}, [setLiked]) try {
const social = getSocialController()
await handleError(() => social.unlike({ templateId: id }))
} catch (e) {
setLiked(id, true)
incrementLikeCount(id)
}
}, [setLiked, incrementLikeCount, decrementLikeCount, getSocialController])
// 收藏/取消收藏处理 // 收藏/取消收藏处理
const handleFavorite = useCallback((id: string) => { const handleFavorite = useCallback(async (id: string) => {
setFavorited(id, true) setFavorited(id, true)
console.log('Favorite template:', id) try {
}, [setFavorited]) const social = getSocialController()
await handleError(() => social.favorite({ templateId: id }))
} catch (e) {
setFavorited(id, false)
}
}, [setFavorited, getSocialController])
const handleUnfavorite = useCallback((id: string) => { const handleUnfavorite = useCallback(async (id: string) => {
setFavorited(id, false) setFavorited(id, false)
console.log('Unfavorite template:', id) try {
}, [setFavorited]) const social = getSocialController()
await handleError(() => social.unfavorite({ templateId: id }))
} catch (e) {
setFavorited(id, true)
}
}, [setFavorited, getSocialController])
// 状态判断 // 状态判断
const isLoading = useMemo(() => loading, [loading]) const isLoading = useMemo(() => loading, [loading])
@@ -137,6 +169,7 @@ export default function FavoritesScreen() {
onPress={handleTemplatePress} onPress={handleTemplatePress}
liked={template.isLiked} liked={template.isLiked}
favorited={template.isFavorited} favorited={template.isFavorited}
likeCount={template.likeCount}
onLike={handleLike} onLike={handleLike}
onUnlike={handleUnlike} onUnlike={handleUnlike}
onFavorite={handleFavorite} onFavorite={handleFavorite}

View File

@@ -18,6 +18,9 @@ import ErrorState from '@/components/ErrorState'
import LoadingState from '@/components/LoadingState' import LoadingState from '@/components/LoadingState'
import { useUserLikes } from '@/hooks' import { useUserLikes } from '@/hooks'
import { useTemplateSocialStore } from '@/stores/templateSocialStore' import { useTemplateSocialStore } from '@/stores/templateSocialStore'
import { root } from '@repo/core'
import { TemplateSocialController } from '@repo/sdk'
import { handleError } from '@/hooks/use-error'
const NUM_COLUMNS = 2 const NUM_COLUMNS = 2
const HORIZONTAL_PADDING = 16 const HORIZONTAL_PADDING = 16
@@ -37,7 +40,7 @@ export default function LikesScreen() {
const [refreshing, setRefreshing] = useState(false) const [refreshing, setRefreshing] = useState(false)
// 使用 Store 中的点赞/收藏状态 // 使用 Store 中的点赞/收藏状态
const { setLiked, setFavorited } = useTemplateSocialStore() const { setLiked, setFavorited, incrementLikeCount, decrementLikeCount } = useTemplateSocialStore()
// 获取用户点赞列表 // 获取用户点赞列表
const { const {
@@ -78,27 +81,56 @@ export default function LikesScreen() {
}) })
}, [router]) }, [router])
// 点赞/取消点赞处理 // 获取 social controller
const handleLike = useCallback((id: string) => { const getSocialController = useCallback(() => {
setLiked(id, true) return root.get(TemplateSocialController)
console.log('Like template:', id) }, [])
}, [setLiked])
const handleUnlike = useCallback((id: string) => { // 点赞/取消点赞处理
const handleLike = useCallback(async (id: string) => {
setLiked(id, true)
incrementLikeCount(id)
try {
const social = getSocialController()
await handleError(() => social.like({ templateId: id }))
} catch (e) {
setLiked(id, false)
decrementLikeCount(id)
}
}, [setLiked, incrementLikeCount, decrementLikeCount, getSocialController])
const handleUnlike = useCallback(async (id: string) => {
setLiked(id, false) setLiked(id, false)
console.log('Unlike template:', id) decrementLikeCount(id)
}, [setLiked]) try {
const social = getSocialController()
await handleError(() => social.unlike({ templateId: id }))
} catch (e) {
setLiked(id, true)
incrementLikeCount(id)
}
}, [setLiked, incrementLikeCount, decrementLikeCount, getSocialController])
// 收藏/取消收藏处理 // 收藏/取消收藏处理
const handleFavorite = useCallback((id: string) => { const handleFavorite = useCallback(async (id: string) => {
setFavorited(id, true) setFavorited(id, true)
console.log('Favorite template:', id) try {
}, [setFavorited]) const social = getSocialController()
await handleError(() => social.favorite({ templateId: id }))
} catch (e) {
setFavorited(id, false)
}
}, [setFavorited, getSocialController])
const handleUnfavorite = useCallback((id: string) => { const handleUnfavorite = useCallback(async (id: string) => {
setFavorited(id, false) setFavorited(id, false)
console.log('Unfavorite template:', id) try {
}, [setFavorited]) const social = getSocialController()
await handleError(() => social.unfavorite({ templateId: id }))
} catch (e) {
setFavorited(id, true)
}
}, [setFavorited, getSocialController])
// 状态判断 // 状态判断
const showEmptyState = useMemo(() => const showEmptyState = useMemo(() =>
@@ -133,6 +165,7 @@ export default function LikesScreen() {
onPress={handleTemplatePress} onPress={handleTemplatePress}
liked={item.template.isLiked} liked={item.template.isLiked}
favorited={item.template.isFavorited} favorited={item.template.isFavorited}
likeCount={item.template.likeCount}
onLike={handleLike} onLike={handleLike}
onUnlike={handleUnlike} onUnlike={handleUnlike}
onFavorite={handleFavorite} onFavorite={handleFavorite}

View File

@@ -4,7 +4,7 @@ import { Image } from 'expo-image'
import { LinearGradient } from 'expo-linear-gradient' import { LinearGradient } from 'expo-linear-gradient'
import { Ionicons } from '@expo/vector-icons' import { Ionicons } from '@expo/vector-icons'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useTemplateSocialStore } from '@/stores/templateSocialStore' import { useTemplateSocialStore, useTemplateLiked, useTemplateFavorited, useTemplateLikeCount } from '@/stores/templateSocialStore'
export interface TemplateCardProps { export interface TemplateCardProps {
id?: string id?: string
@@ -18,6 +18,7 @@ export interface TemplateCardProps {
onPress: (id: string) => void onPress: (id: string) => void
liked?: boolean liked?: boolean
favorited?: boolean favorited?: boolean
likeCount?: number
onLike?: (id: string) => void onLike?: (id: string) => void
onUnlike?: (id: string) => void onUnlike?: (id: string) => void
onFavorite?: (id: string) => void onFavorite?: (id: string) => void
@@ -51,6 +52,23 @@ export function getImageUri(
return webpPreviewUrl || previewUrl || coverImageUrl return webpPreviewUrl || previewUrl || coverImageUrl
} }
/**
* 格式化数字显示
* 1000以下: 显示原数字
* 1000-9999: 1.2k
* 10000-99999: 1w
* 100000以上: 10w
*/
export function formatCount(count: number): string {
if (count < 1000) {
return count.toString()
}
if (count < 10000) {
return `${(count / 1000).toFixed(1).replace(/\.0$/, '')}k`
}
return `${(count / 10000).toFixed(1).replace(/\.0$/, '')}w`
}
// 渐变颜色常量,避免每次渲染创建新数组 // 渐变颜色常量,避免每次渲染创建新数组
const GRADIENT_COLORS = ['rgba(17, 17, 17, 0)', 'rgba(17, 17, 17, 0.9)'] as const const GRADIENT_COLORS = ['rgba(17, 17, 17, 0)', 'rgba(17, 17, 17, 0.9)'] as const
const GRADIENT_START = { x: 0, y: 0 } const GRADIENT_START = { x: 0, y: 0 }
@@ -68,6 +86,7 @@ const TemplateCardComponent: React.FC<TemplateCardProps> = ({
onPress, onPress,
liked: likedProp, liked: likedProp,
favorited: favoritedProp, favorited: favoritedProp,
likeCount: likeCountProp,
onLike, onLike,
onUnlike, onUnlike,
onFavorite, onFavorite,
@@ -76,12 +95,16 @@ const TemplateCardComponent: React.FC<TemplateCardProps> = ({
}) => { }) => {
const { i18n } = useTranslation() const { i18n } = useTranslation()
// 获取 Store 中的状态(用于本地状态覆盖) // 订阅特定模板的点赞/收藏状态和点赞数量
const { isLiked: isLikedInStore, isFavorited: isFavoritedInStore } = useTemplateSocialStore() // 当该模板的状态变化时才会触发重新渲染,不影响其他卡片
const storeLiked = useTemplateLiked(id)
const storeFavorited = useTemplateFavorited(id)
const storeLikeCount = useTemplateLikeCount(id)
// 合并 props 状态和 store 状态store 优先(乐观更新) // 合并 props 状态和 store 状态store 优先(乐观更新)
const liked = id !== undefined ? isLikedInStore(id) ?? likedProp : likedProp const liked = storeLiked ?? likedProp
const favorited = id !== undefined ? isFavoritedInStore(id) ?? favoritedProp : favoritedProp const favorited = storeFavorited ?? favoritedProp
const likeCount = storeLikeCount ?? likeCountProp
const aspectRatio = useMemo(() => parseAspectRatio(aspectRatioString), [aspectRatioString]) const aspectRatio = useMemo(() => parseAspectRatio(aspectRatioString), [aspectRatioString])
const imageUri = useMemo(() => getImageUri(webpPreviewUrl, previewUrl, coverImageUrl), [webpPreviewUrl, previewUrl, coverImageUrl]) const imageUri = useMemo(() => getImageUri(webpPreviewUrl, previewUrl, coverImageUrl), [webpPreviewUrl, previewUrl, coverImageUrl])
@@ -179,7 +202,12 @@ const TemplateCardComponent: React.FC<TemplateCardProps> = ({
hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }} hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
testID={`${testID}-like-button`} testID={`${testID}-like-button`}
> >
<Ionicons name={likeIconName} size={16} color={likeIconColor} style={styles.icon} /> <View style={styles.likeButtonContainer}>
<Ionicons name={likeIconName} size={16} color={likeIconColor} style={styles.icon} />
{likeCount !== undefined && likeCount > 0 && (
<Text style={styles.likeCount}>{formatCount(likeCount)}</Text>
)}
</View>
</Pressable> </Pressable>
<Pressable <Pressable
onPress={(e) => { onPress={(e) => {
@@ -196,7 +224,12 @@ const TemplateCardComponent: React.FC<TemplateCardProps> = ({
) : ( ) : (
// 没有回调时显示为静态图标 // 没有回调时显示为静态图标
<View style={styles.iconsContainer}> <View style={styles.iconsContainer}>
<Ionicons name={likeIconName} size={16} color={likeIconColor} style={styles.icon} /> <View style={styles.likeButtonContainer}>
<Ionicons name={likeIconName} size={16} color={likeIconColor} style={styles.icon} />
{likeCount !== undefined && likeCount > 0 && (
<Text style={styles.likeCount}>{formatCount(likeCount)}</Text>
)}
</View>
<Ionicons name={favoriteIconName} size={16} color={favoriteIconColor} style={styles.icon} /> <Ionicons name={favoriteIconName} size={16} color={favoriteIconColor} style={styles.icon} />
</View> </View>
)} )}
@@ -238,6 +271,11 @@ const styles = StyleSheet.create({
flexDirection: 'row', flexDirection: 'row',
gap: 4, gap: 4,
}, },
likeButtonContainer: {
flexDirection: 'row',
alignItems: 'center',
gap: 2,
},
iconButton: { iconButton: {
padding: 4, padding: 4,
}, },
@@ -248,6 +286,15 @@ const styles = StyleSheet.create({
shadowRadius: 2, shadowRadius: 2,
elevation: 2, elevation: 2,
}, },
likeCount: {
fontSize: 10,
fontWeight: '600',
color: '#F5F5F5',
textShadowColor: 'rgba(0, 0, 0, 0.5)',
textShadowOffset: { width: 0, height: 1 },
textShadowRadius: 2,
minWidth: 12,
},
cardTitle: { cardTitle: {
position: 'absolute', position: 'absolute',
bottom: 8, bottom: 8,

View File

@@ -1,4 +1,5 @@
import { create } from 'zustand' import { create } from 'zustand'
import { devtools } from 'zustand/middleware'
interface TemplateSocialState { interface TemplateSocialState {
// 点赞状态缓存: templateId -> boolean // 点赞状态缓存: templateId -> boolean
@@ -7,70 +8,166 @@ interface TemplateSocialState {
// 收藏状态缓存: templateId -> boolean // 收藏状态缓存: templateId -> boolean
favoritedMap: Record<string, boolean> favoritedMap: Record<string, boolean>
// 点赞数量缓存: templateId -> number
likeCountMap: Record<string, number>
// 批量更新点赞状态 // 批量更新点赞状态
setLikedStates: (states: Record<string, boolean>) => void setLikedStates: (states: Record<string, boolean>) => void
// 批量更新收藏状态 // 批量更新收藏状态
setFavoritedStates: (states: Record<string, boolean>) => void setFavoritedStates: (states: Record<string, boolean>) => void
// 批量更新点赞数量
setLikeCountStates: (states: Record<string, number>) => void
// 更新单个点赞状态 // 更新单个点赞状态
setLiked: (templateId: string, liked: boolean) => void setLiked: (templateId: string, liked: boolean) => void
// 更新单个收藏状态 // 更新单个收藏状态
setFavorited: (templateId: string, favorited: boolean) => void setFavorited: (templateId: string, favorited: boolean) => void
// 获取点赞状态 // 更新单个点赞数量
setLikeCount: (templateId: string, count: number) => void
// 增加点赞数量(乐观更新)
incrementLikeCount: (templateId: string) => void
// 减少点赞数量(乐观更新)
decrementLikeCount: (templateId: string) => void
// 获取点赞状态(如果不存在返回 undefined
getLiked: (templateId: string) => boolean | undefined
// 获取收藏状态(如果不存在返回 undefined
getFavorited: (templateId: string) => boolean | undefined
// 获取点赞数量(如果不存在返回 undefined
getLikeCount: (templateId: string) => number | undefined
// 获取点赞状态(如果不存在返回 false
isLiked: (templateId: string) => boolean isLiked: (templateId: string) => boolean
// 获取收藏状态 // 获取收藏状态(如果不存在返回 false
isFavorited: (templateId: string) => boolean isFavorited: (templateId: string) => boolean
// 清空所有缓存 // 清空所有缓存
clear: () => void clear: () => void
} }
export const useTemplateSocialStore = create<TemplateSocialState>((set, get) => ({ export const useTemplateSocialStore = create<TemplateSocialState>()(
// State devtools(
likedMap: {}, (set, get) => ({
favoritedMap: {}, // State
// Actions
setLikedStates: (states) => {
set((state) => ({
likedMap: { ...state.likedMap, ...states },
}))
},
setFavoritedStates: (states) => {
set((state) => ({
favoritedMap: { ...state.favoritedMap, ...states },
}))
},
setLiked: (templateId, liked) => {
set((state) => ({
likedMap: { ...state.likedMap, [templateId]: liked },
}))
},
setFavorited: (templateId, favorited) => {
set((state) => ({
favoritedMap: { ...state.favoritedMap, [templateId]: favorited },
}))
},
isLiked: (templateId) => {
return get().likedMap[templateId] || false
},
isFavorited: (templateId) => {
return get().favoritedMap[templateId] || false
},
clear: () => {
set({
likedMap: {}, likedMap: {},
favoritedMap: {}, favoritedMap: {},
}) likeCountMap: {},
},
})) // Actions
setLikedStates: (states) => {
set((state) => ({
likedMap: { ...state.likedMap, ...states },
}))
},
setFavoritedStates: (states) => {
set((state) => ({
favoritedMap: { ...state.favoritedMap, ...states },
}))
},
setLikeCountStates: (states) => {
set((state) => ({
likeCountMap: { ...state.likeCountMap, ...states },
}))
},
setLiked: (templateId, liked) => {
set((state) => ({
likedMap: { ...state.likedMap, [templateId]: liked },
}))
},
setFavorited: (templateId, favorited) => {
set((state) => ({
favoritedMap: { ...state.favoritedMap, [templateId]: favorited },
}))
},
setLikeCount: (templateId, count) => {
set((state) => ({
likeCountMap: { ...state.likeCountMap, [templateId]: count },
}))
},
incrementLikeCount: (templateId) => {
set((state) => ({
likeCountMap: {
...state.likeCountMap,
[templateId]: (state.likeCountMap[templateId] || 0) + 1,
},
}))
},
decrementLikeCount: (templateId) => {
set((state) => {
const currentCount = state.likeCountMap[templateId] || 0
return {
likeCountMap: {
...state.likeCountMap,
[templateId]: Math.max(0, currentCount - 1),
},
}
})
},
getLiked: (templateId) => {
return get().likedMap[templateId]
},
getFavorited: (templateId) => {
return get().favoritedMap[templateId]
},
getLikeCount: (templateId) => {
return get().likeCountMap[templateId]
},
isLiked: (templateId) => {
return get().likedMap[templateId] || false
},
isFavorited: (templateId) => {
return get().favoritedMap[templateId] || false
},
clear: () => {
set({
likedMap: {},
favoritedMap: {},
likeCountMap: {},
})
},
}),
{ name: 'TemplateSocialStore' }
)
)
// 选择器 hook只订阅特定模板的状态
// 当该模板的状态变化时才会触发重新渲染
export function useTemplateLiked(templateId: string | undefined) {
return useTemplateSocialStore((state) =>
templateId ? state.likedMap[templateId] : undefined
)
}
export function useTemplateFavorited(templateId: string | undefined) {
return useTemplateSocialStore((state) =>
templateId ? state.favoritedMap[templateId] : undefined
)
}
export function useTemplateLikeCount(templateId: string | undefined) {
return useTemplateSocialStore((state) =>
templateId ? state.likeCountMap[templateId] : undefined
)
}