HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

【经验分享】完美解决uni-app编译APP-PLUS 使用阿里云验证码(加载外部js使用滑动验证、图形验证)

webview通信 uni.postMessage plus.globalEvent 滑动验证 阿里云验证码 app加载外部js web_view

先上最终效果图,H5 与 App对比:




由于uni-app除H5外 均不支持document、window等浏览器的js API,所以阿里云的验证码https://g.alicdn.com/AWSC/AWSC/awsc.js(dom操作) 无法在App中直接使用。

故改为web-view加载本地html文件做滑动校验操作,通过验证将sessionId token等参数传回vue页面,最终效果与h5一模一样,用户不会感知是web-view加载的验证。

vue 页面代码:


// 点击发送验证码判断是否为App  
// #ifdef APP-PLUS  
return this.appCreateVerify()  
// #endif  

// plus创建web-view方法  
appCreateVerify() {  
    // 阿里云验证码 App打开本地verify页面(uni-app本地html存放在根目录/hybrid/html中)  
    if (wv) {  
        return wv.show()  
    }  
    wv = plus.webview.create('', 'custom-webview', {  
        'uni-app': 'none',  
        background: 'transparent',  
        webviewBGTransparent: true  
    }, {  
        appkey: this.nc.appkey,  
        scene: this.nc.scene  
    })  
    wv.loadURL('/hybrid/html/awsc-verify.html')  
    const currentWebview = this.$scope.$getAppWebview()  
        // 此处监听uni.postMessage传递参数  
    plus.globalEvent.addEventListener('plusMessage', msg => {  
        const result = msg.data.args.data  
        if(result.name == 'postMessage'){  
            this.querySendCode(result.arg)  
        }    
    })  
    currentWebview.append(wv)  
},  
// 发送验证码请求  
querySendCode(data) {  
    if (this.sending) return // 阻止awsc或事件监听 重复触发问题  
    this.sending = true  
    LoginSendCode({  
        phone: this.form.phone,  
        ...data,  
        scene: this.nc.scene  
    }).then(res => {  
        this.sending = false  
        if (!res.success) {  
            return uni.showToast({  
                title: res.msg,  
                icon: 'none'  
            })  
        }  
        uni.showToast({  
            title: '验证码发送成功'  
        })  
        this.second = 60  
        const timer = setInterval(() => {  
            this.second--  
            if (this.second <= 0) {  
                clearInterval(timer)  
            }  
        }, 1000)  
    })  
},  

本地html页面代码:

<style>...设置页面背景透明、滑动验证样式等</style>  

<script src="https://g.alicdn.com/AWSC/AWSC/awsc.js"></script>  
<script src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.1.js"></script>  

<script>  
    document.addEventListener('plusready', function() {  
        var wv = plus.webview.currentWebview()  
        // 阿里云滑动验证  
        window.AWSC.use('nc', function(state, module) {  
            window.nc = module.init({  
                appkey: wv.appkey,  
                scene: wv.scene,  
                renderTo: 'ncContainer',  
                success: function(data) {  
                    uni.postMessage({  
                        data  
                    })  
                    wv.hide()  
                    window.nc.reset()  
                }  
            })  
        })  
    })  
</script>  

效果还算理想,由此可见其他类似的需要操作dom的功能都能如此实现,小程序同样可以使用 <web-view>标签去实现类似功能

vue页面与本地html文件消息传输方式补充:

最近学到了新的消息传输方式,plus.globalEvent监听uni.postMessage推送的消息会出现重复推送等问题,建议改为Webview url拦截的方式获取html文件数据。

// html中跳转自定义url,会被拦截,不会进行跳转  
window.location.href = 'push?params=loading'  

// vue页面wv拦截url变更  
wv.overrideUrlLoading({mode:'reject'}, e => {  
    var params = decodeURI(e.url.split('push?params=')[1])  
})

url拦截更实时,准确率更高,不会重复接收消息,只有App支持,H5+文档参考:https://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewObject.overrideUrlLoading

继续阅读 »

先上最终效果图,H5 与 App对比:




由于uni-app除H5外 均不支持document、window等浏览器的js API,所以阿里云的验证码https://g.alicdn.com/AWSC/AWSC/awsc.js(dom操作) 无法在App中直接使用。

故改为web-view加载本地html文件做滑动校验操作,通过验证将sessionId token等参数传回vue页面,最终效果与h5一模一样,用户不会感知是web-view加载的验证。

vue 页面代码:


// 点击发送验证码判断是否为App  
// #ifdef APP-PLUS  
return this.appCreateVerify()  
// #endif  

// plus创建web-view方法  
appCreateVerify() {  
    // 阿里云验证码 App打开本地verify页面(uni-app本地html存放在根目录/hybrid/html中)  
    if (wv) {  
        return wv.show()  
    }  
    wv = plus.webview.create('', 'custom-webview', {  
        'uni-app': 'none',  
        background: 'transparent',  
        webviewBGTransparent: true  
    }, {  
        appkey: this.nc.appkey,  
        scene: this.nc.scene  
    })  
    wv.loadURL('/hybrid/html/awsc-verify.html')  
    const currentWebview = this.$scope.$getAppWebview()  
        // 此处监听uni.postMessage传递参数  
    plus.globalEvent.addEventListener('plusMessage', msg => {  
        const result = msg.data.args.data  
        if(result.name == 'postMessage'){  
            this.querySendCode(result.arg)  
        }    
    })  
    currentWebview.append(wv)  
},  
// 发送验证码请求  
querySendCode(data) {  
    if (this.sending) return // 阻止awsc或事件监听 重复触发问题  
    this.sending = true  
    LoginSendCode({  
        phone: this.form.phone,  
        ...data,  
        scene: this.nc.scene  
    }).then(res => {  
        this.sending = false  
        if (!res.success) {  
            return uni.showToast({  
                title: res.msg,  
                icon: 'none'  
            })  
        }  
        uni.showToast({  
            title: '验证码发送成功'  
        })  
        this.second = 60  
        const timer = setInterval(() => {  
            this.second--  
            if (this.second <= 0) {  
                clearInterval(timer)  
            }  
        }, 1000)  
    })  
},  

本地html页面代码:

<style>...设置页面背景透明、滑动验证样式等</style>  

<script src="https://g.alicdn.com/AWSC/AWSC/awsc.js"></script>  
<script src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.1.js"></script>  

<script>  
    document.addEventListener('plusready', function() {  
        var wv = plus.webview.currentWebview()  
        // 阿里云滑动验证  
        window.AWSC.use('nc', function(state, module) {  
            window.nc = module.init({  
                appkey: wv.appkey,  
                scene: wv.scene,  
                renderTo: 'ncContainer',  
                success: function(data) {  
                    uni.postMessage({  
                        data  
                    })  
                    wv.hide()  
                    window.nc.reset()  
                }  
            })  
        })  
    })  
</script>  

效果还算理想,由此可见其他类似的需要操作dom的功能都能如此实现,小程序同样可以使用 <web-view>标签去实现类似功能

vue页面与本地html文件消息传输方式补充:

最近学到了新的消息传输方式,plus.globalEvent监听uni.postMessage推送的消息会出现重复推送等问题,建议改为Webview url拦截的方式获取html文件数据。

// html中跳转自定义url,会被拦截,不会进行跳转  
window.location.href = 'push?params=loading'  

// vue页面wv拦截url变更  
wv.overrideUrlLoading({mode:'reject'}, e => {  
    var params = decodeURI(e.url.split('push?params=')[1])  
})

url拦截更实时,准确率更高,不会重复接收消息,只有App支持,H5+文档参考:https://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewObject.overrideUrlLoading

收起阅读 »

好好优化你们的云打包吧,都等了一个小时了。

云打包

不管是云打包还是安心打包,都是要在云上排队等待,然后就一直等待,一直等待,都等了1一个小时了。从17:41开始等待,现在都18:45分了。把人都等得心凉。茶凉人走。

不管是云打包还是安心打包,都是要在云上排队等待,然后就一直等待,一直等待,都等了1一个小时了。从17:41开始等待,现在都18:45分了。把人都等得心凉。茶凉人走。

app端ios下map marker中label的anchorY不生效,安卓中label会被marker覆盖

map

nvue模式下开发map,动态添加marker点,并设置label,ios下label的anchorY不生效,anchorX斜着移动,安卓中anchorX和anchorY均能正常移动,但是安卓中,label会被maker覆盖遮挡,无法做出如图的点聚合效果

nvue模式下开发map,动态添加marker点,并设置label,ios下label的anchorY不生效,anchorX斜着移动,安卓中anchorX和anchorY均能正常移动,但是安卓中,label会被maker覆盖遮挡,无法做出如图的点聚合效果

华为离线推送记录

离线推送 unipush

之前app云打包的证书是生成的.keystore,因为hbuild提示如何生成证书一步步来就是生成的这个,然后华为开发者后台让我们用Android Studio生成的是.jks的证书,我去查了下这俩证书有啥区别反正说的是
keystore 是Eclipse 打包生成的签名。 而 。jks是Android  studio 生成的签名!都是用来打包的,并保证应用的唯一性!这就是他们的最大的区别。
   备注:很多第三方市场,我们上传apk的时候,他们只支持keystore,需要我们把.jks签名转化为.keystore!

因为一开始不知道所以就导致了已经在华为开发者后台配置了“SHA256证书指纹”但是还是推送不成功,然后我就去unipush后台根据cid故障排查发现还是没有deviceId,然后我就按照这个文章开始排查Unipush常见问题
然后就开始adb调试发现报6003,再去查HMS Core SDK框架错误码
才发现是证书不对,然后我再hbuild打包的时候证书用的华为开发者后台配置的内个.jks的证书,在unipush后台重新提交一下华为的需要的东西,再进行重新云打包,再进行adb调试就可以获取到了

继续阅读 »

之前app云打包的证书是生成的.keystore,因为hbuild提示如何生成证书一步步来就是生成的这个,然后华为开发者后台让我们用Android Studio生成的是.jks的证书,我去查了下这俩证书有啥区别反正说的是
keystore 是Eclipse 打包生成的签名。 而 。jks是Android  studio 生成的签名!都是用来打包的,并保证应用的唯一性!这就是他们的最大的区别。
   备注:很多第三方市场,我们上传apk的时候,他们只支持keystore,需要我们把.jks签名转化为.keystore!

