uniapp 全局弹窗通知

961 阅读3分钟

在需要出现这个通知的页面,都将这个组件引入,然后将时间进行处理,等到剩余xx时间的时候出现这个弹窗,出现几秒后消失,然后间隔xx秒后再次出现

<template>
    <view class="result">
        <view class="notice flex-align" :class="{'fold':isShow}">
            <image class="logo" :src="logo图片" mode="widthFix">
            </image>
            <view class="info flex-justify">
                <view>
                    <view class="font-size-left-10 font-bold">内容:啊哈哈哈</text>
                    </view>
                    <view class="font-size-left-10 font-bold mt-1">
                        xxxxxxxxxxxxxxxxxxxx
                    </view>
                </view>
                <view>
                    <view class="text font-bold">倒计时</view>
                    <view class="count-down flex-center mt-1">
                        <view v-for="(m,index) in minute.toString()" :key="'m'+index">{{m}}</view>
                        <view>:</view>
                        <view v-for="(s,index) in second.toString()" :key="'s'+index">{{s}}</view>
                    </view>
                </view>
            </view>
        </view>
    </view>
</template>

<script>
    export default {
        data() {
            return {
                minute: 0,
                second: 0,
                residue_time:600,
                isShow: false,
                timer: null,
                timeoutTimer: null
            }
        },
        mounted() {
            const that = this
            uni.addInterceptor('navigateTo', { //监听跳转
                invoke(e) {
                    that.routeChange()
                },
            })
            uni.addInterceptor('redirectTo', { //监听关闭本页面跳转
                invoke(e) {
                    that.routeChange()
                }
            })
            uni.addInterceptor('switchTab', { //监听tabBar跳转
                invoke(e) {
                    that.routeChange()
                }
            })
            uni.addInterceptor('navigateBack', { //监听返回
                invoke(e) {
                    that.routeChange()
                }
            })
        },
        methods: {
            routeChange() {
                // 监听路由发生改变时清除定时器和延时器
                if (this.timer) {
                    clearInterval(this.timer)
                    this.timer = null
                }
                if (this.timeoutTimer) {
                    clearTimeout(this.timeoutTimer)
                    this.timeoutTimer = null
                }
            },
            init() {
                this.getTask()
            },
            getTask() {
                // 剩余时间
                this.time1=300
                // 间隔时间
                this.time2=30
                
                if (this.residue_time > 0) {
                    this.timer = setInterval(() => {
                        // 时间格式处理
                        if (this.residue_time > 0) {
                            this.countDown();
                        }

                        // 剩余300秒开始出现
                        if (this.residue_time <= Number(this.time1) && !this.isShow) {
                            // 下次展示时间,如果没有下次时间就是当前时间(直接出现)
                            const nextTime = uni.getStorageSync('next_time') || this
                                .residue_time
                            // 切换页面后不立马出现,等下次出现时间到了再出现
                            if (nextTime >= this.residue_time) {
                                // 设置下次出现时间 = 当前时间 - 间隔时间
                                uni.setStorageSync('next_time', Number(this.residue_time) - Number(this.time2))

                                // 展示4秒后关闭
                                this.isShow = true
                                setTimeout(() => {
                                    this.isShow = false
                                    clearInterval(this.timer)
                                    this.timer = null
                                }, 4000)

                                // 每隔30秒弹一次
                                this.timeoutTimer = setTimeout(() => {
                                    this.getTask()
                                    // 在当前页面间隔时间到了直接出现
                                    uni.removeStorageSync('next_time')
                                }, Number(this.time2) * 1000)
                            }
                        }
                        if (0 >= this.residue_time) {
                            this.isShow = false
                            this.routeChange()
                            uni.removeStorageSync('next_time')
                        }
                    }, 1000)
                } else {
                    this.routeChange()
                    uni.removeStorageSync('next_time')
                }
            },
            countDown() {
                const {
                    i,
                    s
                } = this.secondsFormat(this.residue_time);
                this.minute = i;
                this.second = s;
                this.residue_time--;
            },
            // 将秒转为天数,小时。分钟,秒数
            secondsFormat(seconds){
                let [day, hour, minute, second] = [0, 0, 0, 0]
                if (seconds > 0) {
                    day = Math.floor(seconds / (60 * 60 * 24))
                    hour = Math.floor(seconds / (60 * 60)) - (day * 24)
                    minute = Math.floor(seconds / 60) - (day * 24 * 60) - (hour * 60)
                    second = Math.floor(seconds) - (day * 24 * 60 * 60) - (hour * 60 * 60) - (minute * 60)
                }
                if (day < 10) {
                    day = '0' + day
                }
                if (hour < 10) {
                    hour = '0' + hour
                }
                if (minute < 10) {
                    minute = '0' + minute
                }
                if (second < 10) {
                    second = '0' + second
                }
                return {
                    d: day,
                    h: hour,
                    i: minute,
                    s: second
                };
            }
        }
    }
</script>

