PK创意闹新春,我正在参加「春节创意投稿大赛」,详情请看:春节创意投稿大赛
效果
| 体验 | 发送页面 | 领取页面 | 拜年姿势识别页面 |
|---|---|---|---|
一、发红包
二、领红包
-
思路
- 一张背景图
- 一张红包图 加一个边框
- 点击开红包时,加一个动画
- 动画结束后,调用服务端抢红包
- 服务端开红包,发钱
-
代码实现
- 页面代码
<view> 背景图片 <image class="background_image" src='https://img.yeting.wang/new_year/WechatIMG93215.jpeg?x-oss-process=style/yasuo-30'></image> <image style="height: 750rpx;width: 100%; position: absolute; left: 0; top: 0; display: block; z-index: -998;" src='https://img.yeting.wang/new_year/hhu2.png'></image> 抢红包记录 <view style="margin-top: 6vh;width: 550rpx;"> <view v-if="redPacket.receiveList.length>0"> <u-notice-bar color="#FFFFFF" bgColor="rgba(250, 250, 230, 0.0)" direction="column" :text="redPacket.receiveList"> </u-notice-bar> </view> <view v-else> <u-notice-bar color="#FFFFFF" bgColor="rgba(250, 250, 230, 0.0)" icon=" "> </u-notice-bar> </view> </view> 红包 @tap="$u.throttle(rotateAndScale, 2000)" 节流然后调用动画 <view :animation="animationData" style="padding-left: 100rpx;padding-right: 100rpx;margin-top: 17vh;" @tap="$u.throttle(rotateAndScale, 2000)"> 弹出动画 <u-transition :show="show" :mode="mode" duration="1000"> 红包图片 <image style="width: 550rpx;height: 815rpx;display: block;position: absolute; z-index: 100; border-radius: 13px; box-shadow: 0 15px 30px rgba(0,0,0,0.8); " src="https://img.yeting.wang/new_year/hongbao.png"></image> <view style="margin-top: 510rpx;z-index: 200;padding-left:60rpx ;padding-right: 80rpx;"> <view style="display:flex;"> <u-avatar size="30" shape="circle" :src="redPacket.avatarUrl"></u-avatar> <view style="margin-left: 15rpx;"></view> <view style="width: 360rpx; margin-top: 7rpx;"> <u--text lines="1" color="#FFFFFF" :text="redPacket.nickName+receivingMethodM(redPacket.receivingMethod)"> </u--text> </view> </view> <view style="margin-top: 25rpx;"> <u--text lines="2" align="center" color="#FFFFFF" :text="redPacket.redPacketBlessing"> </u--text> </view> </view> </u-transition> </view> 这几个 u-modal 是 点开红包弹出的模态框 <u-modal :show="res_lingqushow" :confirmText="redPacketReceive.buttonContext" @confirm="resBut(redPacketReceive.buttonMethod)"> <view class="slot-content"> {{redPacketReceive.message}} </view> </u-modal> <u-modal :show="zhufuyu_lingqushow" confirmText="确定" @confirm="zhufuyu" closeOnClickOverlay @close="zhufuyu_lingqushow = false"> <view class="slot-content"> <view>新年祝福语红包需填写祝福语</view>️ <u--textarea v-model="zhufuyu_value" placeholder="新年祝福语" count maxlength="30"></u--textarea> </view> </u-modal> <u-modal :show="shoushi_lingqushow" confirmText="去拜年" @confirm="goshoushi" closeOnClickOverlay @close="shoushi_lingqushow = false"> <view class="slot-content"> 手势拜年红包,需做出拜年动作即可领取 </view> </u-modal> <u-modal :show="login_show" content="获取头像昵称, 用于红包展示领取人 ~" closeOnClickOverlay showCancelButton> <u-button slot="confirmButton" text="授权" type="primary" @click="getUserInfo"></u-button> </u-modal> 领取红包时的loading <u-loading-page bg-color='rgba(0, 0, 0, 0.2)' loadingText="领取中..." loadingMode="circle" :loading="receive_loading_show"></u-loading-page> <u-notify ref="uNotify" message="Hi uView"></u-notify> </view>- js代码
//抢红包动画 rotateAndScale() { var animation = uni.createAnimation({ duration: 500, timingFunction: 'ease', }) this.animation = animation var next = true; // 无限循环动画 this.timer = setInterval(function() { if (next) { // 你要执行动画链(详见文档) this.animation.scale(0.95).step() next = !next; } else { // 你要执行动画链(详见文档) this.animation.scale(1).step() next = !next; } // 导出动画 this.animationData = this.animation.export() }.bind(this), 500) //2秒后抢红包 setTimeout(() => { //清楚动画 clearInterval(this.timer) this.receiveRedPacket() }, 2000) }, receiveRedPacket() { //判断一下抢完了吗 if (this.redPacket.status == -10 || this.redPacket.status == -5 || this.redPacket.num == this.redPacket.receiveList) { this.redPacketReceive.message = '来晚了,红包已被领完~' this.redPacketReceive.buttonMethod = 10 this.redPacketReceive.buttonContext = '我也发一个~' this.res_lingqushow = true return } //判断一下自己抢过没有 uni.$u.http.post('/redPacket/meReceive', { redPacketId: this.redPacketId, userId: this.redPacketUserId, blessingWords: this.zhufuyu_value }).then(res => { console.log('meReceive' + res) if (res == true) { this.redPacketReceive.message = '已经领取过红包了哦~' this.redPacketReceive.buttonMethod = 10 this.redPacketReceive.buttonContext = '我也发一个~' this.res_lingqushow = true } else { //没抢过,判断红包类型 if (this.redPacket.receivingMethod == 1) { //普通红包,直接领取 this.receive_loading_show = true //ui 已经节流,所以这里不需要节流 this.receive() } else if (this.redPacket.receivingMethod == 2) { //祝福语红包,弹出祝福卡框 this.zhufuyu_lingqushow = true } else if (this.redPacket.receivingMethod == 3) { //手势拜年红包,跳到拜年页面 this.shoushi_lingqushow = true } } }) }, receive() { //调用抢红包接口 console.log("领取红包") uni.$u.http.post('/redPacket/receive', { redPacketId: this.redPacketId, userId: this.redPacketUserId, blessingWords: this.zhufuyu_value }).then(res => { console.log(JSON.stringify(res)) this.redPacketReceive = res this.receive_loading_show = false this.res_lingqushow = true // if (res.status) { // this.receive_loading_show = false // this.res_lingqushow = true // } else { // this.receive_loading_show = false // console.log("领取失败") // } }) },- 后端代码
@Override public Result<?> receive(UserBo user, RedPacketVo redPacketVo) { String redPacketId = redPacketVo.getRedPacketId(); String redPacketUserId = redPacketVo.getUserId(); if (StringUtils.isBlank(redPacketId) || StringUtils.isBlank(redPacketUserId)) { return Result.parameterError(); } RedPacketReceiveDto redPacketReceiveDto = new RedPacketReceiveDto(); redPacketReceiveDto.setRedPacketId(redPacketId); // 红包锁 RLock lock = redissonClient.getLock("RedPacket:receive:" + redPacketId); lock.lock(); try { //查询红包 RedPacket redPacket = getOne(new LambdaQueryWrapper<RedPacket>() .eq(RedPacket::getRedPacketId, redPacketId) .eq(RedPacket::getUserId, redPacketUserId) ); if (redPacket != null) { if (redPacket.getStatus().equals(10)) { //已经支付过的 //查下红包记录 List<RedPacketReceive> redPacketReceiveList = redPacketReceiveService.list(new LambdaQueryWrapper<RedPacketReceive>() .eq(RedPacketReceive::getRedPacketId, redPacketId) ); if (redPacket.getNum() == redPacketReceiveList.size()) { //领完了 redPacketReceiveDto.setStatus(false); redPacketReceiveDto.setSendMoneyStatus(false); redPacketReceiveDto.setMessage("来晚了,红包已被领完~"); redPacketReceiveDto.setButtonContext("我也发一个~"); } else { //没领完 //看下是否已经领过 List<RedPacketReceive> receivedList = redPacketReceiveList.stream().filter(redPacketReceive -> redPacketReceive.getUserId().equals(user.getUserId())).collect(Collectors.toList()); if (receivedList.size() > 0) { redPacketReceiveDto.setStatus(false); redPacketReceiveDto.setSendMoneyStatus(false); redPacketReceiveDto.setMessage("已经领取过红包了哦~"); redPacketReceiveDto.setButtonContext("我也发一个~"); } else { //没领过 //发钱 //按顺序拿一个钱 int index = redPacketReceiveList.size(); Integer fee = redPacket.getRedPacketFeeList().get(index); RedPacketReceive redPacketReceive = new RedPacketReceive() .setRedPacketId(redPacket.getRedPacketId()) .setUserId(user.getUserId()) .setNickName(user.getNickName()) .setAvatarUrl(user.getAvatarUrl()) .setOpenId(user.getOpenId()) .setFeeIndex(index) .setFee(fee) .setPartnerTradeNo(WxPayKit.generateStr()) .setStatus(0) .setBlessingWords(redPacketVo.getBlessingWords()); boolean saveReceive = redPacketReceiveService.save(redPacketReceive); if (saveReceive) { log.warn("发钱: {}", JSONUtil.toJsonStr(redPacketReceive)); //调用微信发钱 Boolean transfers = weChatPayService.transfers(redPacketReceive); boolean updateReceive = redPacketReceiveService.updateById(redPacketReceive); if (transfers) { if (updateReceive) { //全部成功 log.warn("发钱成功: {}", JSONUtil.toJsonStr(redPacketReceive)); } else { log.error("警告,发钱成功,更新失败: {}", JSONUtil.toJsonStr(redPacketReceive)); } redPacketReceiveDto.setStatus(true); redPacketReceiveDto.setSendMoneyStatus(true); redPacketReceiveDto.setMessage("¥ " + (NumberUtil.div(redPacketReceive.getFee().toString(), "100").setScale(2, RoundingMode.HALF_UP)) + " 领取成功,已存入微信钱包"); redPacketReceiveDto.setButtonContext("我也发一个~"); } else { log.error("发钱失败: {}", JSONUtil.toJsonStr(redPacketReceive)); if (!updateReceive) { log.error("警告,发钱失败,更新失败: {}", JSONUtil.toJsonStr(redPacketReceive)); } redPacketReceiveDto.setStatus(true); redPacketReceiveDto.setSendMoneyStatus(false); redPacketReceiveDto.setMessage("领取成功,转账失败,如在24小时没收到,请联系客服处理~"); redPacketReceiveDto.setButtonContext("我也发一个~"); } } else { redPacketReceiveDto.setStatus(false); redPacketReceiveDto.setSendMoneyStatus(false); redPacketReceiveDto.setMessage("领取失败,请稍后重试~"); redPacketReceiveDto.setButtonMethod(-10); redPacketReceiveDto.setButtonContext("稍后重试"); } } } } else if (redPacket.getStatus().equals(-5) || redPacket.getStatus().equals(-10)) { redPacketReceiveDto.setStatus(false); redPacketReceiveDto.setSendMoneyStatus(false); redPacketReceiveDto.setMessage("来晚了,红包已被领完~"); redPacketReceiveDto.setButtonContext("我也发一个~"); } else { redPacketReceiveDto.setStatus(false); redPacketReceiveDto.setSendMoneyStatus(false); redPacketReceiveDto.setMessage("红包未支付哦~"); redPacketReceiveDto.setButtonContext("我也发一个~"); } } else { redPacketReceiveDto.setStatus(false); redPacketReceiveDto.setSendMoneyStatus(false); redPacketReceiveDto.setMessage("红包不正常哦~"); redPacketReceiveDto.setButtonContext("我也发一个~"); } } catch (Exception e) { log.error("领红包失败:{}", JSONUtil.toJsonStr(redPacketVo), e); redPacketReceiveDto.setStatus(false); redPacketReceiveDto.setSendMoneyStatus(false); redPacketReceiveDto.setMessage("领取失败,请稍后重试~"); redPacketReceiveDto.setButtonMethod(-10); redPacketReceiveDto.setButtonContext("稍后重试"); } finally { lock.unlock(); } return Result.success(redPacketReceiveDto); }