因为一开始不知道所以就导致了已经在华为开发者后台配置了“SHA256证书指纹”但是还是推送不成功,然后我就去unipush后台根据cid故障排查发现还是没有deviceId,然后我就按照这个文章开始排查Unipush常见问题
然后就开始adb调试发现报6003,再去查HMS Core SDK框架错误码
才发现是证书不对,然后我再hbuild打包的时候证书用的华为开发者后台配置的内个.jks的证书,在unipush后台重新提交一下华为的需要的东西,再进行重新云打包,再进行adb调试就可以获取到了

收起阅读 »

“明知他人利用信息网络实施犯罪”该如何认定?

法律科普

大家好,我是鹅师傅。今天我们来聊聊最近十分热门的网络犯罪——帮助信息网络犯罪活动罪

是不是十分绕口?为了方便,实践中都简称“帮信罪”

近年来,网络犯罪猖獗不休,各种传统犯罪日益向互联网迁移,网络犯罪呈高发多发态势,犯罪手法更是多种多样,打击网络犯罪成为经济社会稳定发展的重要任务。

帮信罪就是在这样的大背景下由《刑法修正案(九)》设立的新罪名。

截至今日,裁判文书网中涉及该罪的判决书已高达8062份,有成为网络犯罪第一罪的趋势。

而在2019年帮信罪司法解释出台之前,该罪的司法适用并没那么普遍,可以说,这个司法解释打开了帮信罪司法适用的“任督二脉”

所谓的“任督二脉”,一个是情节标准,一个就是主观明知的认定。

实践中,后者的争议最大,如何认定“明知他人利用信息网络实施犯罪”,证据达到什么状态或标准才能推定明知?

针对这个问题,鹅师傅梳理并总结了相关司法解释及裁判要点,希望可以帮助大家增进对“明知”的理解。

1、如何证明“知道”?

“我的确知道他在干违法犯罪的勾当!”

行为人自认知道对方正在利用信息网络实施违法犯罪行为,这无非是实践中最为理想的状态。虽然根据我国刑事诉讼法的规定,孤证仍不能定罪,还需要结合物证、书证等其他客观证据综合认定。但有了供述后,可以提升认定明知的内心确信,其他客观证据的要求也会明显降低。

裁判要点

①行为人明确供述知道他人利用信息网络实施犯罪的,属于明知。
[(2020)沪02刑终1125号]

②行为人供述证实其知道App软件用于诈骗并对其维护的,属于明知。
[(2020)闽04刑终221号]

③行为人供述知道办理营业执照、对公账户是出售获利,并有被犯罪使用证明的,属于明知。
[(2020)豫0502刑初314号]

④行为人供述知道银行卡购买者可能用来实施违法行为的,属于明知。
[(2020)豫0191刑初1489号]

2、“应当知道”vs“知道可能”

除了“我确实知道”情形之外,实践中更多出现的是“我并不完全确定对方是不是在做违法犯罪行为”情形。

这种不确定的主观心理状态究竟能不能被认定为“明知”,是在行为人“应当知道”还是“知道可能”的时候可以认定,存在着很大的争议。

司法解释立场

司法解释以往经常将“应当知道”规定为“明知”的一种情形。例如,2001年最高院《关于审理为境外窃取、刺探、收买、非法提供国家秘密、情报案件具体应用法律若干问题的解释》第5条中直接使用了“知道或者应当知道”。

不过,近些年来的司法解释对“明知”的态度发生了变化,不再像以前那样直接使用“知道或者应当知道”的表述,而是通过罗列相关要素的方式一般化地规定认定标准

以帮信罪相关司法解释为例,2016年两院一部所发《关于办理电信网络诈骗等刑事案件适用法律若干问题的意见》中第四部分第三点规定:“上述规定的‘明知他人实施电信网络诈骗犯罪’,应当结合被告人的认知能力,既往经历,行为次数和手段,与他人关系,获利情况,是否曾因电信网络诈骗受过处罚,是否故意规避调查等主客观因素进行综合分析认定。”

2019年两院所发《关于办理非法利用信息网络、帮助信息网络犯罪活动等刑事案件适用法律若干问题的解释》的标准更加具体化,其第十一条规定:“为他人实施犯罪提供技术支持或者帮助,具有下列情形之一的,可以认定行为人明知他人利用信息网络实施犯罪,但是有相反证据的除外:
(一)经监管部门告知后仍然实施有关行为的;  
(二)接到举报后不履行法定管理职责的;  
(三)交易价格或者方式明显异常的;  
(四)提供专门用于违法犯罪的程序、工具或者其他技术支持、帮助的;  
(五)频繁采用隐蔽上网、加密通信、销毁数据等措施或者使用虚假身份,逃避监管或者规避调查的;  
(六)为他人逃避监管或者规避调查提供技术支持、帮助的;  
(七)其他足以认定行为人明知的情形。”

两院《解释》发布之后,法院处理这种不确定的心理状态便有了指向标。从数量统计上来看,法院在认定“明知”时,对“知道可能”的使用频率要稍高于“应当知道”

需要注意的是,“知道可能”和“可能知道”不同。因为无论是“可能知道”,还是“或许知道”,都包含着行为人事实上不知道的情形,此时属于过失心理状态,不能认定为“明知”。

裁判要点

(1)使用“应当知道”的司法案例

①基于一般人所应遵守的注意义务范围,结合行为人行为样态分析,其出卖银行账户相关资料的同时按期获取高额报酬。对此种明显异常的交易方式应意识到行为基本法益的侵害性,仍放任结果的发生,能够推定被告人主观“明知”状态。
[(2020)皖1204刑初146号]

②行为人开发软件并恶意设置逾期还款功能的行为足以证实其知道或者应当知道,可以认定为明知。
[(2020)豫1329刑初179号]

③结合当地打击电信网络诈骗违法犯罪的高压态势和被告人的认知能力,属于应当明知。
[(2019)桂0126刑初535号]

④行为人违反相关规定,在自己没有实际经营的情况下,以虚假注册公司为他人办理对公账户供他人使用,属于应当明知。
[(2020)豫1328刑初545号]

⑤行为人应当明知银行卡套件可能会被网络犯罪和洗黑钱使用,可以证明被告人杜某的主观明知。
[(2021)豫0703刑初17号]

⑥行为人应该知道这种明显异常的交易价格及方式可能会被他人利用并从事违法犯罪活动。
[(2020)湘1081刑初309号]

(2)使用“知道可能”的司法案例

①根据其办理银行卡用于出租非法获利的事实,结合其作为正常成年人的认知能力,其完全能够认识到出租银行卡可能被用于利用信息网络实施犯罪,因此应认定其主观上明知。
[(2020)豫0325刑初420号]

②行为人长期频繁销毁手机和电脑中的电子数据,规避调查,故对其服务对象系可能涉嫌犯罪主观上实际是明知的。
[(2020)粤1581刑初886号]

③行为人明知他人可能利用信息网络实施犯罪,仍积极为犯罪分子到大陆开办银行卡,已构成帮忙信息网络犯罪活动罪。
[(2019)浙07刑终445号]

④行为人明知他人可能利用手机卡从事信息网络犯罪活动,通过QQ分别联系上家出售实名制手机卡,并获取收货地址的行为已构成帮信罪
[(2020)粤0607刑初388号]

⑤行为人明知将银行卡售卖于他人可能用于实施犯罪行为,为其提供支付结算帮助,其行为已构成帮信罪。
[(2020)豫0505刑初118号]

⑥行为人明知开办的银行卡可能用于网络犯罪活动,仍通过开办银行卡的方式为犯罪提供支付结算帮助,已构成帮信罪。
[(2020)闽0602刑初232号]

⑦行为人明知出卖自己实名认证的支付宝账号和实名开户的银行卡可能被他人用于信息网络犯罪活动,仍将其支付宝账号及银行卡提供给他人,导致被用于网络赌博大量资金支付结算,已构成帮信罪。
[(2020)闽0602刑初232号]

⑧行为人知道租用者可能利用其出租的固定电话号码从事违法犯罪活动,仍为了牟利,放任危害结果的发生,符合间接故意的主观心理态度。
[(2016)浙0604刑初1032号]

这种“知道可能”的主观心理状态意味着,行为人主观上知道他人可能会利用信息网络实施犯罪,持的是一种放任的心态,属于间接故意。帮信罪可由间接故意构成的观点也得到了司法实践的肯定

裁判要点

①行为人知道租用者可能从事违法犯罪活动,仍为了牟利,放任危害结果的发生,符合间接故意的主观心理态度。
[(2016)浙0604刑初1032号]

②行为人应当明知其开办的对公账户可能用于实施电信网络诈骗等犯罪行为,仍持放任态度帮助他人开办银行卡,应当认定主观系明知。
[(2020)豫1328刑初545号]

3、推定成立的标准是什么?

在帮信罪中,无论是司法解释还是裁判文书,司法机关均流露出对推定方法的青睐

法律上的推定,就是通过一些客观事实,如交易价格或者方式明显异常等,来推断出行为人的主观心理状态是否属于“明知”。

运用推定方法认定“明知”,得出结论一定要经过周密的论证,排除其他各种可能,并提出充分的、切实可靠的证据。如果未达到事实清楚、证据确实充分的程度,将被作为不起诉案件处理

裁判要点

①认定行为人明知第三人利用“百业链”App实施诈骗的主观故意不清、证据不足,不符合起诉条件,决定对其不起诉。
[灌检一部刑不诉〔2020〕130号]

现有的证据不足以证实被不起诉人明知第三人从事的是帮助信息网络犯罪活动,不符合起诉条件,决定对其不起诉。
[上检一部刑不诉〔2020〕16号]

③行为人主观上明知他人利用信息网络实施犯罪的主观犯意及所造成的后果事实不清,证据不足,不符合起诉条件。
[娄星检公诉刑不诉〔2020〕76号]