<style lang="scss" scoped>
    .result {

        .notice {
            width: calc(100% - 60rpx);
            position: fixed;
            left: 30rpx;
            top: -500rpx;
            background: rgba(255, 255, 255, 0.8);
            border-radius: 42rpx;
            padding: 30rpx;
            box-sizing: border-box;
            z-index: 9999;

            .logo {
                width: 72rpx;
                height: 72rpx;
                margin-right: 20rpx;
            }

            .info {
                width: calc(100% - 92rpx);

                view {
                    color: #0A0C0D;
                    line-height: 1;
                }
            }

            .text {
                color: #000;
                font-size: 24rpx;

                text {
                    color: #FF0000;
                    font-size: 36rpx;
                }
            }

            .count-down {
                view {
                    color: #FF0000;
                    font-size: 34rpx;
                }
            }
        }

        .fold {
            animation: appear 0.5s linear forwards, disappear 0.5s linear 3s forwards;
            // 出现动画
            @keyframes appear {
                0% {
                    top: -500rpx;
                }

                100% {
                    top: 40rpx;
                }
            }
            // 消失动画
            @keyframes disappear {
                0% {
                    top: 40rpx;
                }

                100% {
                    top: -500rpx;
                }
            }
        }
    }
</style>

参考链接:juejin.cn/post/729966…

间隔xx时间请求接口:

<template>
    <view class="result" @click="gotoPage" v-if="hasData">
        <view class="notice flex-align" :class="{'fold':isShow}">
            <image class="logo" src="/static/logo.png" mode="widthFix">
            </image>
            <view class="info flex-justify">
                <view>
                    <view class="font-size-10 font-bold">标题</view>
                    <view class="font-size-10 font-bold mt-1">内容</view>
                </view>
            </view>
        </view>
    </view>
</template>

<script>
    export default {
        data() {
            return {
                isShow: false,
                hasData: false,
                timer: null,
                timeoutTimer: null
            }
        },
        mounted() {
            const that = this
            uni.addInterceptor('navigateTo', { //监听跳转
                invoke(e) {
                    that.clearTimer()
                },
            })
            uni.addInterceptor('redirectTo', { //监听关闭本页面跳转
                invoke(e) {
                    that.clearTimer()
                }
            })
            uni.addInterceptor('switchTab', { //监听tabBar跳转
                invoke(e) {
                    that.clearTimer()
                }
            })
            uni.addInterceptor('navigateBack', { //监听返回
                invoke(e) {
                    that.clearTimer()
                }
            })
        },
        methods: {
            clearTimer() {
                if (this.timer) {
                    clearInterval(this.timer)
                    this.timer = null
                }
                if (this.timeoutTimer) {
                    clearTimeout(this.timeoutTimer)
                    this.timeoutTimer = null
                }
            },
            init() {
                if (uni.getStorageSync('token')) {
                    this.getInfo()
                }
            },
            getInfo() {
                // 先清除定时器
                this.clearTimer()
                this.$api.sendRequest({
                    url: 'xxx',
                    data: {},
                    success: res => {
                        if (200 === res.code) {
                            this.hasData = true
                            // 定时器去检测时间
                            this.timer = setInterval(() => {
                                let nowTime = new Date().getTime()
                                // 下次展示时间,如果没有下次时间就是当前时间(直接出现)
                                const nextTime = uni.getStorageSync('next_time') || nowTime;
                                // 切换页面后不立马出现,等下次展示时间到了再出现
                                if (nextTime <= nowTime) {
                                    // 设置下次出现时间
                                    uni.setStorageSync('next_time', Number(nowTime) +
                                        Number(res.data.popup_tips_time) * 1000)
                                    // 展示4秒后关闭
                                    this.isShow = true
                                    setTimeout(() => {
                                        this.isShow = false
                                    }, 4000)
                                    // 每隔多少秒弹一次
                                    this.timeoutTimer = setTimeout(() => {
                                        this.getInfo()
                                        // 在当前页面间隔时间到了直接出现
                                        uni.removeStorageSync('next_time')
                                    }, Number(res.data.popup_tips_time) * 1000)
                                }
                            }, 1000)
                        } else {
                            this.hasData = false
                            uni.removeStorageSync('next_time')
                            this.clearTimer()
                        }
                    }
                });
            },
            gotoPage() {
                // 点击跳转相关页面
            }
        }
    }
</script>

<style lang="scss" scoped>
    .result {

        .notice {
            width: calc(100% - 60rpx);
            position: fixed;
            left: 30rpx;
            top: -500rpx;
            background: rgba(255, 255, 255, 0.8);
            border-radius: 42rpx;
            padding: 30rpx;
            box-sizing: border-box;
            z-index: 9999;

            .logo {
                width: 72rpx;
                height: 72rpx;
                margin-right: 20rpx;
            }

            .info {
                width: calc(100% - 92rpx);

                view {
                    color: #0A0C0D;
                    line-height: 1;
                }
            }

            .text {
                color: #000;
                font-size: 24rpx;

                text {
                    color: #FF0000;
                    font-size: 36rpx;
                }
            }

            .count-down {
                view {
                    color: #FF0000;
                    font-size: 34rpx;
                }
            }
        }

        .fold {
            animation: appear 0.5s linear forwards, disappear 0.5s linear 3s forwards;

            @keyframes appear {
                0% {
                    top: -500rpx;
                }

                100% {
                    top: 40rpx;

                    // #ifdef APP-PLUS
                    top: 100rpx;
                    // #endif
                }
            }

            @keyframes disappear {
                0% {
                    top: 40rpx;

                    // #ifdef APP-PLUS
                    top: 100rpx;
                    // #endif
                }

                100% {
                    top: -500rpx;
                }
            }
        }
    }
</style>