liziyu 发布的文章

type UserBasic struct {
    gorm.Model
    Name          string    `gorm:"size:150;default:'';not null;comment:姓名"`
    Password      string    `gorm:"size:255;default:'';not null;comment:密码"`
    Phone         string    `gorm:"size:11;default:'';not null;comment:手机号码"`
    Email         string    `gorm:"size:150;default:'';not null;comment:邮箱"`
    Client        string    `gorm:"size:100;default:'';not null;comment:客户端"`
    Identity      string    `gorm:"size:255;default:'';not null;comment:暂无"`
    ClientIp      string    `gorm:"size:20;default:'';not null;comment:客户端IP"`
    ClientPort    string    `gorm:"size:10;default:'';not null;comment:客户端端口"`
    LoginTime     time.Time `gorm:"comment:登陆时间"`
    HeartbeatTime time.Time `gorm:"comment:心跳时间"`
    LogoutTime    time.Time `gorm:"comment:退出时间"`
    IsLogout      bool      `gorm:"default:true;not null;comment:是否登陆"`
    DeviceInfo    string    `gorm:"size:255;default:'';not null;comment:设备信息"`
}

package service

import (
    "encoding/json"
    "fmt"
    "ginStudy/tool"
    "github.com/aliyun/alibaba-cloud-sdk-go/sdk"
    "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
    "github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi"
    "math/rand"
    "time"
)

type MemberService struct {
}

func (ms *MemberService) SendSms(phone string) bool {
    //1.产生一个验证码
    code := fmt.Sprintf("%04v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(1000))
    //2.调用全局配置参数
    config := tool.GetConfig().Sms
    configSdk := sdk.NewConfig()
    credential := credentials.NewAccessKeyCredential(config.AppKey, config.AppSecret)

    client, err := dysmsapi.NewClientWithOptions(config.RegionId, configSdk, credential)
    if err != nil {
        panic(err)
    }

    //3.构造请求参数
    request := dysmsapi.CreateSendSmsRequest()
    request.Scheme = "https"
    request.SignName = config.SignName
    request.TemplateCode = config.TemplateCode
    request.PhoneNumbers = phone
    par, err := json.Marshal(map[string]interface{}{
        "code": code,
    })
    request.TemplateParam = string(par)
    //接收响应
    response, err := client.SendSms(request)
    if err != nil {
        fmt.Print(err.Error())
        return false
    }
    fmt.Printf("response is %#v\n", response)
    //5.判断返回
    if response.Code == "OK" {
        return true
    }
    return false
}


chan 的值或者状态会有很多种情况,一些操作可能会出现panic异常场景,如下表:

接收/发送nil channel有值 channel没值 channel满 channel
<- ch (发送数据)阻塞发送成功发送成功阻塞
ch <- (接收数据)阻塞接收成功阻塞接收成功
close (ch) 关闭 channelpanic关闭成功关闭成功关闭成功

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