④行为人出售银行卡套件时对银行卡用途有所质疑,但没有证据显示其明知对方用于实施犯罪活动而继续提供帮助,且其在发现银行卡交易异常后到相关银行进行了挂失处理,故,本案认定的犯罪事实不清、证据不足,不符合起诉条件。
[新检公诉刑不诉〔2020〕42号]

没有充分证据证实行为人在明知其提供的银行卡被用于实施违法犯罪活动时继续提供帮助,本案认定的犯罪事实不清、证据不足,不符合起诉条件。
[新检公诉刑不诉〔2020〕41号]

证明行为人明知第三人收买自己的银行卡用于实施违法犯罪的证据不足,且其提供的银行卡没有明显异常的流水交易情况,故,本案认定的犯罪事实不清、证据不足,不符合起诉条件。
[新检公诉刑不诉〔2020〕40号]

⑦法院审查并退回补充侦查后,现有证据仍无法证明行为人主观上具有明知他人利用信息网络实施诈骗犯罪从而提供帮助,属于犯罪事实不清、证据不足,决定对其不起诉。
[舟普检公诉刑不诉〔2018〕8号]

需要注意的是,只要运用推定,就必须允许行为人提出相反证据以推翻推定

两院《解释》第十一条“但是有相反证据的除外”,以及新检公诉刑不诉〔2020〕42号、新检公诉刑不诉〔2020〕40号等裁判文书均体现出司法实践中对行为人反证出罪方式的认可,彰显出法律人的智慧。

4、如何运用推定方法认定“明知”?

两院在《解释》第十一条里共提出了7种可以推定“明知”的客观情形。那么,在司法实践中,哪些事实属于这些情形,并可以在此基础上认定存在“明知”呢?

鹅师傅在梳理过程中发现,这些案件主要涉及信用卡、银行卡、手机卡、U盾、对公账户、支付宝或微信账户等的违法使用。除此之外,如违法搭建第四方支付平台、违法使用猫池设备等行为也有存在。

裁判要点

(1)接到举报后不履行法定管理职责

①行为人在接到诈骗投诉、警告后仍未停止实施行为,应推定其对所推广的非企客户实施犯罪活动具有明知。
[(2018)鲁1727刑初75号]

(2)交易价格或者方式明显异常

①行为人以每张银行卡2000元的价格卖与他人,交易价格明显异常,可以认定为明知。
[(2020)冀0408刑初178号]

②行为人有偿出售的银行卡交易价格超出其办理银行卡的成本,交易价格明显异常,可以认定为明知。
[(2021)闽0581刑初239号]

③行为人频繁出卖自己银行卡的行为属交易异常,可视为明知。
[(2020)豫1625刑初651号]

④行为人频繁办理银行卡及“四件套”,然后以每张500—1000元的价格出售给他人,这种交易的价格及方式明显异常,可以认定为明知。
[(2020)湘1081刑初309号]

⑤行为人向他人出售工商营业执照、对公银行账户等资料,俨然属于交易价格和方式明显异常,可以认定为明知。
[(2020)粤2071刑初2446号]

⑥行为人注册公司的目的就是为了出售公司对公账户等公司资料,此种交易明显异常,应认定为“明知他人利用信息网络实施犯罪”。
[(2020)皖0722刑初76号]

⑦行为人以虚假身份取得电话卡后以150元至180元不等的价格批量出售获利,交易价格或者方式明显异常,可以认定明知。
[(2019)桂0126刑初535号]

(3)提供专门用于的违法犯罪程序、工具或者其他技术支持、帮助

①行为人专为他人解冻被冻结的微信号,这程序并非社会正常活动所需,而系为违法犯罪活动提供帮助的专门服务,可以认定为明知。
[(2020)粤1581刑初886号]

②行为人甲制作“普瑞斯’虚假投资平台所需的CRM用户管理系统,并将其提供给他人使用;乙将非法的MT4软件提供给技术人员使用,并为其提供日常维护、技术咨询服务。据此,可以认定其二人为明知。
[(2019)闽0781刑初295号]

③行为人在未取得《支付业务许可证》的情况下,提供支付结算平台“云闪电”,非法从事资金支付结算业务,可以认定为明知。
[(2020)闽0721刑初49号]

④行为人为他人架设“多卡宝”网络设备用于直接拨打被害人电话,并口头约定所得利益均分的行为可以认定为明知。
[(2020)闽0702刑初86号]

⑤行为人专门从事为网络赌博违法人员提供花呗、信用卡等套现结算服务,并从中赚取手续费的行为可以认定为明知。
[(2020)闽09刑终51号]

⑥行为人私自架设两台“猫池”设备,为他人拨打电话实施信息网络犯罪提供通讯技术支持的行为可以认定为明知。
[(2020)闽0622刑初214号]

⑦行为人开发的网络贷款软件可以通过登录后台查看用户信息,还设置有登录障碍功能,故意造成贷款人逾期还款,据此可认定为明知。
[(2020)豫1329刑初179号]

(4)频繁采用隐蔽上网、加密通信、销毁数据等措施或者使用虚假身份,逃避监管或者规避调查;为他人逃避监管或者规避调查提供技术支持、帮助

①行为人使用虚假身份、频繁更换地点、人员与设备分离、安装摄像头监控等措施帮助他人安装GOIP网关设备,逃避监管打击,可以认定为明知。
[(2020)陕0730刑初4号]

②行为人长期频繁销毁手机和电脑中的电子数据,规避调查,可以认定为明知。
[(2020)粤1581刑初886号]

③行为人在公安机关侦查时刻意规避调查,可以认定其主观上系明知他人利用信息网络实施犯罪。
[(2020)晋11刑终31号]

④行为人在知晓当地进行物流管控,并对大批量电话卡、银行卡进行严格监管的情况下,仍使用虚假身份以逃避监管,可以认定为明知。
[(2019)桂0126刑初535号]

⑤行为人向他人提供的IP代理技术软件,能够隐藏真实IP地址,规避官方调查,可以认定为明知。
[(2020)豫0902刑初429号]

⑥三行为人驾车到不同城市搭建“通信中转站”,逃避监管,应认定被告人明知他人利用信息网络实施犯罪。
[(2020)苏1091刑初96号]

⑦行为人以频繁更换作案地点、隐蔽作案工具、大量更换频繁被封的手机卡等为诈骗团伙提供通讯传输等技术支持,并从中获取与其工作内容不相符的高额回报,能够认定主观上明知上游客户存在违法犯罪活动。
[(2020)粤1972刑初1901号]

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

原文链接

继续阅读 »

大家好,我是鹅师傅。今天我们来聊聊最近十分热门的网络犯罪——帮助信息网络犯罪活动罪

是不是十分绕口?为了方便,实践中都简称“帮信罪”

近年来,网络犯罪猖獗不休,各种传统犯罪日益向互联网迁移,网络犯罪呈高发多发态势,犯罪手法更是多种多样,打击网络犯罪成为经济社会稳定发展的重要任务。

帮信罪就是在这样的大背景下由《刑法修正案(九)》设立的新罪名。

截至今日,裁判文书网中涉及该罪的判决书已高达8062份,有成为网络犯罪第一罪的趋势。

而在2019年帮信罪司法解释出台之前,该罪的司法适用并没那么普遍,可以说,这个司法解释打开了帮信罪司法适用的“任督二脉”

所谓的“任督二脉”,一个是情节标准,一个就是主观明知的认定。

实践中,后者的争议最大,如何认定“明知他人利用信息网络实施犯罪”,证据达到什么状态或标准才能推定明知?

针对这个问题,鹅师傅梳理并总结了相关司法解释及裁判要点,希望可以帮助大家增进对“明知”的理解。

1、如何证明“知道”?

“我的确知道他在干违法犯罪的勾当!”

行为人自认知道对方正在利用信息网络实施违法犯罪行为,这无非是实践中最为理想的状态。虽然根据我国刑事诉讼法的规定,孤证仍不能定罪,还需要结合物证、书证等其他客观证据综合认定。但有了供述后,可以提升认定明知的内心确信,其他客观证据的要求也会明显降低。

裁判要点

①行为人明确供述知道他人利用信息网络实施犯罪的,属于明知。
[(2020)沪02刑终1125号]

②行为人供述证实其知道App软件用于诈骗并对其维护的,属于明知。
[(2020)闽04刑终221号]

③行为人供述知道办理营业执照、对公账户是出售获利,并有被犯罪使用证明的,属于明知。
[(2020)豫0502刑初314号]

④行为人供述知道银行卡购买者可能用来实施违法行为的,属于明知。
[(2020)豫0191刑初1489号]

2、“应当知道”vs“知道可能”

除了“我确实知道”情形之外,实践中更多出现的是“我并不完全确定对方是不是在做违法犯罪行为”情形。

这种不确定的主观心理状态究竟能不能被认定为“明知”,是在行为人“应当知道”还是“知道可能”的时候可以认定,存在着很大的争议。

司法解释立场

司法解释以往经常将“应当知道”规定为“明知”的一种情形。例如,2001年最高院《关于审理为境外窃取、刺探、收买、非法提供国家秘密、情报案件具体应用法律若干问题的解释》第5条中直接使用了“知道或者应当知道”。

不过,近些年来的司法解释对“明知”的态度发生了变化,不再像以前那样直接使用“知道或者应当知道”的表述,而是通过罗列相关要素的方式一般化地规定认定标准

以帮信罪相关司法解释为例,2016年两院一部所发《关于办理电信网络诈骗等刑事案件适用法律若干问题的意见》中第四部分第三点规定:“上述规定的‘明知他人实施电信网络诈骗犯罪’,应当结合被告人的认知能力,既往经历,行为次数和手段,与他人关系,获利情况,是否曾因电信网络诈骗受过处罚,是否故意规避调查等主客观因素进行综合分析认定。”

