HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

警惕!8人利用清粉软件窃取用户信息,被网警抓获后获刑

法律科普

“打扰了,这是一条清粉信息,看看我还在不在你的通讯录里。如有打扰,非常抱歉。”

相信大家在微信中都收到过这样的清粉信息吧。由于微信只能单向删除好友,并不通知被删的人,所以想要知道自己事都被删,只能给对方发个消息看看。有些人为了清理微信中的单向好友,就会给微信里的人群发这样的信息,如果哪条信息发送失败,则显示对方已经把你删除。

有许多人想清粉的时候,担心群发信息会打扰到朋友而感到不好意思,所以就想到了一些清粉软件。这就给了不法分子可乘之机。

最近法院就宣判了一件因为利用微信清粉软件来盗取用户信息的案件。

在2020年6月,南通市的网警在工作的时候发现,有一些人的朋友圈和群聊之中,都会为一些僵粉软件做广告。这些软件需要登录用户的微信或者让用户自己授权,来检测哪些好友已经把你删除。

这些清粉软件没有官方认证,都是用服务器来自行搭建的系统,用户授权登录之后软件就会开始运行,盗窃用户信息,情节十分恶劣。在调查之后,警方抓获了包含张某在内的八名犯罪嫌疑人。前几日,这个案件刚刚宣判,张某等8人因为非法获取计算机信息系统数据、非法控制计算机信息系统罪被判刑

不要小看这些清粉软件,不法分子可以通过这些软件获取用户的群聊二维码,也可以使用用户的微信来进行关注、阅读、点赞等等。这也就是为什么不少人发现自己会莫名其妙地被拉入一些广告群,或者是显示有人通过自己的二维码扫码进了自己的群,其实都不是自己操作的,是自己的信息被这些非法网站给获取了。

在这里不得不吐槽,微信里想删除单向好友的功能确实存在一定的不完善性。

但是也要提醒各位,在使用微信的过程中,不要随意扫描未知的二维码,也不要随意授权自己的微信登录一些小程序或者网站。因为现在的微信基本都经过实名认证,连接个人信息和银行卡,轻易授权给别人就容易造成经济损失。

【来源:腾讯新闻客户端自媒体】,声明:转载此文是出于传递更多信息之目的。若有来源标注错误或侵犯了您的合法权益,请作者持权属证明与本网联系,我们将及时更正、删除,谢谢。 邮箱地址:pufa@dcloud.io 。

原文链接

继续阅读 »

“打扰了,这是一条清粉信息,看看我还在不在你的通讯录里。如有打扰,非常抱歉。”

相信大家在微信中都收到过这样的清粉信息吧。由于微信只能单向删除好友,并不通知被删的人,所以想要知道自己事都被删,只能给对方发个消息看看。有些人为了清理微信中的单向好友,就会给微信里的人群发这样的信息,如果哪条信息发送失败,则显示对方已经把你删除。

有许多人想清粉的时候,担心群发信息会打扰到朋友而感到不好意思,所以就想到了一些清粉软件。这就给了不法分子可乘之机。

最近法院就宣判了一件因为利用微信清粉软件来盗取用户信息的案件。

在2020年6月,南通市的网警在工作的时候发现,有一些人的朋友圈和群聊之中,都会为一些僵粉软件做广告。这些软件需要登录用户的微信或者让用户自己授权,来检测哪些好友已经把你删除。

这些清粉软件没有官方认证,都是用服务器来自行搭建的系统,用户授权登录之后软件就会开始运行,盗窃用户信息,情节十分恶劣。在调查之后,警方抓获了包含张某在内的八名犯罪嫌疑人。前几日,这个案件刚刚宣判,张某等8人因为非法获取计算机信息系统数据、非法控制计算机信息系统罪被判刑

不要小看这些清粉软件,不法分子可以通过这些软件获取用户的群聊二维码,也可以使用用户的微信来进行关注、阅读、点赞等等。这也就是为什么不少人发现自己会莫名其妙地被拉入一些广告群,或者是显示有人通过自己的二维码扫码进了自己的群,其实都不是自己操作的,是自己的信息被这些非法网站给获取了。

在这里不得不吐槽,微信里想删除单向好友的功能确实存在一定的不完善性。

但是也要提醒各位,在使用微信的过程中,不要随意扫描未知的二维码,也不要随意授权自己的微信登录一些小程序或者网站。因为现在的微信基本都经过实名认证,连接个人信息和银行卡,轻易授权给别人就容易造成经济损失。

【来源:腾讯新闻客户端自媒体】,声明:转载此文是出于传递更多信息之目的。若有来源标注错误或侵犯了您的合法权益,请作者持权属证明与本网联系,我们将及时更正、删除,谢谢。 邮箱地址:pufa@dcloud.io 。

原文链接

收起阅读 »

UniPush 推送遇到的相关问题(华为已测成功)(记录分享)

5+App开发 华为 离线推送 推送 unipush

踩坑3天,解决部分推送问题,供各位坑友参考。
本人亲测华为手机已没有问题,可以实现离线推送,其他手册品牌如有坑友测试通过的,最好能在评论区一起分享。

环境说明:
1、服务端环境:node.js
2、个推RestAPI V2 协议
3、测试手机:华为 HONOR Play4T Pro (AQM-AL10)

注:以下复现步骤均以上述环境为主,如果是其他服务环境请参考个推手册
新手请先阅读: UniPush使用指南(仔细阅读)
其他常见问题:UniPush常见问题 (仔细阅读)

步骤一
进入 Dcloud开发者中心,在厂商推送设置中设置相应厂商的各种参数。
特别提醒:在华为开发者平台中,必须要设置应用的SHA256证书指纹,否则会导致无法离线推送。

步骤二:个推推送参数

{  
    "request_id":"xxxxxx", //请求唯一标识号,10-32位之间;如果request_id重复,会导致消息丢失  
    "settings":{  
        "ttl":-1,//消息离线时间设置,单位毫秒,-1表示不设离线,-1 ~ 3 * 24 * 3600 * 1000(3天)之间  
        "strategy":{  
            "default":1 //1: 表示该消息在用户在线时推送个推通道,用户离线时推送厂商通道;  
        }  
    },  
    "audience":{  
        "cid":[  
            "推送的用户CID"  
        ]  
    },  
    "push_message":{  
        "notification":{  
            "title":"标题内容", //通知消息标题,长度 ≤ 50  
            "body":"消息内容", //通知消息内容,长度 ≤ 256  
            //"logo":"logo.png",//通知的图标名称,包含后缀名(需要在客户端开发时嵌入),如“push.png”,长度 ≤ 64  
            //"logo_url":"http://xxxx/a.png",//通知图标URL地址,长度 ≤ 256  
            "click_type":"intent",//点击后启动应用  
            "channel_level":4,  
            "intent":"intent:#Intent;launchFlags=0x04000000;action=android.intent.action.oppopush;component=你的应用包名/io.dcloud.PandoraEntry;S.UP-OL-SU=true;S.title=标题内容;S.content=消息内容;S.payload=test;end"    

        }  
    },  
    "push_channel":{ //离线推送的成败都在这段配置里面,根据自己的实际情况进行配置  
        "android":{  
            "ups":{  
                "notification":{  
                    "title":"标题内容", //通知消息标题,长度 ≤ 50  
                    "body":"消息内容", //通知消息内容,长度 ≤ 256  
                    //"logo":"logo.png",//通知的图标名称,包含后缀名(需要在客户端开发时嵌入),如“push.png”,长度 ≤ 64  
                    //"logo_url":"http://xxxx/a.png",//通知图标URL地址,长度 ≤ 256  
                    "click_type":"intent",//点击后启动应用  
                    "channel_level":4,  
                    "intent":"intent:#Intent;launchFlags=0x04000000;action=android.intent.action.oppopush;component=你的应用包名/io.dcloud.PandoraEntry;S.UP-OL-SU=true;S.title=标题内容;S.content=消息内容;S.payload=test;end"    
                },  
                "options":{  
                    //各厂商的特殊参数,选填  
                    "HW":{  
                        "/message/android/urgency":"HIGH",  
                        "/message/android/category":"PLAY_VOICE"  
                    }  
                }  
            }  
        },  
        "ios":{  
            "type":"notify",  
            "payload":"自定义消息",  
            "aps":{  
                "alert":{  
                    "title":"请填写ios标题",  
                    "body":"请填写ios内容"  
                },  
                "content-available":0  
            },  
            "auto_badge":"+1"  
        }  
    }  
}

