做一个 拜年手势红包,从此红包不被白嫖「可体验」(二)

1,431 阅读2分钟

PK创意闹新春,我正在参加「春节创意投稿大赛」,详情请看:春节创意投稿大赛

效果

体验发送页面领取页面拜年姿势识别页面
gh_15bfd4eab8ac_258.jpgimage.pngimage.pngimage.png

一、发红包

文章地址

二、领红包

image.png

  • 思路

    • 一张背景图
    • 一张红包图 加一个边框
    • 点击开红包时,加一个动画
    • 动画结束后,调用服务端抢红包
    • 服务端开红包,发钱
  • 代码实现

    • 页面代码
    <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);
        }
    

三、拜年手势领红包

文章地址