2019年两院所发《关于办理非法利用信息网络、帮助信息网络犯罪活动等刑事案件适用法律若干问题的解释》的标准更加具体化,其第十一条规定:“为他人实施犯罪提供技术支持或者帮助,具有下列情形之一的,可以认定行为人明知他人利用信息网络实施犯罪,但是有相反证据的除外:
(一)经监管部门告知后仍然实施有关行为的;  
(二)接到举报后不履行法定管理职责的;  
(三)交易价格或者方式明显异常的;  
(四)提供专门用于违法犯罪的程序、工具或者其他技术支持、帮助的;  
(五)频繁采用隐蔽上网、加密通信、销毁数据等措施或者使用虚假身份,逃避监管或者规避调查的;  
(六)为他人逃避监管或者规避调查提供技术支持、帮助的;  
(七)其他足以认定行为人明知的情形。”

两院《解释》发布之后,法院处理这种不确定的心理状态便有了指向标。从数量统计上来看,法院在认定“明知”时,对“知道可能”的使用频率要稍高于“应当知道”

需要注意的是,“知道可能”和“可能知道”不同。因为无论是“可能知道”,还是“或许知道”,都包含着行为人事实上不知道的情形,此时属于过失心理状态,不能认定为“明知”。

裁判要点

(1)使用“应当知道”的司法案例

①基于一般人所应遵守的注意义务范围,结合行为人行为样态分析,其出卖银行账户相关资料的同时按期获取高额报酬。对此种明显异常的交易方式应意识到行为基本法益的侵害性,仍放任结果的发生,能够推定被告人主观“明知”状态。
[(2020)皖1204刑初146号]

②行为人开发软件并恶意设置逾期还款功能的行为足以证实其知道或者应当知道,可以认定为明知。
[(2020)豫1329刑初179号]

③结合当地打击电信网络诈骗违法犯罪的高压态势和被告人的认知能力,属于应当明知。
[(2019)桂0126刑初535号]

④行为人违反相关规定,在自己没有实际经营的情况下,以虚假注册公司为他人办理对公账户供他人使用,属于应当明知。
[(2020)豫1328刑初545号]

⑤行为人应当明知银行卡套件可能会被网络犯罪和洗黑钱使用,可以证明被告人杜某的主观明知。
[(2021)豫0703刑初17号]

⑥行为人应该知道这种明显异常的交易价格及方式可能会被他人利用并从事违法犯罪活动。
[(2020)湘1081刑初309号]

(2)使用“知道可能”的司法案例

①根据其办理银行卡用于出租非法获利的事实,结合其作为正常成年人的认知能力,其完全能够认识到出租银行卡可能被用于利用信息网络实施犯罪,因此应认定其主观上明知。
[(2020)豫0325刑初420号]

②行为人长期频繁销毁手机和电脑中的电子数据,规避调查,故对其服务对象系可能涉嫌犯罪主观上实际是明知的。
[(2020)粤1581刑初886号]

③行为人明知他人可能利用信息网络实施犯罪,仍积极为犯罪分子到大陆开办银行卡,已构成帮忙信息网络犯罪活动罪。
[(2019)浙07刑终445号]

④行为人明知他人可能利用手机卡从事信息网络犯罪活动,通过QQ分别联系上家出售实名制手机卡,并获取收货地址的行为已构成帮信罪
[(2020)粤0607刑初388号]

⑤行为人明知将银行卡售卖于他人可能用于实施犯罪行为,为其提供支付结算帮助,其行为已构成帮信罪。
[(2020)豫0505刑初118号]

⑥行为人明知开办的银行卡可能用于网络犯罪活动,仍通过开办银行卡的方式为犯罪提供支付结算帮助,已构成帮信罪。
[(2020)闽0602刑初232号]

⑦行为人明知出卖自己实名认证的支付宝账号和实名开户的银行卡可能被他人用于信息网络犯罪活动,仍将其支付宝账号及银行卡提供给他人,导致被用于网络赌博大量资金支付结算,已构成帮信罪。
[(2020)闽0602刑初232号]

⑧行为人知道租用者可能利用其出租的固定电话号码从事违法犯罪活动,仍为了牟利,放任危害结果的发生,符合间接故意的主观心理态度。
[(2016)浙0604刑初1032号]

这种“知道可能”的主观心理状态意味着,行为人主观上知道他人可能会利用信息网络实施犯罪,持的是一种放任的心态,属于间接故意。帮信罪可由间接故意构成的观点也得到了司法实践的肯定

裁判要点

①行为人知道租用者可能从事违法犯罪活动,仍为了牟利,放任危害结果的发生,符合间接故意的主观心理态度。
[(2016)浙0604刑初1032号]

②行为人应当明知其开办的对公账户可能用于实施电信网络诈骗等犯罪行为,仍持放任态度帮助他人开办银行卡,应当认定主观系明知。
[(2020)豫1328刑初545号]

3、推定成立的标准是什么?

在帮信罪中,无论是司法解释还是裁判文书,司法机关均流露出对推定方法的青睐

法律上的推定,就是通过一些客观事实,如交易价格或者方式明显异常等,来推断出行为人的主观心理状态是否属于“明知”。

运用推定方法认定“明知”,得出结论一定要经过周密的论证,排除其他各种可能,并提出充分的、切实可靠的证据。如果未达到事实清楚、证据确实充分的程度,将被作为不起诉案件处理

裁判要点

①认定行为人明知第三人利用“百业链”App实施诈骗的主观故意不清、证据不足,不符合起诉条件,决定对其不起诉。
[灌检一部刑不诉〔2020〕130号]

现有的证据不足以证实被不起诉人明知第三人从事的是帮助信息网络犯罪活动,不符合起诉条件,决定对其不起诉。
[上检一部刑不诉〔2020〕16号]

③行为人主观上明知他人利用信息网络实施犯罪的主观犯意及所造成的后果事实不清,证据不足,不符合起诉条件。
[娄星检公诉刑不诉〔2020〕76号]

④行为人出售银行卡套件时对银行卡用途有所质疑,但没有证据显示其明知对方用于实施犯罪活动而继续提供帮助,且其在发现银行卡交易异常后到相关银行进行了挂失处理,故,本案认定的犯罪事实不清、证据不足,不符合起诉条件。
[新检公诉刑不诉〔2020〕42号]

没有充分证据证实行为人在明知其提供的银行卡被用于实施违法犯罪活动时继续提供帮助,本案认定的犯罪事实不清、证据不足,不符合起诉条件。
[新检公诉刑不诉〔2020〕41号]

证明行为人明知第三人收买自己的银行卡用于实施违法犯罪的证据不足,且其提供的银行卡没有明显异常的流水交易情况,故,本案认定的犯罪事实不清、证据不足,不符合起诉条件。
[新检公诉刑不诉〔2020〕40号]

⑦法院审查并退回补充侦查后,现有证据仍无法证明行为人主观上具有明知他人利用信息网络实施诈骗犯罪从而提供帮助,属于犯罪事实不清、证据不足,决定对其不起诉。
[舟普检公诉刑不诉〔2018〕8号]

需要注意的是,只要运用推定,就必须允许行为人提出相反证据以推翻推定

两院《解释》第十一条“但是有相反证据的除外”,以及新检公诉刑不诉〔2020〕42号、新检公诉刑不诉〔2020〕40号等裁判文书均体现出司法实践中对行为人反证出罪方式的认可,彰显出法律人的智慧。

4、如何运用推定方法认定“明知”?

两院在《解释》第十一条里共提出了7种可以推定“明知”的客观情形。那么,在司法实践中,哪些事实属于这些情形,并可以在此基础上认定存在“明知”呢?

鹅师傅在梳理过程中发现,这些案件主要涉及信用卡、银行卡、手机卡、U盾、对公账户、支付宝或微信账户等的违法使用。除此之外,如违法搭建第四方支付平台、违法使用猫池设备等行为也有存在。

裁判要点

(1)接到举报后不履行法定管理职责

①行为人在接到诈骗投诉、警告后仍未停止实施行为,应推定其对所推广的非企客户实施犯罪活动具有明知。
[(2018)鲁1727刑初75号]

(2)交易价格或者方式明显异常

①行为人以每张银行卡2000元的价格卖与他人,交易价格明显异常,可以认定为明知。
[(2020)冀0408刑初178号]

②行为人有偿出售的银行卡交易价格超出其办理银行卡的成本,交易价格明显异常,可以认定为明知。
[(2021)闽0581刑初239号]

③行为人频繁出卖自己银行卡的行为属交易异常,可视为明知。
[(2020)豫1625刑初651号]

④行为人频繁办理银行卡及“四件套”,然后以每张500—1000元的价格出售给他人,这种交易的价格及方式明显异常,可以认定为明知。
[(2020)湘1081刑初309号]

⑤行为人向他人出售工商营业执照、对公银行账户等资料,俨然属于交易价格和方式明显异常,可以认定为明知。
[(2020)粤2071刑初2446号]

⑥行为人注册公司的目的就是为了出售公司对公账户等公司资料,此种交易明显异常,应认定为“明知他人利用信息网络实施犯罪”。
[(2020)皖0722刑初76号]

⑦行为人以虚假身份取得电话卡后以150元至180元不等的价格批量出售获利,交易价格或者方式明显异常,可以认定明知。
[(2019)桂0126刑初535号]

(3)提供专门用于的违法犯罪程序、工具或者其他技术支持、帮助

①行为人专为他人解冻被冻结的微信号,这程序并非社会正常活动所需,而系为违法犯罪活动提供帮助的专门服务,可以认定为明知。
[(2020)粤1581刑初886号]

②行为人甲制作“普瑞斯’虚假投资平台所需的CRM用户管理系统,并将其提供给他人使用;乙将非法的MT4软件提供给技术人员使用,并为其提供日常维护、技术咨询服务。据此,可以认定其二人为明知。
[(2019)闽0781刑初295号]

③行为人在未取得《支付业务许可证》的情况下,提供支付结算平台“云闪电”,非法从事资金支付结算业务,可以认定为明知。
[(2020)闽0721刑初49号]

④行为人为他人架设“多卡宝”网络设备用于直接拨打被害人电话,并口头约定所得利益均分的行为可以认定为明知。
[(2020)闽0702刑初86号]

⑤行为人专门从事为网络赌博违法人员提供花呗、信用卡等套现结算服务,并从中赚取手续费的行为可以认定为明知。
[(2020)闽09刑终51号]