以上参数中需要特别注意的是 push_channel 字段中的内容,是走离线推送的通道设置。不可省略。其中 click_type 必须为 intent,intent 中的内容保持上述我的模板,替换你自己的应用包名即可。S.title=标题内容;S.content=消息内容;S.payload=test 可以替换成你自己的内容,与 title ,body 保持一致。

其他问题:
1、离线推送后手机不亮屏、不提醒声音及震动的解决方法。
华为手机可能会把APP的推送划为营销短信,因此被静默,需要手动在手机的 “设置”-》“通知”-》“你的应用”-》“营销通知” -》“允许通知及相关的提醒设置”

继续阅读 »

踩坑3天,解决部分推送问题,供各位坑友参考。
本人亲测华为手机已没有问题,可以实现离线推送,其他手册品牌如有坑友测试通过的,最好能在评论区一起分享。

环境说明:
1、服务端环境:node.js
2、个推RestAPI V2 协议
3、测试手机:华为 HONOR Play4T Pro (AQM-AL10)

注:以下复现步骤均以上述环境为主,如果是其他服务环境请参考个推手册
新手请先阅读: UniPush使用指南(仔细阅读)
其他常见问题:UniPush常见问题 (仔细阅读)

步骤一
进入 Dcloud开发者中心,在厂商推送设置中设置相应厂商的各种参数。
特别提醒:在华为开发者平台中,必须要设置应用的SHA256证书指纹,否则会导致无法离线推送。

步骤二:个推推送参数

{  
    "request_id":"xxxxxx", //请求唯一标识号,10-32位之间;如果request_id重复,会导致消息丢失  
    "settings":{  
        "ttl":-1,//消息离线时间设置,单位毫秒,-1表示不设离线,-1 ~ 3 * 24 * 3600 * 1000(3天)之间  
        "strategy":{  
            "default":1 //1: 表示该消息在用户在线时推送个推通道,用户离线时推送厂商通道;  
        }  
    },  
    "audience":{  
        "cid":[  
            "推送的用户CID"  
        ]  
    },  
    "push_message":{  
        "notification":{  
            "title":"标题内容", //通知消息标题,长度 ≤ 50  
            "body":"消息内容", //通知消息内容,长度 ≤ 256  
            //"logo":"logo.png",//通知的图标名称,包含后缀名(需要在客户端开发时嵌入),如“push.png”,长度 ≤ 64  
            //"logo_url":"http://xxxx/a.png",//通知图标URL地址,长度 ≤ 256  
            "click_type":"intent",//点击后启动应用  
            "channel_level":4,  
            "intent":"intent:#Intent;launchFlags=0x04000000;action=android.intent.action.oppopush;component=你的应用包名/io.dcloud.PandoraEntry;S.UP-OL-SU=true;S.title=标题内容;S.content=消息内容;S.payload=test;end"    

        }  
    },  
    "push_channel":{ //离线推送的成败都在这段配置里面,根据自己的实际情况进行配置  
        "android":{  
            "ups":{  
                "notification":{  
                    "title":"标题内容", //通知消息标题,长度 ≤ 50  
                    "body":"消息内容", //通知消息内容,长度 ≤ 256  
                    //"logo":"logo.png",//通知的图标名称,包含后缀名(需要在客户端开发时嵌入),如“push.png”,长度 ≤ 64  
                    //"logo_url":"http://xxxx/a.png",//通知图标URL地址,长度 ≤ 256  
                    "click_type":"intent",//点击后启动应用  
                    "channel_level":4,  
                    "intent":"intent:#Intent;launchFlags=0x04000000;action=android.intent.action.oppopush;component=你的应用包名/io.dcloud.PandoraEntry;S.UP-OL-SU=true;S.title=标题内容;S.content=消息内容;S.payload=test;end"    
                },  
                "options":{  
                    //各厂商的特殊参数,选填  
                    "HW":{  
                        "/message/android/urgency":"HIGH",  
                        "/message/android/category":"PLAY_VOICE"  
                    }  
                }  
            }  
        },  
        "ios":{  
            "type":"notify",  
            "payload":"自定义消息",  
            "aps":{  
                "alert":{  
                    "title":"请填写ios标题",  
                    "body":"请填写ios内容"  
                },  
                "content-available":0  
            },  
            "auto_badge":"+1"  
        }  
    }  
}

以上参数中需要特别注意的是 push_channel 字段中的内容,是走离线推送的通道设置。不可省略。其中 click_type 必须为 intent,intent 中的内容保持上述我的模板,替换你自己的应用包名即可。S.title=标题内容;S.content=消息内容;S.payload=test 可以替换成你自己的内容,与 title ,body 保持一致。

其他问题:
1、离线推送后手机不亮屏、不提醒声音及震动的解决方法。
华为手机可能会把APP的推送划为营销短信,因此被静默,需要手动在手机的 “设置”-》“通知”-》“你的应用”-》“营销通知” -》“允许通知及相关的提醒设置”

收起阅读 »

有没有想接外包的呢?uniapp开发的小程序,主要是修改bug

外包 小程序

有没有想接外包的呢?uniapp开发的小程序,主要是修改bug
有兴趣的联系我哦
qq:506747229
微信:else_null

有没有想接外包的呢?uniapp开发的小程序,主要是修改bug
有兴趣的联系我哦
qq:506747229
微信:else_null

vuejs视频教程

vuejs视频教程

https://learning.dcloud.io/index.html#/?vid=8

vuejs视频教程

vuejs视频教程

https://learning.dcloud.io/index.html#/?vid=8

vuejs视频教程

MUI 和 Html 5 plus开发的APP中,底部选项卡凸起大图标功能实现 [从登录页进入主页的情况]

在这里写的文章无法访问,参考的我的博客:https://blog.csdn.net/qzyw525942/article/details/115749934
或者下载下面的附件Demo查看效果

在这里写的文章无法访问,参考的我的博客:https://blog.csdn.net/qzyw525942/article/details/115749934
或者下载下面的附件Demo查看效果

MUI 和 Html 5 plus开发的APP中底部选项卡凸起大图标功能实现 [从登录页进入主页的情况]

a、官方案例的效果:

效果如下,中间有个选项卡是凸起的:

在开发工具中,创建项目的时候,选择如下即可创建模板:

注意:这个功能只能用在初始页进来就是首页的情况,如果进来的第一个页面是登录页,则登录页就会有底部选项卡,这种功能不可取。不建议使用,应该使用下面的改造案例:

b、基于官方案例的改造

上面已经提到官方案例有所欠缺,下面基于官方案例进行改造。

其实官方案例之所以会出现,如果登录页是第一个页面的话,登录页也会有底部选项卡的情况,主要原因就是其在manifest.json中的plus下配置了launchwebview:

