feat:修改点赞接口bug
This commit is contained in:
parent
7dbcf50a39
commit
dd34def217
@ -253,7 +253,8 @@ func (p *SocialProvider) LikeAsset(ctx context.Context, req *pb.LikeAssetRequest
|
||||
)
|
||||
|
||||
// 调用业务逻辑层
|
||||
if err := p.assetLikeService.LikeAsset(ctx, req.AssetId, userID, starID); err != nil {
|
||||
likeCount, err := p.assetLikeService.LikeAsset(ctx, req.AssetId, userID, starID)
|
||||
if err != nil {
|
||||
logger.Logger.Error("Failed to like asset",
|
||||
zap.Error(err),
|
||||
zap.Int64("asset_id", req.AssetId),
|
||||
@ -274,6 +275,9 @@ func (p *SocialProvider) LikeAsset(ctx context.Context, req *pb.LikeAssetRequest
|
||||
Message: "Successfully liked asset",
|
||||
Timestamp: time.Now().UnixMilli(),
|
||||
},
|
||||
AssetId: req.AssetId,
|
||||
NewLikeCount: likeCount,
|
||||
IsLiked: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@ -30,7 +30,7 @@ func NewAssetLikeService(assetClient *client.AssetClient, socialRepo repository.
|
||||
}
|
||||
|
||||
// LikeAsset 点赞资产
|
||||
func (s *AssetLikeService) LikeAsset(ctx context.Context, assetID, userID, starID int64) error {
|
||||
func (s *AssetLikeService) LikeAsset(ctx context.Context, assetID, userID, starID int64) (int32, error) {
|
||||
logger.Logger.Debug("AssetLikeService.LikeAsset called",
|
||||
zap.Int64("asset_id", assetID),
|
||||
zap.Int64("user_id", userID),
|
||||
@ -47,7 +47,7 @@ func (s *AssetLikeService) LikeAsset(ctx context.Context, assetID, userID, starI
|
||||
zap.Error(err),
|
||||
zap.Int64("asset_id", assetID),
|
||||
)
|
||||
return fmt.Errorf("获取藏品信息失败,请稍后重试")
|
||||
return 0, fmt.Errorf("获取藏品信息失败,请稍后重试")
|
||||
}
|
||||
|
||||
if getAssetResp.Base.Code != pbCommon.StatusCode_STATUS_OK {
|
||||
@ -56,7 +56,7 @@ func (s *AssetLikeService) LikeAsset(ctx context.Context, assetID, userID, starI
|
||||
zap.Int32("code", int32(getAssetResp.Base.Code)),
|
||||
zap.String("message", getAssetResp.Base.Message),
|
||||
)
|
||||
return fmt.Errorf("藏品不存在")
|
||||
return 0, fmt.Errorf("藏品不存在")
|
||||
}
|
||||
|
||||
// 2. 检查是否已点赞
|
||||
@ -71,7 +71,7 @@ func (s *AssetLikeService) LikeAsset(ctx context.Context, assetID, userID, starI
|
||||
zap.Error(err),
|
||||
zap.Int64("asset_id", assetID),
|
||||
)
|
||||
return fmt.Errorf("点赞失败,请稍后重试")
|
||||
return 0, fmt.Errorf("点赞失败,请稍后重试")
|
||||
}
|
||||
|
||||
if checkLikeResp.IsLiked {
|
||||
@ -79,7 +79,7 @@ func (s *AssetLikeService) LikeAsset(ctx context.Context, assetID, userID, starI
|
||||
zap.Int64("asset_id", assetID),
|
||||
zap.Int64("user_id", userID),
|
||||
)
|
||||
return fmt.Errorf("当前展示已点赞")
|
||||
return 0, fmt.Errorf("当前展示已点赞")
|
||||
}
|
||||
|
||||
// 3. 调用 Asset Service 点赞接口
|
||||
@ -92,7 +92,7 @@ func (s *AssetLikeService) LikeAsset(ctx context.Context, assetID, userID, starI
|
||||
zap.Error(err),
|
||||
zap.Int64("asset_id", assetID),
|
||||
)
|
||||
return fmt.Errorf("点赞失败,请稍后重试")
|
||||
return 0, fmt.Errorf("点赞失败,请稍后重试")
|
||||
}
|
||||
|
||||
if likeResp.Base.Code != pbCommon.StatusCode_STATUS_OK {
|
||||
@ -101,19 +101,20 @@ func (s *AssetLikeService) LikeAsset(ctx context.Context, assetID, userID, starI
|
||||
zap.Int32("code", int32(likeResp.Base.Code)),
|
||||
zap.String("message", likeResp.Base.Message),
|
||||
)
|
||||
return fmt.Errorf("点赞失败: %s", likeResp.Base.Message)
|
||||
return 0, fmt.Errorf("点赞失败: %s", likeResp.Base.Message)
|
||||
}
|
||||
|
||||
logger.Logger.Info("Successfully liked asset",
|
||||
zap.Int64("asset_id", assetID),
|
||||
zap.Int64("user_id", userID),
|
||||
zap.Int64("star_id", starID),
|
||||
zap.Int32("new_like_count", likeResp.LikeCount),
|
||||
)
|
||||
|
||||
// 缓存失效
|
||||
_ = database.InvalidateAssetLikersCache(ctx, assetID)
|
||||
|
||||
return nil
|
||||
return likeResp.LikeCount, nil
|
||||
}
|
||||
|
||||
// UnlikeAsset 取消点赞资产
|
||||
|
||||
@ -30,3 +30,10 @@ REDIS_HOST=topfans-redis
|
||||
REDIS_PORT=6379
|
||||
REDIS_PASSWORD=123456
|
||||
REDIS_DB=0
|
||||
|
||||
# ==================== SMS Configuration ====================
|
||||
SMS_ACCESS_KEY_ID=LTAI5t6QcdJHpYbCPxM8SXYE
|
||||
SMS_ACCESS_KEY_SECRET=ybvjSEb7wilMt3qT5nOppYPoNVayCD
|
||||
SMS_SIGN_NAME=TopFans
|
||||
SMS_TEMPLATE_CODE=SMS_314621237
|
||||
SMS_REGION=cn-hangzhou
|
||||
|
||||
@ -120,10 +120,10 @@ RUN apk add --no-cache ca-certificates tzdata
|
||||
WORKDIR /app
|
||||
COPY --from=builder /tmp/galleryservice /app/galleryservice
|
||||
|
||||
EXPOSE 20004
|
||||
EXPOSE 20001
|
||||
|
||||
HEALTHCHECK --interval=10s --timeout=5s --start-period=10s --retries=3 \
|
||||
CMD wget --no-verbose --tries=1 --spider http://localhost:20004 || exit 1
|
||||
CMD wget --no-verbose --tries=1 --spider http://localhost:21001 || exit 1
|
||||
|
||||
ENTRYPOINT ["/app/galleryservice"]
|
||||
|
||||
@ -135,10 +135,10 @@ RUN apk add --no-cache ca-certificates tzdata
|
||||
WORKDIR /app
|
||||
COPY --from=builder /tmp/activityservice /app/activityservice
|
||||
|
||||
EXPOSE 20005
|
||||
EXPOSE 20004
|
||||
|
||||
HEALTHCHECK --interval=10s --timeout=5s --start-period=10s --retries=3 \
|
||||
CMD wget --no-verbose --tries=1 --spider http://localhost:20005 || exit 1
|
||||
CMD wget --no-verbose --tries=1 --spider http://localhost:21004 || exit 1
|
||||
|
||||
ENTRYPOINT ["/app/activityservice"]
|
||||
|
||||
@ -165,9 +165,9 @@ RUN apk add --no-cache ca-certificates tzdata
|
||||
WORKDIR /app
|
||||
COPY --from=builder /tmp/starbookservice /app/starbookservice
|
||||
|
||||
EXPOSE 20007
|
||||
EXPOSE 20005
|
||||
|
||||
HEALTHCHECK --interval=10s --timeout=5s --start-period=10s --retries=3 \
|
||||
CMD wget --no-verbose --tries=1 --spider http://localhost:21007 || exit 1
|
||||
CMD wget --no-verbose --tries=1 --spider http://localhost:21005 || exit 1
|
||||
|
||||
ENTRYPOINT ["/app/starbookservice"]
|
||||
|
||||
@ -63,12 +63,14 @@ services:
|
||||
image: redis:latest
|
||||
container_name: topfans-redis
|
||||
restart: always
|
||||
environment:
|
||||
REDIS_PASSWORD: ${REDIS_PASSWORD:-123456}
|
||||
ports:
|
||||
- "6379:6379"
|
||||
networks:
|
||||
- topfans-net
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-123456}", "ping"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
@ -117,9 +119,20 @@ services:
|
||||
DB_USER: postgres
|
||||
DB_PASSWORD: ${DB_PASSWORD:-postgres123}
|
||||
DB_NAME: topfans
|
||||
REDIS_HOST: topfans-redis
|
||||
REDIS_PORT: 6379
|
||||
REDIS_PASSWORD: ${REDIS_PASSWORD:-123456}
|
||||
REDIS_DB: 0
|
||||
SMS_ACCESS_KEY_ID: ${SMS_ACCESS_KEY_ID:-}
|
||||
SMS_ACCESS_KEY_SECRET: ${SMS_ACCESS_KEY_SECRET:-}
|
||||
SMS_SIGN_NAME: ${SMS_SIGN_NAME:-}
|
||||
SMS_TEMPLATE_CODE: ${SMS_TEMPLATE_CODE:-}
|
||||
SMS_REGION: ${SMS_REGION:-cn-hangzhou}
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- topfans-net
|
||||
expose:
|
||||
@ -276,9 +289,15 @@ services:
|
||||
DB_PASSWORD: ${DB_PASSWORD:-postgres123}
|
||||
DB_NAME: topfans
|
||||
USER_SERVICE_URL: tri://userservice:20000
|
||||
REDIS_HOST: topfans-redis
|
||||
REDIS_PORT: 6379
|
||||
REDIS_PASSWORD: ${REDIS_PASSWORD:-123456}
|
||||
REDIS_DB: 0
|
||||
depends_on:
|
||||
userservice:
|
||||
condition: service_started
|
||||
redis:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- topfans-net
|
||||
expose:
|
||||
@ -342,7 +361,7 @@ services:
|
||||
restart: always
|
||||
environment:
|
||||
<<: *common-env
|
||||
PORT: 20007
|
||||
PORT: 20005
|
||||
DB_HOST: postgres
|
||||
DB_PORT: 5432
|
||||
DB_USER: postgres
|
||||
@ -357,9 +376,9 @@ services:
|
||||
networks:
|
||||
- topfans-net
|
||||
expose:
|
||||
- "20007"
|
||||
- "20005"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:21007 || exit 1"]
|
||||
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:21005 || exit 1"]
|
||||
<<: *healthcheck
|
||||
deploy:
|
||||
resources:
|
||||
@ -391,8 +410,11 @@ services:
|
||||
DUBBO_GALLERY_SERVICE_URL: tri://galleryservice:20001
|
||||
DUBBO_ACTIVITY_SERVICE_URL: tri://activityservice:20004
|
||||
DUBBO_TASK_SERVICE_URL: tri://taskservice:20006
|
||||
DUBBO_STARBOOK_SERVICE_URL: tri://starbookservice:20007
|
||||
DUBBO_STARBOOK_SERVICE_URL: tri://starbookservice:20005
|
||||
REDIS_HOST: topfans-redis
|
||||
REDIS_PORT: 6379
|
||||
REDIS_PASSWORD: ${REDIS_PASSWORD:-123456}
|
||||
REDIS_DB: 0
|
||||
depends_on:
|
||||
userservice:
|
||||
condition: service_started
|
||||
@ -408,6 +430,8 @@ services:
|
||||
condition: service_started
|
||||
starbookservice:
|
||||
condition: service_started
|
||||
redis:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- topfans-net
|
||||
ports:
|
||||
|
||||
@ -2,6 +2,10 @@
|
||||
<view class="creation-grid">
|
||||
<view v-for="(item, index) in creationList" :key="item.id" class="creation-card" @click="handleCardClick(item)">
|
||||
<image class="creation-image" :src="item.cover_image" mode="aspectFill"></image>
|
||||
<!-- 光波动画层 - 外层 -->
|
||||
<view class="wf-like-wave wf-like-wave-outer" :class="{ 'wf-like-wave-active': likingMap[item.id] }" />
|
||||
<!-- 光波动画层 - 内层 -->
|
||||
<view class="wf-like-wave wf-like-wave-inner" :class="{ 'wf-like-wave-active': likingMap[item.id] }" />
|
||||
<view class="creation-info">
|
||||
<view class="creation-id">
|
||||
<text class="id-text">#{{ item.certificate_id }}</text>
|
||||
@ -47,6 +51,7 @@ const creationList = ref([])
|
||||
const cursor = ref('')
|
||||
const isLoading = ref(false)
|
||||
const noMore = ref(false)
|
||||
const likingMap = ref({})
|
||||
let isComponentMounted = false
|
||||
|
||||
const formatCount = (count) => {
|
||||
@ -141,11 +146,28 @@ watch(() => props.isActive, (active) => {
|
||||
|
||||
onMounted(() => {
|
||||
isComponentMounted = true
|
||||
// 监听点赞事件,实时更新点赞数
|
||||
uni.$on('assetLiked', ({ asset_id, data }) => {
|
||||
console.log('[CreationGrid] 收到点赞事件', asset_id, data)
|
||||
// 触发动画
|
||||
likingMap.value = { ...likingMap.value, [asset_id]: true }
|
||||
setTimeout(() => {
|
||||
likingMap.value = { ...likingMap.value, [asset_id]: false }
|
||||
}, 600)
|
||||
const idx = creationList.value.findIndex(c => c.id === asset_id)
|
||||
console.log('[CreationGrid] 卡片索引:', idx, '总卡片数:', creationList.value.length)
|
||||
if (idx !== -1 && data && typeof data.new_like_count === 'number') {
|
||||
console.log('[CreationGrid] 更新点赞数:', creationList.value[idx].like_count, '->', data.new_like_count)
|
||||
creationList.value[idx].like_count = data.new_like_count
|
||||
creationList.value = [...creationList.value]
|
||||
}
|
||||
})
|
||||
loadUsers()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
isComponentMounted = false
|
||||
uni.off('assetLiked')
|
||||
})
|
||||
|
||||
defineExpose({ loadMore })
|
||||
@ -168,6 +190,7 @@ defineExpose({ loadMore })
|
||||
overflow: hidden;
|
||||
backdrop-filter: blur(10rpx);
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.creation-image {
|
||||
@ -175,7 +198,44 @@ defineExpose({ loadMore })
|
||||
height: 400rpx;
|
||||
}
|
||||
|
||||
/* 光波动画 */
|
||||
.wf-like-wave {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 400rpx;
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.wf-like-wave-outer {
|
||||
background: radial-gradient(circle, rgba(255, 107, 107, 0.8) 0%, transparent 70%);
|
||||
}
|
||||
|
||||
.wf-like-wave-inner {
|
||||
background: radial-gradient(circle, rgba(255, 184, 0, 0.6) 0%, transparent 70%);
|
||||
}
|
||||
|
||||
.wf-like-wave-active {
|
||||
animation: likeWave 0.6s ease-out forwards;
|
||||
}
|
||||
|
||||
@keyframes likeWave {
|
||||
0% {
|
||||
opacity: 0.9;
|
||||
transform: scale(0.8);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: scale(1.5);
|
||||
}
|
||||
}
|
||||
|
||||
.creation-info {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
padding: 16rpx;
|
||||
}
|
||||
|
||||
|
||||
@ -918,6 +918,15 @@ onMounted(() => {
|
||||
isIOS = sysInfo.platform === 'ios'
|
||||
const containerH = props.screenHeight - props.bannerBottom
|
||||
layout = new WaterfallLayout(props.screenWidth, containerH, GAP)
|
||||
// 监听点赞事件,实时更新点赞数
|
||||
uni.$on('assetLiked', ({ asset_id, data }) => {
|
||||
const idx = cards.value.findIndex(c => c.id === asset_id)
|
||||
if (idx !== -1 && data && typeof data.likes === 'number') {
|
||||
cards.value[idx].likes = data.likes
|
||||
// 强制触发响应式更新
|
||||
cards.value = [...cards.value]
|
||||
}
|
||||
})
|
||||
loadUsers().then(() => {
|
||||
isInitialLoading = false
|
||||
nextTick(() => {
|
||||
@ -1034,6 +1043,7 @@ onUnmounted(() => {
|
||||
try {
|
||||
uni.offAppShow(onAppShowHandler)
|
||||
uni.offAppHide(onAppHideHandler)
|
||||
uni.off('assetLiked')
|
||||
} catch (_) { }
|
||||
}
|
||||
})
|
||||
|
||||
@ -97,6 +97,7 @@ import BannerCarousel from './components/BannerCarousel.vue'
|
||||
import CreationGrid from './components/CreationGrid.vue'
|
||||
import { clearSubStepProgress, shouldShowGuideStartModal } from '@/utils/guideConfig.js'
|
||||
import { useBanner } from './composables/useBanner.js'
|
||||
import { doubleTapLike } from '@/utils/likeHelper.js'
|
||||
import { USE_MOCK_DATA } from './config/mockData.js'
|
||||
|
||||
// ========== Store & User Info ==========
|
||||
@ -111,6 +112,8 @@ const showRankingModal = ref(false)
|
||||
const isActive = ref(true)
|
||||
const isFixed = ref(false)
|
||||
const creationGridRef = ref(null)
|
||||
const cardTapTimers = {}
|
||||
const likingMap = ref({})
|
||||
|
||||
// ========== 分类配置 ==========
|
||||
const categories = ref([
|
||||
@ -145,7 +148,32 @@ const bannerBottomPx = computed(() => Math.round(screenWidth.value / 750 * 715))
|
||||
// ========== Handlers ==========
|
||||
|
||||
const handleCardClick = (card) => {
|
||||
// CreationGrid 组件内部已处理单击跳转和双击点赞
|
||||
if (cardTapTimers[card.id]) {
|
||||
// 第二次点击,双击点赞
|
||||
clearTimeout(cardTapTimers[card.id]);
|
||||
delete cardTapTimers[card.id];
|
||||
|
||||
|
||||
// 触发动画
|
||||
likingMap.value = { ...likingMap.value, [card.id]: true };
|
||||
setTimeout(() => {
|
||||
likingMap.value = { ...likingMap.value, [card.id]: false };
|
||||
}, 600);
|
||||
|
||||
doubleTapLike(card.id, card.exhibition_id || 0, (success) => {
|
||||
if (success) {
|
||||
uni.showToast({ title: '点赞成功', icon: 'success' })
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 第一次点击,单击跳转
|
||||
if (card.id) {
|
||||
cardTapTimers[card.id] = setTimeout(() => {
|
||||
delete cardTapTimers[card.id];
|
||||
uni.navigateTo({ url: `/pages/asset-detail/asset-detail?asset_id=${card.id}` });
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handleScrollToLower = () => {
|
||||
|
||||
@ -54,7 +54,7 @@ export function doubleTapLike(assetId, exhibitionId, callback) {
|
||||
// }
|
||||
|
||||
likeAssetApi(assetId).then(res => {
|
||||
console.log('点赞成功', res);
|
||||
console.log('[likeHelper] 点赞成功', res);
|
||||
// 记录点赞
|
||||
try {
|
||||
const storage = uni.getStorageSync(LIKE_STORAGE_KEY) || {};
|
||||
@ -64,6 +64,7 @@ export function doubleTapLike(assetId, exhibitionId, callback) {
|
||||
console.error('存储点赞记录失败:', e);
|
||||
}
|
||||
// 触发全局点赞成功事件
|
||||
console.log('[likeHelper] 触发 assetLiked 事件', { asset_id: assetId, exhibition_id: actualExhibitionId, data: res.data });
|
||||
uni.$emit('assetLiked', {
|
||||
asset_id: assetId,
|
||||
exhibition_id: actualExhibitionId,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user