⑥行为人私自架设两台“猫池”设备,为他人拨打电话实施信息网络犯罪提供通讯技术支持的行为可以认定为明知。
[(2020)闽0622刑初214号]

⑦行为人开发的网络贷款软件可以通过登录后台查看用户信息,还设置有登录障碍功能,故意造成贷款人逾期还款,据此可认定为明知。
[(2020)豫1329刑初179号]

(4)频繁采用隐蔽上网、加密通信、销毁数据等措施或者使用虚假身份,逃避监管或者规避调查;为他人逃避监管或者规避调查提供技术支持、帮助

①行为人使用虚假身份、频繁更换地点、人员与设备分离、安装摄像头监控等措施帮助他人安装GOIP网关设备,逃避监管打击,可以认定为明知。
[(2020)陕0730刑初4号]

②行为人长期频繁销毁手机和电脑中的电子数据,规避调查,可以认定为明知。
[(2020)粤1581刑初886号]

③行为人在公安机关侦查时刻意规避调查,可以认定其主观上系明知他人利用信息网络实施犯罪。
[(2020)晋11刑终31号]

④行为人在知晓当地进行物流管控,并对大批量电话卡、银行卡进行严格监管的情况下,仍使用虚假身份以逃避监管,可以认定为明知。
[(2019)桂0126刑初535号]

⑤行为人向他人提供的IP代理技术软件,能够隐藏真实IP地址,规避官方调查,可以认定为明知。
[(2020)豫0902刑初429号]

⑥三行为人驾车到不同城市搭建“通信中转站”,逃避监管,应认定被告人明知他人利用信息网络实施犯罪。
[(2020)苏1091刑初96号]

⑦行为人以频繁更换作案地点、隐蔽作案工具、大量更换频繁被封的手机卡等为诈骗团伙提供通讯传输等技术支持,并从中获取与其工作内容不相符的高额回报,能够认定主观上明知上游客户存在违法犯罪活动。
[(2020)粤1972刑初1901号]

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

原文链接

收起阅读 »

HBuilderX Git 使用技巧

Git HBuilderX

easy-git, 是基于HBuilderX API开发的可视化图形Git插件,界面参考vscode源代码管理器。包含源代码管理器文件视图、日志视图、分支/tag视图、文件对比视图,且支持命令面板操作。

easy-git安装:下载地址

下面将介绍HBuilderX easy-git插件技巧。

技巧1. 查看当前文件在另一个分支的内容

通常,查看文件在另一个分支的内容,需要切换分支,或打开终端使用命令行进行查看。费时费力,还需要记忆各种命令。

easy-git,在编辑器打开文件,右键菜单【查看当前文件在另一个分支的内容】

技巧2. 显示当前行代码最后一次提交信息

在大项目工作时,大家问的最多的问题是“这一行到底是谁写的”。easy-git插件,提供了基于git blame显示某行最后提交者的功能。

打开文件,将光标置于要查看的行上,右键菜单【easy-git】【blame - 显示当前行代码最后一次提交信息】

技巧3. 用提交信息标注文件中的每一行

作为程序媛,难免会有锅砸在头上,这个时候可以使用annotate,查看当前文件每一行代码修改时间及修改人。

打开文件,将光标置于要查看的行上,右键菜单【easy-git】【annotate - 用提交信息标注文件中的每一行】

技巧4. git reflog

git reflog, 又被称为救命神器。

开发过程中,难免误操作,导致提交丢失。这个时候,可以利用reflog找到commitid,然后重置到相应提交。

技巧5. 命令面板

命令面板是一个非常特殊的 UI 组件,如果您用过 VSCode 或者 Sublime 之类的编辑器,那么您就会离不开它。

easy-git,提供了git 命令面板,可以方便快捷的操作git。

技巧6. 搜索github仓库,并克隆

通常,克隆仓库之前,您需要知道知道git仓库地址。

easy-git,支持在克隆窗口,输入关键字回车搜索,在Github搜索结果中,选择相应仓库进行克隆,克隆更便捷。

技巧7. 创建远程仓库

如果您使用的是github、gitee,创建远程仓库时,需要打开浏览器,打开相应页面,创建费事费力。创建完之后,还需要手动克隆,更是麻烦。

easy-git,支持在HBuilderX内,打开相应窗口,直接创建远程操作,创建完成之后,直接克隆到本地。

技巧8. 对比两个分支提交

多人协作开发时,通常会有好几个分支,比如masterdevtest等。每个人在部分的分支上开发,怎么比较分支有哪些不通呢?

easy-git,支持查看两个分支不通之处。具体见截图。

继续阅读 »

easy-git, 是基于HBuilderX API开发的可视化图形Git插件,界面参考vscode源代码管理器。包含源代码管理器文件视图、日志视图、分支/tag视图、文件对比视图,且支持命令面板操作。

easy-git安装:下载地址

下面将介绍HBuilderX easy-git插件技巧。

技巧1. 查看当前文件在另一个分支的内容

通常,查看文件在另一个分支的内容,需要切换分支,或打开终端使用命令行进行查看。费时费力,还需要记忆各种命令。

easy-git,在编辑器打开文件,右键菜单【查看当前文件在另一个分支的内容】

技巧2. 显示当前行代码最后一次提交信息

在大项目工作时,大家问的最多的问题是“这一行到底是谁写的”。easy-git插件,提供了基于git blame显示某行最后提交者的功能。

打开文件,将光标置于要查看的行上,右键菜单【easy-git】【blame - 显示当前行代码最后一次提交信息】

技巧3. 用提交信息标注文件中的每一行

作为程序媛,难免会有锅砸在头上,这个时候可以使用annotate,查看当前文件每一行代码修改时间及修改人。

打开文件,将光标置于要查看的行上,右键菜单【easy-git】【annotate - 用提交信息标注文件中的每一行】

技巧4. git reflog

git reflog, 又被称为救命神器。

开发过程中,难免误操作,导致提交丢失。这个时候,可以利用reflog找到commitid,然后重置到相应提交。

技巧5. 命令面板

命令面板是一个非常特殊的 UI 组件,如果您用过 VSCode 或者 Sublime 之类的编辑器,那么您就会离不开它。

easy-git,提供了git 命令面板,可以方便快捷的操作git。

技巧6. 搜索github仓库,并克隆

通常,克隆仓库之前,您需要知道知道git仓库地址。

easy-git,支持在克隆窗口,输入关键字回车搜索,在Github搜索结果中,选择相应仓库进行克隆,克隆更便捷。

技巧7. 创建远程仓库

如果您使用的是github、gitee,创建远程仓库时,需要打开浏览器,打开相应页面,创建费事费力。创建完之后,还需要手动克隆,更是麻烦。

easy-git,支持在HBuilderX内,打开相应窗口,直接创建远程操作,创建完成之后,直接克隆到本地。

技巧8. 对比两个分支提交

多人协作开发时,通常会有好几个分支,比如masterdevtest等。每个人在部分的分支上开发,怎么比较分支有哪些不通呢?

easy-git,支持查看两个分支不通之处。具体见截图。

收起阅读 »

工具里的拖拽条,都太细了,要用显微镜照着才能拖到

体验 已优化

这个玩意,考验视力

这个玩意,考验视力

vite.js+vue3+electron12.0.4超清爽UI界面前端中后台管理系统

vuex Vue

上次有给大家分享一个Electron跨端仿抖音短视频项目,这次带来最新研发的vite.js+electron开发vue3中后台管理系统。

vite2-vue3-electronAdmin:一套基于electron+vite.js和element-plus组件库开发的客户端后台管理系统EXE。使用了最新的vue3全家桶技术,内置了 Vue-i18n 国际化解决方案,支持PC桌面端和平板自适应布局。

electron12 vite2.x仿制抖音短视频|直播聊天

img

基于最新的前端技术栈vite2+vue3全家桶+electron12+element-plus+echarts5开发而来。

img

技术栈

  • 编码器:VScode
  • 构建工具:Vitejs
  • vue3全家桶:Vue3.0+Vuex4+Vue-router@4
  • 跨端框架:Electron^12.0.4
  • 打包工具:vue-cli-plugin-electron-builder
  • UI组件库:element-plus^1.0.2 (饿了么vue3组件库)
  • 表格拖拽:Sortablejs^1.13
  • 图表组件:Echarts^5.1
  • 国际化:vue-i18n^9.1
  • 模拟请求:mockjs^1.1

img

特性

  • 使用最新前端技术栈开发
  • 支持桌面端及平板响应式布局
  • 支持组件式+指令式两种权限认证方式
  • 支持中英文/繁体国际化方案
  • 支持表格拖拽排序、全屏表格、树形表格等功能
  • 支持个性化换肤

img

项目结构

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

main.js配置

/**  
 * 渲染进程主入口  
 * @author XiaoYan  
 */  

import { createApp } from 'vue'  
import App from './App.vue'  
import Router from './router'  
import Store from './store'  

// 引入公共配置  
import gPlugins from './plugins'  

import { winCfg, loadWin } from './windows/actions'  

loadWin().then(config => {  
    winCfg.window = config  
    createApp(App)  
    .use(Router)  
    .use(Store)  
    .use(gPlugins)  
    .mount('#app')  
})

vue-router路由配置

项目中的路由采用了结构化分层加载,分为验证路由authRoutes.js和主模块路由mainRoutes.js两大部分。

/**  
 * 路由配置 Router util  
 * @author XiaoYan  
 */  

import { createRouter, createWebHashHistory } from "vue-router"  

import { ElLoading } from "element-plus"  
import { loginWin } from "@/windows/actions"  

import store from '@/store'  

// 导入公共模板/路由配置  
import mainLayout from "@/layouts/main"  
import authLayout from "@/layouts/auth"  
import mainRoutes from "@/layouts/main/routes.js"  
import authRoutes from "@/layouts/auth/routes.js"  

const RoutesLs = [  
    // 主页面模块  
    {  
        path: '/',  
        redirect: '/home/index',  
        component: mainLayout,  
        children: mainRoutes,  
    },  
    // 验证模块  
    {  
        path: '/auth',  
        redirect: '/auth/login',  
        component: authLayout,  
        children: authRoutes,  
    },  
    // 错误模块  
    {  
        path: '/:pathMatch(.*)*',  
        component: () => import('@/views/error/404.vue'),  
        meta: {  
            title: 'app__global-page-notfound',  
        }  
    }  
]  

