2023年1月

PC前端JS实现

<script>
    layui.use(['layer'], function () {
        var $ = layui.jquery;
        var layer = layui.layer;

        //长轮询实现
        var updateTimer = setInterval(() => {
            var videoId = window.btoa('<?=$video->id;?>');
            $.post('<?=route("member.xxx.time");?>', {video_id: videoId}, function (res) {
                if (res.code === 2023) {
                    clearInterval(updateTimer);//出现想要的结果,停止重复提交
                    layer.msg(res.msg, {icon: 1, time: 3000}, function () {
                        parent.location.reload();
                    });
                } else {
                    clearInterval(updateTimer);//出现想要的结果,停止重复提交
                    layer.msg(res.msg, {icon: 2, time: 3000}, function () {
                        parent.location.reload();
                    });
                }
            }, 'json');
        }, 1000 * 60) //每分钟请求一次
    });
</script>

后端PHP实现控制

....
//让前端停止再请求
if ($longTime == $learnedTime) {
    throw new \Exception('恭喜您,通过实践',2023);
}




代码片段:

data:{
    waitTimes:0,//超时变量
    timeList:[],//定时器列表
},
myUpdate() {
    var maxWait = 10 //超时次数
    var newWait = this.data.waitTimes + 1 //执行的次数
    if (newWait >= maxWait) { //超时了
        console.log(util.formatTime(new Date()), '轮询超时')
    } else { //未超时
        var time = setTimeout(this.myUpdate, 2000)
        this.data.timeList.push(time) // 存储定时器
        console.log(util.formatTime(new Date()), '第', newWait, '次轮询中...')
        if (newWait === 6) { //拿到数据,轮询终止
            console.log(util.formatTime(new Date()), '拿到了所需数据!轮询停止')
            this.stopWaiting()
        } else { //继续轮询
            this.setData({
                waitTimes: newWait
            })
        }
    }
},
startWaiting() {
    setTimeout(this.myUpdate, 2000)
},
stopWaiting() {
    for (var i = 0; i < this.data.timeList.length; i++) {
        clearTimeout(this.data.timeList[i]); //清除了所有定时器
    }
}



/**
 * 生命周期函数--监听页面隐藏
 */
// 点击系统Home键返回上一步时候触发
onHide: function () {
  this.stopWaiting()
},

/**
 * 生命周期函数--监听页面卸载
 */
// 点击左上角返回箭头时候触发
onUnload: function () {
  this.stopWaiting()
},

转载:https://blog.csdn.net/qq_37398834/article/details/115675331
另一个参考:http://willless.com/settimeout-polling-in-applet-to-judge-data-jump-after-updating.html

$(document).ready(function () {
    var options = {
    };
    var player = videojs('demo-video', options, function onPlayerReady() {
        var time1;
        var t1 = 0;
        function aa() {
            t1 += 0.25;
            document.getElementById('aa').value = t1;
            console.log('aa-' + t1);
        }
        //开始播放视频时
        this.on('play', function () {
            console.log('开始播放'); 
        });
        //结束和暂时时清除定时器,并向后台发送数据
        this.on('ended', function () {
            console.log('结束播放');
            window.clearInterval(time1);
            countTime();   //向后台发数据
        });
        this.on('pause', function () {
            console.log('暂停播放');
            window.clearInterval(time1);
            countTime();  //向后台发数据
        });
        //被主动暂停或网络暂停缓冲后重新播放会触发该事件
        //开始播放视频时,设置一个定时器,每250毫秒调用一次aa(),观看时长加2.5秒,
        //定时器需要放在playing事件中,否则无法实现网络缓冲后继续计时的功能
        this.on("playing",function(){
            console.log('开始播放');
            time1 = setInterval(function () {
                aa();
            }, 250)
        }),
        //当因网络原因导致暂停时会触发该事件
        this.on("waiting",function(){
            window.clearInterval(time1);
                    countTime();   //向后台发数据
             console.log('waiting');
        })
    });
    //直接关闭页面,并向后台发送数据
    if(window.addEventListener){
        window.addEventListener("beforeunload",countTime,false);
    }else{
        window.attachEvent("onbeforeunload",countTime);
    }
    
    function countTime(){
        console.log('countTime',document.getElementById('aa').value);
    }
})

源码下载:video.zip

转载:https://blog.csdn.net/king2wang/article/details/83001087

条件聚合

实际上有一种非常简单的方法可以查询计算这些总数。诀窍是将条件放在聚合函数中。下面是一个 SQL 示例:

select
  count(*) as total,
  count(case when status = 'confirmed' then 1 end) as confirmed,
  count(case when status = 'unconfirmed' then 1 end) as unconfirmed,
  count(case when status = 'cancelled' then 1 end) as cancelled,
  count(case when status = 'bounced' then 1 end) as bounced
from subscribers

 total | confirmed | unconfirmed | cancelled | bounced
-------+-----------+-------------+-----------+---------
   200 |       150 |          50 |        30 |      25

以下是在 Model 中使用查询构建器编写此查询:

$totals = DB::table('subscribers')
    ->selectRaw('count(*) as total')
    ->selectRaw("count(case when status = 'confirmed' then 1 end) as confirmed")
    ->selectRaw("count(case when status = 'unconfirmed' then 1 end) as unconfirmed")
    ->selectRaw("count(case when status = 'cancelled' then 1 end) as cancelled")
    ->selectRaw("count(case when status = 'bounced' then 1 end) as bounced")
    ->first();

