This commit is contained in:
gpu 2026-02-02 20:25:31 +08:00
parent b46950feeb
commit b9324e221a
7 changed files with 177 additions and 2 deletions

View File

@ -46,3 +46,12 @@ export const getDanYe = async (type) => {
export const getDanYeContent = async (type) => {
return await RequestManager.getCache('/danye', { type });
}
/**
* 获取悬浮球配置列表
* @returns {Promise} 悬浮球配置列表
*/
export const getFloatBall = async () => {
const res = await RequestManager.get("getFloatBall", {});
return res.data || [];
}

View File

@ -3,6 +3,14 @@
*/
import RequestManager from '../request';
/**
* 获取待领取优惠券数量
* @returns {Promise} 待领取优惠券数量
*/
export const getPendingCouponCount = async () => {
return await RequestManager.get('/coupon_pending_count', {}, true);
};
/**
* 获取优惠券列表
* @param {Object} params 查询参数

View File

@ -5,6 +5,15 @@
-->
<template>
<view class="content">
<!-- 待领取优惠券悬浮球 - Requirements 1.1.0 -->
<view
v-if="pendingCouponCount > 0"
class="coupon-float-ball"
@tap="onPendingCouponClick"
>
<image :src="couponFloatBallImage || 'https://youdas-1308826010.cos.ap-shanghai.myqcloud.com/static/web/static/common/quan.png'" class="coupon-ball-icon" mode="aspectFit"></image>
</view>
<view class="navLeft align-center" :style="{ top: statusBarHeight + 'px' }" @tap="jumapSlots()">
<view class="flex column" style="width: 100%">
<view class="title1 row" style="height: 64rpx; margin-top: 5rpx;">
@ -149,14 +158,16 @@
import PrizeDetailPopup from "@/components/prize-detail-popup/prize-detail-popup.vue";
import {
getAdvert,
getDanYe
getDanYe,
getFloatBall
} from "@/common/server/config";
import {
getGoodsList
} from "@/common/server/goods";
import {
receiveCoupons,
getAvailableCoupons
getAvailableCoupons,
getPendingCouponCount
} from "@/common/server/coupon";
import {
getPrizeAnnouncements
@ -198,6 +209,8 @@
gonggao: "",
couponData: "",
canGetCoupon: false,
pendingCouponCount: 0, //
couponFloatBallImage: "", //
swCur: 0,
statusBarHeight
};
@ -230,6 +243,8 @@
let that = this;
this.aa = true;
this.getCoupon();
this.fetchPendingCouponCount(); //
this.fetchCouponFloatBall(); //
if (!this.isLoading) {
this.getnews();
}
@ -255,6 +270,52 @@
// getBallStylegetPopupStyle
},
methods: {
/**
* @description: 获取待领取优惠券数量
* Requirements: 1.1.0 - 待领取优惠券固定入口
*/
async fetchPendingCouponCount() {
try {
const res = await getPendingCouponCount();
if (res && res.count !== undefined) {
this.pendingCouponCount = res.count;
} else {
this.pendingCouponCount = 0;
}
} catch (error) {
console.log('获取待领取优惠券数量失败', error);
this.pendingCouponCount = 0;
}
},
/**
* @description: 点击待领取优惠券入口
* Requirements: 1.1.0 - 待领取优惠券固定入口
*/
onPendingCouponClick() {
//
this.getCoupon();
},
/**
* @description: 获取优惠券悬浮球配置
* Requirements: 1.1.0 - 待领取优惠券固定入口
*/
async fetchCouponFloatBall() {
try {
const floatBalls = await getFloatBall();
// link_urlcoupon
const couponBall = floatBalls.find(ball =>
ball.link_url && ball.link_url.toLowerCase().includes('coupon')
);
if (couponBall && couponBall.image) {
this.couponFloatBallImage = couponBall.image;
}
} catch (error) {
console.log('获取优惠券悬浮球配置失败', error);
}
},
/**
* @description: 获取中奖公告列表
* @return {*}
@ -333,6 +394,8 @@
}, 100);
this.$refs.couponPop.close();
//
this.fetchPendingCouponCount();
}
},
@ -446,6 +509,25 @@
</script>
<style lang="scss">
/* 待领取优惠券悬浮球样式 - Requirements 1.1.0 三 */
.coupon-float-ball {
position: fixed;
right: 0;
top: 50%;
transform: translateY(-50%);
z-index: 999;
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
.coupon-ball-icon {
width: 80rpx;
height: 80rpx;
}
}
.title1 {
width: 100%;
display: flex;

View File

@ -319,6 +319,40 @@ public class CouponController : ControllerBase
}
}
/// <summary>
/// 获取待领取优惠券数量
/// </summary>
/// <remarks>
/// GET /api/coupon_pending_count
///
/// 获取用户待领取的优惠券数量,用于首页入口显示/隐藏
/// Requirements: 1.1.0 - 三、待领取优惠券固定入口
/// </remarks>
/// <returns>待领取优惠券数量</returns>
[HttpGet("coupon_pending_count")]
[Authorize]
[ProducesResponseType(typeof(ApiResponse<PendingCouponCountResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ApiResponse<PendingCouponCountResponse>), StatusCodes.Status401Unauthorized)]
public async Task<ApiResponse<PendingCouponCountResponse>> GetPendingCouponCount()
{
var userId = GetCurrentUserId();
if (userId == null)
{
return ApiResponse<PendingCouponCountResponse>.Unauthorized();
}
try
{
var count = await _couponService.GetPendingCouponCountAsync(userId.Value);
return ApiResponse<PendingCouponCountResponse>.Success(new PendingCouponCountResponse { Count = count });
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to get pending coupon count: UserId={UserId}", userId);
return ApiResponse<PendingCouponCountResponse>.Fail("获取待领取优惠券数量失败");
}
}
/// <summary>
/// 获取可领取的优惠券列表
/// </summary>

View File

@ -96,4 +96,11 @@ public interface ICouponService
/// <param name="couponId">优惠券ID</param>
/// <returns>领取结果</returns>
Task<ClaimCouponResponse> ReceiveCouponCenterAsync(int userId, int couponId);
/// <summary>
/// 获取待领取优惠券数量
/// </summary>
/// <param name="userId">用户ID</param>
/// <returns>待领取优惠券数量</returns>
Task<int> GetPendingCouponCountAsync(int userId);
}

View File

@ -827,4 +827,25 @@ public class CouponService : ICouponService
}
#endregion
/// <inheritdoc />
public async Task<int> GetPendingCouponCountAsync(int userId)
{
_logger.LogInformation("获取待领取优惠券数量: UserId={UserId}", userId);
// 检查用户是否已领取过优惠券
var user = await _dbContext.Users.FindAsync(userId);
if (user == null || user.IsUseCoupon == 1)
{
// 已领取过返回0
return 0;
}
// 获取可领取的优惠券数量 (status=0, type=1)
var count = await _dbContext.Coupons
.Where(c => c.Status == 0 && c.Type == 1)
.CountAsync();
return count;
}
}

View File

@ -1,3 +1,5 @@
using System.Text.Json.Serialization;
namespace HoneyBox.Model.Models.Coupon;
/// <summary>
@ -58,6 +60,18 @@ public class BatchReceiveCouponRequest
public string CouponId { get; set; } = string.Empty;
}
/// <summary>
/// 待领取优惠券数量响应
/// </summary>
public class PendingCouponCountResponse
{
/// <summary>
/// 待领取优惠券数量
/// </summary>
[JsonPropertyName("count")]
public int Count { get; set; }
}
/// <summary>
/// 可领取优惠券列表响应
/// </summary>