const router = createRouter({  
    history: createWebHashHistory(),  
    routes: RoutesLs,  
})  

let loadingIns  
router.beforeEach((to, from, next) => {  
    // 开启加载提示  
    loadingIns = ElLoading.service({  
        lock: true,  
        text: 'Loading...',  
        spinner: 'el-icon-loading',  
        background: 'rgba(19, 209, 122, .1)'  
    })  

    // 判断当前路由状态  
    const isLogined = store.state.isLogin  
    if(to.meta.auth) {  
        if(isLogined) {  
            next()  
        }else {  
            loginWin()  
            loadingIns.close()  
        }  
    }else {  
        next()  
    }  
})  

router.afterEach(() => {  
    loadingIns.close()  
})

electron-vue3自定义仿Mac导航栏

项目中顶部导航条采用的是mac导航条风格,关闭/最小化/最大化按钮在左侧。
img

<!-- //仿Mac导航条 -->  
<template>  
    <WinBar zIndex="1000">  
        <template #wbtn>  
            <MsgMenu />  
            <Lang />  
            <a class="wbtn" @click="handleSkinWin"><i class="iconfont icon-huanfu"></i></a>  
            <Setting />  
            <a class="wbtn" @click="handleRefresh"><i class="iconfont el-icon-refresh"></i></a>  
            <a class="wbtn" :class="{'on': isAlwaysOnTop}" :title="isAlwaysOnTop ? '取消置顶' : '置顶'" @click="handleAlwaysTop"><i class="iconfont icon-ding"></i></a>  
            <Avatar @logout="handleLogout" />  
        </template>  
    </WinBar>  
</template>

vue-i18n国际化方案

img

新建一个locale目录用来存放项目中语言文件。

img

/**  
 * @desc    vue-i18n国际化配置文件  
 * @Time    andy by 2021-05  
 * @Author      Q:282310962  wx:xy190310  
 */  

import { createI18n } from 'vue-i18n'  
import Storage from '@/utils/storage'  

// 默认设置  
export const langKey = 'lang'  
export const langVal = 'zh-CN'  

/**  
 * 引入element-plus国际化包  
 */  
import enUS from 'element-plus/lib/locale/lang/en'  
import zhCN from 'element-plus/lib/locale/lang/zh-cn'  
import zhTW from 'element-plus/lib/locale/lang/zh-tw'  
export const ElPlusLang = {  
    'en-US': enUS,  
    'zh-CN': zhCN,  
    'zh-TW': zhTW  
}  

/**  
 * 初始化多语言  
 */  
export const $messages = importLang()  
export const $lang = getLang()  
const i18n = createI18n({  
    legacy: false,  
    locale: $lang,  
    messages: $messages  
})  

/**  
 * 自动导入语言配置  
 */  
export function importLang() {  
    const localeModule = {}  
    try {  
        // 导入 @/layouts 文件夹下包含子目录locale中的xxx.js文件  
        const layoutsCtx = require.context('@/layouts', true, /[/\\]locale[/\\]([a-z]{2})-?([A-Z]{2})?\.js$/)  
        layoutsCtx.keys().map(path => {  
            const pathCtx = layoutsCtx(path)  
            if(pathCtx.default) {  
                const pathName = path.replace(/(.*\/)*([^.]+).*/ig, '$2')  
                if(localeModule[pathName]) {  
                    localeModule[pathName] = {  
                        ...localeModule[pathName], ...pathCtx.default  
                    }  
                }else {  
                    localeModule[pathName] = pathCtx.default  
                }  
            }  
        })  
    } catch (error) {  
        console.log(error)  
    }  

    return localeModule  
}  

/**  
 * 存储设置语言  
 * @param lang 语言类型 zh-CN | zh-TW | en-US  
 */  
export function setLang(lang, reload = false) {  
    if(getLang() !== lang) {  
        Storage.set(langKey, lang || '')  
        // 设置全局语言  
        i18n.global.locale.value = lang  

        if(reload) {  
            window.location.reload()  
        }  
    }  
}  

/**  
 * 获取语言  
 */  
export function getLang() {  
    const lang = Storage.get(langKey)  
    return lang || langVal  
}

vite2+electron主模板布局

项目整体分为顶部导航条、侧边栏、路由菜单、右侧上面包屑导航、右侧下主体内容。

<!-- //Main主模块模板 -->  
<template>  
    <div class="vadmin__wrapper" :style="{'--themeSkin': store.state.skin}">  
        <div v-if="!route.meta.isNewin" class="vadmin__layouts-main flexbox flex-col">  
            <!-- //顶部导航 -->  
            <div class="layout__topbar">  
                <TopNav />  
            </div>  

            <div class="layout__workpanel flex1 flexbox">  
                <!-- //侧边栏 -->  
                <div v-show="rootRouteEnable" class="panel__leftlayer">  
                    <SideMenu :routes="mainRoutes" :rootRoute="rootRoute" />  
                </div>  

                <!-- //中间栏 -->  
                <div class="panel__middlelayer" :class="{'collapsed': collapsed}">  
                    <RouteMenu   
                        :routes="getAllRoutes"   
                        :rootRoute="rootRoute"   
                        :defaultActive="defaultActive"   
                        :rootRouteEnable="rootRouteEnable"   
                    />  
                </div>  

                <!-- //右边栏 -->  
                <div class="panel__rightlayer flex1 flexbox flex-col">  
                    <!-- 面包屑导航 -->  
                    <BreadCrumb />  

                    <!-- 主内容区 -->  
                    <v3-scroll autohide>  
                        <div class="lay__container">  
                            <!-- //路由权限控制 -->  
                            <permission :roles="route.meta.roles">  
                                <template #tooltips>  
                                    <Forbidden />  
                                </template>  
                                <router-view></router-view>  
                            </permission>  
                        </div>  
                    </v3-scroll>  
                </div>  
            </div>  
        </div>  
        <router-view v-else class="vadmin__layouts-main flexbox flex-col"></router-view>  
    </div>  
</template>

Vue3图表化Hook

项目中多个地方需要使用到图表功能,于是就封装了一个图表hook函数。

/**  
 * 封装图表Hook  
 * @author XiaoYan  
 */  

import { onMounted, onBeforeUnmount, ref } from "vue"  
import * as echarts from "echarts"  
import elementResizeDetectorMaker from "element-resize-detector"  
import utils from "@/utils"  

export default function useChart(refs, options) {  
    let chartInst  
    let chartRef = ref(null)  
    let erd = elementResizeDetectorMaker()  

    const handleResize = utils.debounce(() => {  
        chartInst.resize()  
    }, 100)  

    onMounted(() => {  
        if(refs.value) {  
            chartInst = echarts.init(refs.value)  
            chartInst.setOption(options)  
            chartRef.value = chartInst  
        }  
        // window.addEventListener('resize', handleResize)  
        erd.listenTo(refs.value, handleResize)  
    })  

    onBeforeUnmount(() => {  
        chartInst.dispose()  
        // window.removeEventListener('resize', handleResize)  
        erd.removeListener(refs.value, handleResize)  
    })  

    return chartRef  
}

Okay,基于vite.js+vue3+electron开发管理后台就分享到这里。希望对小伙伴们有些帮助!

img

链接:https://juejin.cn/post/6963310387945013261/
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

继续阅读 »

上次有给大家分享一个Electron跨端仿抖音短视频项目,这次带来最新研发的vite.js+electron开发vue3中后台管理系统。

vite2-vue3-electronAdmin:一套基于electron+vite.js和element-plus组件库开发的客户端后台管理系统EXE。使用了最新的vue3全家桶技术,内置了 Vue-i18n 国际化解决方案,支持PC桌面端和平板自适应布局。

electron12 vite2.x仿制抖音短视频|直播聊天

img

基于最新的前端技术栈vite2+vue3全家桶+electron12+element-plus+echarts5开发而来。

img

技术栈

  • 编码器:VScode
  • 构建工具:Vitejs
  • vue3全家桶:Vue3.0+Vuex4+Vue-router@4
  • 跨端框架:Electron^12.0.4
  • 打包工具:vue-cli-plugin-electron-builder
  • UI组件库:element-plus^1.0.2 (饿了么vue3组件库)
  • 表格拖拽:Sortablejs^1.13
  • 图表组件:Echarts^5.1
  • 国际化:vue-i18n^9.1
  • 模拟请求:mockjs^1.1

img

特性

  • 使用最新前端技术栈开发
  • 支持桌面端及平板响应式布局
  • 支持组件式+指令式两种权限认证方式
  • 支持中英文/繁体国际化方案
  • 支持表格拖拽排序、全屏表格、树形表格等功能
  • 支持个性化换肤

img

项目结构

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

main.js配置

/**  
 * 渲染进程主入口  
 * @author XiaoYan  
 */  

import { createApp } from 'vue'  
import App from './App.vue'  
import Router from './router'  
import Store from './store'  

// 引入公共配置  
import gPlugins from './plugins'  

import { winCfg, loadWin } from './windows/actions'  

loadWin().then(config => {  
    winCfg.window = config  
    createApp(App)  
    .use(Router)  
    .use(Store)  
    .use(gPlugins)  
    .mount('#app')  
})

vue-router路由配置

项目中的路由采用了结构化分层加载,分为验证路由authRoutes.js和主模块路由mainRoutes.js两大部分。

/**  
 * 路由配置 Router util  
 * @author XiaoYan  
 */  

import { createRouter, createWebHashHistory } from "vue-router"  

import { ElLoading } from "element-plus"  
import { loginWin } from "@/windows/actions"  

import store from '@/store'  

// 导入公共模板/路由配置  
import mainLayout from "@/layouts/main"  
import authLayout from "@/layouts/auth"  
import mainRoutes from "@/layouts/main/routes.js"  
import authRoutes from "@/layouts/auth/routes.js"  