"plus": {  
        "launchwebview": {  
            "bottom": "0px",  
            "background": "#fff",  
            "subNViews": [  
                {  

这就会导致第一个启动页面就会有底部选项卡。如果APP是先经过登录再进入主页的情况,这种方式显然不可取。

创建一个5+app新项目,index.html中如下: [这个页面模拟登录页,不会出现底部选项卡的情况]

<body>  
        <button type="button" class="mui-btn mui-btn-blue" id="info">跳转主页面</button>  
    </body>  
    <script type="text/javascript">  
        mui.plusReady(function() {  
            document.getElementById('info').addEventListener('tap', function() {  
                //打开页面  
                mui.openWindow({  
                    url: 'bth.html',  
                    id: 'bth.html'  
                });  
            });  
        })  
    </script>

其中btn.html如下:

<!DOCTYPE html>  
<html>  
    <head>  
        <meta charset="utf-8">  
        <meta name="viewport"  
            content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />  
        <title></title>  
        <script src="js/mui.js" type="text/javascript" charset="utf-8"></script>  
        <link rel="stylesheet" type="text/css" href="./css/mui.css" />  
        <script src="js/util.js" type="text/javascript" charset="utf-8"></script> <!-- -->  
        <script src="js/jquery-3.5.1.min.js" type="text/javascript" charset="utf-8"></script>  
        <script type="text/javascript" charset="utf-8">  
            mui.init();  
        </script>  
    </head>  
    <body>  
        <nav class="mui-bar mui-bar-tab">  
            <a class="mui-tab-item" href="pages/a.html">  
                <span class="mui-icon mui-icon-home"></span>  
                <span class="mui-tab-label">首页</span>  
            </a>  
            <a class="mui-tab-item" href="pages/b.html">  
                <span class="mui-icon mui-icon-phone"></span>  
                <span class="mui-tab-label">电话</span>  
            </a>  
            <a class="mui-tab-item"><!-- 给中部凸起大图标占个位置,使得左右两边的tab按钮均匀分布,实际这个tab没用到 -->  
                <span>占位</span>  
            </a>  
            <a class="mui-tab-item" href="pages/c.html">  
                <span class="mui-icon mui-icon-email"></span>  
                <span class="mui-tab-label">邮件</span>  
            </a>  
            <a class="mui-tab-item" href="pages/d.html">  
                <span class="mui-icon mui-icon-gear"></span>  
                <span class="mui-tab-label">设置</span>  
            </a>  
        </nav>  
    </body>  
    <script type="text/javascript">  
        var index = 0;  
        var subpages = ['pages/a.html', 'pages/b.html', 'pages/center.html', 'pages/c.html', 'pages/d.html'];  
        mui.plusReady(function() {  
            var self = plus.webview.currentWebview();  

            //如下在中部添加一个凸起图标  
            var leftPos = Math.ceil((window.innerWidth - 60) / 2); // 设置凸起大图标为水平居中  

            /**  
             * drawNativeIcon 绘制中部凸起大图标,具体参数含义参考plus.nativeObj.View(id, styles, tags)文档说明[http://www.html5plus.org/doc/zh_cn/nativeobj.html#plus.nativeObj.View]  
             * 实现原理:  
             *   id为bg的tag 创建带边框的圆  
             *   id为bg2的tag 创建白色矩形遮住圆下半部分,只显示凸起带边框部分  
             *   id为iconBg的红色背景图  
             *   id为icon的字体图标  
             *   注意创建先后顺序,创建越晚的层级越高  
             */  
            var drawNativeIcon = util.drawNative('icon', {  
                bottom: '5px',  
                left: leftPos + 'px',  
                width: '60px',  
                height: '60px'  
            }, [{  
                    tag: 'rect', //创建带边框的圆。 "rect" - 绘制矩形区域,与drawRect操作一致,此时id、color、position、rectStyles属性值有效  
                    id: 'bg',  
                    position: {  
                        top: '1px',  
                        left: '0px',  
                        width: '100%',  
                        height: '100%'  
                    },  
                    rectStyles: {  
                        color: '#fff',  
                        radius: '50%',  
                        borderColor: '#ccc',  
                        borderWidth: '1px'  
                    }  
                }, {  
                    tag: 'rect', //创建白色矩形遮住圆下半部分,只显示凸起带边框部分  
                    id: 'bg2',  
                    position: {  
                        bottom: '-0.5px',  
                        left: '0px',  
                        width: '100%',  
                        height: '45px'  
                    },  
                    rectStyles: {  
                        color: '#fff'  
                    }  
                }, {  
                    tag: 'rect', //创建绿色背景图  
                    id: 'iconBg',  
                    position: {  
                        top: '5px',  
                        left: '5px',  
                        width: '50px',  
                        height: '50px'  
                    },  
                    rectStyles: {  
                        color: '#00aa00',  
                        radius: '50%'  
                    }  
                }, {  
                    tag: 'font', //创建文字。 "font" - 绘制文本内容,与drawText操作一致,此时id、position、text、textStyles属性值有效;  
                    id: 'icon',  
                    text: 'B',  
                    position: {  
                        top: '0px',  
                        left: '5px',  
                        width: '50px',  
                        height: '100%'  
                    },  
                    textStyles: {  
                        fontSrc: '_www/fonts/iconfont.ttf',  
                        align: 'center',  
                        color: '#fff',  
                        size: '30px'  
                    }  
                },  
                /* {  
                tag: 'img', //"img" - 绘制图片,与drawBitmap操作一致,此时id、src、position、sprite属性值有效;   
                id: 'img',  
                src: 'img/a.png',  
                position: {  
                    top: '15px',  
                    left: '5px',  
                    width: '50px',  
                    height: '80%'  
                }  
            } */  
            ]);  

            // 把创建的中央凸起图标append 到父webview中  
            self.append(drawNativeIcon);  

            //自定义监听凸起图标点击事件  
            var active_color = '#fff'; //激活的颜色  
            drawNativeIcon.addEventListener('click', function(e) {  

                //显示凸起图标对应的页面,隐藏其它几个Tab对应的页面  
                plus.webview.show('pages/center.html');  
                plus.webview.hide('pages/a.html');  
                plus.webview.hide('pages/b.html');  
                plus.webview.hide('pages/c.html');  
                plus.webview.hide('pages/d.html');  

                //取消其它几个Tab对应的页面的选中效果  
                $(".mui-tab-item").removeClass('mui-active');  

                // 重绘字体颜色  
                if (active_color == '#fff') {  
                    drawNativeIcon.drawText('A', {}, {  
                        fontSrc: '_www/fonts/iconfont.ttf',  
                        align: 'center',  
                        color: '#000',  
                        size: '30px'  
                    }, 'icon');  
                    active_color = '#000';  
                } else {  
                    drawNativeIcon.drawText('B', {}, {  
                        fontSrc: '_www/fonts/iconfont.ttf',  
                        align: 'center',  
                        color: '#fff',  
                        size: '30px'  
                    }, 'icon');  
                    active_color = '#fff';  
                }  
            });  

            //如下把每个tab对应的页面加载到当前webview  
            for (var i = 0; i < 5; i++) {  
                var sub = plus.webview.create(  
                    subpages[i], //url  
                    subpages[i], //id  
                    {  
                        top: "45px", //子页面距离顶部的位置  
                        bottom: "50px" //子页面距离底部的位置  
                    }  
                );  

                if (i != index) {  
                    sub.hide()  
                }  

                self.append(sub);  
            }  
        })   

        //如下设置除了中部大图标的四个Tab的点击切换事件  
        var activetab = subpages[index];  
        mui(".mui-bar-tab").on('tap', 'a', function(e) {  
            var targetTab = this.getAttribute('href');  
            if (activetab == targetTab) {  
                return;  
            }  

            plus.webview.show(targetTab);  
            plus.webview.hide(activetab);  

            activetab = targetTab;  
        })  
    </script>  

</html>

其中a.html、b.html、center.html、c.html、d.html很简单,每个页面只有一句话:

<body>  
    <span>我是b页面</span>  
</body>

util.js如下:

var util = {  
    /**  
     *  简单封装了绘制原生view控件的方法  
     *  绘制内容支持font(文本,字体图标),图片img , 矩形区域rect  
     */  
    drawNative: function(id, styles, tags) {  
        var view = new plus.nativeObj.View(id, styles, tags);  
        return view;  
    }  
};

manifest.json无需配置任何东西即可。

效果如下:

Demo源码见本文后面的附件:ButtomTabHump.zip

也可以参考我的博客:https://blog.csdn.net/qzyw525942/article/details/115749934

继续阅读 »

a、官方案例的效果:

效果如下,中间有个选项卡是凸起的:

在开发工具中,创建项目的时候,选择如下即可创建模板:

注意:这个功能只能用在初始页进来就是首页的情况,如果进来的第一个页面是登录页,则登录页就会有底部选项卡,这种功能不可取。不建议使用,应该使用下面的改造案例:

b、基于官方案例的改造

上面已经提到官方案例有所欠缺,下面基于官方案例进行改造。

其实官方案例之所以会出现,如果登录页是第一个页面的话,登录页也会有底部选项卡的情况,主要原因就是其在manifest.json中的plus下配置了launchwebview:

"plus": {  
        "launchwebview": {  
            "bottom": "0px",  
            "background": "#fff",  
            "subNViews": [  
                {  

这就会导致第一个启动页面就会有底部选项卡。如果APP是先经过登录再进入主页的情况,这种方式显然不可取。

创建一个5+app新项目,index.html中如下: [这个页面模拟登录页,不会出现底部选项卡的情况]

<body>  
        <button type="button" class="mui-btn mui-btn-blue" id="info">跳转主页面</button>  
    </body>  
    <script type="text/javascript">  
        mui.plusReady(function() {  
            document.getElementById('info').addEventListener('tap', function() {  
                //打开页面  
                mui.openWindow({  
                    url: 'bth.html',  
                    id: 'bth.html'  
                });  
            });  
        })  
    </script>

其中btn.html如下:

<!DOCTYPE html>  
<html>  
    <head>  
        <meta charset="utf-8">  
        <meta name="viewport"  
            content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />  
        <title></title>  
        <script src="js/mui.js" type="text/javascript" charset="utf-8"></script>  
        <link rel="stylesheet" type="text/css" href="./css/mui.css" />  
        <script src="js/util.js" type="text/javascript" charset="utf-8"></script> <!-- -->  
        <script src="js/jquery-3.5.1.min.js" type="text/javascript" charset="utf-8"></script>  
        <script type="text/javascript" charset="utf-8">  
            mui.init();  
        </script>  
    </head>  
    <body>  
        <nav class="mui-bar mui-bar-tab">  
            <a class="mui-tab-item" href="pages/a.html">  
                <span class="mui-icon mui-icon-home"></span>  
                <span class="mui-tab-label">首页</span>  
            </a>  
            <a class="mui-tab-item" href="pages/b.html">  
                <span class="mui-icon mui-icon-phone"></span>  
                <span class="mui-tab-label">电话</span>  
            </a>  
            <a class="mui-tab-item"><!-- 给中部凸起大图标占个位置,使得左右两边的tab按钮均匀分布,实际这个tab没用到 -->  
                <span>占位</span>  
            </a>  
            <a class="mui-tab-item" href="pages/c.html">  
                <span class="mui-icon mui-icon-email"></span>  
                <span class="mui-tab-label">邮件</span>  
            </a>  
            <a class="mui-tab-item" href="pages/d.html">  
                <span class="mui-icon mui-icon-gear"></span>  
                <span class="mui-tab-label">设置</span>  
            </a>  
        </nav>  
    </body>  
    <script type="text/javascript">  
        var index = 0;  
        var subpages = ['pages/a.html', 'pages/b.html', 'pages/center.html', 'pages/c.html', 'pages/d.html'];  
        mui.plusReady(function() {  
            var self = plus.webview.currentWebview();  

            //如下在中部添加一个凸起图标  
            var leftPos = Math.ceil((window.innerWidth - 60) / 2); // 设置凸起大图标为水平居中  

            /**  
             * drawNativeIcon 绘制中部凸起大图标,具体参数含义参考plus.nativeObj.View(id, styles, tags)文档说明[http://www.html5plus.org/doc/zh_cn/nativeobj.html#plus.nativeObj.View]  
             * 实现原理:  
             *   id为bg的tag 创建带边框的圆  
             *   id为bg2的tag 创建白色矩形遮住圆下半部分,只显示凸起带边框部分  
             *   id为iconBg的红色背景图  
             *   id为icon的字体图标  
             *   注意创建先后顺序,创建越晚的层级越高  
             */  
            var drawNativeIcon = util.drawNative('icon', {  
                bottom: '5px',  
                left: leftPos + 'px',  
                width: '60px',  
                height: '60px'  
            }, [{  
                    tag: 'rect', //创建带边框的圆。 "rect" - 绘制矩形区域,与drawRect操作一致,此时id、color、position、rectStyles属性值有效  
                    id: 'bg',  
                    position: {  
                        top: '1px',  
                        left: '0px',  
                        width: '100%',  
                        height: '100%'  
                    },  
                    rectStyles: {  
                        color: '#fff',  
                        radius: '50%',  
                        borderColor: '#ccc',  
                        borderWidth: '1px'  
                    }  
                }, {  
                    tag: 'rect', //创建白色矩形遮住圆下半部分,只显示凸起带边框部分  
                    id: 'bg2',  
                    position: {  
                        bottom: '-0.5px',  
                        left: '0px',  
                        width: '100%',  
                        height: '45px'  
                    },  
                    rectStyles: {  
                        color: '#fff'  
                    }  
                }, {  
                    tag: 'rect', //创建绿色背景图  
                    id: 'iconBg',  
                    position: {  
                        top: '5px',  
                        left: '5px',  
                        width: '50px',  
                        height: '50px'  
                    },  
                    rectStyles: {  
                        color: '#00aa00',  
                        radius: '50%'  
                    }  
                }, {  
                    tag: 'font', //创建文字。 "font" - 绘制文本内容,与drawText操作一致,此时id、position、text、textStyles属性值有效;  
                    id: 'icon',  
                    text: 'B',  
                    position: {  
                        top: '0px',  
                        left: '5px',  
                        width: '50px',  
                        height: '100%'  
                    },  
                    textStyles: {  
                        fontSrc: '_www/fonts/iconfont.ttf',  
                        align: 'center',  
                        color: '#fff',  
                        size: '30px'  
                    }  
                },  
                /* {  
                tag: 'img', //"img" - 绘制图片,与drawBitmap操作一致,此时id、src、position、sprite属性值有效;   
                id: 'img',  
                src: 'img/a.png',  
                position: {  
                    top: '15px',  
                    left: '5px',  
                    width: '50px',  
                    height: '80%'  
                }  
            } */  
            ]);  

            // 把创建的中央凸起图标append 到父webview中  
            self.append(drawNativeIcon);  

            //自定义监听凸起图标点击事件  
            var active_color = '#fff'; //激活的颜色  
            drawNativeIcon.addEventListener('click', function(e) {  

                //显示凸起图标对应的页面,隐藏其它几个Tab对应的页面  
                plus.webview.show('pages/center.html');  
                plus.webview.hide('pages/a.html');  
                plus.webview.hide('pages/b.html');  
                plus.webview.hide('pages/c.html');  
                plus.webview.hide('pages/d.html');  

                //取消其它几个Tab对应的页面的选中效果  
                $(".mui-tab-item").removeClass('mui-active');  

                // 重绘字体颜色  
                if (active_color == '#fff') {  
                    drawNativeIcon.drawText('A', {}, {  
                        fontSrc: '_www/fonts/iconfont.ttf',  
                        align: 'center',  
                        color: '#000',  
                        size: '30px'  
                    }, 'icon');  
                    active_color = '#000';  
                } else {  
                    drawNativeIcon.drawText('B', {}, {  
                        fontSrc: '_www/fonts/iconfont.ttf',  
                        align: 'center',  
                        color: '#fff',  
                        size: '30px'  
                    }, 'icon');  
                    active_color = '#fff';  
                }  
            });  

            //如下把每个tab对应的页面加载到当前webview  
            for (var i = 0; i < 5; i++) {  
                var sub = plus.webview.create(  
                    subpages[i], //url  
                    subpages[i], //id  
                    {  
                        top: "45px", //子页面距离顶部的位置  
                        bottom: "50px" //子页面距离底部的位置  
                    }  
                );  

                if (i != index) {  
                    sub.hide()  
                }  

                self.append(sub);  
            }  
        })   

        //如下设置除了中部大图标的四个Tab的点击切换事件  
        var activetab = subpages[index];  
        mui(".mui-bar-tab").on('tap', 'a', function(e) {  
            var targetTab = this.getAttribute('href');  
            if (activetab == targetTab) {  
                return;  
            }  

            plus.webview.show(targetTab);  
            plus.webview.hide(activetab);  

            activetab = targetTab;  
        })  
    </script>  

</html>

其中a.html、b.html、center.html、c.html、d.html很简单,每个页面只有一句话:

<body>  
    <span>我是b页面</span>  
</body>

util.js如下:

var util = {  
    /**  
     *  简单封装了绘制原生view控件的方法  
     *  绘制内容支持font(文本,字体图标),图片img , 矩形区域rect  
     */  
    drawNative: function(id, styles, tags) {  
        var view = new plus.nativeObj.View(id, styles, tags);  
        return view;  
    }  
};

manifest.json无需配置任何东西即可。

效果如下:

Demo源码见本文后面的附件:ButtomTabHump.zip

也可以参考我的博客:https://blog.csdn.net/qzyw525942/article/details/115749934

收起阅读 »

tailwind,Hbuilder创建的uniApp项目

参考以下大神的文章
https://blog.csdn.net/weixin_48299611/article/details/111567736
https://wyz.xyz/d/150-uni-app-tailwindcss
https://ask.dcloud.net.cn/article/38697

主要是第一篇文章,后两篇,是改了三个配置

separator: "", // 兼容小程序,将 : 替换成

// 兼容小程序,将默认配置里带 .和/ 清除

corePlugins: {
// 兼容小程序,将带有 * 选择器的插件禁用
preflight: false,
space: false,
divideColor: false,
divideOpacity: false,
divideStyle: false,
divideWidth: false
},

继续阅读 »

参考以下大神的文章
https://blog.csdn.net/weixin_48299611/article/details/111567736
https://wyz.xyz/d/150-uni-app-tailwindcss
https://ask.dcloud.net.cn/article/38697

主要是第一篇文章,后两篇,是改了三个配置

separator: "", // 兼容小程序,将 : 替换成

// 兼容小程序,将默认配置里带 .和/ 清除

corePlugins: {
// 兼容小程序,将带有 * 选择器的插件禁用
preflight: false,
space: false,
divideColor: false,
divideOpacity: false,
divideStyle: false,
divideWidth: false
},

收起阅读 »

clientDB联表查询策略优化调整公告

uniCloud clientDB

JQL联表查询策略调整

clientDB将于2021-04-28日上午10点,调整联表查询策略。在此时间点后如果不改动服务空间,不会有变化。如果改动了schema、uni-id模块,则会自动升级clientDB到新策略。

调整前

  • 以field方法为联表查询依据,field内存在{}时才会进行联表查询
  • collection中写3个表,第3个表可与第2个表关联查询(其实本身是错误写法,但之前版本未限制这种做法)

调整后

  • field方法仅用于字段过滤,只要collection方法内有多个表名,就会自动联表查询,无需在field中编写{}。(详见下方说明)
  • collection中写多个表名时,只要第一个表是主表,剩余表均与主表做关联查询。第3个表只能与主表联查,不能与第2个表联查。嵌套联表查询的错误用法不再予以支持,后续会提供其他写法对嵌套联表查询进行支持

调整后clientDB会自动从schema读取所有collection方法内出现的表的关联关系进行联表查询。

当多表之间存在多个foreignKey关系时,之前通过field字段指定要使用哪些foreignKey。从3.1.10版本起,clientDB新增了foreignKey方法,可通过白名单方式手动指定使用的关联关系。
类似于field白名单策略,不写就代表全要,写了就只要指定的。
foreignKey方法的参数格式是字符串。
例如:

db.collection('comment,uni-id-users')  
.foreignKey('comment.sender,comment.receiver')  
.get()

上述代码表示联查时仅使用comment表内的sender字段和receiver字段对应的foreignKey,忽略其他foreignKey关系。

clientDB已发布过渡版本3.1.10,支持foreignKey方法以方便开发者编写兼容代码,过渡版本是向下兼容的,但对即将废弃的用途做了告警。

开发者若想知道自己的联查代码是否涉及将被废弃的写法,推荐尽快更新到HBuilderX 3.1.10版本,连接本地云函数环境运行测试,触发clientDB请求,即将废弃的写法产生的请求会在控制台打印如下信息:[System Info]clientDB会在2021年4月26日进行升级,此写法不再兼容,如何调整请参考:https://ask.dcloud.net.cn/article/38966

在截止日期后,会自动移除对废弃写法的支持。

如果连接云端云函数测试clientDB兼容性,需要上传一次schema触发云端clientDB更新到3.1.10+版本

下面以附录内的三个表为例,讲解联表查询具体调整,(_id在mongoDB内有特殊的表现,下面三个表内均不以_id举例),下方所有示例代码schema及数据可在本贴附件内找到

限制错误写法

嵌套联表查询

调整前clientDB虽未暴露嵌套联查用法,但是也没有做出限制,导致有部分开发者错误的使用了下方示例的写法进行嵌套联表查询。调整后仅支持第一个表作为主表,关联其他表进行查询,不可在副表之间再进行关联,即以下写法不再支持(后续会提供其他写法来进行此类查询)

// 错误写法  
db.collection('comment,article,user')  
.field('content,article{author{name}}')  
.get()

将某字段使用as重命名为表内存在的字段

// 错误写法  
db.collection('comment')  
.field('content as comment_id') // 不支持将content重命名为comment_id因为comment_id也是comment表的字段  
.get()

联表查询副表字段过滤新写法

调整前如果要对副表数据进行过滤需要在field方法的花括号内进行过滤,如以下写法对副表user进行字段过滤,仅获取user表的name

调整后应将主表副表合并查询后的结果看作一个表,直接通过.进行副表字段的筛选。旧写法仍支持

// 调整前写法  
db.collection('article,user')  
.where('article_id=="1"')  
.field('title,content,author{name}')  
.get()
// 调整后写法  
db.collection('article,user')  
.where('article_id=="1"')  
.field('title,content,author.name')  
.get()

注意此写法副表别名的表现,见下方示例

// 调整后写法  
db.collection('article,user')  
.where('article_id=="1"')  
.field('title,content,author.name as author_name')  
.get()

返回结果

[{  
  "title": "title1",  
  "content": "content1",  
  "author_name": ["user1"] // 联表后author是一个数组,此处表现为将author下每一项的name提取出来作为一个数组  
}]

自动进行数据表的关联

调整前clientDB会根据传入的field对collection内的表进行关联,即仅使用field内{}明确表示的关联关系。调整后,clientDB会自动补足主表和副表之间的关联关系,即使field内不存在{}

此调整可能会导致原有联表查询访问调整前并未访问的字段,如果此字段恰好无权访问会导致查询报错

例1:

db.collection('comment,article')  
.where('comment_id=="1-1"')  
.field('content,article')  
.get()

由于collection内包含两个集合,上述代码在调整后会自动进行联表查询(使用所有的关联关系),查询到的结果如下

// 调整后结果  
[{  
  "content": "comment1-1",  
  "article": [{  
    "article_id": "1",  
    "title": "title1",  
    "content": "content1",  
    "author": "1"  
  }]  
}]  

// 调整前结果  
[{  
  "content": "comment1-1",  
  "article": "1"  
}]

例1在调整前下不会进行联表查询,如果希望维持旧的表现只需要去除collection方法内的article表即可

db.collection('comment')  
.where('comment_id=="1-1"')  
.field('content,article')  
.get()

例2:

db.collection('comment,user')  
.where('comment_id=="1-1"')  
.field('content,sender,receiver{name}')  
.get()

comment表内sender和receiver均存在foreignKey指向user表,调整前上述写法不会使用sender对应的foreignKey进行联表查询,调整后sender对应的foreignKey也会进行一次联表查询,如果仅希望receiver字段对应的foreignKey生效可以使用如下写法

// 例2调整为此写法能同时兼容新旧用法  
db.collection('comment,user')  
.where('comment_id=="1-1"')  
.field('content,sender,receiver.name') // 去除原查询中的花括号  
.foreignKey('comment.receiver') // 仅使用comment表内receiver字段下的foreignKey  
.get()

<unicloud-db>组件调整也和clientDB api类似,新增了一个foreignKey属性传值同上

<unicloud-db collection="comment,user" where="comment_id=='1-1'" field="content,sender,receiver{name}" foreignKey="comment.receiver"></unicloud-db>

例3:

存在不止两个表的联表查询也是一样会自动补足所有副表和主表的关系(注意仅在所有副表和主表之间进行关联查询,副表之间即使存在关联关系也无法进行关联查询)

db.collection('comment,article,user')  
.where('comment_id=="1-1"')  
.get()

返回结果如下

[{  
  "comment_id": "1-1",  
  "content": "comment1-1",  
  "article": [{  
    "article_id": "1",  
    "title": "title1",  
    "content": "content1",  
    "author": "1"  
  }],  
  "sender": [{  
    "uid": "1",  
    "name": "user1"  
  }],  
  "receiver": [{  
    "uid": "2",  
    "name": "user2"  
  }]  
}]

副表foreignKey联查

之前的clientDB版本,只支持主表的foreignKey,把副本内容嵌入主表的foreignKey字段下面。不支持处理副本的foreignKey。(如果你觉得能用,其实是bug,查出来的数是乱的,别依赖这种写法)

调整后,新版将正式支持副表foreignKey联查。将把副本的数据以数组的方式嵌入到主表中。

例:

db.collection('article,comment')  
.where('article_id=="1"')  
.field('content,article_id')  
.get()

查询结果如下:

[{  
  "content": "content1",  
  "article_id": {  
    "comment": [{ // 逆向foreignKey查询时此处会自动插入一层副表表名  
      "comment_id": "1-1",  
      "content": "comment1-1",  
      "article": "1",  
      "sender": "1",  
      "receiver": "2"  
    },  
    {  
      "comment_id": "1-2",  
      "content": "comment1-2",  
      "article": "1",  
      "sender": "2",  
      "receiver": "1"  
    }]  
  }  
}]

如需对上述查询的副表字段进行过滤,需要注意多插入的一层副表表名

// 过滤副表字段  
db.collection('article,comment')  
.where('article_id=="1"')  
.field('content,article_id{comment{content}}')  
.get()  

// 查询结果如下  
[{  
  "content": "content1",  
  "article_id": {  
    "comment": [{ // 使用副本foreignKey联查时此处会自动插入一层副表表名  
      "content": "comment1-1"  
    },  
    {  
      "content": "comment1-2"  
    }]  
  }  
}]

附录

表结构及数据

// user - 用户表  

// schema  
{  
  "bsonType": "object",  
  "required": [],  
  "permission": {  
    "read": true,  
    "create": false,  
    "update": false,  
    "delete": false  
  },  
  "properties": {  
    "uid": {  
      "bsonType": "string"  
    },  
    "name": {  
      "bsonType": "string"  
    }  
  }  
}  

// data  
{  
  "uid": "1",  
  "name": "user1"  
}  
{  
  "uid": "2",  
  "name": "user2"  
}
// article - 文章表  

// schema  
{  
  "bsonType": "object",  
  "required": [],  
  "permission": {  
    "read": true,  
    "create": false,  
    "update": false,  
    "delete": false  
  },  
  "properties": {  
    "article_id": {  
      "bsonType": "string"  
    },  
    "title": {  
      "bsonType": "string"  
    },  
    "content": {  
      "bsonType": "string"  
    },  
    "author": {  
      "bsonType": "string",  
      "foreignKey": "user.uid"  
    }  
  }  
}  

// data  
{  
  "article_id": "1",  
  "title": "title1",  
  "content": "content1",  
  "author": "1"  
}  
{  
  "article_id": "2",  
  "title": "title2",  
  "content": "content2",  
  "author": "1"  
}  
{  
  "article_id": "3",  
  "title": "title3",  
  "content": "content3",  
  "author": "2"  
}
// comment - 评论表  

// schema  
{  
  "bsonType": "object",  
  "required": [],  
  "permission": {  
    "read": true,  
    "create": false,  
    "update": false,  
    "delete": false  
  },  
  "properties": {  
    "comment_id": {  
      "bsonType": "string"  
    },  
    "content": {  
      "bsonType": "string"  
    },  
    "article": {  
      "bsonType": "string",  
      "foreignKey": "article.article_id"  
    },  
    "sender": {  
      "bsonType": "string",  
      "foreignKey": "user.uid"  
    },  
    "receiver": {  
      "bsonType": "string",  
      "foreignKey": "user.uid"  
    }  
  }  
}  

// data  
{  
  "comment_id": "1-1",  
  "content": "comment1-1",  
  "article": "1",  
  "sender": "1",  
  "receiver": "2"  
}  
{  
  "comment_id": "1-2",  
  "content": "comment1-2",  
  "article": "1",  
  "sender": "2",  
  "receiver": "1"  
}  
{  
  "comment_id": "2-1",  
  "content": "comment2-1",  
  "article": "2",  
  "sender": "1",  
  "receiver": "2"  
}  
{  
  "comment_id": "2-2",  
  "content": "comment2-2",  
  "article": "2",  
  "sender": "2",  
  "receiver": "1"  
}
继续阅读 »

JQL联表查询策略调整

clientDB将于2021-04-28日上午10点,调整联表查询策略。在此时间点后如果不改动服务空间,不会有变化。如果改动了schema、uni-id模块,则会自动升级clientDB到新策略。

调整前

  • 以field方法为联表查询依据,field内存在{}时才会进行联表查询
  • collection中写3个表,第3个表可与第2个表关联查询(其实本身是错误写法,但之前版本未限制这种做法)

调整后

  • field方法仅用于字段过滤,只要collection方法内有多个表名,就会自动联表查询,无需在field中编写{}。(详见下方说明)
  • collection中写多个表名时,只要第一个表是主表,剩余表均与主表做关联查询。第3个表只能与主表联查,不能与第2个表联查。嵌套联表查询的错误用法不再予以支持,后续会提供其他写法对嵌套联表查询进行支持

调整后clientDB会自动从schema读取所有collection方法内出现的表的关联关系进行联表查询。

当多表之间存在多个foreignKey关系时,之前通过field字段指定要使用哪些foreignKey。从3.1.10版本起,clientDB新增了foreignKey方法,可通过白名单方式手动指定使用的关联关系。
类似于field白名单策略,不写就代表全要,写了就只要指定的。
foreignKey方法的参数格式是字符串。
例如:

db.collection('comment,uni-id-users')  
.foreignKey('comment.sender,comment.receiver')  
.get()

上述代码表示联查时仅使用comment表内的sender字段和receiver字段对应的foreignKey,忽略其他foreignKey关系。

clientDB已发布过渡版本3.1.10,支持foreignKey方法以方便开发者编写兼容代码,过渡版本是向下兼容的,但对即将废弃的用途做了告警。

开发者若想知道自己的联查代码是否涉及将被废弃的写法,推荐尽快更新到HBuilderX 3.1.10版本,连接本地云函数环境运行测试,触发clientDB请求,即将废弃的写法产生的请求会在控制台打印如下信息:[System Info]clientDB会在2021年4月26日进行升级,此写法不再兼容,如何调整请参考:https://ask.dcloud.net.cn/article/38966

在截止日期后,会自动移除对废弃写法的支持。

如果连接云端云函数测试clientDB兼容性,需要上传一次schema触发云端clientDB更新到3.1.10+版本

下面以附录内的三个表为例,讲解联表查询具体调整,(_id在mongoDB内有特殊的表现,下面三个表内均不以_id举例),下方所有示例代码schema及数据可在本贴附件内找到

限制错误写法

嵌套联表查询

调整前clientDB虽未暴露嵌套联查用法,但是也没有做出限制,导致有部分开发者错误的使用了下方示例的写法进行嵌套联表查询。调整后仅支持第一个表作为主表,关联其他表进行查询,不可在副表之间再进行关联,即以下写法不再支持(后续会提供其他写法来进行此类查询)

// 错误写法  
db.collection('comment,article,user')  
.field('content,article{author{name}}')  
.get()

将某字段使用as重命名为表内存在的字段

// 错误写法  
db.collection('comment')  
.field('content as comment_id') // 不支持将content重命名为comment_id因为comment_id也是comment表的字段  
.get()

联表查询副表字段过滤新写法

调整前如果要对副表数据进行过滤需要在field方法的花括号内进行过滤,如以下写法对副表user进行字段过滤,仅获取user表的name

调整后应将主表副表合并查询后的结果看作一个表,直接通过.进行副表字段的筛选。旧写法仍支持

// 调整前写法  
db.collection('article,user')  
.where('article_id=="1"')  
.field('title,content,author{name}')  
.get()
// 调整后写法  
db.collection('article,user')  
.where('article_id=="1"')  
.field('title,content,author.name')  
.get()

注意此写法副表别名的表现,见下方示例

// 调整后写法  
db.collection('article,user')  
.where('article_id=="1"')  
.field('title,content,author.name as author_name')  
.get()

返回结果

[{  
  "title": "title1",  
  "content": "content1",  
  "author_name": ["user1"] // 联表后author是一个数组,此处表现为将author下每一项的name提取出来作为一个数组  
}]

自动进行数据表的关联

调整前clientDB会根据传入的field对collection内的表进行关联,即仅使用field内{}明确表示的关联关系。调整后,clientDB会自动补足主表和副表之间的关联关系,即使field内不存在{}

此调整可能会导致原有联表查询访问调整前并未访问的字段,如果此字段恰好无权访问会导致查询报错

例1:

db.collection('comment,article')  
.where('comment_id=="1-1"')  
.field('content,article')  
.get()

由于collection内包含两个集合,上述代码在调整后会自动进行联表查询(使用所有的关联关系),查询到的结果如下

// 调整后结果  
[{  
  "content": "comment1-1",  
  "article": [{  
    "article_id": "1",  
    "title": "title1",  
    "content": "content1",  
    "author": "1"  
  }]  
}]  

// 调整前结果  
[{  
  "content": "comment1-1",  
  "article": "1"  
}]

例1在调整前下不会进行联表查询,如果希望维持旧的表现只需要去除collection方法内的article表即可

db.collection('comment')  
.where('comment_id=="1-1"')  
.field('content,article')  
.get()

例2:

db.collection('comment,user')  
.where('comment_id=="1-1"')  
.field('content,sender,receiver{name}')  
.get()

comment表内sender和receiver均存在foreignKey指向user表,调整前上述写法不会使用sender对应的foreignKey进行联表查询,调整后sender对应的foreignKey也会进行一次联表查询,如果仅希望receiver字段对应的foreignKey生效可以使用如下写法

// 例2调整为此写法能同时兼容新旧用法  
db.collection('comment,user')  
.where('comment_id=="1-1"')  
.field('content,sender,receiver.name') // 去除原查询中的花括号  
.foreignKey('comment.receiver') // 仅使用comment表内receiver字段下的foreignKey  
.get()

<unicloud-db>组件调整也和clientDB api类似,新增了一个foreignKey属性传值同上

<unicloud-db collection="comment,user" where="comment_id=='1-1'" field="content,sender,receiver{name}" foreignKey="comment.receiver"></unicloud-db>

例3:

存在不止两个表的联表查询也是一样会自动补足所有副表和主表的关系(注意仅在所有副表和主表之间进行关联查询,副表之间即使存在关联关系也无法进行关联查询)

db.collection('comment,article,user')  
.where('comment_id=="1-1"')  
.get()

返回结果如下

[{  
  "comment_id": "1-1",  
  "content": "comment1-1",  
  "article": [{  
    "article_id": "1",  
    "title": "title1",  
    "content": "content1",  
    "author": "1"  
  }],  
  "sender": [{  
    "uid": "1",  
    "name": "user1"  
  }],  
  "receiver": [{  
    "uid": "2",  
    "name": "user2"  
  }]  
}]

副表foreignKey联查

之前的clientDB版本,只支持主表的foreignKey,把副本内容嵌入主表的foreignKey字段下面。不支持处理副本的foreignKey。(如果你觉得能用,其实是bug,查出来的数是乱的,别依赖这种写法)

调整后,新版将正式支持副表foreignKey联查。将把副本的数据以数组的方式嵌入到主表中。

例:

db.collection('article,comment')  
.where('article_id=="1"')  
.field('content,article_id')  
.get()

查询结果如下:

[{  
  "content": "content1",  
  "article_id": {  
    "comment": [{ // 逆向foreignKey查询时此处会自动插入一层副表表名  
      "comment_id": "1-1",  
      "content": "comment1-1",  
      "article": "1",  
      "sender": "1",  
      "receiver": "2"  
    },  
    {  
      "comment_id": "1-2",  
      "content": "comment1-2",  
      "article": "1",  
      "sender": "2",  
      "receiver": "1"  
    }]  
  }  
}]

如需对上述查询的副表字段进行过滤,需要注意多插入的一层副表表名

// 过滤副表字段  
db.collection('article,comment')  
.where('article_id=="1"')  
.field('content,article_id{comment{content}}')  
.get()  

// 查询结果如下  
[{  
  "content": "content1",  
  "article_id": {  
    "comment": [{ // 使用副本foreignKey联查时此处会自动插入一层副表表名  
      "content": "comment1-1"  
    },  
    {  
      "content": "comment1-2"  
    }]  
  }  
}]

附录

表结构及数据

// user - 用户表  

// schema  
{  
  "bsonType": "object",  
  "required": [],  
  "permission": {  
    "read": true,  
    "create": false,  
    "update": false,  
    "delete": false  
  },  
  "properties": {  
    "uid": {  
      "bsonType": "string"  
    },  
    "name": {  
      "bsonType": "string"  
    }  
  }  
}  

// data  
{  
  "uid": "1",  
  "name": "user1"  
}  
{  
  "uid": "2",  
  "name": "user2"  
}
// article - 文章表  

// schema  
{  
  "bsonType": "object",  
  "required": [],  
  "permission": {  
    "read": true,  
    "create": false,  
    "update": false,  
    "delete": false  
  },  
  "properties": {  
    "article_id": {  
      "bsonType": "string"  
    },  
    "title": {  
      "bsonType": "string"  
    },  
    "content": {  
      "bsonType": "string"  
    },  
    "author": {  
      "bsonType": "string",  
      "foreignKey": "user.uid"  
    }  
  }  
}  

// data  
{  
  "article_id": "1",  
  "title": "title1",  
  "content": "content1",  
  "author": "1"  
}  
{  
  "article_id": "2",  
  "title": "title2",  
  "content": "content2",  
  "author": "1"  
}  
{  
  "article_id": "3",  
  "title": "title3",  
  "content": "content3",  
  "author": "2"  
}
// comment - 评论表  

// schema  
{  
  "bsonType": "object",  
  "required": [],  
  "permission": {  
    "read": true,  
    "create": false,  
    "update": false,  
    "delete": false  
  },  
  "properties": {  
    "comment_id": {  
      "bsonType": "string"  
    },  
    "content": {  
      "bsonType": "string"  
    },  
    "article": {  
      "bsonType": "string",  
      "foreignKey": "article.article_id"  
    },  
    "sender": {  
      "bsonType": "string",  
      "foreignKey": "user.uid"  
    },  
    "receiver": {  
      "bsonType": "string",  
      "foreignKey": "user.uid"  
    }  
  }  
}  

// data  
{  
  "comment_id": "1-1",  
  "content": "comment1-1",  
  "article": "1",  
  "sender": "1",  
  "receiver": "2"  
}  
{  
  "comment_id": "1-2",  
  "content": "comment1-2",  
  "article": "1",  
  "sender": "2",  
  "receiver": "1"  
}  
{  
  "comment_id": "2-1",  
  "content": "comment2-1",  
  "article": "2",  
  "sender": "1",  
  "receiver": "2"  
}  
{  
  "comment_id": "2-2",  
  "content": "comment2-2",  
  "article": "2",  
  "sender": "2",  
  "receiver": "1"  
}
收起阅读 »

无视法律从事网络赌博客服非法获利50万元,7人在开州获刑

法律科普

随着互联网和信息化技术的蓬勃发展,许多赌博活动改头换面,从现实生活中转移到网络空间,令人防不胜防,而通过网络邀请、发展他人参与赌博等违法行为更是与日俱增,值得警醒。


经法院审理查明

谭某、邱某(均已判刑)组织人员分别在重庆市开州区、万州区、渝中区、四川省成都市等地设立网络赌博代理点,先后运营“大满贯”、“黄金娱乐城”、“极乐宝典”等赌博APP,招募姜某、邓某燕、吴某月等7人在各代理点作为客服人员,负责日常赌博游戏宣传,向参赌人员销售赌博游戏“金币”、游戏“金币”兑换现金以及转账等工作,并以固定工资加销售提成的方式获利。

经统计

姜某、邓某燕、吴某月等7人在网络赌博代理点工作期间的非法获利从五万元到十万元不等,7人共计获利近五十万元。

2020年末,姜某、邓某燕、吴某月等7人经民警电话通知分别主动投案,后如实供述自己的犯罪事实。

法院审理认为

被告人姜某、吴某月、邓某燕、左某杨、张某、谢某、林某英帮助开设赌场,其行为均已构成开设赌场罪,被告人姜某、邓某燕、吴某月等7人犯罪以后自动投案,如实供述自己的罪行,均系自首,依法可以从轻处罚。依法判处被告人姜某、吴某月、邓某燕、左某杨、张某、谢某、林某英有期徒刑一年,缓刑一年至拘役三个月,缓刑五个月,并处罚金不等的刑罚。各被告人违法所得,依法予以追缴,上缴国库。

法律链接

《中华人民共和国刑法》第三百零三条第二款

开设赌场的,处三年以下有期徒刑、拘役或者管制,并处罚金;情节严重的,处三年以上十年以下有期徒刑,并处罚金

《最高人民法院、最高人民检察院、公安部办理跨境赌博犯罪案件若干问题的意见》规定:

明知是赌博网站、应用程序,有下列情形之一的,以开设赌场罪的共犯论处:

  • 为赌博网站、应用程序提供软件开发、技术支持、互联网接入、服务器托管、网络存储空间、通讯传输通道、广告投放、 会员发展、资金支付结算等服务的;

  • 为赌博网站、应用程序担任代理并发展玩家、会员、下线的

法官提醒

请广大群众一定要分清娱乐与赌博的界限,不要对线上参赌行为抱有侥幸心理,为了家人和自己请自觉抵制网络赌博,避免受到法律的制裁!

【来源:重庆市开州区人民法院】,转载自公众号:重庆市开州区人民法院,如有不当联系邮箱:pufa@dcloud.io 。
原文链接

继续阅读 »

随着互联网和信息化技术的蓬勃发展,许多赌博活动改头换面,从现实生活中转移到网络空间,令人防不胜防,而通过网络邀请、发展他人参与赌博等违法行为更是与日俱增,值得警醒。


经法院审理查明

谭某、邱某(均已判刑)组织人员分别在重庆市开州区、万州区、渝中区、四川省成都市等地设立网络赌博代理点,先后运营“大满贯”、“黄金娱乐城”、“极乐宝典”等赌博APP,招募姜某、邓某燕、吴某月等7人在各代理点作为客服人员,负责日常赌博游戏宣传,向参赌人员销售赌博游戏“金币”、游戏“金币”兑换现金以及转账等工作,并以固定工资加销售提成的方式获利。

经统计

姜某、邓某燕、吴某月等7人在网络赌博代理点工作期间的非法获利从五万元到十万元不等,7人共计获利近五十万元。

2020年末,姜某、邓某燕、吴某月等7人经民警电话通知分别主动投案,后如实供述自己的犯罪事实。

法院审理认为

被告人姜某、吴某月、邓某燕、左某杨、张某、谢某、林某英帮助开设赌场,其行为均已构成开设赌场罪,被告人姜某、邓某燕、吴某月等7人犯罪以后自动投案,如实供述自己的罪行,均系自首,依法可以从轻处罚。依法判处被告人姜某、吴某月、邓某燕、左某杨、张某、谢某、林某英有期徒刑一年,缓刑一年至拘役三个月,缓刑五个月,并处罚金不等的刑罚。各被告人违法所得,依法予以追缴,上缴国库。

法律链接

《中华人民共和国刑法》第三百零三条第二款

开设赌场的,处三年以下有期徒刑、拘役或者管制,并处罚金;情节严重的,处三年以上十年以下有期徒刑,并处罚金

《最高人民法院、最高人民检察院、公安部办理跨境赌博犯罪案件若干问题的意见》规定:

明知是赌博网站、应用程序,有下列情形之一的,以开设赌场罪的共犯论处:

  • 为赌博网站、应用程序提供软件开发、技术支持、互联网接入、服务器托管、网络存储空间、通讯传输通道、广告投放、 会员发展、资金支付结算等服务的;

  • 为赌博网站、应用程序担任代理并发展玩家、会员、下线的

法官提醒

请广大群众一定要分清娱乐与赌博的界限,不要对线上参赌行为抱有侥幸心理,为了家人和自己请自觉抵制网络赌博,避免受到法律的制裁!

【来源:重庆市开州区人民法院】,转载自公众号:重庆市开州区人民法院,如有不当联系邮箱:pufa@dcloud.io 。
原文链接

收起阅读 »

承接uniapp、小程序、网站开发,前后端都可以,多年项目经验,坐标武汉,其他地区也可以,微信 batik88

外包接单

承接uniapp、小程序、网站开发,前后端都可以,多年项目经验,坐标武汉,其他地区也可以,欢迎加微信详谈 batik88

承接uniapp、小程序、网站开发,前后端都可以,多年项目经验,坐标武汉,其他地区也可以,欢迎加微信详谈 batik88

承接uniapp、小程序、网站开发,前后端都可以,多年项目经验,坐标武汉,微信 batik88

外包接单

承接uniapp、小程序、网站开发,前后端都可以,多年项目经验,坐标武汉,欢迎咨询微信 batik88

承接uniapp、小程序、网站开发,前后端都可以,多年项目经验,坐标武汉,欢迎咨询微信 batik88