<div>Total: {{ $totals->total }}</div>
<div>Confirmed: {{ $totals->confirmed }}</div>
<div>Unconfirmed: {{ $totals->unconfirmed }}</div>
<div>Cancelled: {{ $totals->cancelled }}</div>
<div>Bounced: {{ $totals->bounced }}</div>


onlaunch:当小程序初始化完成时,会触发 onLaunch(全局只触发一次)(app.js);
onLoad: 页面加载小程序注册完成后,加载页面,触发onLoad方法。一个页面只会调用一次,可以在 onLoad 中获取打开当前页面所调用的 query 参数(页面js)。
onShow: 页面显示页面载入后触发onShow方法,显示页面。每次打开页面都会调用一次(比如当小程序有后台进入到前台运行或重新进入页面时)。
onReady: 首次显示页面,页面初次渲染完成,会触发onReady方法,渲染页面元素和样式,一个页面只会调用一次,代表页面已经准备妥当,可以和视图层进行交互。对界面的设置如wx.setNavigationBarTitle请在onReady之后设置。
onHide: 页面隐藏当navigateTo、底部tab切换、上传文件选择图片时调用。
onUnload: 页面卸载当返回上一页wx.navigateBack、wx.relanch、wx.redirectTo时都会被调用(这里的坑有点深)。

基本上可以说执行顺序为onLaunch–>onLoad–>onShow–>onReady–>onHide.虽然说onLaunch在onLoad之前执行,但是在onLaunch里请求获取是否有权限,等待返回值的时候Page里的onLoad事件就已经执行了。

解决办法:

在APP里面onLanch中的网络请求中设置判断
if (this.userInfoReadyCallback) {
    this.userInfoReadyCallback(res)
}

在page的onLoad中设置一个回调
app.userInfoReadyCallback = res => {
    if (res != '') {
        console.log("app.globalData.userInfo")
    }
}

转截:https://www.cnblogs.com/kaicy/p/14894777.html

方法1:

使用number_format()函数。number_format()函数用于将字符串转换为数字。它会在成功时返回格式化的数字,否则会在失败时给出E_WARNING。
<?php

    $num = "1000.314"; //1,000

    // 使用number_format()函数将字符串转换为数字
    echo number_format($num); //1,000.31

    // 函数的作用是:将字符串转换为数字
    echo number_format($num, 2);

?>

方法2:

使用类型转换:类型转换可以直接将字符串转换为float,double或integer基本类型。这是将字符串转换为数字而不使用任何函数的最佳方法。
<?php

    // 字符串格式的数字
    $num = "1000.314"; 

    // 使用int类型转换
    echo (int)$num; //1000

    // 使用float 类型转换
    echo (float)$num; //1000.314

    // 使用double 类型转换
    echo (double)$num; //1000.314

?>


方法3:

使用intval()和floatval()函数。intval()和floatval()函数也可用于将字符串分别转换为其对应的整数和浮点值。
<?php

    // 字符串格式的数字
    $num = "1000.314";

    // intval函数的作用是:将字符串转换为整数
    echo intval($num); //1000

    // floatval函数的作用是:将字符串转换为浮点数
    echo floatval($num); //1000.314

?>


方法4:

通过添加0或执行数学运算。通过在字符串中添加0,也可以将字符串编号转换为整数或浮点数。在PHP中,执行数学运算时,字符串将隐式转换为整数或浮点数。
<?php

    // 数字转换成字符串格式
    $num = "1000.314";

    // 对隐式类型转换执行数学运算
    echo $num + 0; //1000.314

    // 对隐式类型转换执行数学运算
    echo $num + 0.0; //1000.314

    // 对隐式类型转换执行数学运算
    echo $num + 0.1; //1000.414

?>

曾经踩过一个坑,用方法4解决的。

代码实现

  1. 微信开发者工具上可以通过「编译模式」下的「下次编译模拟更新」开关来调试
  2. 小程序开发版/体验版没有「版本」概念,所以无法在开发版/体验版上测试版本更新情况
// app.js
onLaunch: function() {
    this.checkForUpdate();
},
// 检查是否有新版本
checkForUpdate: function() {
    if (wx.canIUse('getUpdateManager')) { // 判断getUpdateManager在当前版本是否可用
        const updateManager = wx.getUpdateManager();
        updateManager.onCheckForUpdate(function(res) {
            // 请求完新版本信息的回调
            if (res.hasUpdate) { // 有新版本
                updateManager.onUpdateReady(function() {
                    wx.showModal({
                        title: '更新提示',
                        content: '新版本已经准备好,是否重启应用?',
                        success: function(res) {
                            if (res.confirm) {
                                // 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
                                updateManager.applyUpdate();
                            }
                        }
                    })
                })
                updateManager.onUpdateFailed(function() {
                    // 新版本下载失败
                    wx.showModal({
                        title: '已经有新版本了哟~',
                        content: '新版本已经上线,请您删除当前小程序,重新搜索打开哟~'
                    })
                })
            }
        })
    } else {
        wx.showModal({
            title: '提示',
            content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。'
        })
    }
},

本文转自:https://www.jinjin.link/2021/06/09/小程序强制更新全解析/