const RoutesLs = [  
    // 主页面模块  
    {  
        path: '/',  
        redirect: '/home/index',  
        component: mainLayout,  
        children: mainRoutes,  
    },  
    // 验证模块  
    {  
        path: '/auth',  
        redirect: '/auth/login',  
        component: authLayout,  
        children: authRoutes,  
    },  
    // 错误模块  
    {  
        path: '/:pathMatch(.*)*',  
        component: () => import('@/views/error/404.vue'),  
        meta: {  
            title: 'app__global-page-notfound',  
        }  
    }  
]  

const router = createRouter({  
    history: createWebHashHistory(),  
    routes: RoutesLs,  
})  

let loadingIns  
router.beforeEach((to, from, next) => {  
    // 开启加载提示  
    loadingIns = ElLoading.service({  
        lock: true,  
        text: 'Loading...',  
        spinner: 'el-icon-loading',  
        background: 'rgba(19, 209, 122, .1)'  
    })  

    // 判断当前路由状态  
    const isLogined = store.state.isLogin  
    if(to.meta.auth) {  
        if(isLogined) {  
            next()  
        }else {  
            loginWin()  
            loadingIns.close()  
        }  
    }else {  
        next()  
    }  
})  

router.afterEach(() => {  
    loadingIns.close()  
})

electron-vue3自定义仿Mac导航栏

项目中顶部导航条采用的是mac导航条风格,关闭/最小化/最大化按钮在左侧。
img

<!-- //仿Mac导航条 -->  
<template>  
    <WinBar zIndex="1000">  
        <template #wbtn>  
            <MsgMenu />  
            <Lang />  
            <a class="wbtn" @click="handleSkinWin"><i class="iconfont icon-huanfu"></i></a>  
            <Setting />  
            <a class="wbtn" @click="handleRefresh"><i class="iconfont el-icon-refresh"></i></a>  
            <a class="wbtn" :class="{'on': isAlwaysOnTop}" :title="isAlwaysOnTop ? '取消置顶' : '置顶'" @click="handleAlwaysTop"><i class="iconfont icon-ding"></i></a>  
            <Avatar @logout="handleLogout" />  
        </template>  
    </WinBar>  
</template>

vue-i18n国际化方案

img

新建一个locale目录用来存放项目中语言文件。

img

/**  
 * @desc    vue-i18n国际化配置文件  
 * @Time    andy by 2021-05  
 * @Author      Q:282310962  wx:xy190310  
 */  

import { createI18n } from 'vue-i18n'  
import Storage from '@/utils/storage'  

// 默认设置  
export const langKey = 'lang'  
export const langVal = 'zh-CN'  

/**  
 * 引入element-plus国际化包  
 */  
import enUS from 'element-plus/lib/locale/lang/en'  
import zhCN from 'element-plus/lib/locale/lang/zh-cn'  
import zhTW from 'element-plus/lib/locale/lang/zh-tw'  
export const ElPlusLang = {  
    'en-US': enUS,  
    'zh-CN': zhCN,  
    'zh-TW': zhTW  
}  

/**  
 * 初始化多语言  
 */  
export const $messages = importLang()  
export const $lang = getLang()  
const i18n = createI18n({  
    legacy: false,  
    locale: $lang,  
    messages: $messages  
})  

/**  
 * 自动导入语言配置  
 */  
export function importLang() {  
    const localeModule = {}  
    try {  
        // 导入 @/layouts 文件夹下包含子目录locale中的xxx.js文件  
        const layoutsCtx = require.context('@/layouts', true, /[/\\]locale[/\\]([a-z]{2})-?([A-Z]{2})?\.js$/)  
        layoutsCtx.keys().map(path => {  
            const pathCtx = layoutsCtx(path)  
            if(pathCtx.default) {  
                const pathName = path.replace(/(.*\/)*([^.]+).*/ig, '$2')  
                if(localeModule[pathName]) {  
                    localeModule[pathName] = {  
                        ...localeModule[pathName], ...pathCtx.default  
                    }  
                }else {  
                    localeModule[pathName] = pathCtx.default  
                }  
            }  
        })  
    } catch (error) {  
        console.log(error)  
    }  

    return localeModule  
}  

/**  
 * 存储设置语言  
 * @param lang 语言类型 zh-CN | zh-TW | en-US  
 */  
export function setLang(lang, reload = false) {  
    if(getLang() !== lang) {  
        Storage.set(langKey, lang || '')  
        // 设置全局语言  
        i18n.global.locale.value = lang  

        if(reload) {  
            window.location.reload()  
        }  
    }  
}  

/**  
 * 获取语言  
 */  
export function getLang() {  
    const lang = Storage.get(langKey)  
    return lang || langVal  
}

vite2+electron主模板布局

项目整体分为顶部导航条、侧边栏、路由菜单、右侧上面包屑导航、右侧下主体内容。

<!-- //Main主模块模板 -->  
<template>  
    <div class="vadmin__wrapper" :style="{'--themeSkin': store.state.skin}">  
        <div v-if="!route.meta.isNewin" class="vadmin__layouts-main flexbox flex-col">  
            <!-- //顶部导航 -->  
            <div class="layout__topbar">  
                <TopNav />  
            </div>  

            <div class="layout__workpanel flex1 flexbox">  
                <!-- //侧边栏 -->  
                <div v-show="rootRouteEnable" class="panel__leftlayer">  
                    <SideMenu :routes="mainRoutes" :rootRoute="rootRoute" />  
                </div>  

                <!-- //中间栏 -->  
                <div class="panel__middlelayer" :class="{'collapsed': collapsed}">  
                    <RouteMenu   
                        :routes="getAllRoutes"   
                        :rootRoute="rootRoute"   
                        :defaultActive="defaultActive"   
                        :rootRouteEnable="rootRouteEnable"   
                    />  
                </div>  

                <!-- //右边栏 -->  
                <div class="panel__rightlayer flex1 flexbox flex-col">  
                    <!-- 面包屑导航 -->  
                    <BreadCrumb />  

                    <!-- 主内容区 -->  
                    <v3-scroll autohide>  
                        <div class="lay__container">  
                            <!-- //路由权限控制 -->  
                            <permission :roles="route.meta.roles">  
                                <template #tooltips>  
                                    <Forbidden />  
                                </template>  
                                <router-view></router-view>  
                            </permission>  
                        </div>  
                    </v3-scroll>  
                </div>  
            </div>  
        </div>  
        <router-view v-else class="vadmin__layouts-main flexbox flex-col"></router-view>  
    </div>  
</template>

Vue3图表化Hook

项目中多个地方需要使用到图表功能,于是就封装了一个图表hook函数。

/**  
 * 封装图表Hook  
 * @author XiaoYan  
 */  

import { onMounted, onBeforeUnmount, ref } from "vue"  
import * as echarts from "echarts"  
import elementResizeDetectorMaker from "element-resize-detector"  
import utils from "@/utils"  

export default function useChart(refs, options) {  
    let chartInst  
    let chartRef = ref(null)  
    let erd = elementResizeDetectorMaker()  

    const handleResize = utils.debounce(() => {  
        chartInst.resize()  
    }, 100)  

    onMounted(() => {  
        if(refs.value) {  
            chartInst = echarts.init(refs.value)  
            chartInst.setOption(options)  
            chartRef.value = chartInst  
        }  
        // window.addEventListener('resize', handleResize)  
        erd.listenTo(refs.value, handleResize)  
    })  

    onBeforeUnmount(() => {  
        chartInst.dispose()  
        // window.removeEventListener('resize', handleResize)  
        erd.removeListener(refs.value, handleResize)  
    })  

    return chartRef  
}

Okay,基于vite.js+vue3+electron开发管理后台就分享到这里。希望对小伙伴们有些帮助!

img

链接:https://juejin.cn/post/6963310387945013261/
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

收起阅读 »

uview组件from-item在小程序与h5里表现一不致(附解决方案)

在使用uview组件开发项目时,使用下面代码,碰到一个问题:
代码为:

        <u-form class="from-submit" ref="uForm" label-width="160" :error-type="['toast', 'border-bottom']">  
            <u-form-item label="上课时间" prop="beginTime" class="u-flex" :required="true">  
                <view>xxx</view>  
                <text class="label-text">至</text>  
                <view>xxx</view>  
            </u-form-item>  
        </u-form>

大家看图:

可以发现,同一套代码,在两个平台,表现的却不是一致的。

同样是选择from-item,他们的显示区域却不尽相同。

虽然看起来样式差不多,但表现却不一致,通过调试,最终得到解决方案:

给from-item下面的view元素,添加 display:inline-flex 样式即可

最终代码(非优化代码,仅作示例):

        <u-form class="from-submit" ref="uForm" label-width="160" :error-type="['toast', 'border-bottom']">  
            <u-form-item label="上课时间" prop="beginTime" class="u-flex" :required="true">  
                <view style="display: inline-flex;">xxx</view>  
                <text class="label-text">至</text>  
                <view style="display: inline-flex;">xxx</view>  
            </u-form-item>  
        </u-form>

最终效果,”鸡乎一样“ 了

继续阅读 »

在使用uview组件开发项目时,使用下面代码,碰到一个问题:
代码为:

        <u-form class="from-submit" ref="uForm" label-width="160" :error-type="['toast', 'border-bottom']">  
            <u-form-item label="上课时间" prop="beginTime" class="u-flex" :required="true">  
                <view>xxx</view>  
                <text class="label-text">至</text>  
                <view>xxx</view>  
            </u-form-item>  
        </u-form>

大家看图:

可以发现,同一套代码,在两个平台,表现的却不是一致的。

同样是选择from-item,他们的显示区域却不尽相同。

虽然看起来样式差不多,但表现却不一致,通过调试,最终得到解决方案:

给from-item下面的view元素,添加 display:inline-flex 样式即可

最终代码(非优化代码,仅作示例):

        <u-form class="from-submit" ref="uForm" label-width="160" :error-type="['toast', 'border-bottom']">  
            <u-form-item label="上课时间" prop="beginTime" class="u-flex" :required="true">  
                <view style="display: inline-flex;">xxx</view>  
                <text class="label-text">至</text>  
                <view style="display: inline-flex;">xxx</view>  
            </u-form-item>  
        </u-form>

最终效果,”鸡乎一样“ 了

收起阅读 »

有丰富的uniapp开发经验,后端技术栈java,全栈工程师,接单

有丰富的uniapp开发经验,
后端技术栈java,
全栈工程师,
有充足的时间,
有需要的可以联系我

接单:微信小程序应用、uniapp开发、java开发、后台管理系统、APP、网站、vue开发。
联系方式Q.Q,V.X号:443409972
淘宝开发小店:https://item.taobao.com/item.htm?id=630595051308

继续阅读 »

有丰富的uniapp开发经验,
后端技术栈java,
全栈工程师,
有充足的时间,
有需要的可以联系我

接单:微信小程序应用、uniapp开发、java开发、后台管理系统、APP、网站、vue开发。
联系方式Q.Q,V.X号:443409972
淘宝开发小店:https://item.taobao.com/item.htm?id=630595051308

收起阅读 »

Android应用市场上架uni-app(5+App)应用合规指南,以及收到工信部或应用市场合规整改通知的解决办法

审核 合规 应用上架 非法获取 违规获取 android ID 隐私政策 合规指南 上架被拒 不合规

此文档将不再维护,请参考新文档:https://uniapp.dcloud.net.cn/tutorial/android-store

背景

为有效治理App强制授权、过度索权、超范围收集个人信息等现象,落实《网络安全法》《消费者权益保护法》的要求,保障个人信息安全,2019年1月,中央网信办、工信部、公安部、市场监管总局等四部委发布了《关于开展App违法违规收集使用个人信息专项治理的公告》,在全国范围组织开展App违法违规收集使用个人信息专项治理,并陆续出台完善了《App违法违规收集使用个人信息行为认定方法》、《GB/T 35273-2020 信息安全技术 个人信息安全规范》等标准规范。

根据以上规范要求,各大应用市场都加强应用的检测,要求应用必须符合相关政策,否则应用将有被通报或下架的风险。

APP因合规问题无法上架

请认真的阅读以下步骤来检测自己的APP!有效的解决上架问题

  • APP不是由HbuilderX3.6.1+云打包生产的请抓紧时间升级到HbuilderX3.6.1+版本。重新打包!
  • APP是离线打包请升级SDK到3.6.1+版本重新编辑打包!下载地址
  • 不要将自定义基座提交平台审核。调试模式下不会处理合规问题。需要注意!
  • APP没有配置隐私与政策提示框。请认真阅读Android平台隐私与政策提示框配置方法配置你APP的隐私弹窗。
  • 配置隐私弹窗时一定要配置使用template模式。否则无法上架应用市场。应用内部自己实现的隐私弹窗也不行。一定要使用uni提供的隐私弹窗并使用template模式切记!
    //androidPrivacy.json  
    {    
    "version": "1",      
    "prompt": "template",    
    "title": "服务协议和隐私政策",    
    "message": "..."  
    }  
  • 填写隐私协一定要结合实际使用的模块功能。填写相关隐私条款!不能含糊不清。模块收集了什么信息都要填写完整。否则影响上架!请参考当前文档中的隐私政策注意事项
  • 查看是否集成uni原生插件。有些权限或是违规获取可能是uni原生插件引发的。建议使用排除法删除插件重新打包检测
  • 检查是否集成了fcm推送(包含unipush中的fcm)、google统计、google推送、google登录模块。由于这些模块都集成google的gms服务会提前获取android id导致无法在国内正常上架。打包时请在manifest.json配置中排除这些功能模块。
  • APP都符合以上条件要求。上架依然失败!请向检测平台要求提供代码调用堆栈。请拿着堆栈信息去ASK论坛发帖说明问题并@管理人员反馈

<a id="zhuyishixiang">隐私政策注意事项</a>

  • 必须确保应用存在《隐私政策》,在应用首次启动时弹出提示并取得用户同意。
  • 一定要配置使用template模式隐私与政策提示框 详情参考
  • 必须在“隐私与政策”非常清楚、全面地说明(不要用可能收集、了解用户信息这种模糊不清晰的词语)收集用户个人信息的目的、方式和范围,用户个人信息包括但不限于mac地址、设备序列号、imei、imsi、软件安装列表、通讯录信息、短信信息等。
  • 如果反馈说有违规获取敏感信息行为,请查看Android平台各功能模块隐私合规协议各功能模块隐私协议。如果你集成了相关模块就一定要写入到app的隐私协议中。
  • 必须在《隐私政策》中必告知用户您的应用基于DCloud uni-app(5+ App/Wap2App)开发,添加如下协议:

    我们的产品基于DCloud uni-app(5+ App/Wap2App)开发,应用运行期间需要收集您的设备唯一识别码(IMEI/android ID/DEVICE_ID/IDFA、SIM 卡 IMSI 信息、OAID)以提供统计分析服务,并通过应用启动数据及异常错误日志分析改进性能和用户体验,为用户提供更好的服务。

各大应用市场上架合规审查细节可能存在差异,如果开发者碰到相关问题请及时反馈,我们会及时汇总整理供大家参考

相关参考

继续阅读 »

此文档将不再维护,请参考新文档:https://uniapp.dcloud.net.cn/tutorial/android-store

背景

为有效治理App强制授权、过度索权、超范围收集个人信息等现象,落实《网络安全法》《消费者权益保护法》的要求,保障个人信息安全,2019年1月,中央网信办、工信部、公安部、市场监管总局等四部委发布了《关于开展App违法违规收集使用个人信息专项治理的公告》,在全国范围组织开展App违法违规收集使用个人信息专项治理,并陆续出台完善了《App违法违规收集使用个人信息行为认定方法》、《GB/T 35273-2020 信息安全技术 个人信息安全规范》等标准规范。

根据以上规范要求,各大应用市场都加强应用的检测,要求应用必须符合相关政策,否则应用将有被通报或下架的风险。

APP因合规问题无法上架

请认真的阅读以下步骤来检测自己的APP!有效的解决上架问题

  • APP不是由HbuilderX3.6.1+云打包生产的请抓紧时间升级到HbuilderX3.6.1+版本。重新打包!
  • APP是离线打包请升级SDK到3.6.1+版本重新编辑打包!下载地址
  • 不要将自定义基座提交平台审核。调试模式下不会处理合规问题。需要注意!
  • APP没有配置隐私与政策提示框。请认真阅读Android平台隐私与政策提示框配置方法配置你APP的隐私弹窗。
  • 配置隐私弹窗时一定要配置使用template模式。否则无法上架应用市场。应用内部自己实现的隐私弹窗也不行。一定要使用uni提供的隐私弹窗并使用template模式切记!
    //androidPrivacy.json  
    {    
    "version": "1",      
    "prompt": "template",    
    "title": "服务协议和隐私政策",    
    "message": "..."  
    }  
  • 填写隐私协一定要结合实际使用的模块功能。填写相关隐私条款!不能含糊不清。模块收集了什么信息都要填写完整。否则影响上架!请参考当前文档中的隐私政策注意事项
  • 查看是否集成uni原生插件。有些权限或是违规获取可能是uni原生插件引发的。建议使用排除法删除插件重新打包检测
  • 检查是否集成了fcm推送(包含unipush中的fcm)、google统计、google推送、google登录模块。由于这些模块都集成google的gms服务会提前获取android id导致无法在国内正常上架。打包时请在manifest.json配置中排除这些功能模块。
  • APP都符合以上条件要求。上架依然失败!请向检测平台要求提供代码调用堆栈。请拿着堆栈信息去ASK论坛发帖说明问题并@管理人员反馈

<a id="zhuyishixiang">隐私政策注意事项</a>

  • 必须确保应用存在《隐私政策》,在应用首次启动时弹出提示并取得用户同意。
  • 一定要配置使用template模式隐私与政策提示框 详情参考
  • 必须在“隐私与政策”非常清楚、全面地说明(不要用可能收集、了解用户信息这种模糊不清晰的词语)收集用户个人信息的目的、方式和范围,用户个人信息包括但不限于mac地址、设备序列号、imei、imsi、软件安装列表、通讯录信息、短信信息等。
  • 如果反馈说有违规获取敏感信息行为,请查看Android平台各功能模块隐私合规协议各功能模块隐私协议。如果你集成了相关模块就一定要写入到app的隐私协议中。
  • 必须在《隐私政策》中必告知用户您的应用基于DCloud uni-app(5+ App/Wap2App)开发,添加如下协议:

    我们的产品基于DCloud uni-app(5+ App/Wap2App)开发,应用运行期间需要收集您的设备唯一识别码(IMEI/android ID/DEVICE_ID/IDFA、SIM 卡 IMSI 信息、OAID)以提供统计分析服务,并通过应用启动数据及异常错误日志分析改进性能和用户体验,为用户提供更好的服务。

各大应用市场上架合规审查细节可能存在差异,如果开发者碰到相关问题请及时反馈,我们会及时汇总整理供大家参考

相关参考

收起阅读 »

提示appkey未配置,请检查build.gradle

配置signingConfigs节点下的证书,
buildTypes节点下minifyEnabled改为true,官方给的demo这里是false,严重怀疑官方故意误导!

    signingConfigs {  
        config {  
            keyAlias ''  
            keyPassword ''  
            storeFile file('.jks')  
            storePassword ''  
            v1SigningEnabled true  
            v2SigningEnabled true  
        }  
    }  

    buildTypes {  
        debug {  
            signingConfig signingConfigs.config  
            minifyEnabled true  
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'  
        }  
        release {  
            signingConfig signingConfigs.config  
            minifyEnabled true  
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'  
        }  
    }
继续阅读 »

配置signingConfigs节点下的证书,
buildTypes节点下minifyEnabled改为true,官方给的demo这里是false,严重怀疑官方故意误导!

    signingConfigs {  
        config {  
            keyAlias ''  
            keyPassword ''  
            storeFile file('.jks')  
            storePassword ''  
            v1SigningEnabled true  
            v2SigningEnabled true  
        }  
    }  

    buildTypes {  
        debug {  
            signingConfig signingConfigs.config  
            minifyEnabled true  
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'  
        }  
        release {  
            signingConfig signingConfigs.config  
            minifyEnabled true  
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'  
        }  
    }
收起阅读 »